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 ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
2121 zone_perror(zone, err, B_FALSE);
2122 goto done;
2123 }
2124
2125 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2126 rt_to_str(RT_SECFLAGS));
2127 export_prop(of, PT_DEFAULT, secflagstab.zone_secflags_default);
2128 export_prop(of, PT_LOWER, secflagstab.zone_secflags_lower);
2129 export_prop(of, PT_UPPER, secflagstab.zone_secflags_upper);
2130 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2131
2132 /*
2133 * There is nothing to export for pcap since this resource is just
2134 * a container for an rctl alias.
2135 */
2136
2137 done:
2138 if (need_to_close)
2139 (void) fclose(of);
2140 }
2141
2142 void
2143 exit_func(cmd_t *cmd)
2144 {
2145 int arg, answer;
2146 boolean_t arg_err = B_FALSE;
2147
2148 optind = 0;
2149 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2150 switch (arg) {
2151 case '?':
2191 {
2192 if (path[0] != '/') {
2193 zerr(gettext("%s is not an absolute path."), path);
2194 return (Z_ERR);
2195 }
2196 /* If path is all slashes, then fail */
2197 if (strspn(path, "/") == strlen(path)) {
2198 zerr(gettext("/ is not allowed as a %s."),
2199 pt_to_str(PT_ZONEPATH));
2200 return (Z_ERR);
2201 }
2202 return (Z_OK);
2203 }
2204
2205 static void
2206 add_resource(cmd_t *cmd)
2207 {
2208 int type;
2209 struct zone_psettab tmp_psettab;
2210 struct zone_mcaptab tmp_mcaptab;
2211 struct zone_secflagstab tmp_secflagstab;
2212 uint64_t tmp;
2213 uint64_t tmp_mcap;
2214 char pool[MAXNAMELEN];
2215
2216 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2217 long_usage(CMD_ADD, B_TRUE);
2218 goto bad;
2219 }
2220
2221 switch (type) {
2222 case RT_FS:
2223 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2224 return;
2225 case RT_NET:
2226 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2227 return;
2228 case RT_DEVICE:
2229 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2230 return;
2231 case RT_RCTL:
2303 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2304 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2305 == Z_OK ||
2306 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2307 &tmp_mcap) == Z_OK) {
2308 zerr(gettext("The %s resource or a related resource "
2309 "control already exists."), rt_to_str(RT_MCAP));
2310 goto bad;
2311 }
2312 if (global_zone)
2313 zerr(gettext("WARNING: Setting a global zone memory "
2314 "cap too low could deny\nservice "
2315 "to even the root user; "
2316 "this could render the system impossible\n"
2317 "to administer. Please use caution."));
2318 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2319 return;
2320 case RT_ADMIN:
2321 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2322 return;
2323 case RT_SECFLAGS:
2324 /* Make sure we haven't already set this */
2325 if (zonecfg_lookup_secflags(handle, &tmp_secflagstab) == Z_OK)
2326 zerr(gettext("The %s resource already exists."),
2327 rt_to_str(RT_SECFLAGS));
2328 bzero(&in_progress_secflagstab,
2329 sizeof (in_progress_secflagstab));
2330 return;
2331 default:
2332 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2333 long_usage(CMD_ADD, B_TRUE);
2334 usage(B_FALSE, HELP_RESOURCES);
2335 }
2336 bad:
2337 global_scope = B_TRUE;
2338 end_op = -1;
2339 }
2340
2341 static void
2342 do_complex_rctl_val(complex_property_ptr_t cp)
2343 {
2344 struct zone_rctlvaltab *rctlvaltab;
2345 complex_property_ptr_t cx;
2346 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2347 seen_action = B_FALSE;
2348 rctlblk_t *rctlblk;
2349 int err;
2350
2980 case PT_USER:
2981 (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2982 sizeof (admintab->zone_admin_user));
2983 break;
2984 case PT_AUTHS:
2985 (void) strlcpy(admintab->zone_admin_auths,
2986 pp->pv_simple, sizeof (admintab->zone_admin_auths));
2987 break;
2988 default:
2989 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2990 Z_NO_PROPERTY_TYPE, B_TRUE);
2991 return (Z_INSUFFICIENT_SPEC);
2992 }
2993 }
2994 if (fill_in_only)
2995 return (Z_OK);
2996 err = zonecfg_lookup_admin(handle, admintab);
2997 return (err);
2998 }
2999
3000 static int
3001 fill_in_secflagstab(cmd_t *cmd, struct zone_secflagstab *secflagstab,
3002 boolean_t fill_in_only)
3003 {
3004 int err, i;
3005 property_value_ptr_t pp;
3006
3007 if ((err = initialize(B_TRUE)) != Z_OK)
3008 return (err);
3009
3010 bzero(secflagstab, sizeof (*secflagstab));
3011 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
3012 pp = cmd->cmd_property_ptr[i];
3013 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
3014 zerr(gettext("A simple value was expected here."));
3015 saw_error = B_TRUE;
3016 return (Z_INSUFFICIENT_SPEC);
3017 }
3018 switch (cmd->cmd_prop_name[i]) {
3019 case PT_DEFAULT:
3020 (void) strlcpy(secflagstab->zone_secflags_default,
3021 pp->pv_simple,
3022 sizeof (secflagstab->zone_secflags_default));
3023 break;
3024 case PT_LOWER:
3025 (void) strlcpy(secflagstab->zone_secflags_lower,
3026 pp->pv_simple,
3027 sizeof (secflagstab->zone_secflags_lower));
3028 break;
3029 case PT_UPPER:
3030 (void) strlcpy(secflagstab->zone_secflags_upper,
3031 pp->pv_simple,
3032 sizeof (secflagstab->zone_secflags_upper));
3033 break;
3034 default:
3035 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3036 Z_NO_PROPERTY_TYPE, B_TRUE);
3037 return (Z_INSUFFICIENT_SPEC);
3038 }
3039 }
3040 if (fill_in_only)
3041 return (Z_OK);
3042
3043 err = zonecfg_lookup_secflags(handle, secflagstab);
3044
3045 return (err);
3046 }
3047
3048 static void
3049 remove_aliased_rctl(int type, char *name)
3050 {
3051 int err;
3052 uint64_t tmp;
3053
3054 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
3055 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3056 zonecfg_strerror(err));
3057 saw_error = B_TRUE;
3058 return;
3059 }
3060 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
3061 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3062 zonecfg_strerror(err));
3063 saw_error = B_TRUE;
3064 } else {
3065 need_to_commit = B_TRUE;
3066 }
3067 }
3430 return;
3431 } else {
3432 /*
3433 * unqualified admin removal.
3434 * remove all admins but prompt if more
3435 * than one.
3436 */
3437 if (!prompt_remove_resource(cmd, "admin"))
3438 return;
3439
3440 if ((err = zonecfg_delete_admins(handle, zone))
3441 != Z_OK)
3442 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3443 err, B_TRUE);
3444 else
3445 need_to_commit = B_TRUE;
3446 }
3447 }
3448
3449 static void
3450 remove_secflags()
3451 {
3452 int err;
3453 struct zone_secflagstab sectab = { 0 };
3454
3455 if (zonecfg_lookup_secflags(handle, §ab) != Z_OK) {
3456 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3457 rt_to_str(RT_SECFLAGS),
3458 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3459 return;
3460 }
3461
3462 if ((err = zonecfg_delete_secflags(handle, §ab)) != Z_OK) {
3463 z_cmd_rt_perror(CMD_REMOVE, RT_SECFLAGS, err, B_TRUE);
3464 return;
3465 }
3466
3467 need_to_commit = B_TRUE;
3468 }
3469
3470 static void
3471 remove_resource(cmd_t *cmd)
3472 {
3473 int type;
3474 int arg;
3475 boolean_t arg_err = B_FALSE;
3476
3477 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3478 long_usage(CMD_REMOVE, B_TRUE);
3479 return;
3480 }
3481
3482 optind = 0;
3483 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3484 switch (arg) {
3485 case '?':
3486 longer_usage(CMD_REMOVE);
3487 arg_err = B_TRUE;
3488 break;
3489 case 'F':
3490 break;
3514 remove_rctl(cmd);
3515 return;
3516 case RT_ATTR:
3517 remove_attr(cmd);
3518 return;
3519 case RT_DATASET:
3520 remove_dataset(cmd);
3521 return;
3522 case RT_DCPU:
3523 remove_pset();
3524 return;
3525 case RT_PCAP:
3526 remove_pcap();
3527 return;
3528 case RT_MCAP:
3529 remove_mcap();
3530 return;
3531 case RT_ADMIN:
3532 remove_admin(cmd);
3533 return;
3534 case RT_SECFLAGS:
3535 remove_secflags();
3536 return;
3537 default:
3538 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3539 long_usage(CMD_REMOVE, B_TRUE);
3540 usage(B_FALSE, HELP_RESOURCES);
3541 return;
3542 }
3543 }
3544
3545 static void
3546 remove_property(cmd_t *cmd)
3547 {
3548 char *prop_id;
3549 int err, res_type, prop_type;
3550 property_value_ptr_t pp;
3551 struct zone_rctlvaltab *rctlvaltab;
3552 complex_property_ptr_t cx;
3553
3554 res_type = resource_scope;
3555 prop_type = cmd->cmd_prop_name[0];
3556 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3729 if (prop_type == PT_IMPORTANCE) {
3730 in_progress_psettab.zone_importance[0] = '\0';
3731 need_to_commit = B_TRUE;
3732 return;
3733 }
3734 break;
3735 case RT_MCAP:
3736 switch (prop_type) {
3737 case PT_PHYSICAL:
3738 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3739 need_to_commit = B_TRUE;
3740 return;
3741 case PT_SWAP:
3742 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3743 return;
3744 case PT_LOCKED:
3745 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3746 return;
3747 }
3748 break;
3749 case RT_SECFLAGS:
3750 switch (prop_type) {
3751 case PT_LOWER:
3752 in_progress_secflagstab.zone_secflags_lower[0] = '\0';
3753 need_to_commit = B_TRUE;
3754 return;
3755 case PT_DEFAULT:
3756 in_progress_secflagstab.zone_secflags_default[0] = '\0';
3757 need_to_commit = B_TRUE;
3758 return;
3759 case PT_UPPER:
3760 in_progress_secflagstab.zone_secflags_upper[0] = '\0';
3761 need_to_commit = B_TRUE;
3762 return;
3763 }
3764 break;
3765 default:
3766 break;
3767 }
3768
3769 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3770 }
3771
3772 static void
3773 clear_global(cmd_t *cmd)
3774 {
3775 int err, type;
3776
3777 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3778 long_usage(CMD_CLEAR, B_TRUE);
3779 return;
3780 }
3781
3782 if (initialize(B_TRUE) != Z_OK)
3783 return;
3784
3998 B_TRUE);
3999 global_scope = B_TRUE;
4000 }
4001 if (res == Z_OK)
4002 bcopy(&old_mcaptab, &in_progress_mcaptab,
4003 sizeof (struct zone_mcaptab));
4004 else
4005 bzero(&in_progress_mcaptab,
4006 sizeof (in_progress_mcaptab));
4007 return;
4008 case RT_ADMIN:
4009 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
4010 != Z_OK) {
4011 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
4012 B_TRUE);
4013 global_scope = B_TRUE;
4014 }
4015 bcopy(&old_admintab, &in_progress_admintab,
4016 sizeof (struct zone_admintab));
4017 return;
4018 case RT_SECFLAGS:
4019 if ((err = fill_in_secflagstab(cmd, &old_secflagstab, B_FALSE))
4020 != Z_OK) {
4021 z_cmd_rt_perror(CMD_SELECT, RT_SECFLAGS, err,
4022 B_TRUE);
4023 global_scope = B_TRUE;
4024 }
4025 bcopy(&old_secflagstab, &in_progress_secflagstab,
4026 sizeof (struct zone_secflagstab));
4027 return;
4028 default:
4029 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
4030 long_usage(CMD_SELECT, B_TRUE);
4031 usage(B_FALSE, HELP_RESOURCES);
4032 return;
4033 }
4034 }
4035
4036 /*
4037 * Network "addresses" can be one of the following forms:
4038 * <IPv4 address>
4039 * <IPv4 address>/<prefix length>
4040 * <IPv6 address>/<prefix length>
4041 * <host name>
4042 * <host name>/<prefix length>
4043 * In other words, the "/" followed by a prefix length is allowed but not
4044 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4045 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4046 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4047 * Host names must start with an alpha-numeric character, and all subsequent
4924 return;
4925 case RT_ADMIN:
4926 switch (prop_type) {
4927 case PT_USER:
4928 (void) strlcpy(in_progress_admintab.zone_admin_user,
4929 prop_id,
4930 sizeof (in_progress_admintab.zone_admin_user));
4931 return;
4932 case PT_AUTHS:
4933 (void) strlcpy(in_progress_admintab.zone_admin_auths,
4934 prop_id,
4935 sizeof (in_progress_admintab.zone_admin_auths));
4936 return;
4937 default:
4938 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4939 B_TRUE);
4940 long_usage(CMD_SET, B_TRUE);
4941 usage(B_FALSE, HELP_PROPS);
4942 return;
4943 }
4944 case RT_SECFLAGS: {
4945 char *propstr;
4946
4947 switch (prop_type) {
4948 case PT_DEFAULT:
4949 propstr = in_progress_secflagstab.zone_secflags_default;
4950 break;
4951 case PT_UPPER:
4952 propstr = in_progress_secflagstab.zone_secflags_upper;
4953 break;
4954 case PT_LOWER:
4955 propstr = in_progress_secflagstab.zone_secflags_lower;
4956 break;
4957 default:
4958 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4959 B_TRUE);
4960 long_usage(CMD_SET, B_TRUE);
4961 usage(B_FALSE, HELP_PROPS);
4962 return;
4963 }
4964 (void) strlcpy(propstr, prop_id, ZONECFG_SECFLAGS_MAX);
4965 return;
4966 }
4967 default:
4968 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4969 long_usage(CMD_SET, B_TRUE);
4970 usage(B_FALSE, HELP_RESOURCES);
4971 return;
4972 }
4973 }
4974
4975 static void
4976 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4977 {
4978 char *qstr;
4979
4980 if (*pval != '\0') {
4981 qstr = quoteit(pval);
4982 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4983 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4984 qstr);
4985 else
4986 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
5561
5562 bzero(&lookup, sizeof (lookup));
5563 res1 = zonecfg_getmcapent(handle, &lookup);
5564 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5565 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5566 &locked_limit);
5567
5568 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5569 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5570 }
5571
5572 static void
5573 output_auth(FILE *fp, struct zone_admintab *admintab)
5574 {
5575 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5576 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5577 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5578 }
5579
5580 static void
5581 output_secflags(FILE *fp, struct zone_secflagstab *sftab)
5582 {
5583 (void) fprintf(fp, "%s:\n", rt_to_str(RT_SECFLAGS));
5584 output_prop(fp, PT_DEFAULT, sftab->zone_secflags_default, B_TRUE);
5585 output_prop(fp, PT_LOWER, sftab->zone_secflags_lower, B_TRUE);
5586 output_prop(fp, PT_UPPER, sftab->zone_secflags_upper, B_TRUE);
5587 }
5588
5589 static void
5590 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5591 {
5592 struct zone_admintab lookup, user;
5593 boolean_t output = B_FALSE;
5594 int err;
5595
5596 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5597 zone_perror(zone, err, B_TRUE);
5598 return;
5599 }
5600 while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5601 if (cmd->cmd_prop_nv_pairs == 0) {
5602 output_auth(fp, &lookup);
5603 continue;
5604 }
5605 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5606 continue;
5607 if (strlen(user.zone_admin_user) > 0 &&
5608 strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5609 continue; /* no match */
5610 output_auth(fp, &lookup);
5611 output = B_TRUE;
5612 }
5613 (void) zonecfg_endadminent(handle);
5614 /*
5615 * If a property n/v pair was specified, warn the user if there was
5616 * nothing to output.
5617 */
5618 if (!output && cmd->cmd_prop_nv_pairs > 0)
5619 (void) printf(gettext("No such %s resource.\n"),
5620 rt_to_str(RT_ADMIN));
5621 }
5622
5623 static void
5624 info_secflags(zone_dochandle_t handle, FILE *fp)
5625 {
5626 struct zone_secflagstab sftab;
5627 int err;
5628
5629 if ((err = zonecfg_lookup_secflags(handle, &sftab)) != Z_OK) {
5630 zone_perror(zone, err, B_TRUE);
5631 return;
5632 }
5633
5634 output_secflags(fp, &sftab);
5635 }
5636
5637 void
5638 info_func(cmd_t *cmd)
5639 {
5640 FILE *fp = stdout;
5641 boolean_t need_to_close = B_FALSE;
5642 int type;
5643 int res1, res2;
5644 uint64_t swap_limit;
5645 uint64_t locked_limit;
5646
5647 assert(cmd != NULL);
5648
5649 if (initialize(B_TRUE) != Z_OK)
5650 return;
5651
5652 /* don't page error output */
5653 if (interactive_mode) {
5654 if ((fp = pager_open()) != NULL)
5655 need_to_close = B_TRUE;
5656 else
5679 case RT_DATASET:
5680 output_ds(fp, &in_progress_dstab);
5681 break;
5682 case RT_DCPU:
5683 output_pset(fp, &in_progress_psettab);
5684 break;
5685 case RT_PCAP:
5686 output_pcap(fp);
5687 break;
5688 case RT_MCAP:
5689 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5690 &swap_limit);
5691 res2 = zonecfg_get_aliased_rctl(handle,
5692 ALIAS_MAXLOCKEDMEM, &locked_limit);
5693 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5694 res2, locked_limit);
5695 break;
5696 case RT_ADMIN:
5697 output_auth(fp, &in_progress_admintab);
5698 break;
5699 case RT_SECFLAGS:
5700 output_secflags(fp, &in_progress_secflagstab);
5701 break;
5702 }
5703 goto cleanup;
5704 }
5705
5706 type = cmd->cmd_res_type;
5707
5708 if (gz_invalid_rt_property(type)) {
5709 zerr(gettext("%s is not a valid property for the global zone."),
5710 rt_to_str(type));
5711 goto cleanup;
5712 }
5713
5714 if (gz_invalid_resource(type)) {
5715 zerr(gettext("%s is not a valid resource for the global zone."),
5716 rt_to_str(type));
5717 goto cleanup;
5718 }
5719
5720 switch (cmd->cmd_res_type) {
5721 case RT_UNKNOWN:
5738 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5739 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5740 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5741 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5742 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5743 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5744 if (!global_zone) {
5745 info_fs(handle, fp, cmd);
5746 info_net(handle, fp, cmd);
5747 info_dev(handle, fp, cmd);
5748 }
5749 info_pset(handle, fp);
5750 info_pcap(fp);
5751 info_mcap(handle, fp);
5752 if (!global_zone) {
5753 info_attr(handle, fp, cmd);
5754 info_ds(handle, fp, cmd);
5755 info_auth(handle, fp, cmd);
5756 }
5757 info_rctl(handle, fp, cmd);
5758 info_secflags(handle, fp);
5759 break;
5760 case RT_ZONENAME:
5761 info_zonename(handle, fp);
5762 break;
5763 case RT_ZONEPATH:
5764 info_zonepath(handle, fp);
5765 break;
5766 case RT_BRAND:
5767 info_brand(handle, fp);
5768 break;
5769 case RT_AUTOBOOT:
5770 info_autoboot(handle, fp);
5771 break;
5772 case RT_POOL:
5773 info_pool(handle, fp);
5774 break;
5775 case RT_LIMITPRIV:
5776 info_limitpriv(handle, fp);
5777 break;
5778 case RT_BOOTARGS:
5824 info_ds(handle, fp, cmd);
5825 break;
5826 case RT_DCPU:
5827 info_pset(handle, fp);
5828 break;
5829 case RT_PCAP:
5830 info_pcap(fp);
5831 break;
5832 case RT_MCAP:
5833 info_mcap(handle, fp);
5834 break;
5835 case RT_HOSTID:
5836 info_hostid(handle, fp);
5837 break;
5838 case RT_ADMIN:
5839 info_auth(handle, fp, cmd);
5840 break;
5841 case RT_FS_ALLOWED:
5842 info_fs_allowed(handle, fp);
5843 break;
5844 case RT_SECFLAGS:
5845 info_secflags(handle, fp);
5846 break;
5847 default:
5848 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5849 B_TRUE);
5850 }
5851
5852 cleanup:
5853 if (need_to_close)
5854 (void) pager_close(fp);
5855 }
5856
5857 /*
5858 * Helper function for verify-- checks that a required string property
5859 * exists.
5860 */
5861 static void
5862 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5863 {
5864 if (strlen(attr) == 0) {
5865 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5866 pt_to_str(pt));
5978 tmp->xif_has_defrouter = B_TRUE;
5979 return (B_TRUE);
5980 }
5981 }
5982
5983 tmp = malloc(sizeof (*tmp));
5984 if (tmp == NULL) {
5985 zerr(gettext("memory allocation failed for %s"),
5986 nwif->zone_nwif_physical);
5987 return (B_FALSE);
5988 }
5989 strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5990 sizeof (tmp->xif_name));
5991 tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5992 tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5993 tmp->xif_next = xif;
5994 xif = tmp;
5995 return (B_TRUE);
5996 }
5997
5998 boolean_t
5999 verify_secflags(struct zone_secflagstab *tab)
6000 {
6001 secflagdelta_t def = {0};
6002 secflagdelta_t upper = {0};
6003 secflagdelta_t lower = {0};
6004 boolean_t def_set = B_FALSE;
6005 boolean_t upper_set = B_FALSE;
6006 boolean_t lower_set = B_FALSE;
6007 boolean_t ret = B_TRUE;
6008
6009 if (strlen(tab->zone_secflags_default) > 0) {
6010 def_set = B_TRUE;
6011 if (secflags_parse(NULL, tab->zone_secflags_default,
6012 &def) == -1) {
6013 zerr(gettext("default security flags '%s' are invalid"),
6014 tab->zone_secflags_default);
6015 ret = B_FALSE;
6016 }
6017 } else {
6018 secflags_zero(&def.psd_assign);
6019 def.psd_ass_active = B_TRUE;
6020 }
6021
6022 if (strlen(tab->zone_secflags_upper) > 0) {
6023 upper_set = B_TRUE;
6024 if (secflags_parse(NULL, tab->zone_secflags_upper,
6025 &upper) == -1) {
6026 zerr(gettext("upper security flags '%s' are invalid"),
6027 tab->zone_secflags_upper);
6028 ret = B_FALSE;
6029 }
6030 } else {
6031 secflags_fullset(&upper.psd_assign);
6032 upper.psd_ass_active = B_TRUE;
6033 }
6034
6035 if (strlen(tab->zone_secflags_lower) > 0) {
6036 lower_set = B_TRUE;
6037 if (secflags_parse(NULL, tab->zone_secflags_lower,
6038 &lower) == -1) {
6039 zerr(gettext("lower security flags '%s' are invalid"),
6040 tab->zone_secflags_lower);
6041 ret = B_FALSE;
6042 }
6043 } else {
6044 secflags_zero(&lower.psd_assign);
6045 lower.psd_ass_active = B_TRUE;
6046 }
6047
6048 if (def_set && !def.psd_ass_active) {
6049 zerr(gettext("only assignment of security flags is "
6050 "allowed (default: %s)"), tab->zone_secflags_default);
6051 }
6052
6053 if (lower_set && !lower.psd_ass_active) {
6054 zerr(gettext("only assignment of security flags is "
6055 "allowed (lower: %s)"), tab->zone_secflags_lower);
6056 }
6057
6058 if (upper_set && !upper.psd_ass_active) {
6059 zerr(gettext("only assignment of security flags is "
6060 "allowed (upper: %s)"), tab->zone_secflags_upper);
6061 }
6062
6063 if (def.psd_assign & ~upper.psd_assign) { /* In default but not upper */
6064 zerr(gettext("default secflags must be within the "
6065 "upper limit"));
6066 ret = B_FALSE;
6067 }
6068 if (lower.psd_assign & ~def.psd_assign) { /* In lower but not default */
6069 zerr(gettext("default secflags must be above the lower limit"));
6070 ret = B_FALSE;
6071 }
6072 if (lower.psd_assign & ~upper.psd_assign) { /* In lower but not upper */
6073 zerr(gettext("lower secflags must be within the upper limit"));
6074 ret = B_FALSE;
6075 }
6076
6077 return (ret);
6078 }
6079
6080 /*
6081 * See the DTD for which attributes are required for which resources.
6082 *
6083 * This function can be called by commit_func(), which needs to save things,
6084 * in addition to the general call from parse_and_run(), which doesn't need
6085 * things saved. Since the parameters are standardized, we distinguish by
6086 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6087 * that a save is needed.
6088 */
6089 void
6090 verify_func(cmd_t *cmd)
6091 {
6092 struct zone_nwiftab nwiftab;
6093 struct zone_fstab fstab;
6094 struct zone_attrtab attrtab;
6095 struct zone_rctltab rctltab;
6096 struct zone_dstab dstab;
6097 struct zone_psettab psettab;
6098 struct zone_admintab admintab;
6099 struct zone_secflagstab secflagstab;
6100 char zonepath[MAXPATHLEN];
6101 char sched[MAXNAMELEN];
6102 char brand[MAXNAMELEN];
6103 char hostidp[HW_HOSTID_LEN];
6104 char fsallowedp[ZONE_FS_ALLOWED_MAX];
6105 priv_set_t *privs;
6106 char *privname = NULL;
6107 int err, ret_val = Z_OK, arg;
6108 int pset_res;
6109 boolean_t save = B_FALSE;
6110 boolean_t arg_err = B_FALSE;
6111 zone_iptype_t iptype;
6112 boolean_t has_cpu_shares = B_FALSE;
6113 boolean_t has_cpu_cap = B_FALSE;
6114 struct xif *tmp;
6115
6116 optind = 0;
6117 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6118 switch (arg) {
6119 case '?':
6376 }
6377 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6378 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6379 PT_USER, &ret_val);
6380 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6381 PT_AUTHS, &ret_val);
6382 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6383 == NULL)) {
6384 zerr(gettext("%s %s is not a valid username"),
6385 pt_to_str(PT_USER),
6386 admintab.zone_admin_user);
6387 ret_val = Z_BAD_PROPERTY;
6388 }
6389 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6390 admintab.zone_admin_auths, zone))) {
6391 ret_val = Z_BAD_PROPERTY;
6392 }
6393 }
6394 (void) zonecfg_endadminent(handle);
6395
6396 if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
6397 zone_perror(zone, err, B_TRUE);
6398 return;
6399 }
6400
6401 /*
6402 * No properties are required, but any specified should be
6403 * valid
6404 */
6405 if (verify_secflags(&secflagstab) != B_TRUE) {
6406 /* Error is reported from verify_secflags */
6407 ret_val = Z_BAD_PROPERTY;
6408 }
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 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6420 need_to_commit = B_FALSE;
6421 (void) strlcpy(revert_zone, zone,
6422 sizeof (revert_zone));
6423 }
6424 } else {
6425 zerr(gettext("Zone %s failed to verify"), zone);
6426 }
6427 }
6428 if (ret_val != Z_OK)
6429 zone_perror(zone, ret_val, B_TRUE);
6979 sizeof (tmp_admintab.zone_admin_user));
6980 err = zonecfg_lookup_admin(
6981 handle, &tmp_admintab);
6982 if (err == Z_OK) {
6983 zerr(gettext("A %s resource "
6984 "with the %s '%s' already exists."),
6985 rt_to_str(RT_ADMIN),
6986 pt_to_str(PT_USER),
6987 in_progress_admintab.zone_admin_user);
6988 saw_error = B_TRUE;
6989 return;
6990 }
6991 err = zonecfg_add_admin(handle,
6992 &in_progress_admintab, zone);
6993 } else {
6994 err = zonecfg_modify_admin(handle,
6995 &old_admintab, &in_progress_admintab,
6996 zone);
6997 }
6998 break;
6999 case RT_SECFLAGS:
7000 if (verify_secflags(&in_progress_secflagstab) != B_TRUE) {
7001 saw_error = B_TRUE;
7002 return;
7003 }
7004
7005 if (end_op == CMD_ADD) {
7006 err = zonecfg_add_secflags(handle,
7007 &in_progress_secflagstab);
7008 } else {
7009 err = zonecfg_modify_secflags(handle,
7010 &old_secflagstab, &in_progress_secflagstab);
7011 }
7012 break;
7013 default:
7014 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
7015 B_TRUE);
7016 saw_error = B_TRUE;
7017 return;
7018 }
7019
7020 if (err != Z_OK) {
7021 zone_perror(zone, err, B_TRUE);
7022 } else {
7023 need_to_commit = B_TRUE;
7024 global_scope = B_TRUE;
7025 end_op = -1;
7026 }
7027 }
7028
7029 void
7030 commit_func(cmd_t *cmd)
7031 {
7032 int arg;
|