63 #include <stdlib.h>
64 #include <assert.h>
65 #include <sys/stat.h>
66 #include <zone.h>
67 #include <arpa/inet.h>
68 #include <netdb.h>
69 #include <locale.h>
70 #include <libintl.h>
71 #include <alloca.h>
72 #include <signal.h>
73 #include <wait.h>
74 #include <libtecla.h>
75 #include <libzfs.h>
76 #include <sys/brand.h>
77 #include <libbrand.h>
78 #include <sys/systeminfo.h>
79 #include <libdladm.h>
80 #include <libinetutil.h>
81 #include <pwd.h>
82 #include <inet/ip.h>
83 #include <uuid/uuid.h>
84
85 #include <libzonecfg.h>
86 #include "zonecfg.h"
87
88 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
89 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
90 #endif
91
92 #define PAGER "/usr/bin/more"
93 #define EXEC_PREFIX "exec "
94 #define EXEC_LEN (strlen(EXEC_PREFIX))
95
96 struct help {
97 uint_t cmd_num;
98 char *cmd_name;
99 uint_t flags;
100 char *short_usage;
101 };
102
103 extern int yyparse(void);
111
112 /*
113 * Each SHELP_ should be a simple string.
114 */
115
116 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
117 "add <property-name> <property-value>\n\t(resource scope)"
118 #define SHELP_CANCEL "cancel"
119 #define SHELP_CLEAR "clear <property-name>"
120 #define SHELP_COMMIT "commit"
121 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
122 #define SHELP_DELETE "delete [-F]"
123 #define SHELP_END "end"
124 #define SHELP_EXIT "exit [-F]"
125 #define SHELP_EXPORT "export [-f output-file]"
126 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
127 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
128 #define SHELP_REMOVE "remove [-F] <resource-type> " \
129 "[ <property-name>=<property-value> ]*\n" \
130 "\t(global scope)\n" \
131 "remove [-F] <property-name> <property-value>\n" \
132 "\t(resource scope)"
133 #define SHELP_REVERT "revert [-F]"
134 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
135 "<property-value> }"
136 #define SHELP_SET "set <property-name>=<property-value>"
137 #define SHELP_VERIFY "verify"
138
139 static struct help helptab[] = {
140 { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, },
141 { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, },
142 { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, },
143 { CMD_COMMIT, "commit", 0, SHELP_COMMIT, },
144 { CMD_CREATE, "create", 0, SHELP_CREATE, },
145 { CMD_DELETE, "delete", 0, SHELP_DELETE, },
146 { CMD_END, "end", 0, SHELP_END, },
147 { CMD_EXIT, "exit", 0, SHELP_EXIT, },
148 { CMD_EXPORT, "export", 0, SHELP_EXPORT, },
149 { CMD_HELP, "help", 0, SHELP_HELP },
150 { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, },
151 { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, },
172 "attr",
173 "dataset",
174 "limitpriv",
175 "bootargs",
176 "brand",
177 "dedicated-cpu",
178 "capped-memory",
179 ALIAS_MAXLWPS,
180 ALIAS_MAXSHMMEM,
181 ALIAS_MAXSHMIDS,
182 ALIAS_MAXMSGIDS,
183 ALIAS_MAXSEMIDS,
184 ALIAS_SHARES,
185 "scheduling-class",
186 "ip-type",
187 "capped-cpu",
188 "hostid",
189 "admin",
190 "fs-allowed",
191 ALIAS_MAXPROCS,
192 ALIAS_ZFSPRI,
193 "uuid",
194 NULL
195 };
196
197 /* These *must* match the order of the PT_ define's from zonecfg.h */
198 char *prop_types[] = {
199 "unknown",
200 "zonename",
201 "zonepath",
202 "autoboot",
203 "pool",
204 "dir",
205 "special",
206 "type",
207 "options",
208 "address",
209 "physical",
210 "name",
211 "value",
212 "match",
213 "priv",
226 ALIAS_MAXSHMMEM,
227 ALIAS_MAXSHMIDS,
228 ALIAS_MAXMSGIDS,
229 ALIAS_MAXSEMIDS,
230 ALIAS_MAXLOCKEDMEM,
231 ALIAS_MAXSWAP,
232 "scheduling-class",
233 "ip-type",
234 "defrouter",
235 "hostid",
236 "user",
237 "auths",
238 "fs-allowed",
239 ALIAS_MAXPROCS,
240 "allowed-address",
241 ALIAS_ZFSPRI,
242 "mac-addr",
243 "vlan-id",
244 "global-nic",
245 "property",
246 "uuid",
247 NULL
248 };
249
250 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
251 static char *prop_val_types[] = {
252 "simple",
253 "complex",
254 "list",
255 };
256
257 /*
258 * The various _cmds[] lists below are for command tab-completion.
259 */
260
261 /*
262 * remove has a space afterwards because it has qualifiers; the other commands
263 * that have qualifiers (add, select, etc.) don't need a space here because
264 * they have their own _cmds[] lists below.
265 */
266 static const char *global_scope_cmds[] = {
292 "add capped-cpu",
293 "add capped-memory",
294 "add admin",
295 NULL
296 };
297
298 static const char *clear_cmds[] = {
299 "clear autoboot",
300 "clear pool",
301 "clear limitpriv",
302 "clear bootargs",
303 "clear scheduling-class",
304 "clear ip-type",
305 "clear " ALIAS_MAXLWPS,
306 "clear " ALIAS_MAXSHMMEM,
307 "clear " ALIAS_MAXSHMIDS,
308 "clear " ALIAS_MAXMSGIDS,
309 "clear " ALIAS_MAXSEMIDS,
310 "clear " ALIAS_SHARES,
311 "clear " ALIAS_MAXPROCS,
312 "clear " ALIAS_ZFSPRI,
313 NULL
314 };
315
316 static const char *remove_cmds[] = {
317 "remove fs ",
318 "remove net ",
319 "remove device ",
320 "remove rctl ",
321 "remove attr ",
322 "remove dataset ",
323 "remove dedicated-cpu ",
324 "remove capped-cpu ",
325 "remove capped-memory ",
326 "remove admin ",
327 NULL
328 };
329
330 static const char *select_cmds[] = {
331 "select fs ",
332 "select net ",
343
344 static const char *set_cmds[] = {
345 "set zonename=",
346 "set zonepath=",
347 "set brand=",
348 "set autoboot=",
349 "set pool=",
350 "set limitpriv=",
351 "set bootargs=",
352 "set scheduling-class=",
353 "set ip-type=",
354 "set " ALIAS_MAXLWPS "=",
355 "set " ALIAS_MAXSHMMEM "=",
356 "set " ALIAS_MAXSHMIDS "=",
357 "set " ALIAS_MAXMSGIDS "=",
358 "set " ALIAS_MAXSEMIDS "=",
359 "set " ALIAS_SHARES "=",
360 "set hostid=",
361 "set fs-allowed=",
362 "set " ALIAS_MAXPROCS "=",
363 "set " ALIAS_ZFSPRI "=",
364 "set uuid=",
365 NULL
366 };
367
368 static const char *info_cmds[] = {
369 "info fs ",
370 "info net ",
371 "info device ",
372 "info rctl ",
373 "info attr ",
374 "info dataset ",
375 "info capped-memory",
376 "info dedicated-cpu",
377 "info capped-cpu",
378 "info zonename",
379 "info zonepath",
380 "info autoboot",
381 "info pool",
382 "info limitpriv",
383 "info bootargs",
384 "info brand",
385 "info scheduling-class",
386 "info ip-type",
387 "info max-lwps",
388 "info max-shm-memory",
389 "info max-shm-ids",
390 "info max-msg-ids",
391 "info max-sem-ids",
392 "info cpu-shares",
393 "info hostid",
394 "info admin",
395 "info fs-allowed",
396 "info max-processes",
397 "info uuid",
398 NULL
399 };
400
401 static const char *fs_res_scope_cmds[] = {
402 "add options ",
403 "cancel",
404 "end",
405 "exit",
406 "help",
407 "info",
408 "remove options ",
409 "set dir=",
410 "set raw=",
411 "set special=",
412 "set type=",
413 "clear raw",
414 NULL
415 };
416
417 static const char *net_res_scope_cmds[] = {
534 struct xif *xif_next;
535 char xif_name[LIFNAMSIZ];
536 boolean_t xif_has_address;
537 boolean_t xif_has_defrouter;
538 };
539
540 /* Global variables */
541
542 /* list of network interfaces specified for exclusive IP zone */
543 struct xif *xif;
544
545 /* set early in main(), never modified thereafter, used all over the place */
546 static char *execname;
547
548 /* set in main(), used all over the place */
549 static zone_dochandle_t handle;
550
551 /* used all over the place */
552 static char zone[ZONENAME_MAX];
553 static char revert_zone[ZONENAME_MAX];
554 static char new_uuid[UUID_PRINTABLE_STRING_LENGTH];
555
556 /* global brand operations */
557 static brand_handle_t brand;
558
559 /* set in modifying functions, checked in read_input() */
560 static boolean_t need_to_commit = B_FALSE;
561 static boolean_t is_create = B_FALSE;
562 boolean_t saw_error;
563
564 /* set in yacc parser, checked in read_input() */
565 boolean_t newline_terminated;
566
567 /* set in main(), checked in lex error handler */
568 boolean_t cmd_file_mode;
569
570 /* set in exit_func(), checked in read_input() */
571 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
572
573 /* used in short_usage() and zerr() */
574 static char *cmd_file_name = NULL;
575
576 /* checked in read_input() and other places */
577 static boolean_t ok_to_prompt = B_FALSE;
578
579 /* set and checked in initialize() */
580 static boolean_t got_handle = B_FALSE;
581
983 if ((pathstr = getenv("PATH")) == NULL) {
984 if (geteuid() == 0 || getuid() == 0)
985 pathstr = "/usr/sbin:/usr/bin";
986 else
987 pathstr = "/usr/bin:";
988 }
989 cp = strchr(name, '/') ? (const char *) "" : pathstr;
990
991 do {
992 cp = exec_cat(cp, name, fname);
993 if (stat(fname, &stat_buf) != -1) {
994 /* successful find of the file */
995 return (0);
996 }
997 } while (cp != NULL);
998
999 return (-1);
1000 }
1001
1002 static FILE *
1003 pager_open(void)
1004 {
1005 FILE *newfp;
1006 char *pager, *space;
1007
1008 pager = getenv("PAGER");
1009 if (pager == NULL || *pager == '\0')
1010 pager = PAGER;
1011
1012 space = strchr(pager, ' ');
1013 if (space)
1014 *space = '\0';
1015 if (path_find(pager) == 0) {
1016 if (space)
1017 *space = ' ';
1018 if ((newfp = popen(pager, "w")) == NULL)
1019 zerr(gettext("PAGER open failed (%s)."),
1020 strerror(errno));
1021 return (newfp);
1022 } else {
1023 zerr(gettext("PAGER %s does not exist (%s)."),
1024 pager, strerror(errno));
1025 }
1026 return (NULL);
1027 }
1028
1029 static void
1030 pager_close(FILE *fp)
1031 {
1032 int status;
1033
1034 status = pclose(fp);
1035 if (status == -1)
1036 zerr(gettext("PAGER close failed (%s)."),
1037 strerror(errno));
1038 }
1039
1040 /*
1041 * Called with verbose TRUE when help is explicitly requested, FALSE for
1042 * unexpected errors.
1043 */
1044
1045 void
1046 usage(boolean_t verbose, uint_t flags)
1047 {
1048 FILE *fp = verbose ? stdout : stderr;
1049 FILE *newfp;
1050 boolean_t need_to_close = B_FALSE;
1051 int i;
1266 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1267 pt_to_str(PT_USER),
1268 gettext("<single user or role name>"));
1269 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1270 pt_to_str(PT_AUTHS),
1271 gettext("<comma separated list>"));
1272 break;
1273 }
1274 (void) fprintf(fp, gettext("And from any resource scope, you "
1275 "can:\n"));
1276 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1277 gettext("(to conclude this operation)"));
1278 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1279 gettext("(to cancel this operation)"));
1280 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1281 gettext("(to exit the zonecfg utility)"));
1282 }
1283 if (flags & HELP_USAGE) {
1284 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1285 execname, cmd_to_str(CMD_HELP));
1286 (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>}\t\t\t(%s)\n",
1287 execname, gettext("interactive"));
1288 (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>} <command>\n",
1289 execname);
1290 (void) fprintf(fp,
1291 "\t%s {-z <zone>|-u <uuid>} -f <command-file>\n",
1292 execname);
1293 }
1294 if (flags & HELP_SUBCMDS) {
1295 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1296 for (i = 0; i <= CMD_MAX; i++) {
1297 (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1298 if (verbose)
1299 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1300 }
1301 }
1302 if (flags & HELP_SYNTAX) {
1303 if (!verbose)
1304 (void) fprintf(fp, "\n");
1305 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1306 (void) fprintf(fp, gettext("\t(except the reserved words "
1307 "'%s' and anything starting with '%s')\n"), "global",
1308 "SUNW");
1309 (void) fprintf(fp,
1310 gettext("\tName must be less than %d characters.\n"),
1311 ZONENAME_MAX);
1312 if (verbose)
1360 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1361 pt_to_str(PT_IPTYPE));
1362 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1363 pt_to_str(PT_HOSTID));
1364 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1365 pt_to_str(PT_FS_ALLOWED));
1366 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1367 pt_to_str(PT_MAXLWPS));
1368 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1369 pt_to_str(PT_MAXPROCS));
1370 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1371 pt_to_str(PT_MAXSHMMEM));
1372 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1373 pt_to_str(PT_MAXSHMIDS));
1374 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1375 pt_to_str(PT_MAXMSGIDS));
1376 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1377 pt_to_str(PT_MAXSEMIDS));
1378 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1379 pt_to_str(PT_SHARES));
1380 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1381 pt_to_str(PT_UUID));
1382 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1383 pt_to_str(PT_ZFSPRI));
1384 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1385 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1386 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1387 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1388 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n",
1389 rt_to_str(RT_NET),
1390 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1391 pt_to_str(PT_GNIC), pt_to_str(PT_MAC),
1392 pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP),
1393 pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER));
1394 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE),
1395 pt_to_str(PT_MATCH), pt_to_str(PT_NPROP));
1396 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1397 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1398 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1399 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1400 pt_to_str(PT_VALUE));
1401 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1402 pt_to_str(PT_NAME));
1403 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1700 cmd_to_str(cmd_num));
1701 saw_error = B_TRUE;
1702 return (B_TRUE);
1703 }
1704 return (B_FALSE);
1705 }
1706
1707 /*
1708 * Create a new configuration.
1709 */
1710 void
1711 create_func(cmd_t *cmd)
1712 {
1713 int err, arg;
1714 char zone_template[ZONENAME_MAX];
1715 char attach_path[MAXPATHLEN];
1716 zone_dochandle_t tmphandle;
1717 boolean_t force = B_FALSE;
1718 boolean_t attach = B_FALSE;
1719 boolean_t arg_err = B_FALSE;
1720 uuid_t uuid;
1721
1722 assert(cmd != NULL);
1723
1724 /* This is the default if no arguments are given. */
1725 (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1726
1727 optind = 0;
1728 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:X"))
1729 != EOF) {
1730 switch (arg) {
1731 case '?':
1732 if (optopt == '?')
1733 longer_usage(CMD_CREATE);
1734 else
1735 short_usage(CMD_CREATE);
1736 arg_err = B_TRUE;
1737 break;
1738 case 'a':
1739 (void) strlcpy(attach_path, optarg,
1740 sizeof (attach_path));
1741 attach = B_TRUE;
1742 break;
1743 case 'b':
1744 (void) strlcpy(zone_template, "SUNWblank",
1745 sizeof (zone_template));
1746 break;
1747 case 'F':
1748 force = B_TRUE;
1798 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1799 zone, B_FALSE, tmphandle);
1800 else
1801 err = zonecfg_get_template_handle(zone_template, zone,
1802 tmphandle);
1803
1804 if (err != Z_OK) {
1805 zonecfg_fini_handle(tmphandle);
1806 if (attach && err == Z_NO_ZONE)
1807 (void) fprintf(stderr, gettext("invalid path to "
1808 "detached zone\n"));
1809 else if (attach && err == Z_INVALID_DOCUMENT)
1810 (void) fprintf(stderr, gettext("Cannot attach to an "
1811 "earlier release of the operating system\n"));
1812 else
1813 zone_perror(zone_template, err, B_TRUE);
1814 return;
1815 }
1816
1817 need_to_commit = B_TRUE;
1818 is_create = B_TRUE;
1819 zonecfg_fini_handle(handle);
1820 handle = tmphandle;
1821 got_handle = B_TRUE;
1822
1823 /* Allocate a new uuid for this new zone */
1824 uuid_generate(uuid);
1825 uuid_unparse(uuid, new_uuid);
1826 }
1827
1828 /*
1829 * This malloc()'s memory, which must be freed by the caller.
1830 */
1831 static char *
1832 quoteit(char *instr)
1833 {
1834 char *outstr;
1835 size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
1836
1837 if ((outstr = malloc(outstrsize)) == NULL) {
1838 zone_perror(zone, Z_NOMEM, B_FALSE);
1839 exit(Z_ERR);
1840 }
1841 if (strchr(instr, ' ') == NULL) {
1842 (void) strlcpy(outstr, instr, outstrsize);
1843 return (outstr);
1844 }
1845 (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
1866 struct zone_fstab fstab;
1867 struct zone_devtab devtab;
1868 struct zone_attrtab attrtab;
1869 struct zone_rctltab rctltab;
1870 struct zone_dstab dstab;
1871 struct zone_psettab psettab;
1872 struct zone_rctlvaltab *valptr;
1873 struct zone_res_attrtab *rap;
1874 struct zone_admintab admintab;
1875 int err, arg;
1876 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1877 char bootargs[BOOTARGS_MAX];
1878 char sched[MAXNAMELEN];
1879 char brand[MAXNAMELEN];
1880 char hostidp[HW_HOSTID_LEN];
1881 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1882 char *limitpriv;
1883 FILE *of;
1884 boolean_t autoboot;
1885 zone_iptype_t iptype;
1886 uuid_t uuid;
1887 boolean_t need_to_close = B_FALSE;
1888 boolean_t arg_err = B_FALSE;
1889
1890 assert(cmd != NULL);
1891
1892 outfile[0] = '\0';
1893 optind = 0;
1894 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1895 switch (arg) {
1896 case '?':
1897 if (optopt == '?')
1898 longer_usage(CMD_EXPORT);
1899 else
1900 short_usage(CMD_EXPORT);
1901 arg_err = B_TRUE;
1902 break;
1903 case 'f':
1904 (void) strlcpy(outfile, optarg, sizeof (outfile));
1905 break;
1906 default:
1977 pt_to_str(PT_IPTYPE), "shared");
1978 break;
1979 case ZS_EXCLUSIVE:
1980 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1981 pt_to_str(PT_IPTYPE), "exclusive");
1982 break;
1983 }
1984 }
1985
1986 if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1987 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1988 pt_to_str(PT_HOSTID), hostidp);
1989 }
1990
1991 if (zonecfg_get_fs_allowed(handle, fsallowedp,
1992 sizeof (fsallowedp)) == Z_OK) {
1993 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1994 pt_to_str(PT_FS_ALLOWED), fsallowedp);
1995 }
1996
1997 if (zonecfg_get_uuid(zone, uuid) == Z_OK && !uuid_is_null(uuid)) {
1998 char suuid[UUID_PRINTABLE_STRING_LENGTH];
1999
2000 uuid_unparse(uuid, suuid);
2001 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2002 pt_to_str(PT_UUID), suuid);
2003 }
2004
2005 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
2006 zone_perror(zone, err, B_FALSE);
2007 goto done;
2008 }
2009 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2010 zone_fsopt_t *optptr;
2011
2012 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2013 rt_to_str(RT_FS));
2014 export_prop(of, PT_DIR, fstab.zone_fs_dir);
2015 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
2016 export_prop(of, PT_RAW, fstab.zone_fs_raw);
2017 export_prop(of, PT_TYPE, fstab.zone_fs_type);
2018 for (optptr = fstab.zone_fs_options; optptr != NULL;
2019 optptr = optptr->zone_fsopt_next) {
2020 /*
2021 * Simple property values with embedded equal signs
2022 * need to be quoted to prevent the lexer from
2023 * mis-parsing them as complex name=value pairs.
2024 */
2452 do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp)
2453 {
2454 complex_property_ptr_t cp;
2455 struct zone_res_attrtab *np;
2456 int err;
2457 boolean_t seen_name = B_FALSE, seen_value = B_FALSE;
2458
2459 if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) {
2460 zone_perror(zone, Z_NOMEM, B_TRUE);
2461 exit(Z_ERR);
2462 }
2463
2464 for (cp = cpp; cp != NULL; cp = cp->cp_next) {
2465 switch (cp->cp_type) {
2466 case PT_NAME:
2467 if (seen_name) {
2468 zerr(gettext("%s already specified"),
2469 pt_to_str(PT_NAME));
2470 goto bad;
2471 }
2472 if (strlcpy(np->zone_res_attr_name, cp->cp_value,
2473 sizeof (np->zone_res_attr_name)) >=
2474 sizeof (np->zone_res_attr_name)) {
2475 zerr(gettext("Input for %s is too long"),
2476 pt_to_str(PT_NAME));
2477 goto bad;
2478 }
2479 seen_name = B_TRUE;
2480 break;
2481 case PT_VALUE:
2482 if (seen_value) {
2483 zerr(gettext("%s already specified"),
2484 pt_to_str(PT_VALUE));
2485 goto bad;
2486 }
2487 if (strlcpy(np->zone_res_attr_value, cp->cp_value,
2488 sizeof (np->zone_res_attr_value)) >=
2489 sizeof (np->zone_res_attr_value)) {
2490 zerr(gettext("Input for %s is too long"),
2491 pt_to_str(PT_VALUE));
2492 goto bad;
2493 }
2494
2495 seen_value = B_TRUE;
2496 break;
2497 default:
2498 zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE,
2499 B_TRUE);
2500 long_usage(CMD_ADD, B_TRUE);
2501 usage(B_FALSE, HELP_PROPS);
2502 zonecfg_free_res_attr_list(np);
2503 return;
2504 }
2505 }
2506
2507 if (!seen_name)
2508 zerr(gettext("%s not specified"), pt_to_str(PT_NAME));
2509 if (!seen_value)
2510 zerr(gettext("%s not specified"), pt_to_str(PT_VALUE));
2511
2512 err = zonecfg_add_res_attr(headp, np);
2513 if (err != Z_OK)
2514 zone_perror(pt_to_str(PT_NPROP), err, B_TRUE);
2650 default:
2651 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2652 long_usage(CMD_ADD, B_TRUE);
2653 usage(B_FALSE, HELP_RESOURCES);
2654 return;
2655 }
2656 }
2657
2658 static boolean_t
2659 gz_invalid_resource(int type)
2660 {
2661 return (global_zone && (type == RT_FS ||
2662 type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2663 type == RT_DATASET));
2664 }
2665
2666 static boolean_t
2667 gz_invalid_rt_property(int type)
2668 {
2669 return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2670 type == RT_AUTOBOOT || type == RT_LIMITPRIV || type == RT_UUID ||
2671 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2672 type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2673 }
2674
2675 static boolean_t
2676 gz_invalid_property(int type)
2677 {
2678 return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2679 type == PT_AUTOBOOT || type == PT_LIMITPRIV || type == PT_UUID ||
2680 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2681 type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2682 }
2683
2684 void
2685 add_func(cmd_t *cmd)
2686 {
2687 int arg;
2688 boolean_t arg_err = B_FALSE;
2689
2690 assert(cmd != NULL);
2691
2692 optind = 0;
2693 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2694 switch (arg) {
2695 case '?':
2696 longer_usage(CMD_ADD);
2697 arg_err = B_TRUE;
2698 break;
2699 default:
2877 break;
2878 case PT_RAW:
2879 (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2880 sizeof (fstab->zone_fs_raw));
2881 break;
2882 case PT_TYPE:
2883 (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2884 sizeof (fstab->zone_fs_type));
2885 break;
2886 default:
2887 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2888 Z_NO_PROPERTY_TYPE, B_TRUE);
2889 return (Z_INSUFFICIENT_SPEC);
2890 }
2891 }
2892 if (fill_in_only)
2893 return (Z_OK);
2894 return (zonecfg_lookup_filesystem(handle, fstab));
2895 }
2896
2897 /*
2898 * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c
2899 * We're expecting a dst of at least MAXMACADDRLEN size here.
2900 */
2901 static void
2902 normalize_mac_addr(char *dst, const char *src, int len)
2903 {
2904 char *p, *e, *sep = "";
2905 long n;
2906 char buf[MAXMACADDRLEN], tmp[4];
2907
2908 *dst = '\0';
2909 (void) strlcpy(buf, src, sizeof (buf));
2910 p = strtok(buf, ":");
2911 while (p != NULL) {
2912 n = strtol(p, &e, 16);
2913 if (*e != NULL || n > 0xff)
2914 return;
2915 (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n);
2916 (void) strlcat(dst, tmp, len);
2917
2918 sep = ":";
2919 p = strtok(NULL, ":");
2920 }
2921 }
2922
2923 static int
2924 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2925 boolean_t fill_in_only)
2926 {
2927 int err, i;
2928 property_value_ptr_t pp;
2929
2930 if ((err = initialize(B_TRUE)) != Z_OK)
2931 return (err);
2932
2933 bzero(nwiftab, sizeof (*nwiftab));
2934 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2935 pp = cmd->cmd_property_ptr[i];
2936 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2937 zerr(gettext("A simple value was expected here."));
2938 saw_error = B_TRUE;
2939 return (Z_INSUFFICIENT_SPEC);
2940 }
2941 switch (cmd->cmd_prop_name[i]) {
2942 case PT_ADDRESS:
2943 (void) strlcpy(nwiftab->zone_nwif_address,
2944 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2945 break;
2946 case PT_ALLOWED_ADDRESS:
2947 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2948 pp->pv_simple,
2949 sizeof (nwiftab->zone_nwif_allowed_address));
2950 break;
2951 case PT_PHYSICAL:
2952 (void) strlcpy(nwiftab->zone_nwif_physical,
2953 pp->pv_simple,
2954 sizeof (nwiftab->zone_nwif_physical));
2955 break;
2956 case PT_MAC:
2957 normalize_mac_addr(nwiftab->zone_nwif_mac,
2958 pp->pv_simple,
2959 sizeof (nwiftab->zone_nwif_mac));
2960 break;
2961 case PT_VLANID:
2962 (void) strlcpy(nwiftab->zone_nwif_vlan_id,
2963 pp->pv_simple,
2964 sizeof (nwiftab->zone_nwif_vlan_id));
2965 break;
2966 case PT_GNIC:
2967 (void) strlcpy(nwiftab->zone_nwif_gnic,
2968 pp->pv_simple,
2969 sizeof (nwiftab->zone_nwif_gnic));
2970 break;
2971 case PT_DEFROUTER:
2972 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2973 pp->pv_simple,
2974 sizeof (nwiftab->zone_nwif_defrouter));
2975 break;
2976 default:
2977 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3201 boolean_t arg_err = B_FALSE;
3202
3203 optind = 0;
3204 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3205 switch (arg) {
3206 case 'F':
3207 force = B_TRUE;
3208 break;
3209 default:
3210 arg_err = B_TRUE;
3211 break;
3212 }
3213 }
3214 if (arg_err)
3215 return (B_FALSE);
3216
3217
3218 num = zonecfg_num_resources(handle, rsrc);
3219
3220 if (num == 0) {
3221 if (force)
3222 return (B_TRUE);
3223 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
3224 B_TRUE);
3225 return (B_FALSE);
3226 }
3227 if (num > 1 && !force) {
3228 if (!interactive_mode) {
3229 zerr(gettext("There are multiple instances of this "
3230 "resource. Either qualify the resource to\n"
3231 "remove a single instance or use the -F option to "
3232 "remove all instances."));
3233 saw_error = B_TRUE;
3234 return (B_FALSE);
3235 }
3236 (void) snprintf(prompt, sizeof (prompt), gettext(
3237 "Are you sure you want to remove ALL '%s' resources"),
3238 rsrc);
3239 answer = ask_yesno(B_FALSE, prompt);
3240 if (answer == -1) {
3241 zerr(gettext("Resource incomplete."));
3242 return (B_FALSE);
3243 }
3244 if (answer != 1)
3245 return (B_FALSE);
3246 }
3247 return (B_TRUE);
3248 }
3249
3250 static void
3251 remove_fs(cmd_t *cmd, boolean_t force)
3252 {
3253 int err;
3254
3255 /* traditional, qualified fs removal */
3256 if (cmd->cmd_prop_nv_pairs > 0) {
3257 struct zone_fstab fstab;
3258
3259 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
3260 if (!force)
3261 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3262 return;
3263 }
3264 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) {
3265 if (!force)
3266 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3267 } else {
3268 need_to_commit = B_TRUE;
3269 }
3270 zonecfg_free_fs_option_list(fstab.zone_fs_options);
3271 return;
3272 }
3273
3274 /*
3275 * unqualified fs removal. remove all fs's but prompt if more
3276 * than one.
3277 */
3278 if (!prompt_remove_resource(cmd, "fs"))
3279 return;
3280
3281 if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
3282 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3283 else
3284 need_to_commit = B_TRUE;
3285 }
3286
3287 static void
3288 remove_net(cmd_t *cmd, boolean_t force)
3289 {
3290 int err;
3291
3292 /* traditional, qualified net removal */
3293 if (cmd->cmd_prop_nv_pairs > 0) {
3294 struct zone_nwiftab nwiftab;
3295
3296 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
3297 if (!force)
3298 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err,
3299 B_TRUE);
3300 return;
3301 }
3302 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) {
3303 if (!force)
3304 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err,
3305 B_TRUE);
3306 } else {
3307 need_to_commit = B_TRUE;
3308 }
3309 return;
3310 }
3311
3312 /*
3313 * unqualified net removal. remove all nets but prompt if more
3314 * than one.
3315 */
3316 if (!prompt_remove_resource(cmd, "net"))
3317 return;
3318
3319 if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
3320 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3321 else
3322 need_to_commit = B_TRUE;
3323 }
3324
3325 static void
3326 remove_device(cmd_t *cmd, boolean_t force)
3327 {
3328 int err;
3329
3330 /* traditional, qualified device removal */
3331 if (cmd->cmd_prop_nv_pairs > 0) {
3332 struct zone_devtab devtab;
3333
3334 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3335 if (!force)
3336 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err,
3337 B_TRUE);
3338 return;
3339 }
3340 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) {
3341 if (!force)
3342 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err,
3343 B_TRUE);
3344 } else {
3345 need_to_commit = B_TRUE;
3346 }
3347 return;
3348 }
3349
3350 /*
3351 * unqualified device removal. remove all devices but prompt if more
3352 * than one.
3353 */
3354 if (!prompt_remove_resource(cmd, "device"))
3355 return;
3356
3357 if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3358 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3359 else
3360 need_to_commit = B_TRUE;
3361 }
3362
3363 static void
3364 remove_attr(cmd_t *cmd, boolean_t force)
3365 {
3366 int err;
3367
3368 /* traditional, qualified attr removal */
3369 if (cmd->cmd_prop_nv_pairs > 0) {
3370 struct zone_attrtab attrtab;
3371
3372 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3373 if (!force)
3374 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err,
3375 B_TRUE);
3376 return;
3377 }
3378 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) {
3379 if (!force)
3380 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err,
3381 B_TRUE);
3382 } else {
3383 need_to_commit = B_TRUE;
3384 }
3385 return;
3386 }
3387
3388 /*
3389 * unqualified attr removal. remove all attrs but prompt if more
3390 * than one.
3391 */
3392 if (!prompt_remove_resource(cmd, "attr"))
3393 return;
3394
3395 if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3396 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3397 else
3398 need_to_commit = B_TRUE;
3399 }
3400
3401 static void
3402 remove_dataset(cmd_t *cmd, boolean_t force)
3403 {
3404 int err;
3405
3406 /* traditional, qualified dataset removal */
3407 if (cmd->cmd_prop_nv_pairs > 0) {
3408 struct zone_dstab dstab;
3409
3410 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3411 if (!force)
3412 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err,
3413 B_TRUE);
3414 return;
3415 }
3416 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK) {
3417 if (!force)
3418 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err,
3419 B_TRUE);
3420 } else {
3421 need_to_commit = B_TRUE;
3422 }
3423 return;
3424 }
3425
3426 /*
3427 * unqualified dataset removal. remove all datasets but prompt if more
3428 * than one.
3429 */
3430 if (!prompt_remove_resource(cmd, "dataset"))
3431 return;
3432
3433 if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3434 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3435 else
3436 need_to_commit = B_TRUE;
3437 }
3438
3439 static void
3440 remove_rctl(cmd_t *cmd, boolean_t force)
3441 {
3442 int err;
3443
3444 /* traditional, qualified rctl removal */
3445 if (cmd->cmd_prop_nv_pairs > 0) {
3446 struct zone_rctltab rctltab;
3447
3448 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3449 if (!force)
3450 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err,
3451 B_TRUE);
3452 return;
3453 }
3454 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) {
3455 if (!force)
3456 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err,
3457 B_TRUE);
3458 } else {
3459 need_to_commit = B_TRUE;
3460 }
3461 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3462 return;
3463 }
3464
3465 /*
3466 * unqualified rctl removal. remove all rctls but prompt if more
3467 * than one.
3468 */
3469 if (!prompt_remove_resource(cmd, "rctl"))
3470 return;
3471
3472 if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3473 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3474 else
3475 need_to_commit = B_TRUE;
3476 }
3477
3478 static void
3479 remove_pset(boolean_t force)
3480 {
3481 int err;
3482 struct zone_psettab psettab;
3483
3484 if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3485 if (!force)
3486 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3487 return;
3488 }
3489 if ((err = zonecfg_delete_pset(handle)) != Z_OK) {
3490 if (!force)
3491 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3492 } else {
3493 need_to_commit = B_TRUE;
3494 }
3495 }
3496
3497 static void
3498 remove_pcap(boolean_t force)
3499 {
3500 int err;
3501 uint64_t tmp;
3502
3503 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3504 if (!force) {
3505 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3506 rt_to_str(RT_PCAP),
3507 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3508 saw_error = B_TRUE;
3509 }
3510 return;
3511 }
3512
3513 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK) {
3514 if (!force)
3515 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3516 } else {
3517 need_to_commit = B_TRUE;
3518 }
3519 }
3520
3521 static void
3522 remove_mcap(boolean_t force)
3523 {
3524 int err, res1, res2, res3;
3525 uint64_t tmp;
3526 boolean_t revert = B_FALSE;
3527
3528 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp);
3529 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3530 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3531
3532 /* if none of these exist, there is no resource to remove */
3533 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3534 if (!force) {
3535 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3536 rt_to_str(RT_MCAP),
3537 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3538 saw_error = B_TRUE;
3539 }
3540 return;
3541 }
3542 if (res1 == Z_OK) {
3543 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM))
3544 != Z_OK) {
3545 if (!force) {
3546 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3547 B_TRUE);
3548 revert = B_TRUE;
3549 }
3550 } else {
3551 need_to_commit = B_TRUE;
3552 }
3553 }
3554
3555 if (res2 == Z_OK) {
3556 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3557 != Z_OK) {
3558 if (!force) {
3559 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3560 B_TRUE);
3561 revert = B_TRUE;
3562 }
3563 } else {
3564 need_to_commit = B_TRUE;
3565 }
3566 }
3567 if (res3 == Z_OK) {
3568 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3569 != Z_OK) {
3570 if (!force) {
3571 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3572 B_TRUE);
3573 revert = B_TRUE;
3574 }
3575 } else {
3576 need_to_commit = B_TRUE;
3577 }
3578 }
3579
3580 if (revert)
3581 need_to_commit = B_FALSE;
3582 }
3583
3584 static void
3585 remove_admin(cmd_t *cmd, boolean_t force)
3586 {
3587 int err;
3588
3589 /* traditional, qualified attr removal */
3590 if (cmd->cmd_prop_nv_pairs > 0) {
3591 struct zone_admintab admintab;
3592
3593 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3594 if (!force)
3595 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err,
3596 B_TRUE);
3597 return;
3598 }
3599 if ((err = zonecfg_delete_admin(handle, &admintab,
3600 zone)) != Z_OK) {
3601 if (!force)
3602 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err,
3603 B_TRUE);
3604 } else {
3605 need_to_commit = B_TRUE;
3606 }
3607 return;
3608 }
3609
3610 /*
3611 * unqualified admin removal.
3612 * remove all admins but prompt if more than one.
3613 */
3614 if (!prompt_remove_resource(cmd, "admin"))
3615 return;
3616
3617 if ((err = zonecfg_delete_admins(handle, zone)) != Z_OK)
3618 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err, B_TRUE);
3619 else
3620 need_to_commit = B_TRUE;
3621 }
3622
3623 static void
3624 remove_resource(cmd_t *cmd)
3625 {
3626 int type;
3627 int arg;
3628 boolean_t arg_err = B_FALSE;
3629 boolean_t force = B_FALSE;
3630
3631 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3632 long_usage(CMD_REMOVE, B_TRUE);
3633 return;
3634 }
3635
3636 optind = 0;
3637 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3638 switch (arg) {
3639 case '?':
3640 longer_usage(CMD_REMOVE);
3641 arg_err = B_TRUE;
3642 break;
3643 case 'F':
3644 force = B_TRUE;
3645 break;
3646 default:
3647 short_usage(CMD_REMOVE);
3648 arg_err = B_TRUE;
3649 break;
3650 }
3651 }
3652 if (arg_err)
3653 return;
3654
3655 if (initialize(B_TRUE) != Z_OK)
3656 return;
3657
3658 switch (type) {
3659 case RT_FS:
3660 remove_fs(cmd, force);
3661 return;
3662 case RT_NET:
3663 remove_net(cmd, force);
3664 return;
3665 case RT_DEVICE:
3666 remove_device(cmd, force);
3667 return;
3668 case RT_RCTL:
3669 remove_rctl(cmd, force);
3670 return;
3671 case RT_ATTR:
3672 remove_attr(cmd, force);
3673 return;
3674 case RT_DATASET:
3675 remove_dataset(cmd, force);
3676 return;
3677 case RT_DCPU:
3678 remove_pset(force);
3679 return;
3680 case RT_PCAP:
3681 remove_pcap(force);
3682 return;
3683 case RT_MCAP:
3684 remove_mcap(force);
3685 return;
3686 case RT_ADMIN:
3687 remove_admin(cmd, force);
3688 return;
3689 default:
3690 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3691 long_usage(CMD_REMOVE, B_TRUE);
3692 usage(B_FALSE, HELP_RESOURCES);
3693 return;
3694 }
3695 }
3696
3697 static void
3698 remove_property(cmd_t *cmd)
3699 {
3700 char *prop_id;
3701 int err, res_type, prop_type;
3702 property_value_ptr_t pp;
3703 struct zone_rctlvaltab *rctlvaltab;
3704 struct zone_res_attrtab *np;
3705 complex_property_ptr_t cx;
3706 int arg;
3707 boolean_t force = B_FALSE;
3708 boolean_t arg_err = B_FALSE;
3709
3710 optind = 0;
3711 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3712 switch (arg) {
3713 case 'F':
3714 force = B_TRUE;
3715 break;
3716 default:
3717 arg_err = B_TRUE;
3718 break;
3719 }
3720 }
3721 if (arg_err) {
3722 saw_error = B_TRUE;
3723 return;
3724 }
3725
3726 res_type = resource_scope;
3727 prop_type = cmd->cmd_prop_name[0];
3728 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3729 long_usage(CMD_REMOVE, B_TRUE);
3730 return;
3731 }
3732
3733 if (cmd->cmd_prop_nv_pairs != 1) {
3734 long_usage(CMD_ADD, B_TRUE);
3735 return;
3736 }
3737
3738 if (initialize(B_TRUE) != Z_OK)
3739 return;
3740
3741 switch (res_type) {
3742 case RT_FS:
3743 if (prop_type != PT_OPTIONS) {
3744 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3745 B_TRUE);
3746 long_usage(CMD_REMOVE, B_TRUE);
3747 usage(B_FALSE, HELP_PROPS);
3748 return;
3749 }
3750 pp = cmd->cmd_property_ptr[0];
3751 if (pp->pv_type == PROP_VAL_COMPLEX) {
3752 zerr(gettext("A %s or %s value was expected here."),
3753 pvt_to_str(PROP_VAL_SIMPLE),
3754 pvt_to_str(PROP_VAL_LIST));
3755 saw_error = B_TRUE;
3756 return;
3757 }
3758 if (pp->pv_type == PROP_VAL_SIMPLE) {
3759 if (pp->pv_simple == NULL) {
3760 long_usage(CMD_ADD, B_TRUE);
3761 return;
3762 }
3763 prop_id = pp->pv_simple;
3764 err = zonecfg_remove_fs_option(&in_progress_fstab,
3765 prop_id);
3766 if (err != Z_OK && !force)
3767 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3768 } else {
3769 list_property_ptr_t list;
3770
3771 for (list = pp->pv_list; list != NULL;
3772 list = list->lp_next) {
3773 prop_id = list->lp_simple;
3774 if (prop_id == NULL)
3775 break;
3776 err = zonecfg_remove_fs_option(
3777 &in_progress_fstab, prop_id);
3778 if (err != Z_OK && !force)
3779 zone_perror(pt_to_str(prop_type), err,
3780 B_TRUE);
3781 }
3782 }
3783 return;
3784 case RT_NET: /* FALLTHRU */
3785 case RT_DEVICE:
3786 if (prop_type != PT_NPROP) {
3787 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3788 B_TRUE);
3789 long_usage(CMD_REMOVE, B_TRUE);
3790 usage(B_FALSE, HELP_PROPS);
3791 return;
3792 }
3793 pp = cmd->cmd_property_ptr[0];
3794 if (pp->pv_type != PROP_VAL_COMPLEX) {
3795 zerr(gettext("A %s value was expected here."),
3796 pvt_to_str(PROP_VAL_COMPLEX));
3797 saw_error = B_TRUE;
3798 return;
3811 cx->cp_value,
3812 sizeof (np->zone_res_attr_value));
3813 break;
3814 default:
3815 zone_perror(pt_to_str(prop_type),
3816 Z_NO_PROPERTY_TYPE, B_TRUE);
3817 long_usage(CMD_REMOVE, B_TRUE);
3818 usage(B_FALSE, HELP_PROPS);
3819 return;
3820 }
3821 }
3822 np->zone_res_attr_next = NULL;
3823
3824 if (res_type == RT_NET) {
3825 err = zonecfg_remove_res_attr(
3826 &(in_progress_nwiftab.zone_nwif_attrp), np);
3827 } else { /* RT_DEVICE */
3828 err = zonecfg_remove_res_attr(
3829 &(in_progress_devtab.zone_dev_attrp), np);
3830 }
3831 if (err != Z_OK && !force)
3832 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3833 return;
3834 case RT_RCTL:
3835 if (prop_type != PT_VALUE) {
3836 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3837 B_TRUE);
3838 long_usage(CMD_REMOVE, B_TRUE);
3839 usage(B_FALSE, HELP_PROPS);
3840 return;
3841 }
3842 pp = cmd->cmd_property_ptr[0];
3843 if (pp->pv_type != PROP_VAL_COMPLEX) {
3844 zerr(gettext("A %s value was expected here."),
3845 pvt_to_str(PROP_VAL_COMPLEX));
3846 saw_error = B_TRUE;
3847 return;
3848 }
3849 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3850 zone_perror(zone, Z_NOMEM, B_TRUE);
3851 exit(Z_ERR);
3862 cx->cp_value,
3863 sizeof (rctlvaltab->zone_rctlval_limit));
3864 break;
3865 case PT_ACTION:
3866 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3867 cx->cp_value,
3868 sizeof (rctlvaltab->zone_rctlval_action));
3869 break;
3870 default:
3871 zone_perror(pt_to_str(prop_type),
3872 Z_NO_PROPERTY_TYPE, B_TRUE);
3873 long_usage(CMD_ADD, B_TRUE);
3874 usage(B_FALSE, HELP_PROPS);
3875 zonecfg_free_rctl_value_list(rctlvaltab);
3876 return;
3877 }
3878 }
3879 rctlvaltab->zone_rctlval_next = NULL;
3880 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3881 rctlvaltab);
3882 if (err != Z_OK && !force)
3883 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3884 zonecfg_free_rctl_value_list(rctlvaltab);
3885 return;
3886 default:
3887 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3888 long_usage(CMD_REMOVE, B_TRUE);
3889 usage(B_FALSE, HELP_RESOURCES);
3890 return;
3891 }
3892 }
3893
3894 void
3895 remove_func(cmd_t *cmd)
3896 {
3897 if (zone_is_read_only(CMD_REMOVE))
3898 return;
3899
3900 assert(cmd != NULL);
3901
3902 if (global_scope) {
3987 }
3988
3989 static void
3990 clear_global(cmd_t *cmd)
3991 {
3992 int err, type;
3993
3994 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3995 long_usage(CMD_CLEAR, B_TRUE);
3996 return;
3997 }
3998
3999 if (initialize(B_TRUE) != Z_OK)
4000 return;
4001
4002 switch (type) {
4003 case PT_ZONENAME:
4004 /* FALLTHRU */
4005 case PT_ZONEPATH:
4006 /* FALLTHRU */
4007 case PT_UUID:
4008 /* FALLTHRU */
4009 case PT_BRAND:
4010 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
4011 return;
4012 case PT_AUTOBOOT:
4013 /* false is default; we'll treat as equivalent to clearing */
4014 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
4015 z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
4016 else
4017 need_to_commit = B_TRUE;
4018 return;
4019 case PT_POOL:
4020 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
4021 z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
4022 else
4023 need_to_commit = B_TRUE;
4024 return;
4025 case PT_LIMITPRIV:
4026 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
4027 z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
4028 else
4051 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
4052 return;
4053 case PT_MAXPROCS:
4054 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
4055 return;
4056 case PT_MAXSHMMEM:
4057 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
4058 return;
4059 case PT_MAXSHMIDS:
4060 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
4061 return;
4062 case PT_MAXMSGIDS:
4063 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
4064 return;
4065 case PT_MAXSEMIDS:
4066 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
4067 return;
4068 case PT_SHARES:
4069 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
4070 return;
4071 case PT_ZFSPRI:
4072 remove_aliased_rctl(PT_ZFSPRI, ALIAS_ZFSPRI);
4073 return;
4074 case PT_HOSTID:
4075 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
4076 z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
4077 else
4078 need_to_commit = B_TRUE;
4079 return;
4080 case PT_FS_ALLOWED:
4081 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
4082 z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
4083 else
4084 need_to_commit = B_TRUE;
4085 return;
4086 default:
4087 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
4088 long_usage(CMD_CLEAR, B_TRUE);
4089 usage(B_FALSE, HELP_PROPS);
4090 return;
4091 }
4092 }
4093
4544 } else if (prop_type == PT_IPTYPE) {
4545 res_type = RT_IPTYPE;
4546 } else if (prop_type == PT_MAXLWPS) {
4547 res_type = RT_MAXLWPS;
4548 } else if (prop_type == PT_MAXPROCS) {
4549 res_type = RT_MAXPROCS;
4550 } else if (prop_type == PT_MAXSHMMEM) {
4551 res_type = RT_MAXSHMMEM;
4552 } else if (prop_type == PT_MAXSHMIDS) {
4553 res_type = RT_MAXSHMIDS;
4554 } else if (prop_type == PT_MAXMSGIDS) {
4555 res_type = RT_MAXMSGIDS;
4556 } else if (prop_type == PT_MAXSEMIDS) {
4557 res_type = RT_MAXSEMIDS;
4558 } else if (prop_type == PT_SHARES) {
4559 res_type = RT_SHARES;
4560 } else if (prop_type == PT_HOSTID) {
4561 res_type = RT_HOSTID;
4562 } else if (prop_type == PT_FS_ALLOWED) {
4563 res_type = RT_FS_ALLOWED;
4564 } else if (prop_type == PT_ZFSPRI) {
4565 res_type = RT_ZFSPRI;
4566 } else if (prop_type == PT_UUID) {
4567 res_type = RT_UUID;
4568 } else {
4569 zerr(gettext("Cannot set a resource-specific property "
4570 "from the global scope."));
4571 saw_error = B_TRUE;
4572 return;
4573 }
4574 } else {
4575 res_type = resource_scope;
4576 }
4577
4578 if (force_set) {
4579 if (res_type != RT_ZONEPATH) {
4580 zerr(gettext("Only zonepath setting can be forced."));
4581 saw_error = B_TRUE;
4582 return;
4583 }
4584 if (!zonecfg_in_alt_root()) {
4585 zerr(gettext("Zonepath is changeable only in an "
4586 "alternate root."));
4587 saw_error = B_TRUE;
4755 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4756 return;
4757 case RT_MAXPROCS:
4758 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4759 return;
4760 case RT_MAXSHMMEM:
4761 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4762 return;
4763 case RT_MAXSHMIDS:
4764 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4765 return;
4766 case RT_MAXMSGIDS:
4767 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4768 return;
4769 case RT_MAXSEMIDS:
4770 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4771 return;
4772 case RT_SHARES:
4773 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4774 return;
4775 case RT_ZFSPRI:
4776 set_aliased_rctl(ALIAS_ZFSPRI, prop_type, prop_id);
4777 return;
4778 case RT_HOSTID:
4779 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4780 if (err == Z_TOO_BIG) {
4781 zerr(gettext("hostid string is too large: %s"),
4782 prop_id);
4783 saw_error = B_TRUE;
4784 } else {
4785 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4786 }
4787 return;
4788 }
4789 need_to_commit = B_TRUE;
4790 return;
4791 case RT_UUID:
4792 /*
4793 * We can't set here. We have to wait until commit since the
4794 * uuid will be updating the index file and we may not have
4795 * created the zone yet.
4796 */
4797 (void) strlcpy(new_uuid, prop_id, sizeof (new_uuid));
4798 need_to_commit = B_TRUE;
4799 return;
4800 case RT_FS_ALLOWED:
4801 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4802 zone_perror(zone, err, B_TRUE);
4803 else
4804 need_to_commit = B_TRUE;
4805 return;
4806 case RT_FS:
4807 switch (prop_type) {
4808 case PT_DIR:
4809 (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4810 sizeof (in_progress_fstab.zone_fs_dir));
4811 return;
4812 case PT_SPECIAL:
4813 (void) strlcpy(in_progress_fstab.zone_fs_special,
4814 prop_id,
4815 sizeof (in_progress_fstab.zone_fs_special));
4816 return;
4817 case PT_RAW:
4818 (void) strlcpy(in_progress_fstab.zone_fs_raw,
4819 prop_id, sizeof (in_progress_fstab.zone_fs_raw));
4855 switch (prop_type) {
4856 case PT_ADDRESS:
4857 case PT_ALLOWED_ADDRESS:
4858 if (validate_net_address_syntax(prop_id, B_FALSE)
4859 != Z_OK) {
4860 saw_error = B_TRUE;
4861 return;
4862 }
4863 set_in_progress_nwiftab_address(prop_id, prop_type);
4864 break;
4865 case PT_PHYSICAL:
4866 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4867 saw_error = B_TRUE;
4868 return;
4869 }
4870 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4871 prop_id,
4872 sizeof (in_progress_nwiftab.zone_nwif_physical));
4873 break;
4874 case PT_MAC:
4875 normalize_mac_addr(in_progress_nwiftab.zone_nwif_mac,
4876 prop_id,
4877 sizeof (in_progress_nwiftab.zone_nwif_mac));
4878 break;
4879 case PT_VLANID:
4880 (void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id,
4881 prop_id,
4882 sizeof (in_progress_nwiftab.zone_nwif_vlan_id));
4883 break;
4884 case PT_GNIC:
4885 (void) strlcpy(in_progress_nwiftab.zone_nwif_gnic,
4886 prop_id,
4887 sizeof (in_progress_nwiftab.zone_nwif_gnic));
4888 break;
4889 case PT_DEFROUTER:
4890 if (validate_net_address_syntax(prop_id, B_TRUE)
4891 != Z_OK) {
4892 saw_error = B_TRUE;
4893 return;
4894 }
4895 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
5380 }
5381 }
5382
5383 static void
5384 info_hostid(zone_dochandle_t handle, FILE *fp)
5385 {
5386 char hostidp[HW_HOSTID_LEN];
5387 int err;
5388
5389 if ((err = zonecfg_get_hostid(handle, hostidp,
5390 sizeof (hostidp))) == Z_OK) {
5391 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
5392 } else if (err == Z_BAD_PROPERTY) {
5393 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
5394 } else {
5395 zone_perror(zone, err, B_TRUE);
5396 }
5397 }
5398
5399 static void
5400 info_uuid(FILE *fp)
5401 {
5402 uuid_t uuid;
5403 char suuid[UUID_PRINTABLE_STRING_LENGTH];
5404
5405 if (new_uuid[0] != '\0') {
5406 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), new_uuid);
5407 } else if (zonecfg_get_uuid(zone, uuid) == Z_OK &&
5408 !uuid_is_null(uuid)) {
5409 uuid_unparse(uuid, suuid);
5410 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), suuid);
5411 } else {
5412 (void) fprintf(fp, "%s:\n", pt_to_str(PT_UUID));
5413 }
5414 }
5415
5416 static void
5417 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
5418 {
5419 char fsallowedp[ZONE_FS_ALLOWED_MAX];
5420 int err;
5421
5422 if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
5423 sizeof (fsallowedp))) == Z_OK) {
5424 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
5425 fsallowedp);
5426 } else if (err == Z_BAD_PROPERTY) {
5427 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
5428 } else {
5429 zone_perror(zone, err, B_TRUE);
5430 }
5431 }
5432
5433 static void
5434 output_fs(FILE *fp, struct zone_fstab *fstab)
5435 {
5436 zone_fsopt_t *this;
5906 (void) zonecfg_endadminent(handle);
5907 /*
5908 * If a property n/v pair was specified, warn the user if there was
5909 * nothing to output.
5910 */
5911 if (!output && cmd->cmd_prop_nv_pairs > 0)
5912 (void) printf(gettext("No such %s resource.\n"),
5913 rt_to_str(RT_ADMIN));
5914 }
5915
5916 void
5917 info_func(cmd_t *cmd)
5918 {
5919 FILE *fp = stdout;
5920 boolean_t need_to_close = B_FALSE;
5921 int type;
5922 int res1, res2, res3;
5923 uint64_t swap_limit;
5924 uint64_t locked_limit;
5925 uint64_t phys_limit;
5926 struct stat statbuf;
5927
5928 assert(cmd != NULL);
5929
5930 if (initialize(B_TRUE) != Z_OK)
5931 return;
5932
5933 /* don't page error output */
5934 if (interactive_mode) {
5935 if ((fp = pager_open()) != NULL)
5936 need_to_close = B_TRUE;
5937 else
5938 fp = stdout;
5939
5940 setbuf(fp, NULL);
5941 }
5942
5943 if (!global_scope) {
5944 switch (resource_scope) {
5945 case RT_FS:
5946 output_fs(fp, &in_progress_fstab);
5996 rt_to_str(type));
5997 goto cleanup;
5998 }
5999
6000 switch (cmd->cmd_res_type) {
6001 case RT_UNKNOWN:
6002 info_zonename(handle, fp);
6003 if (!global_zone) {
6004 info_zonepath(handle, fp);
6005 info_brand(handle, fp);
6006 info_autoboot(handle, fp);
6007 info_bootargs(handle, fp);
6008 }
6009 info_pool(handle, fp);
6010 if (!global_zone) {
6011 info_limitpriv(handle, fp);
6012 info_sched(handle, fp);
6013 info_iptype(handle, fp);
6014 info_hostid(handle, fp);
6015 info_fs_allowed(handle, fp);
6016 info_uuid(fp);
6017 }
6018 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
6019 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
6020 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
6021 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
6022 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
6023 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
6024 info_aliased_rctl(handle, fp, ALIAS_SHARES);
6025 info_aliased_rctl(handle, fp, ALIAS_ZFSPRI);
6026 if (!global_zone) {
6027 info_fs(handle, fp, cmd);
6028 info_net(handle, fp, cmd);
6029 info_dev(handle, fp, cmd);
6030 }
6031 info_pset(handle, fp);
6032 info_pcap(fp);
6033 info_mcap(handle, fp);
6034 if (!global_zone) {
6035 info_attr(handle, fp, cmd);
6036 info_ds(handle, fp, cmd);
6037 info_auth(handle, fp, cmd);
6038 }
6039 info_rctl(handle, fp, cmd);
6040 break;
6041 case RT_ZONENAME:
6042 info_zonename(handle, fp);
6043 break;
6044 case RT_ZONEPATH:
6045 info_zonepath(handle, fp);
6069 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
6070 break;
6071 case RT_MAXPROCS:
6072 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
6073 break;
6074 case RT_MAXSHMMEM:
6075 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
6076 break;
6077 case RT_MAXSHMIDS:
6078 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
6079 break;
6080 case RT_MAXMSGIDS:
6081 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
6082 break;
6083 case RT_MAXSEMIDS:
6084 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
6085 break;
6086 case RT_SHARES:
6087 info_aliased_rctl(handle, fp, ALIAS_SHARES);
6088 break;
6089 case RT_ZFSPRI:
6090 info_aliased_rctl(handle, fp, ALIAS_ZFSPRI);
6091 break;
6092 case RT_FS:
6093 info_fs(handle, fp, cmd);
6094 break;
6095 case RT_NET:
6096 info_net(handle, fp, cmd);
6097 break;
6098 case RT_DEVICE:
6099 info_dev(handle, fp, cmd);
6100 break;
6101 case RT_RCTL:
6102 info_rctl(handle, fp, cmd);
6103 break;
6104 case RT_ATTR:
6105 info_attr(handle, fp, cmd);
6106 break;
6107 case RT_DATASET:
6108 info_ds(handle, fp, cmd);
6109 break;
6110 case RT_DCPU:
6111 info_pset(handle, fp);
6112 break;
6113 case RT_PCAP:
6114 info_pcap(fp);
6115 break;
6116 case RT_MCAP:
6117 info_mcap(handle, fp);
6118 break;
6119 case RT_HOSTID:
6120 info_hostid(handle, fp);
6121 break;
6122 case RT_UUID:
6123 info_uuid(fp);
6124 break;
6125 case RT_ADMIN:
6126 info_auth(handle, fp, cmd);
6127 break;
6128 case RT_FS_ALLOWED:
6129 info_fs_allowed(handle, fp);
6130 break;
6131 default:
6132 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
6133 B_TRUE);
6134 }
6135
6136 cleanup:
6137 if (need_to_close)
6138 (void) pager_close(fp);
6139 }
6140
6141 /*
6142 * Helper function for verify-- checks that a required string property
6143 * exists.
6144 */
6596
6597 if (!global_scope) {
6598 zerr(gettext("resource specification incomplete"));
6599 saw_error = B_TRUE;
6600 if (ret_val == Z_OK)
6601 ret_val = Z_INSUFFICIENT_SPEC;
6602 }
6603
6604 if (save) {
6605 if (ret_val == Z_OK) {
6606 /*
6607 * If the zone doesn't yet have a debug ID, set one now.
6608 */
6609 if (zonecfg_get_did(handle) == -1)
6610 zonecfg_set_did(handle);
6611
6612 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6613 need_to_commit = B_FALSE;
6614 (void) strlcpy(revert_zone, zone,
6615 sizeof (revert_zone));
6616
6617 if (is_create) {
6618 zonecfg_notify_create(handle);
6619 is_create = B_FALSE;
6620 }
6621 }
6622
6623 /*
6624 * Commit a new uuid at this point since we now know the
6625 * zone index entry will exist.
6626 */
6627 if (new_uuid[0] != '\0') {
6628 if ((err = zonecfg_set_uuid(zone, zonepath,
6629 new_uuid)) != Z_OK)
6630 zone_perror(zone, err, B_FALSE);
6631 else
6632 new_uuid[0] = '\0';
6633 }
6634 } else {
6635 zerr(gettext("Zone %s failed to verify"), zone);
6636 }
6637 }
6638 if (ret_val != Z_OK)
6639 zone_perror(zone, ret_val, B_TRUE);
6640 }
6641
6642 void
6643 cancel_func(cmd_t *cmd)
6644 {
6645 int arg;
6646 boolean_t arg_err = B_FALSE;
6647
6648 assert(cmd != NULL);
6649
6650 optind = 0;
6651 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6652 switch (arg) {
6653 case '?':
7663 for (;;) {
7664 last_slash = strrchr(execfullname, '/');
7665 if (last_slash == NULL) {
7666 execbasename = execfullname;
7667 break;
7668 } else {
7669 execbasename = last_slash + 1;
7670 if (*execbasename == '\0') {
7671 *last_slash = '\0';
7672 continue;
7673 }
7674 break;
7675 }
7676 }
7677 return (execbasename);
7678 }
7679
7680 int
7681 main(int argc, char *argv[])
7682 {
7683 int err, arg, uflag = 0, zflag = 0;
7684 struct stat st;
7685 uuid_t uuidin;
7686 char zonename[ZONENAME_MAX + 1];
7687
7688 /* This must be before anything goes to stdout. */
7689 setbuf(stdout, NULL);
7690
7691 saw_error = B_FALSE;
7692 cmd_file_mode = B_FALSE;
7693 execname = get_execbasename(argv[0]);
7694
7695 (void) setlocale(LC_ALL, "");
7696 (void) textdomain(TEXT_DOMAIN);
7697
7698 if (getzoneid() != GLOBAL_ZONEID) {
7699 zerr(gettext("%s can only be run from the global zone."),
7700 execname);
7701 exit(Z_ERR);
7702 }
7703
7704 if (argc < 2) {
7705 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7706 exit(Z_USAGE);
7707 }
7708 if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7709 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7710 exit(Z_OK);
7711 }
7712
7713 while ((arg = getopt(argc, argv, "?f:R:z:u:")) != EOF) {
7714 switch (arg) {
7715 case '?':
7716 if (optopt == '?')
7717 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7718 else
7719 usage(B_FALSE, HELP_USAGE);
7720 exit(Z_USAGE);
7721 /* NOTREACHED */
7722 case 'f':
7723 cmd_file_name = optarg;
7724 cmd_file_mode = B_TRUE;
7725 break;
7726 case 'R':
7727 if (*optarg != '/') {
7728 zerr(gettext("root path must be absolute: %s"),
7729 optarg);
7730 exit(Z_USAGE);
7731 }
7732 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7733 zerr(gettext(
7734 "root path must be a directory: %s"),
7735 optarg);
7736 exit(Z_USAGE);
7737 }
7738 zonecfg_set_root(optarg);
7739 break;
7740 case 'u':
7741 if (uuid_parse((char *)optarg, uuidin) == -1)
7742 return (Z_INVALID_PROPERTY);
7743
7744 if (zonecfg_get_name_by_uuid(uuidin, zonename,
7745 ZONENAME_MAX) != Z_OK) {
7746 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7747 usage(B_FALSE, HELP_SYNTAX);
7748 exit(Z_USAGE);
7749 }
7750
7751 (void) strlcpy(zone, zonename, sizeof (zone));
7752 (void) strlcpy(revert_zone, zonename, sizeof (zone));
7753 uflag = 1;
7754 break;
7755 case 'z':
7756 if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7757 global_zone = B_TRUE;
7758 } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7759 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7760 usage(B_FALSE, HELP_SYNTAX);
7761 exit(Z_USAGE);
7762 }
7763 (void) strlcpy(zone, optarg, sizeof (zone));
7764 (void) strlcpy(revert_zone, optarg, sizeof (zone));
7765 zflag = 1;
7766 break;
7767 default:
7768 usage(B_FALSE, HELP_USAGE);
7769 exit(Z_USAGE);
7770 }
7771 }
7772
7773 if (optind > argc || strcmp(zone, "") == 0 || (uflag && zflag)) {
7774 usage(B_FALSE, HELP_USAGE);
7775 exit(Z_USAGE);
7776 }
7777
7778 if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7779 read_only_mode = B_FALSE;
7780 } else if (err == Z_ACCES) {
7781 read_only_mode = B_TRUE;
7782 /* skip this message in one-off from command line mode */
7783 if (optind == argc)
7784 (void) fprintf(stderr, gettext("WARNING: you do not "
7785 "have write access to this zone's configuration "
7786 "file;\ngoing into read-only mode.\n"));
7787 } else {
7788 fprintf(stderr, "%s: Could not access zone configuration "
7789 "store: %s\n", execname, zonecfg_strerror(err));
7790 exit(Z_ERR);
7791 }
7792
7793 if ((handle = zonecfg_init_handle()) == NULL) {
|
63 #include <stdlib.h>
64 #include <assert.h>
65 #include <sys/stat.h>
66 #include <zone.h>
67 #include <arpa/inet.h>
68 #include <netdb.h>
69 #include <locale.h>
70 #include <libintl.h>
71 #include <alloca.h>
72 #include <signal.h>
73 #include <wait.h>
74 #include <libtecla.h>
75 #include <libzfs.h>
76 #include <sys/brand.h>
77 #include <libbrand.h>
78 #include <sys/systeminfo.h>
79 #include <libdladm.h>
80 #include <libinetutil.h>
81 #include <pwd.h>
82 #include <inet/ip.h>
83
84 #include <libzonecfg.h>
85 #include "zonecfg.h"
86
87 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
88 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
89 #endif
90
91 #define PAGER "/usr/bin/more"
92 #define EXEC_PREFIX "exec "
93 #define EXEC_LEN (strlen(EXEC_PREFIX))
94
95 struct help {
96 uint_t cmd_num;
97 char *cmd_name;
98 uint_t flags;
99 char *short_usage;
100 };
101
102 extern int yyparse(void);
110
111 /*
112 * Each SHELP_ should be a simple string.
113 */
114
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" \
131 "\t(resource scope)"
132 #define SHELP_REVERT "revert [-F]"
133 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
134 "<property-value> }"
135 #define SHELP_SET "set <property-name>=<property-value>"
136 #define SHELP_VERIFY "verify"
137
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, },
171 "attr",
172 "dataset",
173 "limitpriv",
174 "bootargs",
175 "brand",
176 "dedicated-cpu",
177 "capped-memory",
178 ALIAS_MAXLWPS,
179 ALIAS_MAXSHMMEM,
180 ALIAS_MAXSHMIDS,
181 ALIAS_MAXMSGIDS,
182 ALIAS_MAXSEMIDS,
183 ALIAS_SHARES,
184 "scheduling-class",
185 "ip-type",
186 "capped-cpu",
187 "hostid",
188 "admin",
189 "fs-allowed",
190 ALIAS_MAXPROCS,
191 NULL
192 };
193
194 /* These *must* match the order of the PT_ define's from zonecfg.h */
195 char *prop_types[] = {
196 "unknown",
197 "zonename",
198 "zonepath",
199 "autoboot",
200 "pool",
201 "dir",
202 "special",
203 "type",
204 "options",
205 "address",
206 "physical",
207 "name",
208 "value",
209 "match",
210 "priv",
223 ALIAS_MAXSHMMEM,
224 ALIAS_MAXSHMIDS,
225 ALIAS_MAXMSGIDS,
226 ALIAS_MAXSEMIDS,
227 ALIAS_MAXLOCKEDMEM,
228 ALIAS_MAXSWAP,
229 "scheduling-class",
230 "ip-type",
231 "defrouter",
232 "hostid",
233 "user",
234 "auths",
235 "fs-allowed",
236 ALIAS_MAXPROCS,
237 "allowed-address",
238 ALIAS_ZFSPRI,
239 "mac-addr",
240 "vlan-id",
241 "global-nic",
242 "property",
243 NULL
244 };
245
246 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
247 static char *prop_val_types[] = {
248 "simple",
249 "complex",
250 "list",
251 };
252
253 /*
254 * The various _cmds[] lists below are for command tab-completion.
255 */
256
257 /*
258 * remove has a space afterwards because it has qualifiers; the other commands
259 * that have qualifiers (add, select, etc.) don't need a space here because
260 * they have their own _cmds[] lists below.
261 */
262 static const char *global_scope_cmds[] = {
288 "add capped-cpu",
289 "add capped-memory",
290 "add admin",
291 NULL
292 };
293
294 static const char *clear_cmds[] = {
295 "clear autoboot",
296 "clear pool",
297 "clear limitpriv",
298 "clear bootargs",
299 "clear scheduling-class",
300 "clear ip-type",
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,
308 NULL
309 };
310
311 static const char *remove_cmds[] = {
312 "remove fs ",
313 "remove net ",
314 "remove device ",
315 "remove rctl ",
316 "remove attr ",
317 "remove dataset ",
318 "remove dedicated-cpu ",
319 "remove capped-cpu ",
320 "remove capped-memory ",
321 "remove admin ",
322 NULL
323 };
324
325 static const char *select_cmds[] = {
326 "select fs ",
327 "select net ",
338
339 static const char *set_cmds[] = {
340 "set zonename=",
341 "set zonepath=",
342 "set brand=",
343 "set autoboot=",
344 "set pool=",
345 "set limitpriv=",
346 "set bootargs=",
347 "set scheduling-class=",
348 "set ip-type=",
349 "set " ALIAS_MAXLWPS "=",
350 "set " ALIAS_MAXSHMMEM "=",
351 "set " ALIAS_MAXSHMIDS "=",
352 "set " ALIAS_MAXMSGIDS "=",
353 "set " ALIAS_MAXSEMIDS "=",
354 "set " ALIAS_SHARES "=",
355 "set hostid=",
356 "set fs-allowed=",
357 "set " ALIAS_MAXPROCS "=",
358 NULL
359 };
360
361 static const char *info_cmds[] = {
362 "info fs ",
363 "info net ",
364 "info device ",
365 "info rctl ",
366 "info attr ",
367 "info dataset ",
368 "info capped-memory",
369 "info dedicated-cpu",
370 "info capped-cpu",
371 "info zonename",
372 "info zonepath",
373 "info autoboot",
374 "info pool",
375 "info limitpriv",
376 "info bootargs",
377 "info brand",
378 "info scheduling-class",
379 "info ip-type",
380 "info max-lwps",
381 "info max-shm-memory",
382 "info max-shm-ids",
383 "info max-msg-ids",
384 "info max-sem-ids",
385 "info cpu-shares",
386 "info hostid",
387 "info admin",
388 "info fs-allowed",
389 "info max-processes",
390 NULL
391 };
392
393 static const char *fs_res_scope_cmds[] = {
394 "add options ",
395 "cancel",
396 "end",
397 "exit",
398 "help",
399 "info",
400 "remove options ",
401 "set dir=",
402 "set raw=",
403 "set special=",
404 "set type=",
405 "clear raw",
406 NULL
407 };
408
409 static const char *net_res_scope_cmds[] = {
526 struct xif *xif_next;
527 char xif_name[LIFNAMSIZ];
528 boolean_t xif_has_address;
529 boolean_t xif_has_defrouter;
530 };
531
532 /* Global variables */
533
534 /* list of network interfaces specified for exclusive IP zone */
535 struct xif *xif;
536
537 /* set early in main(), never modified thereafter, used all over the place */
538 static char *execname;
539
540 /* set in main(), used all over the place */
541 static zone_dochandle_t handle;
542
543 /* used all over the place */
544 static char zone[ZONENAME_MAX];
545 static char revert_zone[ZONENAME_MAX];
546
547 /* global brand operations */
548 static brand_handle_t brand;
549
550 /* set in modifying functions, checked in read_input() */
551 static boolean_t need_to_commit = B_FALSE;
552 boolean_t saw_error;
553
554 /* set in yacc parser, checked in read_input() */
555 boolean_t newline_terminated;
556
557 /* set in main(), checked in lex error handler */
558 boolean_t cmd_file_mode;
559
560 /* set in exit_func(), checked in read_input() */
561 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
562
563 /* used in short_usage() and zerr() */
564 static char *cmd_file_name = NULL;
565
566 /* checked in read_input() and other places */
567 static boolean_t ok_to_prompt = B_FALSE;
568
569 /* set and checked in initialize() */
570 static boolean_t got_handle = B_FALSE;
571
973 if ((pathstr = getenv("PATH")) == NULL) {
974 if (geteuid() == 0 || getuid() == 0)
975 pathstr = "/usr/sbin:/usr/bin";
976 else
977 pathstr = "/usr/bin:";
978 }
979 cp = strchr(name, '/') ? (const char *) "" : pathstr;
980
981 do {
982 cp = exec_cat(cp, name, fname);
983 if (stat(fname, &stat_buf) != -1) {
984 /* successful find of the file */
985 return (0);
986 }
987 } while (cp != NULL);
988
989 return (-1);
990 }
991
992 static FILE *
993 pager_open(void) {
994 FILE *newfp;
995 char *pager, *space;
996
997 pager = getenv("PAGER");
998 if (pager == NULL || *pager == '\0')
999 pager = PAGER;
1000
1001 space = strchr(pager, ' ');
1002 if (space)
1003 *space = '\0';
1004 if (path_find(pager) == 0) {
1005 if (space)
1006 *space = ' ';
1007 if ((newfp = popen(pager, "w")) == NULL)
1008 zerr(gettext("PAGER open failed (%s)."),
1009 strerror(errno));
1010 return (newfp);
1011 } else {
1012 zerr(gettext("PAGER %s does not exist (%s)."),
1013 pager, strerror(errno));
1014 }
1015 return (NULL);
1016 }
1017
1018 static void
1019 pager_close(FILE *fp) {
1020 int status;
1021
1022 status = pclose(fp);
1023 if (status == -1)
1024 zerr(gettext("PAGER close failed (%s)."),
1025 strerror(errno));
1026 }
1027
1028 /*
1029 * Called with verbose TRUE when help is explicitly requested, FALSE for
1030 * unexpected errors.
1031 */
1032
1033 void
1034 usage(boolean_t verbose, uint_t flags)
1035 {
1036 FILE *fp = verbose ? stdout : stderr;
1037 FILE *newfp;
1038 boolean_t need_to_close = B_FALSE;
1039 int i;
1254 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1255 pt_to_str(PT_USER),
1256 gettext("<single user or role name>"));
1257 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1258 pt_to_str(PT_AUTHS),
1259 gettext("<comma separated list>"));
1260 break;
1261 }
1262 (void) fprintf(fp, gettext("And from any resource scope, you "
1263 "can:\n"));
1264 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1265 gettext("(to conclude this operation)"));
1266 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1267 gettext("(to cancel this operation)"));
1268 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1269 gettext("(to exit the zonecfg utility)"));
1270 }
1271 if (flags & HELP_USAGE) {
1272 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1273 execname, cmd_to_str(CMD_HELP));
1274 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1275 execname, gettext("interactive"));
1276 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1277 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1278 execname);
1279 }
1280 if (flags & HELP_SUBCMDS) {
1281 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1282 for (i = 0; i <= CMD_MAX; i++) {
1283 (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1284 if (verbose)
1285 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1286 }
1287 }
1288 if (flags & HELP_SYNTAX) {
1289 if (!verbose)
1290 (void) fprintf(fp, "\n");
1291 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1292 (void) fprintf(fp, gettext("\t(except the reserved words "
1293 "'%s' and anything starting with '%s')\n"), "global",
1294 "SUNW");
1295 (void) fprintf(fp,
1296 gettext("\tName must be less than %d characters.\n"),
1297 ZONENAME_MAX);
1298 if (verbose)
1346 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1347 pt_to_str(PT_IPTYPE));
1348 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1349 pt_to_str(PT_HOSTID));
1350 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1351 pt_to_str(PT_FS_ALLOWED));
1352 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1353 pt_to_str(PT_MAXLWPS));
1354 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1355 pt_to_str(PT_MAXPROCS));
1356 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1357 pt_to_str(PT_MAXSHMMEM));
1358 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1359 pt_to_str(PT_MAXSHMIDS));
1360 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1361 pt_to_str(PT_MAXMSGIDS));
1362 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1363 pt_to_str(PT_MAXSEMIDS));
1364 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1365 pt_to_str(PT_SHARES));
1366 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1367 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1368 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1369 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1370 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n",
1371 rt_to_str(RT_NET),
1372 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1373 pt_to_str(PT_GNIC), pt_to_str(PT_MAC),
1374 pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP),
1375 pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER));
1376 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE),
1377 pt_to_str(PT_MATCH), pt_to_str(PT_NPROP));
1378 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1379 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1380 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1381 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1382 pt_to_str(PT_VALUE));
1383 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1384 pt_to_str(PT_NAME));
1385 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1682 cmd_to_str(cmd_num));
1683 saw_error = B_TRUE;
1684 return (B_TRUE);
1685 }
1686 return (B_FALSE);
1687 }
1688
1689 /*
1690 * Create a new configuration.
1691 */
1692 void
1693 create_func(cmd_t *cmd)
1694 {
1695 int err, arg;
1696 char zone_template[ZONENAME_MAX];
1697 char attach_path[MAXPATHLEN];
1698 zone_dochandle_t tmphandle;
1699 boolean_t force = B_FALSE;
1700 boolean_t attach = B_FALSE;
1701 boolean_t arg_err = B_FALSE;
1702
1703 assert(cmd != NULL);
1704
1705 /* This is the default if no arguments are given. */
1706 (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1707
1708 optind = 0;
1709 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
1710 != EOF) {
1711 switch (arg) {
1712 case '?':
1713 if (optopt == '?')
1714 longer_usage(CMD_CREATE);
1715 else
1716 short_usage(CMD_CREATE);
1717 arg_err = B_TRUE;
1718 break;
1719 case 'a':
1720 (void) strlcpy(attach_path, optarg,
1721 sizeof (attach_path));
1722 attach = B_TRUE;
1723 break;
1724 case 'b':
1725 (void) strlcpy(zone_template, "SUNWblank",
1726 sizeof (zone_template));
1727 break;
1728 case 'F':
1729 force = B_TRUE;
1779 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1780 zone, B_FALSE, tmphandle);
1781 else
1782 err = zonecfg_get_template_handle(zone_template, zone,
1783 tmphandle);
1784
1785 if (err != Z_OK) {
1786 zonecfg_fini_handle(tmphandle);
1787 if (attach && err == Z_NO_ZONE)
1788 (void) fprintf(stderr, gettext("invalid path to "
1789 "detached zone\n"));
1790 else if (attach && err == Z_INVALID_DOCUMENT)
1791 (void) fprintf(stderr, gettext("Cannot attach to an "
1792 "earlier release of the operating system\n"));
1793 else
1794 zone_perror(zone_template, err, B_TRUE);
1795 return;
1796 }
1797
1798 need_to_commit = B_TRUE;
1799 zonecfg_fini_handle(handle);
1800 handle = tmphandle;
1801 got_handle = B_TRUE;
1802 }
1803
1804 /*
1805 * This malloc()'s memory, which must be freed by the caller.
1806 */
1807 static char *
1808 quoteit(char *instr)
1809 {
1810 char *outstr;
1811 size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
1812
1813 if ((outstr = malloc(outstrsize)) == NULL) {
1814 zone_perror(zone, Z_NOMEM, B_FALSE);
1815 exit(Z_ERR);
1816 }
1817 if (strchr(instr, ' ') == NULL) {
1818 (void) strlcpy(outstr, instr, outstrsize);
1819 return (outstr);
1820 }
1821 (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
1842 struct zone_fstab fstab;
1843 struct zone_devtab devtab;
1844 struct zone_attrtab attrtab;
1845 struct zone_rctltab rctltab;
1846 struct zone_dstab dstab;
1847 struct zone_psettab psettab;
1848 struct zone_rctlvaltab *valptr;
1849 struct zone_res_attrtab *rap;
1850 struct zone_admintab admintab;
1851 int err, arg;
1852 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1853 char bootargs[BOOTARGS_MAX];
1854 char sched[MAXNAMELEN];
1855 char brand[MAXNAMELEN];
1856 char hostidp[HW_HOSTID_LEN];
1857 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1858 char *limitpriv;
1859 FILE *of;
1860 boolean_t autoboot;
1861 zone_iptype_t iptype;
1862 boolean_t need_to_close = B_FALSE;
1863 boolean_t arg_err = B_FALSE;
1864
1865 assert(cmd != NULL);
1866
1867 outfile[0] = '\0';
1868 optind = 0;
1869 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1870 switch (arg) {
1871 case '?':
1872 if (optopt == '?')
1873 longer_usage(CMD_EXPORT);
1874 else
1875 short_usage(CMD_EXPORT);
1876 arg_err = B_TRUE;
1877 break;
1878 case 'f':
1879 (void) strlcpy(outfile, optarg, sizeof (outfile));
1880 break;
1881 default:
1952 pt_to_str(PT_IPTYPE), "shared");
1953 break;
1954 case ZS_EXCLUSIVE:
1955 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1956 pt_to_str(PT_IPTYPE), "exclusive");
1957 break;
1958 }
1959 }
1960
1961 if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1962 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1963 pt_to_str(PT_HOSTID), hostidp);
1964 }
1965
1966 if (zonecfg_get_fs_allowed(handle, fsallowedp,
1967 sizeof (fsallowedp)) == Z_OK) {
1968 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1969 pt_to_str(PT_FS_ALLOWED), fsallowedp);
1970 }
1971
1972 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
1973 zone_perror(zone, err, B_FALSE);
1974 goto done;
1975 }
1976 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
1977 zone_fsopt_t *optptr;
1978
1979 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1980 rt_to_str(RT_FS));
1981 export_prop(of, PT_DIR, fstab.zone_fs_dir);
1982 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
1983 export_prop(of, PT_RAW, fstab.zone_fs_raw);
1984 export_prop(of, PT_TYPE, fstab.zone_fs_type);
1985 for (optptr = fstab.zone_fs_options; optptr != NULL;
1986 optptr = optptr->zone_fsopt_next) {
1987 /*
1988 * Simple property values with embedded equal signs
1989 * need to be quoted to prevent the lexer from
1990 * mis-parsing them as complex name=value pairs.
1991 */
2419 do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp)
2420 {
2421 complex_property_ptr_t cp;
2422 struct zone_res_attrtab *np;
2423 int err;
2424 boolean_t seen_name = B_FALSE, seen_value = B_FALSE;
2425
2426 if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) {
2427 zone_perror(zone, Z_NOMEM, B_TRUE);
2428 exit(Z_ERR);
2429 }
2430
2431 for (cp = cpp; cp != NULL; cp = cp->cp_next) {
2432 switch (cp->cp_type) {
2433 case PT_NAME:
2434 if (seen_name) {
2435 zerr(gettext("%s already specified"),
2436 pt_to_str(PT_NAME));
2437 goto bad;
2438 }
2439 (void) strlcpy(np->zone_res_attr_name, cp->cp_value,
2440 sizeof (np->zone_res_attr_name));
2441 seen_name = B_TRUE;
2442 break;
2443 case PT_VALUE:
2444 if (seen_value) {
2445 zerr(gettext("%s already specified"),
2446 pt_to_str(PT_VALUE));
2447 goto bad;
2448 }
2449 (void) strlcpy(np->zone_res_attr_value, cp->cp_value,
2450 sizeof (np->zone_res_attr_value));
2451 seen_value = B_TRUE;
2452 break;
2453 default:
2454 zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE,
2455 B_TRUE);
2456 long_usage(CMD_ADD, B_TRUE);
2457 usage(B_FALSE, HELP_PROPS);
2458 zonecfg_free_res_attr_list(np);
2459 return;
2460 }
2461 }
2462
2463 if (!seen_name)
2464 zerr(gettext("%s not specified"), pt_to_str(PT_NAME));
2465 if (!seen_value)
2466 zerr(gettext("%s not specified"), pt_to_str(PT_VALUE));
2467
2468 err = zonecfg_add_res_attr(headp, np);
2469 if (err != Z_OK)
2470 zone_perror(pt_to_str(PT_NPROP), err, B_TRUE);
2606 default:
2607 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2608 long_usage(CMD_ADD, B_TRUE);
2609 usage(B_FALSE, HELP_RESOURCES);
2610 return;
2611 }
2612 }
2613
2614 static boolean_t
2615 gz_invalid_resource(int type)
2616 {
2617 return (global_zone && (type == RT_FS ||
2618 type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2619 type == RT_DATASET));
2620 }
2621
2622 static boolean_t
2623 gz_invalid_rt_property(int type)
2624 {
2625 return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2626 type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
2627 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2628 type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2629 }
2630
2631 static boolean_t
2632 gz_invalid_property(int type)
2633 {
2634 return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2635 type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
2636 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2637 type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2638 }
2639
2640 void
2641 add_func(cmd_t *cmd)
2642 {
2643 int arg;
2644 boolean_t arg_err = B_FALSE;
2645
2646 assert(cmd != NULL);
2647
2648 optind = 0;
2649 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2650 switch (arg) {
2651 case '?':
2652 longer_usage(CMD_ADD);
2653 arg_err = B_TRUE;
2654 break;
2655 default:
2833 break;
2834 case PT_RAW:
2835 (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2836 sizeof (fstab->zone_fs_raw));
2837 break;
2838 case PT_TYPE:
2839 (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2840 sizeof (fstab->zone_fs_type));
2841 break;
2842 default:
2843 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2844 Z_NO_PROPERTY_TYPE, B_TRUE);
2845 return (Z_INSUFFICIENT_SPEC);
2846 }
2847 }
2848 if (fill_in_only)
2849 return (Z_OK);
2850 return (zonecfg_lookup_filesystem(handle, fstab));
2851 }
2852
2853 static int
2854 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2855 boolean_t fill_in_only)
2856 {
2857 int err, i;
2858 property_value_ptr_t pp;
2859
2860 if ((err = initialize(B_TRUE)) != Z_OK)
2861 return (err);
2862
2863 bzero(nwiftab, sizeof (*nwiftab));
2864 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2865 pp = cmd->cmd_property_ptr[i];
2866 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2867 zerr(gettext("A simple value was expected here."));
2868 saw_error = B_TRUE;
2869 return (Z_INSUFFICIENT_SPEC);
2870 }
2871 switch (cmd->cmd_prop_name[i]) {
2872 case PT_ADDRESS:
2873 (void) strlcpy(nwiftab->zone_nwif_address,
2874 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2875 break;
2876 case PT_ALLOWED_ADDRESS:
2877 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2878 pp->pv_simple,
2879 sizeof (nwiftab->zone_nwif_allowed_address));
2880 break;
2881 case PT_PHYSICAL:
2882 (void) strlcpy(nwiftab->zone_nwif_physical,
2883 pp->pv_simple,
2884 sizeof (nwiftab->zone_nwif_physical));
2885 break;
2886 case PT_MAC:
2887 (void) strlcpy(nwiftab->zone_nwif_mac,
2888 pp->pv_simple,
2889 sizeof (nwiftab->zone_nwif_mac));
2890 break;
2891 case PT_VLANID:
2892 (void) strlcpy(nwiftab->zone_nwif_vlan_id,
2893 pp->pv_simple,
2894 sizeof (nwiftab->zone_nwif_vlan_id));
2895 break;
2896 case PT_GNIC:
2897 (void) strlcpy(nwiftab->zone_nwif_gnic,
2898 pp->pv_simple,
2899 sizeof (nwiftab->zone_nwif_gnic));
2900 break;
2901 case PT_DEFROUTER:
2902 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2903 pp->pv_simple,
2904 sizeof (nwiftab->zone_nwif_defrouter));
2905 break;
2906 default:
2907 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3131 boolean_t arg_err = B_FALSE;
3132
3133 optind = 0;
3134 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3135 switch (arg) {
3136 case 'F':
3137 force = B_TRUE;
3138 break;
3139 default:
3140 arg_err = B_TRUE;
3141 break;
3142 }
3143 }
3144 if (arg_err)
3145 return (B_FALSE);
3146
3147
3148 num = zonecfg_num_resources(handle, rsrc);
3149
3150 if (num == 0) {
3151 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
3152 B_TRUE);
3153 return (B_FALSE);
3154 }
3155 if (num > 1 && !force) {
3156 if (!interactive_mode) {
3157 zerr(gettext("There are multiple instances of this "
3158 "resource. Either qualify the resource to\n"
3159 "remove a single instance or use the -F option to "
3160 "remove all instances."));
3161 saw_error = B_TRUE;
3162 return (B_FALSE);
3163 }
3164 (void) snprintf(prompt, sizeof (prompt), gettext(
3165 "Are you sure you want to remove ALL '%s' resources"),
3166 rsrc);
3167 answer = ask_yesno(B_FALSE, prompt);
3168 if (answer == -1) {
3169 zerr(gettext("Resource incomplete."));
3170 return (B_FALSE);
3171 }
3172 if (answer != 1)
3173 return (B_FALSE);
3174 }
3175 return (B_TRUE);
3176 }
3177
3178 static void
3179 remove_fs(cmd_t *cmd)
3180 {
3181 int err;
3182
3183 /* traditional, qualified fs removal */
3184 if (cmd->cmd_prop_nv_pairs > 0) {
3185 struct zone_fstab fstab;
3186
3187 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
3188 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3189 return;
3190 }
3191 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
3192 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3193 else
3194 need_to_commit = B_TRUE;
3195 zonecfg_free_fs_option_list(fstab.zone_fs_options);
3196 return;
3197 }
3198
3199 /*
3200 * unqualified fs removal. remove all fs's but prompt if more
3201 * than one.
3202 */
3203 if (!prompt_remove_resource(cmd, "fs"))
3204 return;
3205
3206 if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
3207 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3208 else
3209 need_to_commit = B_TRUE;
3210 }
3211
3212 static void
3213 remove_net(cmd_t *cmd)
3214 {
3215 int err;
3216
3217 /* traditional, qualified net removal */
3218 if (cmd->cmd_prop_nv_pairs > 0) {
3219 struct zone_nwiftab nwiftab;
3220
3221 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
3222 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3223 return;
3224 }
3225 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
3226 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3227 else
3228 need_to_commit = B_TRUE;
3229 return;
3230 }
3231
3232 /*
3233 * unqualified net removal. remove all nets but prompt if more
3234 * than one.
3235 */
3236 if (!prompt_remove_resource(cmd, "net"))
3237 return;
3238
3239 if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
3240 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3241 else
3242 need_to_commit = B_TRUE;
3243 }
3244
3245 static void
3246 remove_device(cmd_t *cmd)
3247 {
3248 int err;
3249
3250 /* traditional, qualified device removal */
3251 if (cmd->cmd_prop_nv_pairs > 0) {
3252 struct zone_devtab devtab;
3253
3254 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3255 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3256 return;
3257 }
3258 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
3259 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3260 else
3261 need_to_commit = B_TRUE;
3262 return;
3263 }
3264
3265 /*
3266 * unqualified device removal. remove all devices but prompt if more
3267 * than one.
3268 */
3269 if (!prompt_remove_resource(cmd, "device"))
3270 return;
3271
3272 if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3273 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3274 else
3275 need_to_commit = B_TRUE;
3276 }
3277
3278 static void
3279 remove_attr(cmd_t *cmd)
3280 {
3281 int err;
3282
3283 /* traditional, qualified attr removal */
3284 if (cmd->cmd_prop_nv_pairs > 0) {
3285 struct zone_attrtab attrtab;
3286
3287 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3288 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3289 return;
3290 }
3291 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
3292 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3293 else
3294 need_to_commit = B_TRUE;
3295 return;
3296 }
3297
3298 /*
3299 * unqualified attr removal. remove all attrs but prompt if more
3300 * than one.
3301 */
3302 if (!prompt_remove_resource(cmd, "attr"))
3303 return;
3304
3305 if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3306 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3307 else
3308 need_to_commit = B_TRUE;
3309 }
3310
3311 static void
3312 remove_dataset(cmd_t *cmd)
3313 {
3314 int err;
3315
3316 /* traditional, qualified dataset removal */
3317 if (cmd->cmd_prop_nv_pairs > 0) {
3318 struct zone_dstab dstab;
3319
3320 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3321 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3322 return;
3323 }
3324 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
3325 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3326 else
3327 need_to_commit = B_TRUE;
3328 return;
3329 }
3330
3331 /*
3332 * unqualified dataset removal. remove all datasets but prompt if more
3333 * than one.
3334 */
3335 if (!prompt_remove_resource(cmd, "dataset"))
3336 return;
3337
3338 if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3339 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3340 else
3341 need_to_commit = B_TRUE;
3342 }
3343
3344 static void
3345 remove_rctl(cmd_t *cmd)
3346 {
3347 int err;
3348
3349 /* traditional, qualified rctl removal */
3350 if (cmd->cmd_prop_nv_pairs > 0) {
3351 struct zone_rctltab rctltab;
3352
3353 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3354 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3355 return;
3356 }
3357 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
3358 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3359 else
3360 need_to_commit = B_TRUE;
3361 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3362 return;
3363 }
3364
3365 /*
3366 * unqualified rctl removal. remove all rctls but prompt if more
3367 * than one.
3368 */
3369 if (!prompt_remove_resource(cmd, "rctl"))
3370 return;
3371
3372 if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3373 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3374 else
3375 need_to_commit = B_TRUE;
3376 }
3377
3378 static void
3379 remove_pset()
3380 {
3381 int err;
3382 struct zone_psettab psettab;
3383
3384 if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3385 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3386 return;
3387 }
3388 if ((err = zonecfg_delete_pset(handle)) != Z_OK)
3389 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3390 else
3391 need_to_commit = B_TRUE;
3392 }
3393
3394 static void
3395 remove_pcap()
3396 {
3397 int err;
3398 uint64_t tmp;
3399
3400 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3401 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
3402 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3403 saw_error = B_TRUE;
3404 return;
3405 }
3406
3407 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
3408 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3409 else
3410 need_to_commit = B_TRUE;
3411 }
3412
3413 static void
3414 remove_mcap()
3415 {
3416 int err, res1, res2, res3;
3417 uint64_t tmp;
3418 boolean_t revert = B_FALSE;
3419
3420 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp);
3421 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3422 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3423
3424 /* if none of these exist, there is no resource to remove */
3425 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3426 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
3427 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3428 saw_error = B_TRUE;
3429 return;
3430 }
3431 if (res1 == Z_OK) {
3432 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM))
3433 != Z_OK) {
3434 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3435 revert = B_TRUE;
3436 } else {
3437 need_to_commit = B_TRUE;
3438 }
3439 }
3440
3441 if (res2 == Z_OK) {
3442 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3443 != Z_OK) {
3444 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3445 revert = B_TRUE;
3446 } else {
3447 need_to_commit = B_TRUE;
3448 }
3449 }
3450 if (res3 == Z_OK) {
3451 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3452 != Z_OK) {
3453 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3454 revert = B_TRUE;
3455 } else {
3456 need_to_commit = B_TRUE;
3457 }
3458 }
3459
3460 if (revert)
3461 need_to_commit = B_FALSE;
3462 }
3463
3464 static void
3465 remove_admin(cmd_t *cmd)
3466 {
3467 int err;
3468
3469 /* traditional, qualified attr removal */
3470 if (cmd->cmd_prop_nv_pairs > 0) {
3471 struct zone_admintab admintab;
3472
3473 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3474 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3475 err, B_TRUE);
3476 return;
3477 }
3478 if ((err = zonecfg_delete_admin(handle, &admintab,
3479 zone))
3480 != Z_OK)
3481 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3482 err, B_TRUE);
3483 else
3484 need_to_commit = B_TRUE;
3485 return;
3486 } else {
3487 /*
3488 * unqualified admin removal.
3489 * remove all admins but prompt if more
3490 * than one.
3491 */
3492 if (!prompt_remove_resource(cmd, "admin"))
3493 return;
3494
3495 if ((err = zonecfg_delete_admins(handle, zone))
3496 != Z_OK)
3497 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3498 err, B_TRUE);
3499 else
3500 need_to_commit = B_TRUE;
3501 }
3502 }
3503
3504 static void
3505 remove_resource(cmd_t *cmd)
3506 {
3507 int type;
3508 int arg;
3509 boolean_t arg_err = B_FALSE;
3510
3511 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3512 long_usage(CMD_REMOVE, B_TRUE);
3513 return;
3514 }
3515
3516 optind = 0;
3517 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3518 switch (arg) {
3519 case '?':
3520 longer_usage(CMD_REMOVE);
3521 arg_err = B_TRUE;
3522 break;
3523 case 'F':
3524 break;
3525 default:
3526 short_usage(CMD_REMOVE);
3527 arg_err = B_TRUE;
3528 break;
3529 }
3530 }
3531 if (arg_err)
3532 return;
3533
3534 if (initialize(B_TRUE) != Z_OK)
3535 return;
3536
3537 switch (type) {
3538 case RT_FS:
3539 remove_fs(cmd);
3540 return;
3541 case RT_NET:
3542 remove_net(cmd);
3543 return;
3544 case RT_DEVICE:
3545 remove_device(cmd);
3546 return;
3547 case RT_RCTL:
3548 remove_rctl(cmd);
3549 return;
3550 case RT_ATTR:
3551 remove_attr(cmd);
3552 return;
3553 case RT_DATASET:
3554 remove_dataset(cmd);
3555 return;
3556 case RT_DCPU:
3557 remove_pset();
3558 return;
3559 case RT_PCAP:
3560 remove_pcap();
3561 return;
3562 case RT_MCAP:
3563 remove_mcap();
3564 return;
3565 case RT_ADMIN:
3566 remove_admin(cmd);
3567 return;
3568 default:
3569 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3570 long_usage(CMD_REMOVE, B_TRUE);
3571 usage(B_FALSE, HELP_RESOURCES);
3572 return;
3573 }
3574 }
3575
3576 static void
3577 remove_property(cmd_t *cmd)
3578 {
3579 char *prop_id;
3580 int err, res_type, prop_type;
3581 property_value_ptr_t pp;
3582 struct zone_rctlvaltab *rctlvaltab;
3583 struct zone_res_attrtab *np;
3584 complex_property_ptr_t cx;
3585
3586 res_type = resource_scope;
3587 prop_type = cmd->cmd_prop_name[0];
3588 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3589 long_usage(CMD_REMOVE, B_TRUE);
3590 return;
3591 }
3592
3593 if (cmd->cmd_prop_nv_pairs != 1) {
3594 long_usage(CMD_ADD, B_TRUE);
3595 return;
3596 }
3597
3598 if (initialize(B_TRUE) != Z_OK)
3599 return;
3600
3601 switch (res_type) {
3602 case RT_FS:
3603 if (prop_type != PT_OPTIONS) {
3604 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3605 B_TRUE);
3606 long_usage(CMD_REMOVE, B_TRUE);
3607 usage(B_FALSE, HELP_PROPS);
3608 return;
3609 }
3610 pp = cmd->cmd_property_ptr[0];
3611 if (pp->pv_type == PROP_VAL_COMPLEX) {
3612 zerr(gettext("A %s or %s value was expected here."),
3613 pvt_to_str(PROP_VAL_SIMPLE),
3614 pvt_to_str(PROP_VAL_LIST));
3615 saw_error = B_TRUE;
3616 return;
3617 }
3618 if (pp->pv_type == PROP_VAL_SIMPLE) {
3619 if (pp->pv_simple == NULL) {
3620 long_usage(CMD_ADD, B_TRUE);
3621 return;
3622 }
3623 prop_id = pp->pv_simple;
3624 err = zonecfg_remove_fs_option(&in_progress_fstab,
3625 prop_id);
3626 if (err != Z_OK)
3627 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3628 } else {
3629 list_property_ptr_t list;
3630
3631 for (list = pp->pv_list; list != NULL;
3632 list = list->lp_next) {
3633 prop_id = list->lp_simple;
3634 if (prop_id == NULL)
3635 break;
3636 err = zonecfg_remove_fs_option(
3637 &in_progress_fstab, prop_id);
3638 if (err != Z_OK)
3639 zone_perror(pt_to_str(prop_type), err,
3640 B_TRUE);
3641 }
3642 }
3643 return;
3644 case RT_NET: /* FALLTHRU */
3645 case RT_DEVICE:
3646 if (prop_type != PT_NPROP) {
3647 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3648 B_TRUE);
3649 long_usage(CMD_REMOVE, B_TRUE);
3650 usage(B_FALSE, HELP_PROPS);
3651 return;
3652 }
3653 pp = cmd->cmd_property_ptr[0];
3654 if (pp->pv_type != PROP_VAL_COMPLEX) {
3655 zerr(gettext("A %s value was expected here."),
3656 pvt_to_str(PROP_VAL_COMPLEX));
3657 saw_error = B_TRUE;
3658 return;
3671 cx->cp_value,
3672 sizeof (np->zone_res_attr_value));
3673 break;
3674 default:
3675 zone_perror(pt_to_str(prop_type),
3676 Z_NO_PROPERTY_TYPE, B_TRUE);
3677 long_usage(CMD_REMOVE, B_TRUE);
3678 usage(B_FALSE, HELP_PROPS);
3679 return;
3680 }
3681 }
3682 np->zone_res_attr_next = NULL;
3683
3684 if (res_type == RT_NET) {
3685 err = zonecfg_remove_res_attr(
3686 &(in_progress_nwiftab.zone_nwif_attrp), np);
3687 } else { /* RT_DEVICE */
3688 err = zonecfg_remove_res_attr(
3689 &(in_progress_devtab.zone_dev_attrp), np);
3690 }
3691 if (err != Z_OK)
3692 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3693 return;
3694 case RT_RCTL:
3695 if (prop_type != PT_VALUE) {
3696 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3697 B_TRUE);
3698 long_usage(CMD_REMOVE, B_TRUE);
3699 usage(B_FALSE, HELP_PROPS);
3700 return;
3701 }
3702 pp = cmd->cmd_property_ptr[0];
3703 if (pp->pv_type != PROP_VAL_COMPLEX) {
3704 zerr(gettext("A %s value was expected here."),
3705 pvt_to_str(PROP_VAL_COMPLEX));
3706 saw_error = B_TRUE;
3707 return;
3708 }
3709 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3710 zone_perror(zone, Z_NOMEM, B_TRUE);
3711 exit(Z_ERR);
3722 cx->cp_value,
3723 sizeof (rctlvaltab->zone_rctlval_limit));
3724 break;
3725 case PT_ACTION:
3726 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3727 cx->cp_value,
3728 sizeof (rctlvaltab->zone_rctlval_action));
3729 break;
3730 default:
3731 zone_perror(pt_to_str(prop_type),
3732 Z_NO_PROPERTY_TYPE, B_TRUE);
3733 long_usage(CMD_ADD, B_TRUE);
3734 usage(B_FALSE, HELP_PROPS);
3735 zonecfg_free_rctl_value_list(rctlvaltab);
3736 return;
3737 }
3738 }
3739 rctlvaltab->zone_rctlval_next = NULL;
3740 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3741 rctlvaltab);
3742 if (err != Z_OK)
3743 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3744 zonecfg_free_rctl_value_list(rctlvaltab);
3745 return;
3746 default:
3747 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3748 long_usage(CMD_REMOVE, B_TRUE);
3749 usage(B_FALSE, HELP_RESOURCES);
3750 return;
3751 }
3752 }
3753
3754 void
3755 remove_func(cmd_t *cmd)
3756 {
3757 if (zone_is_read_only(CMD_REMOVE))
3758 return;
3759
3760 assert(cmd != NULL);
3761
3762 if (global_scope) {
3847 }
3848
3849 static void
3850 clear_global(cmd_t *cmd)
3851 {
3852 int err, type;
3853
3854 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3855 long_usage(CMD_CLEAR, B_TRUE);
3856 return;
3857 }
3858
3859 if (initialize(B_TRUE) != Z_OK)
3860 return;
3861
3862 switch (type) {
3863 case PT_ZONENAME:
3864 /* FALLTHRU */
3865 case PT_ZONEPATH:
3866 /* FALLTHRU */
3867 case PT_BRAND:
3868 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
3869 return;
3870 case PT_AUTOBOOT:
3871 /* false is default; we'll treat as equivalent to clearing */
3872 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
3873 z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
3874 else
3875 need_to_commit = B_TRUE;
3876 return;
3877 case PT_POOL:
3878 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
3879 z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
3880 else
3881 need_to_commit = B_TRUE;
3882 return;
3883 case PT_LIMITPRIV:
3884 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
3885 z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
3886 else
3909 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
3910 return;
3911 case PT_MAXPROCS:
3912 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
3913 return;
3914 case PT_MAXSHMMEM:
3915 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
3916 return;
3917 case PT_MAXSHMIDS:
3918 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
3919 return;
3920 case PT_MAXMSGIDS:
3921 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
3922 return;
3923 case PT_MAXSEMIDS:
3924 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
3925 return;
3926 case PT_SHARES:
3927 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
3928 return;
3929 case PT_HOSTID:
3930 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
3931 z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
3932 else
3933 need_to_commit = B_TRUE;
3934 return;
3935 case PT_FS_ALLOWED:
3936 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
3937 z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
3938 else
3939 need_to_commit = B_TRUE;
3940 return;
3941 default:
3942 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
3943 long_usage(CMD_CLEAR, B_TRUE);
3944 usage(B_FALSE, HELP_PROPS);
3945 return;
3946 }
3947 }
3948
4399 } else if (prop_type == PT_IPTYPE) {
4400 res_type = RT_IPTYPE;
4401 } else if (prop_type == PT_MAXLWPS) {
4402 res_type = RT_MAXLWPS;
4403 } else if (prop_type == PT_MAXPROCS) {
4404 res_type = RT_MAXPROCS;
4405 } else if (prop_type == PT_MAXSHMMEM) {
4406 res_type = RT_MAXSHMMEM;
4407 } else if (prop_type == PT_MAXSHMIDS) {
4408 res_type = RT_MAXSHMIDS;
4409 } else if (prop_type == PT_MAXMSGIDS) {
4410 res_type = RT_MAXMSGIDS;
4411 } else if (prop_type == PT_MAXSEMIDS) {
4412 res_type = RT_MAXSEMIDS;
4413 } else if (prop_type == PT_SHARES) {
4414 res_type = RT_SHARES;
4415 } else if (prop_type == PT_HOSTID) {
4416 res_type = RT_HOSTID;
4417 } else if (prop_type == PT_FS_ALLOWED) {
4418 res_type = RT_FS_ALLOWED;
4419 } else {
4420 zerr(gettext("Cannot set a resource-specific property "
4421 "from the global scope."));
4422 saw_error = B_TRUE;
4423 return;
4424 }
4425 } else {
4426 res_type = resource_scope;
4427 }
4428
4429 if (force_set) {
4430 if (res_type != RT_ZONEPATH) {
4431 zerr(gettext("Only zonepath setting can be forced."));
4432 saw_error = B_TRUE;
4433 return;
4434 }
4435 if (!zonecfg_in_alt_root()) {
4436 zerr(gettext("Zonepath is changeable only in an "
4437 "alternate root."));
4438 saw_error = B_TRUE;
4606 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4607 return;
4608 case RT_MAXPROCS:
4609 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4610 return;
4611 case RT_MAXSHMMEM:
4612 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4613 return;
4614 case RT_MAXSHMIDS:
4615 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4616 return;
4617 case RT_MAXMSGIDS:
4618 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4619 return;
4620 case RT_MAXSEMIDS:
4621 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4622 return;
4623 case RT_SHARES:
4624 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4625 return;
4626 case RT_HOSTID:
4627 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4628 if (err == Z_TOO_BIG) {
4629 zerr(gettext("hostid string is too large: %s"),
4630 prop_id);
4631 saw_error = B_TRUE;
4632 } else {
4633 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4634 }
4635 return;
4636 }
4637 need_to_commit = B_TRUE;
4638 return;
4639 case RT_FS_ALLOWED:
4640 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4641 zone_perror(zone, err, B_TRUE);
4642 else
4643 need_to_commit = B_TRUE;
4644 return;
4645 case RT_FS:
4646 switch (prop_type) {
4647 case PT_DIR:
4648 (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4649 sizeof (in_progress_fstab.zone_fs_dir));
4650 return;
4651 case PT_SPECIAL:
4652 (void) strlcpy(in_progress_fstab.zone_fs_special,
4653 prop_id,
4654 sizeof (in_progress_fstab.zone_fs_special));
4655 return;
4656 case PT_RAW:
4657 (void) strlcpy(in_progress_fstab.zone_fs_raw,
4658 prop_id, sizeof (in_progress_fstab.zone_fs_raw));
4694 switch (prop_type) {
4695 case PT_ADDRESS:
4696 case PT_ALLOWED_ADDRESS:
4697 if (validate_net_address_syntax(prop_id, B_FALSE)
4698 != Z_OK) {
4699 saw_error = B_TRUE;
4700 return;
4701 }
4702 set_in_progress_nwiftab_address(prop_id, prop_type);
4703 break;
4704 case PT_PHYSICAL:
4705 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4706 saw_error = B_TRUE;
4707 return;
4708 }
4709 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4710 prop_id,
4711 sizeof (in_progress_nwiftab.zone_nwif_physical));
4712 break;
4713 case PT_MAC:
4714 (void) strlcpy(in_progress_nwiftab.zone_nwif_mac,
4715 prop_id,
4716 sizeof (in_progress_nwiftab.zone_nwif_mac));
4717 break;
4718 case PT_VLANID:
4719 (void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id,
4720 prop_id,
4721 sizeof (in_progress_nwiftab.zone_nwif_vlan_id));
4722 break;
4723 case PT_GNIC:
4724 (void) strlcpy(in_progress_nwiftab.zone_nwif_gnic,
4725 prop_id,
4726 sizeof (in_progress_nwiftab.zone_nwif_gnic));
4727 break;
4728 case PT_DEFROUTER:
4729 if (validate_net_address_syntax(prop_id, B_TRUE)
4730 != Z_OK) {
4731 saw_error = B_TRUE;
4732 return;
4733 }
4734 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
5219 }
5220 }
5221
5222 static void
5223 info_hostid(zone_dochandle_t handle, FILE *fp)
5224 {
5225 char hostidp[HW_HOSTID_LEN];
5226 int err;
5227
5228 if ((err = zonecfg_get_hostid(handle, hostidp,
5229 sizeof (hostidp))) == Z_OK) {
5230 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
5231 } else if (err == Z_BAD_PROPERTY) {
5232 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
5233 } else {
5234 zone_perror(zone, err, B_TRUE);
5235 }
5236 }
5237
5238 static void
5239 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
5240 {
5241 char fsallowedp[ZONE_FS_ALLOWED_MAX];
5242 int err;
5243
5244 if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
5245 sizeof (fsallowedp))) == Z_OK) {
5246 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
5247 fsallowedp);
5248 } else if (err == Z_BAD_PROPERTY) {
5249 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
5250 } else {
5251 zone_perror(zone, err, B_TRUE);
5252 }
5253 }
5254
5255 static void
5256 output_fs(FILE *fp, struct zone_fstab *fstab)
5257 {
5258 zone_fsopt_t *this;
5728 (void) zonecfg_endadminent(handle);
5729 /*
5730 * If a property n/v pair was specified, warn the user if there was
5731 * nothing to output.
5732 */
5733 if (!output && cmd->cmd_prop_nv_pairs > 0)
5734 (void) printf(gettext("No such %s resource.\n"),
5735 rt_to_str(RT_ADMIN));
5736 }
5737
5738 void
5739 info_func(cmd_t *cmd)
5740 {
5741 FILE *fp = stdout;
5742 boolean_t need_to_close = B_FALSE;
5743 int type;
5744 int res1, res2, res3;
5745 uint64_t swap_limit;
5746 uint64_t locked_limit;
5747 uint64_t phys_limit;
5748
5749 assert(cmd != NULL);
5750
5751 if (initialize(B_TRUE) != Z_OK)
5752 return;
5753
5754 /* don't page error output */
5755 if (interactive_mode) {
5756 if ((fp = pager_open()) != NULL)
5757 need_to_close = B_TRUE;
5758 else
5759 fp = stdout;
5760
5761 setbuf(fp, NULL);
5762 }
5763
5764 if (!global_scope) {
5765 switch (resource_scope) {
5766 case RT_FS:
5767 output_fs(fp, &in_progress_fstab);
5817 rt_to_str(type));
5818 goto cleanup;
5819 }
5820
5821 switch (cmd->cmd_res_type) {
5822 case RT_UNKNOWN:
5823 info_zonename(handle, fp);
5824 if (!global_zone) {
5825 info_zonepath(handle, fp);
5826 info_brand(handle, fp);
5827 info_autoboot(handle, fp);
5828 info_bootargs(handle, fp);
5829 }
5830 info_pool(handle, fp);
5831 if (!global_zone) {
5832 info_limitpriv(handle, fp);
5833 info_sched(handle, fp);
5834 info_iptype(handle, fp);
5835 info_hostid(handle, fp);
5836 info_fs_allowed(handle, fp);
5837 }
5838 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5839 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5840 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5841 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5842 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5843 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5844 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5845 if (!global_zone) {
5846 info_fs(handle, fp, cmd);
5847 info_net(handle, fp, cmd);
5848 info_dev(handle, fp, cmd);
5849 }
5850 info_pset(handle, fp);
5851 info_pcap(fp);
5852 info_mcap(handle, fp);
5853 if (!global_zone) {
5854 info_attr(handle, fp, cmd);
5855 info_ds(handle, fp, cmd);
5856 info_auth(handle, fp, cmd);
5857 }
5858 info_rctl(handle, fp, cmd);
5859 break;
5860 case RT_ZONENAME:
5861 info_zonename(handle, fp);
5862 break;
5863 case RT_ZONEPATH:
5864 info_zonepath(handle, fp);
5888 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5889 break;
5890 case RT_MAXPROCS:
5891 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5892 break;
5893 case RT_MAXSHMMEM:
5894 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5895 break;
5896 case RT_MAXSHMIDS:
5897 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5898 break;
5899 case RT_MAXMSGIDS:
5900 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5901 break;
5902 case RT_MAXSEMIDS:
5903 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5904 break;
5905 case RT_SHARES:
5906 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5907 break;
5908 case RT_FS:
5909 info_fs(handle, fp, cmd);
5910 break;
5911 case RT_NET:
5912 info_net(handle, fp, cmd);
5913 break;
5914 case RT_DEVICE:
5915 info_dev(handle, fp, cmd);
5916 break;
5917 case RT_RCTL:
5918 info_rctl(handle, fp, cmd);
5919 break;
5920 case RT_ATTR:
5921 info_attr(handle, fp, cmd);
5922 break;
5923 case RT_DATASET:
5924 info_ds(handle, fp, cmd);
5925 break;
5926 case RT_DCPU:
5927 info_pset(handle, fp);
5928 break;
5929 case RT_PCAP:
5930 info_pcap(fp);
5931 break;
5932 case RT_MCAP:
5933 info_mcap(handle, fp);
5934 break;
5935 case RT_HOSTID:
5936 info_hostid(handle, fp);
5937 break;
5938 case RT_ADMIN:
5939 info_auth(handle, fp, cmd);
5940 break;
5941 case RT_FS_ALLOWED:
5942 info_fs_allowed(handle, fp);
5943 break;
5944 default:
5945 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5946 B_TRUE);
5947 }
5948
5949 cleanup:
5950 if (need_to_close)
5951 (void) pager_close(fp);
5952 }
5953
5954 /*
5955 * Helper function for verify-- checks that a required string property
5956 * exists.
5957 */
6409
6410 if (!global_scope) {
6411 zerr(gettext("resource specification incomplete"));
6412 saw_error = B_TRUE;
6413 if (ret_val == Z_OK)
6414 ret_val = Z_INSUFFICIENT_SPEC;
6415 }
6416
6417 if (save) {
6418 if (ret_val == Z_OK) {
6419 /*
6420 * If the zone doesn't yet have a debug ID, set one now.
6421 */
6422 if (zonecfg_get_did(handle) == -1)
6423 zonecfg_set_did(handle);
6424
6425 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6426 need_to_commit = B_FALSE;
6427 (void) strlcpy(revert_zone, zone,
6428 sizeof (revert_zone));
6429 }
6430 } else {
6431 zerr(gettext("Zone %s failed to verify"), zone);
6432 }
6433 }
6434 if (ret_val != Z_OK)
6435 zone_perror(zone, ret_val, B_TRUE);
6436 }
6437
6438 void
6439 cancel_func(cmd_t *cmd)
6440 {
6441 int arg;
6442 boolean_t arg_err = B_FALSE;
6443
6444 assert(cmd != NULL);
6445
6446 optind = 0;
6447 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6448 switch (arg) {
6449 case '?':
7459 for (;;) {
7460 last_slash = strrchr(execfullname, '/');
7461 if (last_slash == NULL) {
7462 execbasename = execfullname;
7463 break;
7464 } else {
7465 execbasename = last_slash + 1;
7466 if (*execbasename == '\0') {
7467 *last_slash = '\0';
7468 continue;
7469 }
7470 break;
7471 }
7472 }
7473 return (execbasename);
7474 }
7475
7476 int
7477 main(int argc, char *argv[])
7478 {
7479 int err, arg;
7480 struct stat st;
7481
7482 /* This must be before anything goes to stdout. */
7483 setbuf(stdout, NULL);
7484
7485 saw_error = B_FALSE;
7486 cmd_file_mode = B_FALSE;
7487 execname = get_execbasename(argv[0]);
7488
7489 (void) setlocale(LC_ALL, "");
7490 (void) textdomain(TEXT_DOMAIN);
7491
7492 if (getzoneid() != GLOBAL_ZONEID) {
7493 zerr(gettext("%s can only be run from the global zone."),
7494 execname);
7495 exit(Z_ERR);
7496 }
7497
7498 if (argc < 2) {
7499 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7500 exit(Z_USAGE);
7501 }
7502 if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7503 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7504 exit(Z_OK);
7505 }
7506
7507 while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
7508 switch (arg) {
7509 case '?':
7510 if (optopt == '?')
7511 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7512 else
7513 usage(B_FALSE, HELP_USAGE);
7514 exit(Z_USAGE);
7515 /* NOTREACHED */
7516 case 'f':
7517 cmd_file_name = optarg;
7518 cmd_file_mode = B_TRUE;
7519 break;
7520 case 'R':
7521 if (*optarg != '/') {
7522 zerr(gettext("root path must be absolute: %s"),
7523 optarg);
7524 exit(Z_USAGE);
7525 }
7526 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7527 zerr(gettext(
7528 "root path must be a directory: %s"),
7529 optarg);
7530 exit(Z_USAGE);
7531 }
7532 zonecfg_set_root(optarg);
7533 break;
7534 case 'z':
7535 if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7536 global_zone = B_TRUE;
7537 } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7538 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7539 usage(B_FALSE, HELP_SYNTAX);
7540 exit(Z_USAGE);
7541 }
7542 (void) strlcpy(zone, optarg, sizeof (zone));
7543 (void) strlcpy(revert_zone, optarg, sizeof (zone));
7544 break;
7545 default:
7546 usage(B_FALSE, HELP_USAGE);
7547 exit(Z_USAGE);
7548 }
7549 }
7550
7551 if (optind > argc || strcmp(zone, "") == 0) {
7552 usage(B_FALSE, HELP_USAGE);
7553 exit(Z_USAGE);
7554 }
7555
7556 if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7557 read_only_mode = B_FALSE;
7558 } else if (err == Z_ACCES) {
7559 read_only_mode = B_TRUE;
7560 /* skip this message in one-off from command line mode */
7561 if (optind == argc)
7562 (void) fprintf(stderr, gettext("WARNING: you do not "
7563 "have write access to this zone's configuration "
7564 "file;\ngoing into read-only mode.\n"));
7565 } else {
7566 fprintf(stderr, "%s: Could not access zone configuration "
7567 "store: %s\n", execname, zonecfg_strerror(err));
7568 exit(Z_ERR);
7569 }
7570
7571 if ((handle = zonecfg_init_handle()) == NULL) {
|