36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
45 *
46 * The rest of this module consists of the various function handlers and
47 * their helper functions. Some of these functions, particularly the
48 * X_to_str() functions, which maps command, resource and property numbers
49 * to strings, are used quite liberally, as doing so results in a better
50 * program w/rt I18N, reducing the need for translation notes.
51 */
52
53 #include <sys/mntent.h>
54 #include <sys/varargs.h>
55 #include <sys/sysmacros.h>
56
57 #include <errno.h>
58 #include <fcntl.h>
59 #include <strings.h>
60 #include <unistd.h>
61 #include <ctype.h>
62 #include <stdlib.h>
63 #include <assert.h>
64 #include <sys/stat.h>
65 #include <zone.h>
66 #include <arpa/inet.h>
67 #include <netdb.h>
68 #include <locale.h>
69 #include <libintl.h>
70 #include <alloca.h>
71 #include <signal.h>
72 #include <wait.h>
73 #include <libtecla.h>
74 #include <libzfs.h>
75 #include <sys/brand.h>
170 "attr",
171 "dataset",
172 "limitpriv",
173 "bootargs",
174 "brand",
175 "dedicated-cpu",
176 "capped-memory",
177 ALIAS_MAXLWPS,
178 ALIAS_MAXSHMMEM,
179 ALIAS_MAXSHMIDS,
180 ALIAS_MAXMSGIDS,
181 ALIAS_MAXSEMIDS,
182 ALIAS_SHARES,
183 "scheduling-class",
184 "ip-type",
185 "capped-cpu",
186 "hostid",
187 "admin",
188 "fs-allowed",
189 ALIAS_MAXPROCS,
190 NULL
191 };
192
193 /* These *must* match the order of the PT_ define's from zonecfg.h */
194 char *prop_types[] = {
195 "unknown",
196 "zonename",
197 "zonepath",
198 "autoboot",
199 "pool",
200 "dir",
201 "special",
202 "type",
203 "options",
204 "address",
205 "physical",
206 "name",
207 "value",
208 "match",
209 "priv",
217 "importance",
218 "swap",
219 "locked",
220 ALIAS_SHARES,
221 ALIAS_MAXLWPS,
222 ALIAS_MAXSHMMEM,
223 ALIAS_MAXSHMIDS,
224 ALIAS_MAXMSGIDS,
225 ALIAS_MAXSEMIDS,
226 ALIAS_MAXLOCKEDMEM,
227 ALIAS_MAXSWAP,
228 "scheduling-class",
229 "ip-type",
230 "defrouter",
231 "hostid",
232 "user",
233 "auths",
234 "fs-allowed",
235 ALIAS_MAXPROCS,
236 "allowed-address",
237 NULL
238 };
239
240 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
241 static char *prop_val_types[] = {
242 "simple",
243 "complex",
244 "list",
245 };
246
247 /*
248 * The various _cmds[] lists below are for command tab-completion.
249 */
250
251 /*
252 * remove has a space afterwards because it has qualifiers; the other commands
253 * that have qualifiers (add, select, etc.) don't need a space here because
254 * they have their own _cmds[] lists below.
255 */
256 static const char *global_scope_cmds[] = {
265 "info",
266 "remove ",
267 "revert",
268 "select",
269 "set",
270 "verify",
271 NULL
272 };
273
274 static const char *add_cmds[] = {
275 "add fs",
276 "add net",
277 "add device",
278 "add rctl",
279 "add attr",
280 "add dataset",
281 "add dedicated-cpu",
282 "add capped-cpu",
283 "add capped-memory",
284 "add admin",
285 NULL
286 };
287
288 static const char *clear_cmds[] = {
289 "clear autoboot",
290 "clear pool",
291 "clear limitpriv",
292 "clear bootargs",
293 "clear scheduling-class",
294 "clear ip-type",
295 "clear " ALIAS_MAXLWPS,
296 "clear " ALIAS_MAXSHMMEM,
297 "clear " ALIAS_MAXSHMIDS,
298 "clear " ALIAS_MAXMSGIDS,
299 "clear " ALIAS_MAXSEMIDS,
300 "clear " ALIAS_SHARES,
301 "clear " ALIAS_MAXPROCS,
302 NULL
303 };
304
305 static const char *remove_cmds[] = {
306 "remove fs ",
307 "remove net ",
308 "remove device ",
309 "remove rctl ",
310 "remove attr ",
311 "remove dataset ",
312 "remove dedicated-cpu ",
313 "remove capped-cpu ",
314 "remove capped-memory ",
315 "remove admin ",
316 NULL
317 };
318
319 static const char *select_cmds[] = {
320 "select fs ",
321 "select net ",
322 "select device ",
323 "select rctl ",
324 "select attr ",
325 "select dataset ",
326 "select dedicated-cpu",
327 "select capped-cpu",
328 "select capped-memory",
329 "select admin",
330 NULL
331 };
332
333 static const char *set_cmds[] = {
334 "set zonename=",
335 "set zonepath=",
336 "set brand=",
337 "set autoboot=",
338 "set pool=",
339 "set limitpriv=",
340 "set bootargs=",
341 "set scheduling-class=",
342 "set ip-type=",
343 "set " ALIAS_MAXLWPS "=",
344 "set " ALIAS_MAXSHMMEM "=",
345 "set " ALIAS_MAXSHMIDS "=",
346 "set " ALIAS_MAXMSGIDS "=",
347 "set " ALIAS_MAXSEMIDS "=",
348 "set " ALIAS_SHARES "=",
349 "set hostid=",
350 "set fs-allowed=",
351 "set " ALIAS_MAXPROCS "=",
352 NULL
353 };
354
355 static const char *info_cmds[] = {
356 "info fs ",
357 "info net ",
358 "info device ",
359 "info rctl ",
360 "info attr ",
361 "info dataset ",
362 "info capped-memory",
363 "info dedicated-cpu",
364 "info capped-cpu",
365 "info zonename",
366 "info zonepath",
367 "info autoboot",
368 "info pool",
369 "info limitpriv",
370 "info bootargs",
371 "info brand",
372 "info scheduling-class",
373 "info ip-type",
374 "info max-lwps",
375 "info max-shm-memory",
376 "info max-shm-ids",
377 "info max-msg-ids",
378 "info max-sem-ids",
379 "info cpu-shares",
380 "info hostid",
381 "info admin",
382 "info fs-allowed",
383 "info max-processes",
384 NULL
487 "set physical=",
488 "set swap=",
489 "set locked=",
490 "clear physical",
491 "clear swap",
492 "clear locked",
493 NULL
494 };
495
496 static const char *admin_res_scope_cmds[] = {
497 "cancel",
498 "end",
499 "exit",
500 "help",
501 "info",
502 "set user=",
503 "set auths=",
504 NULL
505 };
506
507 struct xif {
508 struct xif *xif_next;
509 char xif_name[LIFNAMSIZ];
510 boolean_t xif_has_address;
511 boolean_t xif_has_defrouter;
512 };
513
514 /* Global variables */
515
516 /* list of network interfaces specified for exclusive IP zone */
517 struct xif *xif;
518
519 /* set early in main(), never modified thereafter, used all over the place */
520 static char *execname;
521
522 /* set in main(), used all over the place */
523 static zone_dochandle_t handle;
524
525 /* used all over the place */
526 static char zone[ZONENAME_MAX];
564 static boolean_t global_scope = B_TRUE;
565 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
566 static int end_op = -1; /* operation on end is either add or modify */
567
568 int num_prop_vals; /* for grammar */
569
570 /*
571 * These are for keeping track of resources as they are specified as part of
572 * the multi-step process. They should be initialized by add_resource() or
573 * select_func() and filled in by add_property() or set_func().
574 */
575 static struct zone_fstab old_fstab, in_progress_fstab;
576 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
577 static struct zone_devtab old_devtab, in_progress_devtab;
578 static struct zone_rctltab old_rctltab, in_progress_rctltab;
579 static struct zone_attrtab old_attrtab, in_progress_attrtab;
580 static struct zone_dstab old_dstab, in_progress_dstab;
581 static struct zone_psettab old_psettab, in_progress_psettab;
582 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
583 static struct zone_admintab old_admintab, in_progress_admintab;
584
585 static GetLine *gl; /* The gl_get_line() resource object */
586
587 static void bytes_to_units(char *str, char *buf, int bufsize);
588
589 /* Functions begin here */
590
591 static boolean_t
592 initial_match(const char *line1, const char *line2, int word_end)
593 {
594 if (word_end <= 0)
595 return (B_TRUE);
596 return (strncmp(line1, line2, word_end) == 0);
597 }
598
599 static int
600 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
601 int word_end)
602 {
603 int i, err;
641 case RT_FS:
642 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
643 case RT_NET:
644 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
645 case RT_DEVICE:
646 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
647 case RT_RCTL:
648 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
649 case RT_ATTR:
650 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
651 case RT_DATASET:
652 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
653 case RT_DCPU:
654 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
655 case RT_PCAP:
656 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
657 case RT_MCAP:
658 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
659 case RT_ADMIN:
660 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
661 }
662 return (0);
663 }
664
665 /*
666 * For the main CMD_func() functions below, several of them call getopt()
667 * then check optind against argc to make sure an extra parameter was not
668 * passed in. The reason this is not caught in the grammar is that the
669 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
670 * be "-F" (for example), but could be anything. So (for example) this
671 * check will prevent "create bogus".
672 */
673
674 cmd_t *
675 alloc_cmd(void)
676 {
677 return (calloc(1, sizeof (cmd_t)));
678 }
679
680 void
956 if ((pathstr = getenv("PATH")) == NULL) {
957 if (geteuid() == 0 || getuid() == 0)
958 pathstr = "/usr/sbin:/usr/bin";
959 else
960 pathstr = "/usr/bin:";
961 }
962 cp = strchr(name, '/') ? (const char *) "" : pathstr;
963
964 do {
965 cp = exec_cat(cp, name, fname);
966 if (stat(fname, &stat_buf) != -1) {
967 /* successful find of the file */
968 return (0);
969 }
970 } while (cp != NULL);
971
972 return (-1);
973 }
974
975 static FILE *
976 pager_open(void) {
977 FILE *newfp;
978 char *pager, *space;
979
980 pager = getenv("PAGER");
981 if (pager == NULL || *pager == '\0')
982 pager = PAGER;
983
984 space = strchr(pager, ' ');
985 if (space)
986 *space = '\0';
987 if (path_find(pager) == 0) {
988 if (space)
989 *space = ' ';
990 if ((newfp = popen(pager, "w")) == NULL)
991 zerr(gettext("PAGER open failed (%s)."),
992 strerror(errno));
993 return (newfp);
994 } else {
995 zerr(gettext("PAGER %s does not exist (%s)."),
996 pager, strerror(errno));
997 }
998 return (NULL);
999 }
1000
1001 static void
1002 pager_close(FILE *fp) {
1003 int status;
1004
1005 status = pclose(fp);
1006 if (status == -1)
1007 zerr(gettext("PAGER close failed (%s)."),
1008 strerror(errno));
1009 }
1010
1011 /*
1012 * Called with verbose TRUE when help is explicitly requested, FALSE for
1013 * unexpected errors.
1014 */
1015
1016 void
1017 usage(boolean_t verbose, uint_t flags)
1018 {
1019 FILE *fp = verbose ? stdout : stderr;
1020 FILE *newfp;
1021 boolean_t need_to_close = B_FALSE;
1022 int i;
1210 pt_to_str(PT_SWAP),
1211 gettext("<qualified unsigned decimal>"));
1212 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1213 pt_to_str(PT_LOCKED),
1214 gettext("<qualified unsigned decimal>"));
1215 break;
1216 case RT_ADMIN:
1217 (void) fprintf(fp, gettext("The '%s' resource scope is "
1218 "used to delegate specific zone management\n"
1219 "rights to users and roles. These rights are "
1220 "only applicable to this zone.\n"),
1221 rt_to_str(resource_scope));
1222 (void) fprintf(fp, gettext("Valid commands:\n"));
1223 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1224 pt_to_str(PT_USER),
1225 gettext("<single user or role name>"));
1226 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1227 pt_to_str(PT_AUTHS),
1228 gettext("<comma separated list>"));
1229 break;
1230 }
1231 (void) fprintf(fp, gettext("And from any resource scope, you "
1232 "can:\n"));
1233 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1234 gettext("(to conclude this operation)"));
1235 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1236 gettext("(to cancel this operation)"));
1237 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1238 gettext("(to exit the zonecfg utility)"));
1239 }
1240 if (flags & HELP_USAGE) {
1241 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1242 execname, cmd_to_str(CMD_HELP));
1243 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1244 execname, gettext("interactive"));
1245 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1246 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1247 execname);
1248 }
1249 if (flags & HELP_SUBCMDS) {
1274 (void) fprintf(fp,
1275 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1276 (void) fprintf(fp,
1277 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1278 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1279 "IPv6 address syntax.\n"));
1280 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1281 (void) fprintf(fp,
1282 gettext("<IPv6-prefix-length> := [0-128]\n"));
1283 (void) fprintf(fp,
1284 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1285 }
1286 if (flags & HELP_RESOURCES) {
1287 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1288 "%s | %s | %s | %s | %s\n\n",
1289 gettext("resource type"), rt_to_str(RT_FS),
1290 rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1291 rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1292 rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1293 rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1294 rt_to_str(RT_ADMIN));
1295 }
1296 if (flags & HELP_PROPS) {
1297 (void) fprintf(fp, gettext("For resource type ... there are "
1298 "property types ...:\n"));
1299 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1300 pt_to_str(PT_ZONENAME));
1301 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1302 pt_to_str(PT_ZONEPATH));
1303 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1304 pt_to_str(PT_BRAND));
1305 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1306 pt_to_str(PT_AUTOBOOT));
1307 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1308 pt_to_str(PT_BOOTARGS));
1309 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1310 pt_to_str(PT_POOL));
1311 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1312 pt_to_str(PT_LIMITPRIV));
1313 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1314 pt_to_str(PT_SCHED));
1340 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1341 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1342 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1343 pt_to_str(PT_MATCH));
1344 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1345 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1346 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1347 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1348 pt_to_str(PT_VALUE));
1349 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1350 pt_to_str(PT_NAME));
1351 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1352 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1353 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1354 pt_to_str(PT_NCPUS));
1355 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1356 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1357 pt_to_str(PT_LOCKED));
1358 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1359 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1360 }
1361 if (need_to_close)
1362 (void) pager_close(fp);
1363 }
1364
1365 static void
1366 zone_perror(char *prefix, int err, boolean_t set_saw)
1367 {
1368 zerr("%s: %s", prefix, zonecfg_strerror(err));
1369 if (set_saw)
1370 saw_error = B_TRUE;
1371 }
1372
1373 /*
1374 * zone_perror() expects a single string, but for remove and select
1375 * we have both the command and the resource type, so this wrapper
1376 * function serves the same purpose in a slightly different way.
1377 */
1378
1379 static void
1783 return;
1784 quote_str = quoteit(prop_id);
1785 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1786 pt_to_str(prop_num), quote_str);
1787 free(quote_str);
1788 }
1789
1790 void
1791 export_func(cmd_t *cmd)
1792 {
1793 struct zone_nwiftab nwiftab;
1794 struct zone_fstab fstab;
1795 struct zone_devtab devtab;
1796 struct zone_attrtab attrtab;
1797 struct zone_rctltab rctltab;
1798 struct zone_dstab dstab;
1799 struct zone_psettab psettab;
1800 struct zone_mcaptab mcaptab;
1801 struct zone_rctlvaltab *valptr;
1802 struct zone_admintab admintab;
1803 int err, arg;
1804 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1805 char bootargs[BOOTARGS_MAX];
1806 char sched[MAXNAMELEN];
1807 char brand[MAXNAMELEN];
1808 char hostidp[HW_HOSTID_LEN];
1809 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1810 char *limitpriv;
1811 FILE *of;
1812 boolean_t autoboot;
1813 zone_iptype_t iptype;
1814 boolean_t need_to_close = B_FALSE;
1815 boolean_t arg_err = B_FALSE;
1816
1817 assert(cmd != NULL);
1818
1819 outfile[0] = '\0';
1820 optind = 0;
1821 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1822 switch (arg) {
2052 (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
2053 pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
2054 psettab.zone_ncpu_max);
2055 if (psettab.zone_importance[0] != '\0')
2056 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2057 pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
2058 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2059 }
2060
2061 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
2062 zone_perror(zone, err, B_FALSE);
2063 goto done;
2064 }
2065 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
2066 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2067 rt_to_str(RT_ADMIN));
2068 export_prop(of, PT_USER, admintab.zone_admin_user);
2069 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
2070 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2071 }
2072 (void) zonecfg_endadminent(handle);
2073
2074 /*
2075 * There is nothing to export for pcap since this resource is just
2076 * a container for an rctl alias.
2077 */
2078
2079 done:
2080 if (need_to_close)
2081 (void) fclose(of);
2082 }
2083
2084 void
2085 exit_func(cmd_t *cmd)
2086 {
2087 int arg, answer;
2088 boolean_t arg_err = B_FALSE;
2089
2090 optind = 0;
2091 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2092 switch (arg) {
2093 case '?':
2133 {
2134 if (path[0] != '/') {
2135 zerr(gettext("%s is not an absolute path."), path);
2136 return (Z_ERR);
2137 }
2138 /* If path is all slashes, then fail */
2139 if (strspn(path, "/") == strlen(path)) {
2140 zerr(gettext("/ is not allowed as a %s."),
2141 pt_to_str(PT_ZONEPATH));
2142 return (Z_ERR);
2143 }
2144 return (Z_OK);
2145 }
2146
2147 static void
2148 add_resource(cmd_t *cmd)
2149 {
2150 int type;
2151 struct zone_psettab tmp_psettab;
2152 struct zone_mcaptab tmp_mcaptab;
2153 uint64_t tmp;
2154 uint64_t tmp_mcap;
2155 char pool[MAXNAMELEN];
2156
2157 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2158 long_usage(CMD_ADD, B_TRUE);
2159 goto bad;
2160 }
2161
2162 switch (type) {
2163 case RT_FS:
2164 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2165 return;
2166 case RT_NET:
2167 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2168 return;
2169 case RT_DEVICE:
2170 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2171 return;
2172 case RT_RCTL:
2244 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2245 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2246 == Z_OK ||
2247 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2248 &tmp_mcap) == Z_OK) {
2249 zerr(gettext("The %s resource or a related resource "
2250 "control already exists."), rt_to_str(RT_MCAP));
2251 goto bad;
2252 }
2253 if (global_zone)
2254 zerr(gettext("WARNING: Setting a global zone memory "
2255 "cap too low could deny\nservice "
2256 "to even the root user; "
2257 "this could render the system impossible\n"
2258 "to administer. Please use caution."));
2259 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2260 return;
2261 case RT_ADMIN:
2262 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2263 return;
2264 default:
2265 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2266 long_usage(CMD_ADD, B_TRUE);
2267 usage(B_FALSE, HELP_RESOURCES);
2268 }
2269 bad:
2270 global_scope = B_TRUE;
2271 end_op = -1;
2272 }
2273
2274 static void
2275 do_complex_rctl_val(complex_property_ptr_t cp)
2276 {
2277 struct zone_rctlvaltab *rctlvaltab;
2278 complex_property_ptr_t cx;
2279 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2280 seen_action = B_FALSE;
2281 rctlblk_t *rctlblk;
2282 int err;
2283
2913 case PT_USER:
2914 (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2915 sizeof (admintab->zone_admin_user));
2916 break;
2917 case PT_AUTHS:
2918 (void) strlcpy(admintab->zone_admin_auths,
2919 pp->pv_simple, sizeof (admintab->zone_admin_auths));
2920 break;
2921 default:
2922 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2923 Z_NO_PROPERTY_TYPE, B_TRUE);
2924 return (Z_INSUFFICIENT_SPEC);
2925 }
2926 }
2927 if (fill_in_only)
2928 return (Z_OK);
2929 err = zonecfg_lookup_admin(handle, admintab);
2930 return (err);
2931 }
2932
2933 static void
2934 remove_aliased_rctl(int type, char *name)
2935 {
2936 int err;
2937 uint64_t tmp;
2938
2939 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
2940 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2941 zonecfg_strerror(err));
2942 saw_error = B_TRUE;
2943 return;
2944 }
2945 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
2946 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2947 zonecfg_strerror(err));
2948 saw_error = B_TRUE;
2949 } else {
2950 need_to_commit = B_TRUE;
2951 }
2952 }
3315 return;
3316 } else {
3317 /*
3318 * unqualified admin removal.
3319 * remove all admins but prompt if more
3320 * than one.
3321 */
3322 if (!prompt_remove_resource(cmd, "admin"))
3323 return;
3324
3325 if ((err = zonecfg_delete_admins(handle, zone))
3326 != Z_OK)
3327 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3328 err, B_TRUE);
3329 else
3330 need_to_commit = B_TRUE;
3331 }
3332 }
3333
3334 static void
3335 remove_resource(cmd_t *cmd)
3336 {
3337 int type;
3338 int arg;
3339 boolean_t arg_err = B_FALSE;
3340
3341 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3342 long_usage(CMD_REMOVE, B_TRUE);
3343 return;
3344 }
3345
3346 optind = 0;
3347 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3348 switch (arg) {
3349 case '?':
3350 longer_usage(CMD_REMOVE);
3351 arg_err = B_TRUE;
3352 break;
3353 case 'F':
3354 break;
3378 remove_rctl(cmd);
3379 return;
3380 case RT_ATTR:
3381 remove_attr(cmd);
3382 return;
3383 case RT_DATASET:
3384 remove_dataset(cmd);
3385 return;
3386 case RT_DCPU:
3387 remove_pset();
3388 return;
3389 case RT_PCAP:
3390 remove_pcap();
3391 return;
3392 case RT_MCAP:
3393 remove_mcap();
3394 return;
3395 case RT_ADMIN:
3396 remove_admin(cmd);
3397 return;
3398 default:
3399 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3400 long_usage(CMD_REMOVE, B_TRUE);
3401 usage(B_FALSE, HELP_RESOURCES);
3402 return;
3403 }
3404 }
3405
3406 static void
3407 remove_property(cmd_t *cmd)
3408 {
3409 char *prop_id;
3410 int err, res_type, prop_type;
3411 property_value_ptr_t pp;
3412 struct zone_rctlvaltab *rctlvaltab;
3413 complex_property_ptr_t cx;
3414
3415 res_type = resource_scope;
3416 prop_type = cmd->cmd_prop_name[0];
3417 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3590 if (prop_type == PT_IMPORTANCE) {
3591 in_progress_psettab.zone_importance[0] = '\0';
3592 need_to_commit = B_TRUE;
3593 return;
3594 }
3595 break;
3596 case RT_MCAP:
3597 switch (prop_type) {
3598 case PT_PHYSICAL:
3599 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3600 need_to_commit = B_TRUE;
3601 return;
3602 case PT_SWAP:
3603 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3604 return;
3605 case PT_LOCKED:
3606 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3607 return;
3608 }
3609 break;
3610 default:
3611 break;
3612 }
3613
3614 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3615 }
3616
3617 static void
3618 clear_global(cmd_t *cmd)
3619 {
3620 int err, type;
3621
3622 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3623 long_usage(CMD_CLEAR, B_TRUE);
3624 return;
3625 }
3626
3627 if (initialize(B_TRUE) != Z_OK)
3628 return;
3629
3843 B_TRUE);
3844 global_scope = B_TRUE;
3845 }
3846 if (res == Z_OK)
3847 bcopy(&old_mcaptab, &in_progress_mcaptab,
3848 sizeof (struct zone_mcaptab));
3849 else
3850 bzero(&in_progress_mcaptab,
3851 sizeof (in_progress_mcaptab));
3852 return;
3853 case RT_ADMIN:
3854 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
3855 != Z_OK) {
3856 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
3857 B_TRUE);
3858 global_scope = B_TRUE;
3859 }
3860 bcopy(&old_admintab, &in_progress_admintab,
3861 sizeof (struct zone_admintab));
3862 return;
3863 default:
3864 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3865 long_usage(CMD_SELECT, B_TRUE);
3866 usage(B_FALSE, HELP_RESOURCES);
3867 return;
3868 }
3869 }
3870
3871 /*
3872 * Network "addresses" can be one of the following forms:
3873 * <IPv4 address>
3874 * <IPv4 address>/<prefix length>
3875 * <IPv6 address>/<prefix length>
3876 * <host name>
3877 * <host name>/<prefix length>
3878 * In other words, the "/" followed by a prefix length is allowed but not
3879 * required for IPv4 addresses and host names, and required for IPv6 addresses.
3880 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
3881 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
3882 * Host names must start with an alpha-numeric character, and all subsequent
4759 return;
4760 case RT_ADMIN:
4761 switch (prop_type) {
4762 case PT_USER:
4763 (void) strlcpy(in_progress_admintab.zone_admin_user,
4764 prop_id,
4765 sizeof (in_progress_admintab.zone_admin_user));
4766 return;
4767 case PT_AUTHS:
4768 (void) strlcpy(in_progress_admintab.zone_admin_auths,
4769 prop_id,
4770 sizeof (in_progress_admintab.zone_admin_auths));
4771 return;
4772 default:
4773 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4774 B_TRUE);
4775 long_usage(CMD_SET, B_TRUE);
4776 usage(B_FALSE, HELP_PROPS);
4777 return;
4778 }
4779 default:
4780 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4781 long_usage(CMD_SET, B_TRUE);
4782 usage(B_FALSE, HELP_RESOURCES);
4783 return;
4784 }
4785 }
4786
4787 static void
4788 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4789 {
4790 char *qstr;
4791
4792 if (*pval != '\0') {
4793 qstr = quoteit(pval);
4794 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4795 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4796 qstr);
4797 else
4798 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
5373
5374 bzero(&lookup, sizeof (lookup));
5375 res1 = zonecfg_getmcapent(handle, &lookup);
5376 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5377 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5378 &locked_limit);
5379
5380 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5381 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5382 }
5383
5384 static void
5385 output_auth(FILE *fp, struct zone_admintab *admintab)
5386 {
5387 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5388 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5389 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5390 }
5391
5392 static void
5393 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5394 {
5395 struct zone_admintab lookup, user;
5396 boolean_t output = B_FALSE;
5397 int err;
5398
5399 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5400 zone_perror(zone, err, B_TRUE);
5401 return;
5402 }
5403 while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5404 if (cmd->cmd_prop_nv_pairs == 0) {
5405 output_auth(fp, &lookup);
5406 continue;
5407 }
5408 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5409 continue;
5410 if (strlen(user.zone_admin_user) > 0 &&
5411 strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5412 continue; /* no match */
5413 output_auth(fp, &lookup);
5414 output = B_TRUE;
5415 }
5416 (void) zonecfg_endadminent(handle);
5417 /*
5418 * If a property n/v pair was specified, warn the user if there was
5419 * nothing to output.
5420 */
5421 if (!output && cmd->cmd_prop_nv_pairs > 0)
5422 (void) printf(gettext("No such %s resource.\n"),
5423 rt_to_str(RT_ADMIN));
5424 }
5425
5426 void
5427 info_func(cmd_t *cmd)
5428 {
5429 FILE *fp = stdout;
5430 boolean_t need_to_close = B_FALSE;
5431 int type;
5432 int res1, res2;
5433 uint64_t swap_limit;
5434 uint64_t locked_limit;
5435
5436 assert(cmd != NULL);
5437
5438 if (initialize(B_TRUE) != Z_OK)
5439 return;
5440
5441 /* don't page error output */
5442 if (interactive_mode) {
5443 if ((fp = pager_open()) != NULL)
5444 need_to_close = B_TRUE;
5445 else
5468 case RT_DATASET:
5469 output_ds(fp, &in_progress_dstab);
5470 break;
5471 case RT_DCPU:
5472 output_pset(fp, &in_progress_psettab);
5473 break;
5474 case RT_PCAP:
5475 output_pcap(fp);
5476 break;
5477 case RT_MCAP:
5478 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5479 &swap_limit);
5480 res2 = zonecfg_get_aliased_rctl(handle,
5481 ALIAS_MAXLOCKEDMEM, &locked_limit);
5482 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5483 res2, locked_limit);
5484 break;
5485 case RT_ADMIN:
5486 output_auth(fp, &in_progress_admintab);
5487 break;
5488 }
5489 goto cleanup;
5490 }
5491
5492 type = cmd->cmd_res_type;
5493
5494 if (gz_invalid_rt_property(type)) {
5495 zerr(gettext("%s is not a valid property for the global zone."),
5496 rt_to_str(type));
5497 goto cleanup;
5498 }
5499
5500 if (gz_invalid_resource(type)) {
5501 zerr(gettext("%s is not a valid resource for the global zone."),
5502 rt_to_str(type));
5503 goto cleanup;
5504 }
5505
5506 switch (cmd->cmd_res_type) {
5507 case RT_UNKNOWN:
5524 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5525 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5526 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5527 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5528 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5529 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5530 if (!global_zone) {
5531 info_fs(handle, fp, cmd);
5532 info_net(handle, fp, cmd);
5533 info_dev(handle, fp, cmd);
5534 }
5535 info_pset(handle, fp);
5536 info_pcap(fp);
5537 info_mcap(handle, fp);
5538 if (!global_zone) {
5539 info_attr(handle, fp, cmd);
5540 info_ds(handle, fp, cmd);
5541 info_auth(handle, fp, cmd);
5542 }
5543 info_rctl(handle, fp, cmd);
5544 break;
5545 case RT_ZONENAME:
5546 info_zonename(handle, fp);
5547 break;
5548 case RT_ZONEPATH:
5549 info_zonepath(handle, fp);
5550 break;
5551 case RT_BRAND:
5552 info_brand(handle, fp);
5553 break;
5554 case RT_AUTOBOOT:
5555 info_autoboot(handle, fp);
5556 break;
5557 case RT_POOL:
5558 info_pool(handle, fp);
5559 break;
5560 case RT_LIMITPRIV:
5561 info_limitpriv(handle, fp);
5562 break;
5563 case RT_BOOTARGS:
5609 info_ds(handle, fp, cmd);
5610 break;
5611 case RT_DCPU:
5612 info_pset(handle, fp);
5613 break;
5614 case RT_PCAP:
5615 info_pcap(fp);
5616 break;
5617 case RT_MCAP:
5618 info_mcap(handle, fp);
5619 break;
5620 case RT_HOSTID:
5621 info_hostid(handle, fp);
5622 break;
5623 case RT_ADMIN:
5624 info_auth(handle, fp, cmd);
5625 break;
5626 case RT_FS_ALLOWED:
5627 info_fs_allowed(handle, fp);
5628 break;
5629 default:
5630 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5631 B_TRUE);
5632 }
5633
5634 cleanup:
5635 if (need_to_close)
5636 (void) pager_close(fp);
5637 }
5638
5639 /*
5640 * Helper function for verify-- checks that a required string property
5641 * exists.
5642 */
5643 static void
5644 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5645 {
5646 if (strlen(attr) == 0) {
5647 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5648 pt_to_str(pt));
5760 tmp->xif_has_defrouter = B_TRUE;
5761 return (B_TRUE);
5762 }
5763 }
5764
5765 tmp = malloc(sizeof (*tmp));
5766 if (tmp == NULL) {
5767 zerr(gettext("memory allocation failed for %s"),
5768 nwif->zone_nwif_physical);
5769 return (B_FALSE);
5770 }
5771 strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5772 sizeof (tmp->xif_name));
5773 tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5774 tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5775 tmp->xif_next = xif;
5776 xif = tmp;
5777 return (B_TRUE);
5778 }
5779
5780 /*
5781 * See the DTD for which attributes are required for which resources.
5782 *
5783 * This function can be called by commit_func(), which needs to save things,
5784 * in addition to the general call from parse_and_run(), which doesn't need
5785 * things saved. Since the parameters are standardized, we distinguish by
5786 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
5787 * that a save is needed.
5788 */
5789 void
5790 verify_func(cmd_t *cmd)
5791 {
5792 struct zone_nwiftab nwiftab;
5793 struct zone_fstab fstab;
5794 struct zone_attrtab attrtab;
5795 struct zone_rctltab rctltab;
5796 struct zone_dstab dstab;
5797 struct zone_psettab psettab;
5798 struct zone_admintab admintab;
5799 char zonepath[MAXPATHLEN];
5800 char sched[MAXNAMELEN];
5801 char brand[MAXNAMELEN];
5802 char hostidp[HW_HOSTID_LEN];
5803 char fsallowedp[ZONE_FS_ALLOWED_MAX];
5804 priv_set_t *privs;
5805 char *privname = NULL;
5806 int err, ret_val = Z_OK, arg;
5807 int pset_res;
5808 boolean_t save = B_FALSE;
5809 boolean_t arg_err = B_FALSE;
5810 zone_iptype_t iptype;
5811 boolean_t has_cpu_shares = B_FALSE;
5812 boolean_t has_cpu_cap = B_FALSE;
5813 struct xif *tmp;
5814
5815 optind = 0;
5816 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
5817 switch (arg) {
5818 case '?':
6075 }
6076 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6077 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6078 PT_USER, &ret_val);
6079 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6080 PT_AUTHS, &ret_val);
6081 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6082 == NULL)) {
6083 zerr(gettext("%s %s is not a valid username"),
6084 pt_to_str(PT_USER),
6085 admintab.zone_admin_user);
6086 ret_val = Z_BAD_PROPERTY;
6087 }
6088 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6089 admintab.zone_admin_auths, zone))) {
6090 ret_val = Z_BAD_PROPERTY;
6091 }
6092 }
6093 (void) zonecfg_endadminent(handle);
6094
6095 if (!global_scope) {
6096 zerr(gettext("resource specification incomplete"));
6097 saw_error = B_TRUE;
6098 if (ret_val == Z_OK)
6099 ret_val = Z_INSUFFICIENT_SPEC;
6100 }
6101
6102 if (save) {
6103 if (ret_val == Z_OK) {
6104 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6105 need_to_commit = B_FALSE;
6106 (void) strlcpy(revert_zone, zone,
6107 sizeof (revert_zone));
6108 }
6109 } else {
6110 zerr(gettext("Zone %s failed to verify"), zone);
6111 }
6112 }
6113 if (ret_val != Z_OK)
6114 zone_perror(zone, ret_val, B_TRUE);
6664 sizeof (tmp_admintab.zone_admin_user));
6665 err = zonecfg_lookup_admin(
6666 handle, &tmp_admintab);
6667 if (err == Z_OK) {
6668 zerr(gettext("A %s resource "
6669 "with the %s '%s' already exists."),
6670 rt_to_str(RT_ADMIN),
6671 pt_to_str(PT_USER),
6672 in_progress_admintab.zone_admin_user);
6673 saw_error = B_TRUE;
6674 return;
6675 }
6676 err = zonecfg_add_admin(handle,
6677 &in_progress_admintab, zone);
6678 } else {
6679 err = zonecfg_modify_admin(handle,
6680 &old_admintab, &in_progress_admintab,
6681 zone);
6682 }
6683 break;
6684 default:
6685 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
6686 B_TRUE);
6687 saw_error = B_TRUE;
6688 return;
6689 }
6690
6691 if (err != Z_OK) {
6692 zone_perror(zone, err, B_TRUE);
6693 } else {
6694 need_to_commit = B_TRUE;
6695 global_scope = B_TRUE;
6696 end_op = -1;
6697 }
6698 }
6699
6700 void
6701 commit_func(cmd_t *cmd)
6702 {
6703 int arg;
|
36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
45 *
46 * The rest of this module consists of the various function handlers and
47 * their helper functions. Some of these functions, particularly the
48 * X_to_str() functions, which maps command, resource and property numbers
49 * to strings, are used quite liberally, as doing so results in a better
50 * program w/rt I18N, reducing the need for translation notes.
51 */
52
53 #include <sys/mntent.h>
54 #include <sys/varargs.h>
55 #include <sys/sysmacros.h>
56 #include <sys/secflags.h>
57
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <strings.h>
61 #include <unistd.h>
62 #include <ctype.h>
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>
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 "security-flags",
192 NULL
193 };
194
195 /* These *must* match the order of the PT_ define's from zonecfg.h */
196 char *prop_types[] = {
197 "unknown",
198 "zonename",
199 "zonepath",
200 "autoboot",
201 "pool",
202 "dir",
203 "special",
204 "type",
205 "options",
206 "address",
207 "physical",
208 "name",
209 "value",
210 "match",
211 "priv",
219 "importance",
220 "swap",
221 "locked",
222 ALIAS_SHARES,
223 ALIAS_MAXLWPS,
224 ALIAS_MAXSHMMEM,
225 ALIAS_MAXSHMIDS,
226 ALIAS_MAXMSGIDS,
227 ALIAS_MAXSEMIDS,
228 ALIAS_MAXLOCKEDMEM,
229 ALIAS_MAXSWAP,
230 "scheduling-class",
231 "ip-type",
232 "defrouter",
233 "hostid",
234 "user",
235 "auths",
236 "fs-allowed",
237 ALIAS_MAXPROCS,
238 "allowed-address",
239 "default",
240 "lower",
241 "upper",
242 NULL
243 };
244
245 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
246 static char *prop_val_types[] = {
247 "simple",
248 "complex",
249 "list",
250 };
251
252 /*
253 * The various _cmds[] lists below are for command tab-completion.
254 */
255
256 /*
257 * remove has a space afterwards because it has qualifiers; the other commands
258 * that have qualifiers (add, select, etc.) don't need a space here because
259 * they have their own _cmds[] lists below.
260 */
261 static const char *global_scope_cmds[] = {
270 "info",
271 "remove ",
272 "revert",
273 "select",
274 "set",
275 "verify",
276 NULL
277 };
278
279 static const char *add_cmds[] = {
280 "add fs",
281 "add net",
282 "add device",
283 "add rctl",
284 "add attr",
285 "add dataset",
286 "add dedicated-cpu",
287 "add capped-cpu",
288 "add capped-memory",
289 "add admin",
290 "add security-flags",
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 "remove security-flags",
323 NULL
324 };
325
326 static const char *select_cmds[] = {
327 "select fs ",
328 "select net ",
329 "select device ",
330 "select rctl ",
331 "select attr ",
332 "select dataset ",
333 "select dedicated-cpu",
334 "select capped-cpu",
335 "select capped-memory",
336 "select admin",
337 "select security-flags",
338 NULL
339 };
340
341 static const char *set_cmds[] = {
342 "set zonename=",
343 "set zonepath=",
344 "set brand=",
345 "set autoboot=",
346 "set pool=",
347 "set limitpriv=",
348 "set bootargs=",
349 "set scheduling-class=",
350 "set ip-type=",
351 "set " ALIAS_MAXLWPS "=",
352 "set " ALIAS_MAXSHMMEM "=",
353 "set " ALIAS_MAXSHMIDS "=",
354 "set " ALIAS_MAXMSGIDS "=",
355 "set " ALIAS_MAXSEMIDS "=",
356 "set " ALIAS_SHARES "=",
357 "set hostid=",
358 "set fs-allowed=",
359 "set " ALIAS_MAXPROCS "=",
360 NULL
361 };
362
363 static const char *info_cmds[] = {
364 "info fs ",
365 "info net ",
366 "info device ",
367 "info rctl ",
368 "info attr ",
369 "info dataset ",
370 "info capped-memory",
371 "info dedicated-cpu",
372 "info capped-cpu",
373 "info security-flags",
374 "info zonename",
375 "info zonepath",
376 "info autoboot",
377 "info pool",
378 "info limitpriv",
379 "info bootargs",
380 "info brand",
381 "info scheduling-class",
382 "info ip-type",
383 "info max-lwps",
384 "info max-shm-memory",
385 "info max-shm-ids",
386 "info max-msg-ids",
387 "info max-sem-ids",
388 "info cpu-shares",
389 "info hostid",
390 "info admin",
391 "info fs-allowed",
392 "info max-processes",
393 NULL
496 "set physical=",
497 "set swap=",
498 "set locked=",
499 "clear physical",
500 "clear swap",
501 "clear locked",
502 NULL
503 };
504
505 static const char *admin_res_scope_cmds[] = {
506 "cancel",
507 "end",
508 "exit",
509 "help",
510 "info",
511 "set user=",
512 "set auths=",
513 NULL
514 };
515
516 static const char *secflags_res_scope_cmds[] = {
517 "cancel",
518 "end",
519 "exit",
520 "set default=",
521 "set lower=",
522 "set upper=",
523 NULL
524 };
525
526 struct xif {
527 struct xif *xif_next;
528 char xif_name[LIFNAMSIZ];
529 boolean_t xif_has_address;
530 boolean_t xif_has_defrouter;
531 };
532
533 /* Global variables */
534
535 /* list of network interfaces specified for exclusive IP zone */
536 struct xif *xif;
537
538 /* set early in main(), never modified thereafter, used all over the place */
539 static char *execname;
540
541 /* set in main(), used all over the place */
542 static zone_dochandle_t handle;
543
544 /* used all over the place */
545 static char zone[ZONENAME_MAX];
583 static boolean_t global_scope = B_TRUE;
584 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
585 static int end_op = -1; /* operation on end is either add or modify */
586
587 int num_prop_vals; /* for grammar */
588
589 /*
590 * These are for keeping track of resources as they are specified as part of
591 * the multi-step process. They should be initialized by add_resource() or
592 * select_func() and filled in by add_property() or set_func().
593 */
594 static struct zone_fstab old_fstab, in_progress_fstab;
595 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
596 static struct zone_devtab old_devtab, in_progress_devtab;
597 static struct zone_rctltab old_rctltab, in_progress_rctltab;
598 static struct zone_attrtab old_attrtab, in_progress_attrtab;
599 static struct zone_dstab old_dstab, in_progress_dstab;
600 static struct zone_psettab old_psettab, in_progress_psettab;
601 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
602 static struct zone_admintab old_admintab, in_progress_admintab;
603 static struct zone_secflagstab old_secflagstab, in_progress_secflagstab;
604
605 static GetLine *gl; /* The gl_get_line() resource object */
606
607 static void bytes_to_units(char *str, char *buf, int bufsize);
608
609 /* Functions begin here */
610
611 static boolean_t
612 initial_match(const char *line1, const char *line2, int word_end)
613 {
614 if (word_end <= 0)
615 return (B_TRUE);
616 return (strncmp(line1, line2, word_end) == 0);
617 }
618
619 static int
620 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
621 int word_end)
622 {
623 int i, err;
661 case RT_FS:
662 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
663 case RT_NET:
664 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
665 case RT_DEVICE:
666 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
667 case RT_RCTL:
668 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
669 case RT_ATTR:
670 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
671 case RT_DATASET:
672 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
673 case RT_DCPU:
674 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
675 case RT_PCAP:
676 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
677 case RT_MCAP:
678 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
679 case RT_ADMIN:
680 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
681 case RT_SECFLAGS:
682 return (add_stuff(cpl, line, secflags_res_scope_cmds,
683 word_end));
684
685 }
686 return (0);
687 }
688
689 /*
690 * For the main CMD_func() functions below, several of them call getopt()
691 * then check optind against argc to make sure an extra parameter was not
692 * passed in. The reason this is not caught in the grammar is that the
693 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
694 * be "-F" (for example), but could be anything. So (for example) this
695 * check will prevent "create bogus".
696 */
697
698 cmd_t *
699 alloc_cmd(void)
700 {
701 return (calloc(1, sizeof (cmd_t)));
702 }
703
704 void
980 if ((pathstr = getenv("PATH")) == NULL) {
981 if (geteuid() == 0 || getuid() == 0)
982 pathstr = "/usr/sbin:/usr/bin";
983 else
984 pathstr = "/usr/bin:";
985 }
986 cp = strchr(name, '/') ? (const char *) "" : pathstr;
987
988 do {
989 cp = exec_cat(cp, name, fname);
990 if (stat(fname, &stat_buf) != -1) {
991 /* successful find of the file */
992 return (0);
993 }
994 } while (cp != NULL);
995
996 return (-1);
997 }
998
999 static FILE *
1000 pager_open(void)
1001 {
1002 FILE *newfp;
1003 char *pager, *space;
1004
1005 pager = getenv("PAGER");
1006 if (pager == NULL || *pager == '\0')
1007 pager = PAGER;
1008
1009 space = strchr(pager, ' ');
1010 if (space)
1011 *space = '\0';
1012 if (path_find(pager) == 0) {
1013 if (space)
1014 *space = ' ';
1015 if ((newfp = popen(pager, "w")) == NULL)
1016 zerr(gettext("PAGER open failed (%s)."),
1017 strerror(errno));
1018 return (newfp);
1019 } else {
1020 zerr(gettext("PAGER %s does not exist (%s)."),
1021 pager, strerror(errno));
1022 }
1023 return (NULL);
1024 }
1025
1026 static void
1027 pager_close(FILE *fp)
1028 {
1029 int status;
1030
1031 status = pclose(fp);
1032 if (status == -1)
1033 zerr(gettext("PAGER close failed (%s)."),
1034 strerror(errno));
1035 }
1036
1037 /*
1038 * Called with verbose TRUE when help is explicitly requested, FALSE for
1039 * unexpected errors.
1040 */
1041
1042 void
1043 usage(boolean_t verbose, uint_t flags)
1044 {
1045 FILE *fp = verbose ? stdout : stderr;
1046 FILE *newfp;
1047 boolean_t need_to_close = B_FALSE;
1048 int i;
1236 pt_to_str(PT_SWAP),
1237 gettext("<qualified unsigned decimal>"));
1238 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1239 pt_to_str(PT_LOCKED),
1240 gettext("<qualified unsigned decimal>"));
1241 break;
1242 case RT_ADMIN:
1243 (void) fprintf(fp, gettext("The '%s' resource scope is "
1244 "used to delegate specific zone management\n"
1245 "rights to users and roles. These rights are "
1246 "only applicable to this zone.\n"),
1247 rt_to_str(resource_scope));
1248 (void) fprintf(fp, gettext("Valid commands:\n"));
1249 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1250 pt_to_str(PT_USER),
1251 gettext("<single user or role name>"));
1252 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1253 pt_to_str(PT_AUTHS),
1254 gettext("<comma separated list>"));
1255 break;
1256 case RT_SECFLAGS:
1257 (void) fprintf(fp, gettext("The '%s' resource scope is "
1258 "used to specify the default security-flags\n"
1259 "of this zone, and their upper and lower bound.\n"),
1260 rt_to_str(resource_scope));
1261 (void) fprintf(fp, "\t%s %s=%s\n",
1262 cmd_to_str(CMD_SET), pt_to_str(PT_DEFAULT),
1263 gettext("<security flags>"));
1264 (void) fprintf(fp, "\t%s %s=%s\n",
1265 cmd_to_str(CMD_SET), pt_to_str(PT_LOWER),
1266 gettext("<security flags>"));
1267 (void) fprintf(fp, "\t%s %s=%s\n",
1268 cmd_to_str(CMD_SET), pt_to_str(PT_UPPER),
1269 gettext("<security flags>"));
1270 break;
1271 }
1272 (void) fprintf(fp, gettext("And from any resource scope, you "
1273 "can:\n"));
1274 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1275 gettext("(to conclude this operation)"));
1276 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1277 gettext("(to cancel this operation)"));
1278 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1279 gettext("(to exit the zonecfg utility)"));
1280 }
1281 if (flags & HELP_USAGE) {
1282 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1283 execname, cmd_to_str(CMD_HELP));
1284 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1285 execname, gettext("interactive"));
1286 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1287 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1288 execname);
1289 }
1290 if (flags & HELP_SUBCMDS) {
1315 (void) fprintf(fp,
1316 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1317 (void) fprintf(fp,
1318 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1319 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1320 "IPv6 address syntax.\n"));
1321 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1322 (void) fprintf(fp,
1323 gettext("<IPv6-prefix-length> := [0-128]\n"));
1324 (void) fprintf(fp,
1325 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1326 }
1327 if (flags & HELP_RESOURCES) {
1328 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1329 "%s | %s | %s | %s | %s\n\n",
1330 gettext("resource type"), rt_to_str(RT_FS),
1331 rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1332 rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1333 rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1334 rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1335 rt_to_str(RT_ADMIN), rt_to_str(RT_SECFLAGS));
1336 }
1337 if (flags & HELP_PROPS) {
1338 (void) fprintf(fp, gettext("For resource type ... there are "
1339 "property types ...:\n"));
1340 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1341 pt_to_str(PT_ZONENAME));
1342 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1343 pt_to_str(PT_ZONEPATH));
1344 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1345 pt_to_str(PT_BRAND));
1346 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1347 pt_to_str(PT_AUTOBOOT));
1348 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1349 pt_to_str(PT_BOOTARGS));
1350 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1351 pt_to_str(PT_POOL));
1352 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1353 pt_to_str(PT_LIMITPRIV));
1354 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1355 pt_to_str(PT_SCHED));
1381 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1382 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1383 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1384 pt_to_str(PT_MATCH));
1385 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1386 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1387 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1388 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1389 pt_to_str(PT_VALUE));
1390 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1391 pt_to_str(PT_NAME));
1392 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1393 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1394 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1395 pt_to_str(PT_NCPUS));
1396 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1397 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1398 pt_to_str(PT_LOCKED));
1399 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1400 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1401 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n",
1402 rt_to_str(RT_SECFLAGS), pt_to_str(PT_DEFAULT),
1403 pt_to_str(PT_LOWER), pt_to_str(PT_UPPER));
1404 }
1405 if (need_to_close)
1406 (void) pager_close(fp);
1407 }
1408
1409 static void
1410 zone_perror(char *prefix, int err, boolean_t set_saw)
1411 {
1412 zerr("%s: %s", prefix, zonecfg_strerror(err));
1413 if (set_saw)
1414 saw_error = B_TRUE;
1415 }
1416
1417 /*
1418 * zone_perror() expects a single string, but for remove and select
1419 * we have both the command and the resource type, so this wrapper
1420 * function serves the same purpose in a slightly different way.
1421 */
1422
1423 static void
1827 return;
1828 quote_str = quoteit(prop_id);
1829 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1830 pt_to_str(prop_num), quote_str);
1831 free(quote_str);
1832 }
1833
1834 void
1835 export_func(cmd_t *cmd)
1836 {
1837 struct zone_nwiftab nwiftab;
1838 struct zone_fstab fstab;
1839 struct zone_devtab devtab;
1840 struct zone_attrtab attrtab;
1841 struct zone_rctltab rctltab;
1842 struct zone_dstab dstab;
1843 struct zone_psettab psettab;
1844 struct zone_mcaptab mcaptab;
1845 struct zone_rctlvaltab *valptr;
1846 struct zone_admintab admintab;
1847 struct zone_secflagstab secflagstab;
1848 int err, arg;
1849 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1850 char bootargs[BOOTARGS_MAX];
1851 char sched[MAXNAMELEN];
1852 char brand[MAXNAMELEN];
1853 char hostidp[HW_HOSTID_LEN];
1854 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1855 char *limitpriv;
1856 FILE *of;
1857 boolean_t autoboot;
1858 zone_iptype_t iptype;
1859 boolean_t need_to_close = B_FALSE;
1860 boolean_t arg_err = B_FALSE;
1861
1862 assert(cmd != NULL);
1863
1864 outfile[0] = '\0';
1865 optind = 0;
1866 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1867 switch (arg) {
2097 (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
2098 pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
2099 psettab.zone_ncpu_max);
2100 if (psettab.zone_importance[0] != '\0')
2101 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2102 pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
2103 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2104 }
2105
2106 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
2107 zone_perror(zone, err, B_FALSE);
2108 goto done;
2109 }
2110 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
2111 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2112 rt_to_str(RT_ADMIN));
2113 export_prop(of, PT_USER, admintab.zone_admin_user);
2114 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
2115 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2116 }
2117
2118 (void) zonecfg_endadminent(handle);
2119
2120 if (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
2121 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2122 rt_to_str(RT_SECFLAGS));
2123 export_prop(of, PT_DEFAULT, secflagstab.zone_secflags_default);
2124 export_prop(of, PT_LOWER, secflagstab.zone_secflags_lower);
2125 export_prop(of, PT_UPPER, secflagstab.zone_secflags_upper);
2126 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2127 }
2128
2129 /*
2130 * There is nothing to export for pcap since this resource is just
2131 * a container for an rctl alias.
2132 */
2133
2134 done:
2135 if (need_to_close)
2136 (void) fclose(of);
2137 }
2138
2139 void
2140 exit_func(cmd_t *cmd)
2141 {
2142 int arg, answer;
2143 boolean_t arg_err = B_FALSE;
2144
2145 optind = 0;
2146 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2147 switch (arg) {
2148 case '?':
2188 {
2189 if (path[0] != '/') {
2190 zerr(gettext("%s is not an absolute path."), path);
2191 return (Z_ERR);
2192 }
2193 /* If path is all slashes, then fail */
2194 if (strspn(path, "/") == strlen(path)) {
2195 zerr(gettext("/ is not allowed as a %s."),
2196 pt_to_str(PT_ZONEPATH));
2197 return (Z_ERR);
2198 }
2199 return (Z_OK);
2200 }
2201
2202 static void
2203 add_resource(cmd_t *cmd)
2204 {
2205 int type;
2206 struct zone_psettab tmp_psettab;
2207 struct zone_mcaptab tmp_mcaptab;
2208 struct zone_secflagstab tmp_secflagstab;
2209 uint64_t tmp;
2210 uint64_t tmp_mcap;
2211 char pool[MAXNAMELEN];
2212
2213 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2214 long_usage(CMD_ADD, B_TRUE);
2215 goto bad;
2216 }
2217
2218 switch (type) {
2219 case RT_FS:
2220 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2221 return;
2222 case RT_NET:
2223 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2224 return;
2225 case RT_DEVICE:
2226 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2227 return;
2228 case RT_RCTL:
2300 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2301 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2302 == Z_OK ||
2303 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2304 &tmp_mcap) == Z_OK) {
2305 zerr(gettext("The %s resource or a related resource "
2306 "control already exists."), rt_to_str(RT_MCAP));
2307 goto bad;
2308 }
2309 if (global_zone)
2310 zerr(gettext("WARNING: Setting a global zone memory "
2311 "cap too low could deny\nservice "
2312 "to even the root user; "
2313 "this could render the system impossible\n"
2314 "to administer. Please use caution."));
2315 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2316 return;
2317 case RT_ADMIN:
2318 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2319 return;
2320 case RT_SECFLAGS:
2321 /* Make sure we haven't already set this */
2322 if (zonecfg_lookup_secflags(handle, &tmp_secflagstab) == Z_OK)
2323 zerr(gettext("The %s resource already exists."),
2324 rt_to_str(RT_SECFLAGS));
2325 bzero(&in_progress_secflagstab,
2326 sizeof (in_progress_secflagstab));
2327 return;
2328 default:
2329 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2330 long_usage(CMD_ADD, B_TRUE);
2331 usage(B_FALSE, HELP_RESOURCES);
2332 }
2333 bad:
2334 global_scope = B_TRUE;
2335 end_op = -1;
2336 }
2337
2338 static void
2339 do_complex_rctl_val(complex_property_ptr_t cp)
2340 {
2341 struct zone_rctlvaltab *rctlvaltab;
2342 complex_property_ptr_t cx;
2343 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2344 seen_action = B_FALSE;
2345 rctlblk_t *rctlblk;
2346 int err;
2347
2977 case PT_USER:
2978 (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2979 sizeof (admintab->zone_admin_user));
2980 break;
2981 case PT_AUTHS:
2982 (void) strlcpy(admintab->zone_admin_auths,
2983 pp->pv_simple, sizeof (admintab->zone_admin_auths));
2984 break;
2985 default:
2986 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2987 Z_NO_PROPERTY_TYPE, B_TRUE);
2988 return (Z_INSUFFICIENT_SPEC);
2989 }
2990 }
2991 if (fill_in_only)
2992 return (Z_OK);
2993 err = zonecfg_lookup_admin(handle, admintab);
2994 return (err);
2995 }
2996
2997 static int
2998 fill_in_secflagstab(cmd_t *cmd, struct zone_secflagstab *secflagstab,
2999 boolean_t fill_in_only)
3000 {
3001 int err, i;
3002 property_value_ptr_t pp;
3003
3004 if ((err = initialize(B_TRUE)) != Z_OK)
3005 return (err);
3006
3007 bzero(secflagstab, sizeof (*secflagstab));
3008 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
3009 pp = cmd->cmd_property_ptr[i];
3010 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
3011 zerr(gettext("A simple value was expected here."));
3012 saw_error = B_TRUE;
3013 return (Z_INSUFFICIENT_SPEC);
3014 }
3015 switch (cmd->cmd_prop_name[i]) {
3016 case PT_DEFAULT:
3017 (void) strlcpy(secflagstab->zone_secflags_default,
3018 pp->pv_simple,
3019 sizeof (secflagstab->zone_secflags_default));
3020 break;
3021 case PT_LOWER:
3022 (void) strlcpy(secflagstab->zone_secflags_lower,
3023 pp->pv_simple,
3024 sizeof (secflagstab->zone_secflags_lower));
3025 break;
3026 case PT_UPPER:
3027 (void) strlcpy(secflagstab->zone_secflags_upper,
3028 pp->pv_simple,
3029 sizeof (secflagstab->zone_secflags_upper));
3030 break;
3031 default:
3032 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3033 Z_NO_PROPERTY_TYPE, B_TRUE);
3034 return (Z_INSUFFICIENT_SPEC);
3035 }
3036 }
3037 if (fill_in_only)
3038 return (Z_OK);
3039
3040 err = zonecfg_lookup_secflags(handle, secflagstab);
3041
3042 return (err);
3043 }
3044
3045 static void
3046 remove_aliased_rctl(int type, char *name)
3047 {
3048 int err;
3049 uint64_t tmp;
3050
3051 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
3052 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3053 zonecfg_strerror(err));
3054 saw_error = B_TRUE;
3055 return;
3056 }
3057 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
3058 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3059 zonecfg_strerror(err));
3060 saw_error = B_TRUE;
3061 } else {
3062 need_to_commit = B_TRUE;
3063 }
3064 }
3427 return;
3428 } else {
3429 /*
3430 * unqualified admin removal.
3431 * remove all admins but prompt if more
3432 * than one.
3433 */
3434 if (!prompt_remove_resource(cmd, "admin"))
3435 return;
3436
3437 if ((err = zonecfg_delete_admins(handle, zone))
3438 != Z_OK)
3439 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3440 err, B_TRUE);
3441 else
3442 need_to_commit = B_TRUE;
3443 }
3444 }
3445
3446 static void
3447 remove_secflags()
3448 {
3449 int err;
3450 struct zone_secflagstab sectab = { 0 };
3451
3452 if (zonecfg_lookup_secflags(handle, §ab) != Z_OK) {
3453 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3454 rt_to_str(RT_SECFLAGS),
3455 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3456 return;
3457 }
3458
3459 if ((err = zonecfg_delete_secflags(handle, §ab)) != Z_OK) {
3460 z_cmd_rt_perror(CMD_REMOVE, RT_SECFLAGS, err, B_TRUE);
3461 return;
3462 }
3463
3464 need_to_commit = B_TRUE;
3465 }
3466
3467 static void
3468 remove_resource(cmd_t *cmd)
3469 {
3470 int type;
3471 int arg;
3472 boolean_t arg_err = B_FALSE;
3473
3474 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3475 long_usage(CMD_REMOVE, B_TRUE);
3476 return;
3477 }
3478
3479 optind = 0;
3480 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3481 switch (arg) {
3482 case '?':
3483 longer_usage(CMD_REMOVE);
3484 arg_err = B_TRUE;
3485 break;
3486 case 'F':
3487 break;
3511 remove_rctl(cmd);
3512 return;
3513 case RT_ATTR:
3514 remove_attr(cmd);
3515 return;
3516 case RT_DATASET:
3517 remove_dataset(cmd);
3518 return;
3519 case RT_DCPU:
3520 remove_pset();
3521 return;
3522 case RT_PCAP:
3523 remove_pcap();
3524 return;
3525 case RT_MCAP:
3526 remove_mcap();
3527 return;
3528 case RT_ADMIN:
3529 remove_admin(cmd);
3530 return;
3531 case RT_SECFLAGS:
3532 remove_secflags();
3533 return;
3534 default:
3535 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3536 long_usage(CMD_REMOVE, B_TRUE);
3537 usage(B_FALSE, HELP_RESOURCES);
3538 return;
3539 }
3540 }
3541
3542 static void
3543 remove_property(cmd_t *cmd)
3544 {
3545 char *prop_id;
3546 int err, res_type, prop_type;
3547 property_value_ptr_t pp;
3548 struct zone_rctlvaltab *rctlvaltab;
3549 complex_property_ptr_t cx;
3550
3551 res_type = resource_scope;
3552 prop_type = cmd->cmd_prop_name[0];
3553 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3726 if (prop_type == PT_IMPORTANCE) {
3727 in_progress_psettab.zone_importance[0] = '\0';
3728 need_to_commit = B_TRUE;
3729 return;
3730 }
3731 break;
3732 case RT_MCAP:
3733 switch (prop_type) {
3734 case PT_PHYSICAL:
3735 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3736 need_to_commit = B_TRUE;
3737 return;
3738 case PT_SWAP:
3739 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3740 return;
3741 case PT_LOCKED:
3742 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3743 return;
3744 }
3745 break;
3746 case RT_SECFLAGS:
3747 switch (prop_type) {
3748 case PT_LOWER:
3749 in_progress_secflagstab.zone_secflags_lower[0] = '\0';
3750 need_to_commit = B_TRUE;
3751 return;
3752 case PT_DEFAULT:
3753 in_progress_secflagstab.zone_secflags_default[0] = '\0';
3754 need_to_commit = B_TRUE;
3755 return;
3756 case PT_UPPER:
3757 in_progress_secflagstab.zone_secflags_upper[0] = '\0';
3758 need_to_commit = B_TRUE;
3759 return;
3760 }
3761 break;
3762 default:
3763 break;
3764 }
3765
3766 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3767 }
3768
3769 static void
3770 clear_global(cmd_t *cmd)
3771 {
3772 int err, type;
3773
3774 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3775 long_usage(CMD_CLEAR, B_TRUE);
3776 return;
3777 }
3778
3779 if (initialize(B_TRUE) != Z_OK)
3780 return;
3781
3995 B_TRUE);
3996 global_scope = B_TRUE;
3997 }
3998 if (res == Z_OK)
3999 bcopy(&old_mcaptab, &in_progress_mcaptab,
4000 sizeof (struct zone_mcaptab));
4001 else
4002 bzero(&in_progress_mcaptab,
4003 sizeof (in_progress_mcaptab));
4004 return;
4005 case RT_ADMIN:
4006 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
4007 != Z_OK) {
4008 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
4009 B_TRUE);
4010 global_scope = B_TRUE;
4011 }
4012 bcopy(&old_admintab, &in_progress_admintab,
4013 sizeof (struct zone_admintab));
4014 return;
4015 case RT_SECFLAGS:
4016 if ((err = fill_in_secflagstab(cmd, &old_secflagstab, B_FALSE))
4017 != Z_OK) {
4018 z_cmd_rt_perror(CMD_SELECT, RT_SECFLAGS, err,
4019 B_TRUE);
4020 global_scope = B_TRUE;
4021 }
4022 bcopy(&old_secflagstab, &in_progress_secflagstab,
4023 sizeof (struct zone_secflagstab));
4024 return;
4025 default:
4026 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
4027 long_usage(CMD_SELECT, B_TRUE);
4028 usage(B_FALSE, HELP_RESOURCES);
4029 return;
4030 }
4031 }
4032
4033 /*
4034 * Network "addresses" can be one of the following forms:
4035 * <IPv4 address>
4036 * <IPv4 address>/<prefix length>
4037 * <IPv6 address>/<prefix length>
4038 * <host name>
4039 * <host name>/<prefix length>
4040 * In other words, the "/" followed by a prefix length is allowed but not
4041 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4042 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4043 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4044 * Host names must start with an alpha-numeric character, and all subsequent
4921 return;
4922 case RT_ADMIN:
4923 switch (prop_type) {
4924 case PT_USER:
4925 (void) strlcpy(in_progress_admintab.zone_admin_user,
4926 prop_id,
4927 sizeof (in_progress_admintab.zone_admin_user));
4928 return;
4929 case PT_AUTHS:
4930 (void) strlcpy(in_progress_admintab.zone_admin_auths,
4931 prop_id,
4932 sizeof (in_progress_admintab.zone_admin_auths));
4933 return;
4934 default:
4935 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4936 B_TRUE);
4937 long_usage(CMD_SET, B_TRUE);
4938 usage(B_FALSE, HELP_PROPS);
4939 return;
4940 }
4941 case RT_SECFLAGS: {
4942 char *propstr;
4943
4944 switch (prop_type) {
4945 case PT_DEFAULT:
4946 propstr = in_progress_secflagstab.zone_secflags_default;
4947 break;
4948 case PT_UPPER:
4949 propstr = in_progress_secflagstab.zone_secflags_upper;
4950 break;
4951 case PT_LOWER:
4952 propstr = in_progress_secflagstab.zone_secflags_lower;
4953 break;
4954 default:
4955 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4956 B_TRUE);
4957 long_usage(CMD_SET, B_TRUE);
4958 usage(B_FALSE, HELP_PROPS);
4959 return;
4960 }
4961 (void) strlcpy(propstr, prop_id, ZONECFG_SECFLAGS_MAX);
4962 return;
4963 }
4964 default:
4965 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4966 long_usage(CMD_SET, B_TRUE);
4967 usage(B_FALSE, HELP_RESOURCES);
4968 return;
4969 }
4970 }
4971
4972 static void
4973 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4974 {
4975 char *qstr;
4976
4977 if (*pval != '\0') {
4978 qstr = quoteit(pval);
4979 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4980 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4981 qstr);
4982 else
4983 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
5558
5559 bzero(&lookup, sizeof (lookup));
5560 res1 = zonecfg_getmcapent(handle, &lookup);
5561 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5562 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5563 &locked_limit);
5564
5565 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5566 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5567 }
5568
5569 static void
5570 output_auth(FILE *fp, struct zone_admintab *admintab)
5571 {
5572 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5573 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5574 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5575 }
5576
5577 static void
5578 output_secflags(FILE *fp, struct zone_secflagstab *sftab)
5579 {
5580 (void) fprintf(fp, "%s:\n", rt_to_str(RT_SECFLAGS));
5581 output_prop(fp, PT_DEFAULT, sftab->zone_secflags_default, B_TRUE);
5582 output_prop(fp, PT_LOWER, sftab->zone_secflags_lower, B_TRUE);
5583 output_prop(fp, PT_UPPER, sftab->zone_secflags_upper, B_TRUE);
5584 }
5585
5586 static void
5587 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5588 {
5589 struct zone_admintab lookup, user;
5590 boolean_t output = B_FALSE;
5591 int err;
5592
5593 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5594 zone_perror(zone, err, B_TRUE);
5595 return;
5596 }
5597 while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5598 if (cmd->cmd_prop_nv_pairs == 0) {
5599 output_auth(fp, &lookup);
5600 continue;
5601 }
5602 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5603 continue;
5604 if (strlen(user.zone_admin_user) > 0 &&
5605 strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5606 continue; /* no match */
5607 output_auth(fp, &lookup);
5608 output = B_TRUE;
5609 }
5610 (void) zonecfg_endadminent(handle);
5611 /*
5612 * If a property n/v pair was specified, warn the user if there was
5613 * nothing to output.
5614 */
5615 if (!output && cmd->cmd_prop_nv_pairs > 0)
5616 (void) printf(gettext("No such %s resource.\n"),
5617 rt_to_str(RT_ADMIN));
5618 }
5619
5620 static void
5621 info_secflags(zone_dochandle_t handle, FILE *fp)
5622 {
5623 struct zone_secflagstab sftab;
5624
5625 if (zonecfg_lookup_secflags(handle, &sftab) == Z_OK) {
5626 output_secflags(fp, &sftab);
5627 }
5628 }
5629
5630 void
5631 info_func(cmd_t *cmd)
5632 {
5633 FILE *fp = stdout;
5634 boolean_t need_to_close = B_FALSE;
5635 int type;
5636 int res1, res2;
5637 uint64_t swap_limit;
5638 uint64_t locked_limit;
5639
5640 assert(cmd != NULL);
5641
5642 if (initialize(B_TRUE) != Z_OK)
5643 return;
5644
5645 /* don't page error output */
5646 if (interactive_mode) {
5647 if ((fp = pager_open()) != NULL)
5648 need_to_close = B_TRUE;
5649 else
5672 case RT_DATASET:
5673 output_ds(fp, &in_progress_dstab);
5674 break;
5675 case RT_DCPU:
5676 output_pset(fp, &in_progress_psettab);
5677 break;
5678 case RT_PCAP:
5679 output_pcap(fp);
5680 break;
5681 case RT_MCAP:
5682 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5683 &swap_limit);
5684 res2 = zonecfg_get_aliased_rctl(handle,
5685 ALIAS_MAXLOCKEDMEM, &locked_limit);
5686 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5687 res2, locked_limit);
5688 break;
5689 case RT_ADMIN:
5690 output_auth(fp, &in_progress_admintab);
5691 break;
5692 case RT_SECFLAGS:
5693 output_secflags(fp, &in_progress_secflagstab);
5694 break;
5695 }
5696 goto cleanup;
5697 }
5698
5699 type = cmd->cmd_res_type;
5700
5701 if (gz_invalid_rt_property(type)) {
5702 zerr(gettext("%s is not a valid property for the global zone."),
5703 rt_to_str(type));
5704 goto cleanup;
5705 }
5706
5707 if (gz_invalid_resource(type)) {
5708 zerr(gettext("%s is not a valid resource for the global zone."),
5709 rt_to_str(type));
5710 goto cleanup;
5711 }
5712
5713 switch (cmd->cmd_res_type) {
5714 case RT_UNKNOWN:
5731 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5732 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5733 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5734 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5735 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5736 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5737 if (!global_zone) {
5738 info_fs(handle, fp, cmd);
5739 info_net(handle, fp, cmd);
5740 info_dev(handle, fp, cmd);
5741 }
5742 info_pset(handle, fp);
5743 info_pcap(fp);
5744 info_mcap(handle, fp);
5745 if (!global_zone) {
5746 info_attr(handle, fp, cmd);
5747 info_ds(handle, fp, cmd);
5748 info_auth(handle, fp, cmd);
5749 }
5750 info_rctl(handle, fp, cmd);
5751 info_secflags(handle, fp);
5752 break;
5753 case RT_ZONENAME:
5754 info_zonename(handle, fp);
5755 break;
5756 case RT_ZONEPATH:
5757 info_zonepath(handle, fp);
5758 break;
5759 case RT_BRAND:
5760 info_brand(handle, fp);
5761 break;
5762 case RT_AUTOBOOT:
5763 info_autoboot(handle, fp);
5764 break;
5765 case RT_POOL:
5766 info_pool(handle, fp);
5767 break;
5768 case RT_LIMITPRIV:
5769 info_limitpriv(handle, fp);
5770 break;
5771 case RT_BOOTARGS:
5817 info_ds(handle, fp, cmd);
5818 break;
5819 case RT_DCPU:
5820 info_pset(handle, fp);
5821 break;
5822 case RT_PCAP:
5823 info_pcap(fp);
5824 break;
5825 case RT_MCAP:
5826 info_mcap(handle, fp);
5827 break;
5828 case RT_HOSTID:
5829 info_hostid(handle, fp);
5830 break;
5831 case RT_ADMIN:
5832 info_auth(handle, fp, cmd);
5833 break;
5834 case RT_FS_ALLOWED:
5835 info_fs_allowed(handle, fp);
5836 break;
5837 case RT_SECFLAGS:
5838 info_secflags(handle, fp);
5839 break;
5840 default:
5841 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5842 B_TRUE);
5843 }
5844
5845 cleanup:
5846 if (need_to_close)
5847 (void) pager_close(fp);
5848 }
5849
5850 /*
5851 * Helper function for verify-- checks that a required string property
5852 * exists.
5853 */
5854 static void
5855 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5856 {
5857 if (strlen(attr) == 0) {
5858 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5859 pt_to_str(pt));
5971 tmp->xif_has_defrouter = B_TRUE;
5972 return (B_TRUE);
5973 }
5974 }
5975
5976 tmp = malloc(sizeof (*tmp));
5977 if (tmp == NULL) {
5978 zerr(gettext("memory allocation failed for %s"),
5979 nwif->zone_nwif_physical);
5980 return (B_FALSE);
5981 }
5982 strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5983 sizeof (tmp->xif_name));
5984 tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5985 tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5986 tmp->xif_next = xif;
5987 xif = tmp;
5988 return (B_TRUE);
5989 }
5990
5991 boolean_t
5992 verify_secflags(struct zone_secflagstab *tab)
5993 {
5994 secflagdelta_t def = {0};
5995 secflagdelta_t upper = {0};
5996 secflagdelta_t lower = {0};
5997 boolean_t def_set = B_FALSE;
5998 boolean_t upper_set = B_FALSE;
5999 boolean_t lower_set = B_FALSE;
6000 boolean_t ret = B_TRUE;
6001
6002 if (strlen(tab->zone_secflags_default) > 0) {
6003 def_set = B_TRUE;
6004 if (secflags_parse(NULL, tab->zone_secflags_default,
6005 &def) == -1) {
6006 zerr(gettext("default security flags '%s' are invalid"),
6007 tab->zone_secflags_default);
6008 ret = B_FALSE;
6009 }
6010 } else {
6011 secflags_zero(&def.psd_assign);
6012 def.psd_ass_active = B_TRUE;
6013 }
6014
6015 if (strlen(tab->zone_secflags_upper) > 0) {
6016 upper_set = B_TRUE;
6017 if (secflags_parse(NULL, tab->zone_secflags_upper,
6018 &upper) == -1) {
6019 zerr(gettext("upper security flags '%s' are invalid"),
6020 tab->zone_secflags_upper);
6021 ret = B_FALSE;
6022 }
6023 } else {
6024 secflags_fullset(&upper.psd_assign);
6025 upper.psd_ass_active = B_TRUE;
6026 }
6027
6028 if (strlen(tab->zone_secflags_lower) > 0) {
6029 lower_set = B_TRUE;
6030 if (secflags_parse(NULL, tab->zone_secflags_lower,
6031 &lower) == -1) {
6032 zerr(gettext("lower security flags '%s' are invalid"),
6033 tab->zone_secflags_lower);
6034 ret = B_FALSE;
6035 }
6036 } else {
6037 secflags_zero(&lower.psd_assign);
6038 lower.psd_ass_active = B_TRUE;
6039 }
6040
6041 if (def_set && !def.psd_ass_active) {
6042 zerr(gettext("only assignment of security flags is "
6043 "allowed (default: %s)"), tab->zone_secflags_default);
6044 }
6045
6046 if (lower_set && !lower.psd_ass_active) {
6047 zerr(gettext("only assignment of security flags is "
6048 "allowed (lower: %s)"), tab->zone_secflags_lower);
6049 }
6050
6051 if (upper_set && !upper.psd_ass_active) {
6052 zerr(gettext("only assignment of security flags is "
6053 "allowed (upper: %s)"), tab->zone_secflags_upper);
6054 }
6055
6056 if (def.psd_assign & ~upper.psd_assign) { /* In default but not upper */
6057 zerr(gettext("default secflags must be within the "
6058 "upper limit"));
6059 ret = B_FALSE;
6060 }
6061 if (lower.psd_assign & ~def.psd_assign) { /* In lower but not default */
6062 zerr(gettext("default secflags must be above the lower limit"));
6063 ret = B_FALSE;
6064 }
6065 if (lower.psd_assign & ~upper.psd_assign) { /* In lower but not upper */
6066 zerr(gettext("lower secflags must be within the upper limit"));
6067 ret = B_FALSE;
6068 }
6069
6070 return (ret);
6071 }
6072
6073 /*
6074 * See the DTD for which attributes are required for which resources.
6075 *
6076 * This function can be called by commit_func(), which needs to save things,
6077 * in addition to the general call from parse_and_run(), which doesn't need
6078 * things saved. Since the parameters are standardized, we distinguish by
6079 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6080 * that a save is needed.
6081 */
6082 void
6083 verify_func(cmd_t *cmd)
6084 {
6085 struct zone_nwiftab nwiftab;
6086 struct zone_fstab fstab;
6087 struct zone_attrtab attrtab;
6088 struct zone_rctltab rctltab;
6089 struct zone_dstab dstab;
6090 struct zone_psettab psettab;
6091 struct zone_admintab admintab;
6092 struct zone_secflagstab secflagstab;
6093 char zonepath[MAXPATHLEN];
6094 char sched[MAXNAMELEN];
6095 char brand[MAXNAMELEN];
6096 char hostidp[HW_HOSTID_LEN];
6097 char fsallowedp[ZONE_FS_ALLOWED_MAX];
6098 priv_set_t *privs;
6099 char *privname = NULL;
6100 int err, ret_val = Z_OK, arg;
6101 int pset_res;
6102 boolean_t save = B_FALSE;
6103 boolean_t arg_err = B_FALSE;
6104 zone_iptype_t iptype;
6105 boolean_t has_cpu_shares = B_FALSE;
6106 boolean_t has_cpu_cap = B_FALSE;
6107 struct xif *tmp;
6108
6109 optind = 0;
6110 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6111 switch (arg) {
6112 case '?':
6369 }
6370 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6371 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6372 PT_USER, &ret_val);
6373 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6374 PT_AUTHS, &ret_val);
6375 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6376 == NULL)) {
6377 zerr(gettext("%s %s is not a valid username"),
6378 pt_to_str(PT_USER),
6379 admintab.zone_admin_user);
6380 ret_val = Z_BAD_PROPERTY;
6381 }
6382 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6383 admintab.zone_admin_auths, zone))) {
6384 ret_val = Z_BAD_PROPERTY;
6385 }
6386 }
6387 (void) zonecfg_endadminent(handle);
6388
6389 if (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
6390 /*
6391 * No properties are required, but any specified should be
6392 * valid
6393 */
6394 if (verify_secflags(&secflagstab) != B_TRUE) {
6395 /* Error is reported from verify_secflags */
6396 ret_val = Z_BAD_PROPERTY;
6397 }
6398 }
6399
6400 if (!global_scope) {
6401 zerr(gettext("resource specification incomplete"));
6402 saw_error = B_TRUE;
6403 if (ret_val == Z_OK)
6404 ret_val = Z_INSUFFICIENT_SPEC;
6405 }
6406
6407 if (save) {
6408 if (ret_val == Z_OK) {
6409 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6410 need_to_commit = B_FALSE;
6411 (void) strlcpy(revert_zone, zone,
6412 sizeof (revert_zone));
6413 }
6414 } else {
6415 zerr(gettext("Zone %s failed to verify"), zone);
6416 }
6417 }
6418 if (ret_val != Z_OK)
6419 zone_perror(zone, ret_val, B_TRUE);
6969 sizeof (tmp_admintab.zone_admin_user));
6970 err = zonecfg_lookup_admin(
6971 handle, &tmp_admintab);
6972 if (err == Z_OK) {
6973 zerr(gettext("A %s resource "
6974 "with the %s '%s' already exists."),
6975 rt_to_str(RT_ADMIN),
6976 pt_to_str(PT_USER),
6977 in_progress_admintab.zone_admin_user);
6978 saw_error = B_TRUE;
6979 return;
6980 }
6981 err = zonecfg_add_admin(handle,
6982 &in_progress_admintab, zone);
6983 } else {
6984 err = zonecfg_modify_admin(handle,
6985 &old_admintab, &in_progress_admintab,
6986 zone);
6987 }
6988 break;
6989 case RT_SECFLAGS:
6990 if (verify_secflags(&in_progress_secflagstab) != B_TRUE) {
6991 saw_error = B_TRUE;
6992 return;
6993 }
6994
6995 if (end_op == CMD_ADD) {
6996 err = zonecfg_add_secflags(handle,
6997 &in_progress_secflagstab);
6998 } else {
6999 err = zonecfg_modify_secflags(handle,
7000 &old_secflagstab, &in_progress_secflagstab);
7001 }
7002 break;
7003 default:
7004 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
7005 B_TRUE);
7006 saw_error = B_TRUE;
7007 return;
7008 }
7009
7010 if (err != Z_OK) {
7011 zone_perror(zone, err, B_TRUE);
7012 } else {
7013 need_to_commit = B_TRUE;
7014 global_scope = B_TRUE;
7015 end_op = -1;
7016 }
7017 }
7018
7019 void
7020 commit_func(cmd_t *cmd)
7021 {
7022 int arg;
|