Print this page
Code review comments from pmooney (sundry), and igork (screwups in zonecfg refactoring)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/zonecfg/zonecfg.c
+++ new/usr/src/cmd/zonecfg/zonecfg.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 25 * Copyright 2014 Gary Mills
26 26 */
27 27
28 28 /*
29 29 * zonecfg is a lex/yacc based command interpreter used to manage zone
30 30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
31 31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
32 32 * which takes resources and/or properties as arguments. See the block
33 33 * comments near the end of zonecfg_grammar.y for how the data structures
34 34 * which keep track of these resources and properties are built up.
35 35 *
36 36 * The resource/property data structures are inserted into a command
37 37 * structure (see zonecfg.h), which also keeps track of command names,
38 38 * miscellaneous arguments, and function handlers. The grammar selects
39 39 * the appropriate function handler, each of which takes a pointer to a
40 40 * command structure as its sole argument, and invokes it. The grammar
41 41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 42 * from read_input(), our main driving function. That in turn is called
43 43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 44 * of which is called from main() depending on how the program was invoked.
45 45 *
46 46 * The rest of this module consists of the various function handlers and
47 47 * their helper functions. Some of these functions, particularly the
48 48 * X_to_str() functions, which maps command, resource and property numbers
49 49 * to strings, are used quite liberally, as doing so results in a better
50 50 * program w/rt I18N, reducing the need for translation notes.
51 51 */
52 52
53 53 #include <sys/mntent.h>
54 54 #include <sys/varargs.h>
55 55 #include <sys/sysmacros.h>
56 56 #include <sys/secflags.h>
57 57
58 58 #include <errno.h>
59 59 #include <fcntl.h>
60 60 #include <strings.h>
61 61 #include <unistd.h>
62 62 #include <ctype.h>
63 63 #include <stdlib.h>
64 64 #include <assert.h>
65 65 #include <sys/stat.h>
66 66 #include <zone.h>
67 67 #include <arpa/inet.h>
68 68 #include <netdb.h>
69 69 #include <locale.h>
70 70 #include <libintl.h>
71 71 #include <alloca.h>
72 72 #include <signal.h>
73 73 #include <wait.h>
74 74 #include <libtecla.h>
75 75 #include <libzfs.h>
76 76 #include <sys/brand.h>
77 77 #include <libbrand.h>
78 78 #include <sys/systeminfo.h>
79 79 #include <libdladm.h>
80 80 #include <libinetutil.h>
81 81 #include <pwd.h>
82 82 #include <inet/ip.h>
83 83
84 84 #include <libzonecfg.h>
85 85 #include "zonecfg.h"
86 86
87 87 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
88 88 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
89 89 #endif
90 90
91 91 #define PAGER "/usr/bin/more"
92 92 #define EXEC_PREFIX "exec "
93 93 #define EXEC_LEN (strlen(EXEC_PREFIX))
94 94
95 95 struct help {
96 96 uint_t cmd_num;
97 97 char *cmd_name;
98 98 uint_t flags;
99 99 char *short_usage;
100 100 };
101 101
102 102 extern int yyparse(void);
103 103 extern int lex_lineno;
104 104
105 105 #define MAX_LINE_LEN 1024
106 106 #define MAX_CMD_HIST 1024
107 107 #define MAX_CMD_LEN 1024
108 108
109 109 #define ONE_MB 1048576
110 110
111 111 /*
112 112 * Each SHELP_ should be a simple string.
113 113 */
114 114
115 115 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
116 116 "add <property-name> <property-value>\n\t(resource scope)"
117 117 #define SHELP_CANCEL "cancel"
118 118 #define SHELP_CLEAR "clear <property-name>"
119 119 #define SHELP_COMMIT "commit"
120 120 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
121 121 #define SHELP_DELETE "delete [-F]"
122 122 #define SHELP_END "end"
123 123 #define SHELP_EXIT "exit [-F]"
124 124 #define SHELP_EXPORT "export [-f output-file]"
125 125 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
126 126 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
127 127 #define SHELP_REMOVE "remove [-F] <resource-type> " \
128 128 "[ <property-name>=<property-value> ]*\n" \
129 129 "\t(global scope)\n" \
130 130 "remove <property-name> <property-value>\n" \
131 131 "\t(resource scope)"
132 132 #define SHELP_REVERT "revert [-F]"
133 133 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
134 134 "<property-value> }"
135 135 #define SHELP_SET "set <property-name>=<property-value>"
136 136 #define SHELP_VERIFY "verify"
137 137
138 138 static struct help helptab[] = {
139 139 { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, },
140 140 { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, },
141 141 { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, },
142 142 { CMD_COMMIT, "commit", 0, SHELP_COMMIT, },
143 143 { CMD_CREATE, "create", 0, SHELP_CREATE, },
144 144 { CMD_DELETE, "delete", 0, SHELP_DELETE, },
145 145 { CMD_END, "end", 0, SHELP_END, },
146 146 { CMD_EXIT, "exit", 0, SHELP_EXIT, },
147 147 { CMD_EXPORT, "export", 0, SHELP_EXPORT, },
148 148 { CMD_HELP, "help", 0, SHELP_HELP },
149 149 { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, },
150 150 { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, },
151 151 { CMD_REVERT, "revert", 0, SHELP_REVERT, },
152 152 { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, },
153 153 { CMD_SET, "set", HELP_PROPS, SHELP_SET, },
154 154 { CMD_VERIFY, "verify", 0, SHELP_VERIFY, },
155 155 { 0 },
156 156 };
157 157
158 158 #define MAX_RT_STRLEN 16
159 159
160 160 /* These *must* match the order of the RT_ define's from zonecfg.h */
161 161 char *res_types[] = {
162 162 "unknown",
163 163 "zonename",
164 164 "zonepath",
165 165 "autoboot",
166 166 "pool",
167 167 "fs",
168 168 "net",
169 169 "device",
170 170 "rctl",
171 171 "attr",
172 172 "dataset",
173 173 "limitpriv",
174 174 "bootargs",
175 175 "brand",
176 176 "dedicated-cpu",
177 177 "capped-memory",
178 178 ALIAS_MAXLWPS,
179 179 ALIAS_MAXSHMMEM,
180 180 ALIAS_MAXSHMIDS,
181 181 ALIAS_MAXMSGIDS,
182 182 ALIAS_MAXSEMIDS,
183 183 ALIAS_SHARES,
184 184 "scheduling-class",
185 185 "ip-type",
186 186 "capped-cpu",
187 187 "hostid",
188 188 "admin",
189 189 "fs-allowed",
190 190 ALIAS_MAXPROCS,
191 191 "security-flags",
192 192 NULL
193 193 };
194 194
195 195 /* These *must* match the order of the PT_ define's from zonecfg.h */
196 196 char *prop_types[] = {
197 197 "unknown",
198 198 "zonename",
199 199 "zonepath",
200 200 "autoboot",
201 201 "pool",
202 202 "dir",
203 203 "special",
204 204 "type",
205 205 "options",
206 206 "address",
207 207 "physical",
208 208 "name",
209 209 "value",
210 210 "match",
211 211 "priv",
212 212 "limit",
213 213 "action",
214 214 "raw",
215 215 "limitpriv",
216 216 "bootargs",
217 217 "brand",
218 218 "ncpus",
219 219 "importance",
220 220 "swap",
221 221 "locked",
222 222 ALIAS_SHARES,
223 223 ALIAS_MAXLWPS,
224 224 ALIAS_MAXSHMMEM,
225 225 ALIAS_MAXSHMIDS,
226 226 ALIAS_MAXMSGIDS,
227 227 ALIAS_MAXSEMIDS,
228 228 ALIAS_MAXLOCKEDMEM,
229 229 ALIAS_MAXSWAP,
230 230 "scheduling-class",
231 231 "ip-type",
232 232 "defrouter",
233 233 "hostid",
234 234 "user",
235 235 "auths",
236 236 "fs-allowed",
237 237 ALIAS_MAXPROCS,
238 238 "allowed-address",
239 239 "default",
240 240 "lower",
241 241 "upper",
242 242 NULL
243 243 };
244 244
245 245 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
246 246 static char *prop_val_types[] = {
247 247 "simple",
248 248 "complex",
249 249 "list",
250 250 };
251 251
252 252 /*
253 253 * The various _cmds[] lists below are for command tab-completion.
254 254 */
255 255
256 256 /*
257 257 * remove has a space afterwards because it has qualifiers; the other commands
258 258 * that have qualifiers (add, select, etc.) don't need a space here because
259 259 * they have their own _cmds[] lists below.
260 260 */
261 261 static const char *global_scope_cmds[] = {
262 262 "add",
263 263 "clear",
264 264 "commit",
265 265 "create",
266 266 "delete",
267 267 "exit",
268 268 "export",
269 269 "help",
270 270 "info",
271 271 "remove ",
272 272 "revert",
273 273 "select",
274 274 "set",
275 275 "verify",
276 276 NULL
277 277 };
278 278
279 279 static const char *add_cmds[] = {
280 280 "add fs",
281 281 "add net",
282 282 "add device",
283 283 "add rctl",
284 284 "add attr",
285 285 "add dataset",
286 286 "add dedicated-cpu",
287 287 "add capped-cpu",
288 288 "add capped-memory",
289 289 "add admin",
290 290 "add security-flags",
291 291 NULL
292 292 };
293 293
294 294 static const char *clear_cmds[] = {
295 295 "clear autoboot",
296 296 "clear pool",
297 297 "clear limitpriv",
298 298 "clear bootargs",
299 299 "clear scheduling-class",
300 300 "clear ip-type",
301 301 "clear " ALIAS_MAXLWPS,
302 302 "clear " ALIAS_MAXSHMMEM,
303 303 "clear " ALIAS_MAXSHMIDS,
304 304 "clear " ALIAS_MAXMSGIDS,
305 305 "clear " ALIAS_MAXSEMIDS,
306 306 "clear " ALIAS_SHARES,
307 307 "clear " ALIAS_MAXPROCS,
308 308 NULL
309 309 };
310 310
311 311 static const char *remove_cmds[] = {
312 312 "remove fs ",
313 313 "remove net ",
314 314 "remove device ",
315 315 "remove rctl ",
316 316 "remove attr ",
317 317 "remove dataset ",
318 318 "remove dedicated-cpu ",
319 319 "remove capped-cpu ",
320 320 "remove capped-memory ",
321 321 "remove admin ",
322 322 "remove security-flags",
323 323 NULL
324 324 };
325 325
326 326 static const char *select_cmds[] = {
327 327 "select fs ",
328 328 "select net ",
329 329 "select device ",
330 330 "select rctl ",
331 331 "select attr ",
332 332 "select dataset ",
333 333 "select dedicated-cpu",
334 334 "select capped-cpu",
335 335 "select capped-memory",
336 336 "select admin",
337 337 "select security-flags",
338 338 NULL
339 339 };
340 340
341 341 static const char *set_cmds[] = {
342 342 "set zonename=",
343 343 "set zonepath=",
344 344 "set brand=",
345 345 "set autoboot=",
346 346 "set pool=",
347 347 "set limitpriv=",
348 348 "set bootargs=",
349 349 "set scheduling-class=",
350 350 "set ip-type=",
351 351 "set " ALIAS_MAXLWPS "=",
352 352 "set " ALIAS_MAXSHMMEM "=",
353 353 "set " ALIAS_MAXSHMIDS "=",
354 354 "set " ALIAS_MAXMSGIDS "=",
355 355 "set " ALIAS_MAXSEMIDS "=",
356 356 "set " ALIAS_SHARES "=",
357 357 "set hostid=",
358 358 "set fs-allowed=",
359 359 "set " ALIAS_MAXPROCS "=",
360 360 NULL
361 361 };
362 362
363 363 static const char *info_cmds[] = {
364 364 "info fs ",
365 365 "info net ",
366 366 "info device ",
367 367 "info rctl ",
368 368 "info attr ",
369 369 "info dataset ",
370 370 "info capped-memory",
371 371 "info dedicated-cpu",
372 372 "info capped-cpu",
373 373 "info security-flags",
374 374 "info zonename",
375 375 "info zonepath",
376 376 "info autoboot",
377 377 "info pool",
378 378 "info limitpriv",
379 379 "info bootargs",
380 380 "info brand",
381 381 "info scheduling-class",
382 382 "info ip-type",
383 383 "info max-lwps",
384 384 "info max-shm-memory",
385 385 "info max-shm-ids",
386 386 "info max-msg-ids",
387 387 "info max-sem-ids",
388 388 "info cpu-shares",
389 389 "info hostid",
390 390 "info admin",
391 391 "info fs-allowed",
392 392 "info max-processes",
393 393 NULL
394 394 };
395 395
396 396 static const char *fs_res_scope_cmds[] = {
397 397 "add options ",
398 398 "cancel",
399 399 "end",
400 400 "exit",
401 401 "help",
402 402 "info",
403 403 "remove options ",
404 404 "set dir=",
405 405 "set raw=",
406 406 "set special=",
407 407 "set type=",
408 408 "clear raw",
409 409 NULL
410 410 };
411 411
412 412 static const char *net_res_scope_cmds[] = {
413 413 "cancel",
414 414 "end",
415 415 "exit",
416 416 "help",
417 417 "info",
418 418 "set address=",
419 419 "set physical=",
420 420 "set defrouter=",
421 421 NULL
422 422 };
423 423
424 424 static const char *device_res_scope_cmds[] = {
425 425 "cancel",
426 426 "end",
427 427 "exit",
428 428 "help",
429 429 "info",
430 430 "set match=",
431 431 NULL
432 432 };
433 433
434 434 static const char *attr_res_scope_cmds[] = {
435 435 "cancel",
436 436 "end",
437 437 "exit",
438 438 "help",
439 439 "info",
440 440 "set name=",
441 441 "set type=",
442 442 "set value=",
443 443 NULL
444 444 };
445 445
446 446 static const char *rctl_res_scope_cmds[] = {
447 447 "add value ",
448 448 "cancel",
449 449 "end",
450 450 "exit",
451 451 "help",
452 452 "info",
453 453 "remove value ",
454 454 "set name=",
455 455 NULL
456 456 };
457 457
458 458 static const char *dataset_res_scope_cmds[] = {
459 459 "cancel",
460 460 "end",
461 461 "exit",
462 462 "help",
463 463 "info",
464 464 "set name=",
465 465 NULL
466 466 };
467 467
468 468 static const char *pset_res_scope_cmds[] = {
469 469 "cancel",
470 470 "end",
471 471 "exit",
472 472 "help",
473 473 "info",
474 474 "set ncpus=",
475 475 "set importance=",
476 476 "clear importance",
477 477 NULL
478 478 };
479 479
480 480 static const char *pcap_res_scope_cmds[] = {
481 481 "cancel",
482 482 "end",
483 483 "exit",
484 484 "help",
485 485 "info",
486 486 "set ncpus=",
487 487 NULL
488 488 };
489 489
490 490 static const char *mcap_res_scope_cmds[] = {
491 491 "cancel",
492 492 "end",
493 493 "exit",
494 494 "help",
495 495 "info",
496 496 "set physical=",
497 497 "set swap=",
498 498 "set locked=",
499 499 "clear physical",
500 500 "clear swap",
501 501 "clear locked",
502 502 NULL
503 503 };
504 504
505 505 static const char *admin_res_scope_cmds[] = {
506 506 "cancel",
507 507 "end",
508 508 "exit",
509 509 "help",
510 510 "info",
511 511 "set user=",
512 512 "set auths=",
513 513 NULL
514 514 };
515 515
516 516 static const char *secflags_res_scope_cmds[] = {
517 517 "cancel",
518 518 "end",
519 519 "exit",
520 520 "set default=",
521 521 "set lower=",
522 522 "set upper=",
523 523 NULL
524 524 };
525 525
526 526 struct xif {
527 527 struct xif *xif_next;
528 528 char xif_name[LIFNAMSIZ];
529 529 boolean_t xif_has_address;
530 530 boolean_t xif_has_defrouter;
531 531 };
532 532
533 533 /* Global variables */
534 534
535 535 /* list of network interfaces specified for exclusive IP zone */
536 536 struct xif *xif;
537 537
538 538 /* set early in main(), never modified thereafter, used all over the place */
539 539 static char *execname;
540 540
541 541 /* set in main(), used all over the place */
542 542 static zone_dochandle_t handle;
543 543
544 544 /* used all over the place */
545 545 static char zone[ZONENAME_MAX];
546 546 static char revert_zone[ZONENAME_MAX];
547 547
548 548 /* global brand operations */
549 549 static brand_handle_t brand;
550 550
551 551 /* set in modifying functions, checked in read_input() */
552 552 static boolean_t need_to_commit = B_FALSE;
553 553 boolean_t saw_error;
554 554
555 555 /* set in yacc parser, checked in read_input() */
556 556 boolean_t newline_terminated;
557 557
558 558 /* set in main(), checked in lex error handler */
559 559 boolean_t cmd_file_mode;
560 560
561 561 /* set in exit_func(), checked in read_input() */
562 562 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
563 563
564 564 /* used in short_usage() and zerr() */
565 565 static char *cmd_file_name = NULL;
566 566
567 567 /* checked in read_input() and other places */
568 568 static boolean_t ok_to_prompt = B_FALSE;
569 569
570 570 /* set and checked in initialize() */
571 571 static boolean_t got_handle = B_FALSE;
572 572
573 573 /* initialized in do_interactive(), checked in initialize() */
574 574 static boolean_t interactive_mode;
575 575
576 576 /* set if configuring the global zone */
577 577 static boolean_t global_zone = B_FALSE;
578 578
579 579 /* set in main(), checked in multiple places */
580 580 static boolean_t read_only_mode;
581 581
582 582 /* scope is outer/global or inner/resource */
583 583 static boolean_t global_scope = B_TRUE;
584 584 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
585 585 static int end_op = -1; /* operation on end is either add or modify */
586 586
587 587 int num_prop_vals; /* for grammar */
588 588
589 589 /*
590 590 * These are for keeping track of resources as they are specified as part of
591 591 * the multi-step process. They should be initialized by add_resource() or
592 592 * select_func() and filled in by add_property() or set_func().
593 593 */
594 594 static struct zone_fstab old_fstab, in_progress_fstab;
595 595 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
596 596 static struct zone_devtab old_devtab, in_progress_devtab;
597 597 static struct zone_rctltab old_rctltab, in_progress_rctltab;
598 598 static struct zone_attrtab old_attrtab, in_progress_attrtab;
599 599 static struct zone_dstab old_dstab, in_progress_dstab;
600 600 static struct zone_psettab old_psettab, in_progress_psettab;
601 601 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
602 602 static struct zone_admintab old_admintab, in_progress_admintab;
603 603 static struct zone_secflagstab old_secflagstab, in_progress_secflagstab;
604 604
605 605 static GetLine *gl; /* The gl_get_line() resource object */
606 606
607 607 static void bytes_to_units(char *str, char *buf, int bufsize);
608 608
609 609 /* Functions begin here */
610 610
611 611 static boolean_t
612 612 initial_match(const char *line1, const char *line2, int word_end)
613 613 {
614 614 if (word_end <= 0)
615 615 return (B_TRUE);
616 616 return (strncmp(line1, line2, word_end) == 0);
617 617 }
618 618
619 619 static int
620 620 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
621 621 int word_end)
622 622 {
623 623 int i, err;
624 624
625 625 for (i = 0; list[i] != NULL; i++) {
626 626 if (initial_match(line1, list[i], word_end)) {
627 627 err = cpl_add_completion(cpl, line1, 0, word_end,
628 628 list[i] + word_end, "", "");
629 629 if (err != 0)
630 630 return (err);
631 631 }
632 632 }
633 633 return (0);
634 634 }
635 635
636 636 static
637 637 /* ARGSUSED */
638 638 CPL_MATCH_FN(cmd_cpl_fn)
639 639 {
640 640 if (global_scope) {
641 641 /*
642 642 * The MAX/MIN tests below are to make sure we have at least
643 643 * enough characters to distinguish from other prefixes (MAX)
644 644 * but only check MIN(what we have, what we're checking).
645 645 */
646 646 if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
647 647 return (add_stuff(cpl, line, add_cmds, word_end));
648 648 if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
649 649 return (add_stuff(cpl, line, clear_cmds, word_end));
650 650 if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
651 651 return (add_stuff(cpl, line, select_cmds, word_end));
652 652 if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
653 653 return (add_stuff(cpl, line, set_cmds, word_end));
654 654 if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
655 655 return (add_stuff(cpl, line, remove_cmds, word_end));
656 656 if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
657 657 return (add_stuff(cpl, line, info_cmds, word_end));
658 658 return (add_stuff(cpl, line, global_scope_cmds, word_end));
659 659 }
660 660 switch (resource_scope) {
661 661 case RT_FS:
662 662 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
663 663 case RT_NET:
664 664 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
665 665 case RT_DEVICE:
666 666 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
667 667 case RT_RCTL:
668 668 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
669 669 case RT_ATTR:
670 670 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
671 671 case RT_DATASET:
672 672 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
673 673 case RT_DCPU:
674 674 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
675 675 case RT_PCAP:
676 676 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
677 677 case RT_MCAP:
678 678 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
679 679 case RT_ADMIN:
680 680 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
681 681 case RT_SECFLAGS:
682 682 return (add_stuff(cpl, line, secflags_res_scope_cmds,
683 683 word_end));
684 684
685 685 }
686 686 return (0);
687 687 }
688 688
689 689 /*
690 690 * For the main CMD_func() functions below, several of them call getopt()
691 691 * then check optind against argc to make sure an extra parameter was not
692 692 * passed in. The reason this is not caught in the grammar is that the
693 693 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
694 694 * be "-F" (for example), but could be anything. So (for example) this
695 695 * check will prevent "create bogus".
696 696 */
697 697
698 698 cmd_t *
699 699 alloc_cmd(void)
700 700 {
701 701 return (calloc(1, sizeof (cmd_t)));
702 702 }
703 703
704 704 void
705 705 free_cmd(cmd_t *cmd)
706 706 {
707 707 int i;
708 708
709 709 for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
710 710 if (cmd->cmd_property_ptr[i] != NULL) {
711 711 property_value_ptr_t pp = cmd->cmd_property_ptr[i];
712 712
713 713 switch (pp->pv_type) {
714 714 case PROP_VAL_SIMPLE:
715 715 free(pp->pv_simple);
716 716 break;
717 717 case PROP_VAL_COMPLEX:
718 718 free_complex(pp->pv_complex);
719 719 break;
720 720 case PROP_VAL_LIST:
721 721 free_list(pp->pv_list);
722 722 break;
723 723 }
724 724 }
725 725 for (i = 0; i < cmd->cmd_argc; i++)
726 726 free(cmd->cmd_argv[i]);
727 727 free(cmd);
728 728 }
729 729
730 730 complex_property_ptr_t
731 731 alloc_complex(void)
732 732 {
733 733 return (calloc(1, sizeof (complex_property_t)));
734 734 }
735 735
736 736 void
737 737 free_complex(complex_property_ptr_t complex)
738 738 {
739 739 if (complex == NULL)
740 740 return;
741 741 free_complex(complex->cp_next);
742 742 if (complex->cp_value != NULL)
743 743 free(complex->cp_value);
744 744 free(complex);
745 745 }
746 746
747 747 list_property_ptr_t
748 748 alloc_list(void)
749 749 {
750 750 return (calloc(1, sizeof (list_property_t)));
751 751 }
752 752
753 753 void
754 754 free_list(list_property_ptr_t list)
755 755 {
756 756 if (list == NULL)
757 757 return;
758 758 if (list->lp_simple != NULL)
759 759 free(list->lp_simple);
760 760 free_complex(list->lp_complex);
761 761 free_list(list->lp_next);
762 762 free(list);
763 763 }
764 764
765 765 void
766 766 free_outer_list(list_property_ptr_t list)
767 767 {
768 768 if (list == NULL)
769 769 return;
770 770 free_outer_list(list->lp_next);
771 771 free(list);
772 772 }
773 773
774 774 static struct zone_rctlvaltab *
775 775 alloc_rctlvaltab(void)
776 776 {
777 777 return (calloc(1, sizeof (struct zone_rctlvaltab)));
778 778 }
779 779
780 780 static char *
781 781 rt_to_str(int res_type)
782 782 {
783 783 assert(res_type >= RT_MIN && res_type <= RT_MAX);
784 784 return (res_types[res_type]);
785 785 }
786 786
787 787 static char *
788 788 pt_to_str(int prop_type)
789 789 {
790 790 assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
791 791 return (prop_types[prop_type]);
792 792 }
793 793
794 794 static char *
795 795 pvt_to_str(int pv_type)
796 796 {
797 797 assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
798 798 return (prop_val_types[pv_type]);
799 799 }
800 800
801 801 static char *
802 802 cmd_to_str(int cmd_num)
803 803 {
804 804 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
805 805 return (helptab[cmd_num].cmd_name);
806 806 }
807 807
808 808 /* PRINTFLIKE1 */
809 809 static void
810 810 zerr(const char *fmt, ...)
811 811 {
812 812 va_list alist;
813 813 static int last_lineno;
814 814
815 815 /* lex_lineno has already been incremented in the lexer; compensate */
816 816 if (cmd_file_mode && lex_lineno > last_lineno) {
817 817 if (strcmp(cmd_file_name, "-") == 0)
818 818 (void) fprintf(stderr, gettext("On line %d:\n"),
819 819 lex_lineno - 1);
820 820 else
821 821 (void) fprintf(stderr, gettext("On line %d of %s:\n"),
822 822 lex_lineno - 1, cmd_file_name);
823 823 last_lineno = lex_lineno;
824 824 }
825 825 va_start(alist, fmt);
826 826 (void) vfprintf(stderr, fmt, alist);
827 827 (void) fprintf(stderr, "\n");
828 828 va_end(alist);
829 829 }
830 830
831 831 /*
832 832 * This is a separate function rather than a set of define's because of the
833 833 * gettext() wrapping.
834 834 */
835 835
836 836 /*
837 837 * TRANSLATION_NOTE
838 838 * Each string below should have \t follow \n whenever needed; the
839 839 * initial \t and the terminal \n will be provided by the calling function.
840 840 */
841 841
842 842 static char *
843 843 long_help(int cmd_num)
844 844 {
845 845 static char line[1024]; /* arbitrary large amount */
846 846
847 847 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
848 848 switch (cmd_num) {
849 849 case CMD_HELP:
850 850 return (gettext("Prints help message."));
851 851 case CMD_CREATE:
852 852 (void) snprintf(line, sizeof (line),
853 853 gettext("Creates a configuration for the "
854 854 "specified zone. %s should be\n\tused to "
855 855 "begin configuring a new zone. If overwriting an "
856 856 "existing\n\tconfiguration, the -F flag can be "
857 857 "used to force the action. If\n\t-t template is "
858 858 "given, creates a configuration identical to the\n"
859 859 "\tspecified template, except that the zone name "
860 860 "is changed from\n\ttemplate to zonename. '%s -a' "
861 861 "creates a configuration from a\n\tdetached "
862 862 "zonepath. '%s -b' results in a blank "
863 863 "configuration.\n\t'%s' with no arguments applies "
864 864 "the Sun default settings."),
865 865 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
866 866 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
867 867 return (line);
868 868 case CMD_EXIT:
869 869 return (gettext("Exits the program. The -F flag can "
870 870 "be used to force the action."));
871 871 case CMD_EXPORT:
872 872 return (gettext("Prints configuration to standard "
873 873 "output, or to output-file if\n\tspecified, in "
874 874 "a form suitable for use in a command-file."));
875 875 case CMD_ADD:
876 876 return (gettext("Add specified resource to "
877 877 "configuration."));
878 878 case CMD_DELETE:
879 879 return (gettext("Deletes the specified zone. The -F "
880 880 "flag can be used to force the\n\taction."));
881 881 case CMD_REMOVE:
882 882 return (gettext("Remove specified resource from "
883 883 "configuration. The -F flag can be used\n\tto "
884 884 "force the action."));
885 885 case CMD_SELECT:
886 886 (void) snprintf(line, sizeof (line),
887 887 gettext("Selects a resource to modify. "
888 888 "Resource modification is completed\n\twith the "
889 889 "command \"%s\". The property name/value pairs "
890 890 "must uniquely\n\tidentify a resource. Note that "
891 891 "the curly braces ('{', '}') mean one\n\tor more "
892 892 "of whatever is between them."),
893 893 cmd_to_str(CMD_END));
894 894 return (line);
895 895 case CMD_SET:
896 896 return (gettext("Sets property values."));
897 897 case CMD_CLEAR:
898 898 return (gettext("Clears property values."));
899 899 case CMD_INFO:
900 900 return (gettext("Displays information about the "
901 901 "current configuration. If resource\n\ttype is "
902 902 "specified, displays only information about "
903 903 "resources of\n\tthe relevant type. If resource "
904 904 "id is specified, displays only\n\tinformation "
905 905 "about that resource."));
906 906 case CMD_VERIFY:
907 907 return (gettext("Verifies current configuration "
908 908 "for correctness (some resource types\n\thave "
909 909 "required properties)."));
910 910 case CMD_COMMIT:
911 911 (void) snprintf(line, sizeof (line),
912 912 gettext("Commits current configuration. "
913 913 "Configuration must be committed to\n\tbe used by "
914 914 "%s. Until the configuration is committed, "
915 915 "changes \n\tcan be removed with the %s "
916 916 "command. This operation is\n\tattempted "
917 917 "automatically upon completion of a %s "
918 918 "session."), "zoneadm", cmd_to_str(CMD_REVERT),
919 919 "zonecfg");
920 920 return (line);
921 921 case CMD_REVERT:
922 922 return (gettext("Reverts configuration back to the "
923 923 "last committed state. The -F flag\n\tcan be "
924 924 "used to force the action."));
925 925 case CMD_CANCEL:
926 926 return (gettext("Cancels resource/property "
927 927 "specification."));
928 928 case CMD_END:
929 929 return (gettext("Ends resource/property "
930 930 "specification."));
931 931 }
932 932 /* NOTREACHED */
933 933 return (NULL);
934 934 }
935 935
936 936 /*
937 937 * Return the input filename appended to each component of the path
938 938 * or the filename itself if it is absolute.
939 939 * Parameters: path string, file name, output string.
940 940 */
941 941 /* Copied almost verbatim from libtnfctl/prb_findexec.c */
942 942 static const char *
943 943 exec_cat(const char *s1, const char *s2, char *si)
944 944 {
945 945 char *s;
946 946 /* Number of remaining characters in s */
947 947 int cnt = PATH_MAX + 1;
948 948
949 949 s = si;
950 950 while (*s1 && *s1 != ':') { /* Copy first component of path to si */
951 951 if (cnt > 0) {
952 952 *s++ = *s1++;
953 953 cnt--;
954 954 } else {
955 955 s1++;
956 956 }
957 957 }
958 958 if (si != s && cnt > 0) { /* Add slash if s2 is not absolute */
959 959 *s++ = '/';
960 960 cnt--;
961 961 }
962 962 while (*s2 && cnt > 0) { /* Copy s2 to si */
963 963 *s++ = *s2++;
964 964 cnt--;
965 965 }
966 966 *s = '\0'; /* Terminate the output string */
967 967 return (*s1 ? ++s1 : NULL); /* Return next path component or NULL */
968 968 }
969 969
970 970 /* Determine that a name exists in PATH */
971 971 /* Copied with changes from libtnfctl/prb_findexec.c */
972 972 static int
973 973 path_find(const char *name)
974 974 {
975 975 const char *pathstr;
976 976 char fname[PATH_MAX + 2];
977 977 const char *cp;
978 978 struct stat stat_buf;
979 979
980 980 if ((pathstr = getenv("PATH")) == NULL) {
981 981 if (geteuid() == 0 || getuid() == 0)
982 982 pathstr = "/usr/sbin:/usr/bin";
983 983 else
984 984 pathstr = "/usr/bin:";
985 985 }
986 986 cp = strchr(name, '/') ? (const char *) "" : pathstr;
987 987
988 988 do {
989 989 cp = exec_cat(cp, name, fname);
990 990 if (stat(fname, &stat_buf) != -1) {
991 991 /* successful find of the file */
992 992 return (0);
993 993 }
994 994 } while (cp != NULL);
995 995
996 996 return (-1);
997 997 }
998 998
999 999 static FILE *
1000 1000 pager_open(void)
1001 1001 {
1002 1002 FILE *newfp;
1003 1003 char *pager, *space;
1004 1004
1005 1005 pager = getenv("PAGER");
1006 1006 if (pager == NULL || *pager == '\0')
1007 1007 pager = PAGER;
1008 1008
1009 1009 space = strchr(pager, ' ');
1010 1010 if (space)
1011 1011 *space = '\0';
1012 1012 if (path_find(pager) == 0) {
1013 1013 if (space)
1014 1014 *space = ' ';
1015 1015 if ((newfp = popen(pager, "w")) == NULL)
1016 1016 zerr(gettext("PAGER open failed (%s)."),
1017 1017 strerror(errno));
1018 1018 return (newfp);
1019 1019 } else {
1020 1020 zerr(gettext("PAGER %s does not exist (%s)."),
1021 1021 pager, strerror(errno));
1022 1022 }
1023 1023 return (NULL);
1024 1024 }
1025 1025
1026 1026 static void
1027 1027 pager_close(FILE *fp)
1028 1028 {
1029 1029 int status;
1030 1030
1031 1031 status = pclose(fp);
1032 1032 if (status == -1)
1033 1033 zerr(gettext("PAGER close failed (%s)."),
1034 1034 strerror(errno));
1035 1035 }
1036 1036
1037 1037 /*
1038 1038 * Called with verbose TRUE when help is explicitly requested, FALSE for
1039 1039 * unexpected errors.
1040 1040 */
1041 1041
1042 1042 void
1043 1043 usage(boolean_t verbose, uint_t flags)
1044 1044 {
1045 1045 FILE *fp = verbose ? stdout : stderr;
1046 1046 FILE *newfp;
1047 1047 boolean_t need_to_close = B_FALSE;
1048 1048 int i;
1049 1049
1050 1050 /* don't page error output */
1051 1051 if (verbose && interactive_mode) {
1052 1052 if ((newfp = pager_open()) != NULL) {
1053 1053 need_to_close = B_TRUE;
1054 1054 fp = newfp;
1055 1055 }
1056 1056 }
1057 1057
1058 1058 if (flags & HELP_META) {
1059 1059 (void) fprintf(fp, gettext("More help is available for the "
1060 1060 "following:\n"));
1061 1061 (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
1062 1062 cmd_to_str(CMD_HELP));
1063 1063 (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
1064 1064 cmd_to_str(CMD_HELP));
1065 1065 (void) fprintf(fp, "\tusage ('%s usage')\n\n",
1066 1066 cmd_to_str(CMD_HELP));
1067 1067 (void) fprintf(fp, gettext("You may also obtain help on any "
1068 1068 "command by typing '%s <command-name>.'\n"),
1069 1069 cmd_to_str(CMD_HELP));
1070 1070 }
1071 1071 if (flags & HELP_RES_SCOPE) {
1072 1072 switch (resource_scope) {
1073 1073 case RT_FS:
1074 1074 (void) fprintf(fp, gettext("The '%s' resource scope is "
1075 1075 "used to configure a file-system.\n"),
1076 1076 rt_to_str(resource_scope));
1077 1077 (void) fprintf(fp, gettext("Valid commands:\n"));
1078 1078 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1079 1079 pt_to_str(PT_DIR), gettext("<path>"));
1080 1080 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1081 1081 pt_to_str(PT_SPECIAL), gettext("<path>"));
1082 1082 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1083 1083 pt_to_str(PT_RAW), gettext("<raw-device>"));
1084 1084 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1085 1085 pt_to_str(PT_TYPE), gettext("<file-system type>"));
1086 1086 (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
1087 1087 pt_to_str(PT_OPTIONS),
1088 1088 gettext("<file-system options>"));
1089 1089 (void) fprintf(fp, "\t%s %s %s\n",
1090 1090 cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
1091 1091 gettext("<file-system options>"));
1092 1092 (void) fprintf(fp, gettext("Consult the file-system "
1093 1093 "specific manual page, such as mount_ufs(1M), "
1094 1094 "for\ndetails about file-system options. Note "
1095 1095 "that any file-system options with an\nembedded "
1096 1096 "'=' character must be enclosed in double quotes, "
1097 1097 /*CSTYLED*/
1098 1098 "such as \"%s=5\".\n"), MNTOPT_RETRY);
1099 1099 break;
1100 1100 case RT_NET:
1101 1101 (void) fprintf(fp, gettext("The '%s' resource scope is "
1102 1102 "used to configure a network interface.\n"),
1103 1103 rt_to_str(resource_scope));
1104 1104 (void) fprintf(fp, gettext("Valid commands:\n"));
1105 1105 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1106 1106 pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
1107 1107 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1108 1108 pt_to_str(PT_ALLOWED_ADDRESS),
1109 1109 gettext("<IP-address>"));
1110 1110 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1111 1111 pt_to_str(PT_PHYSICAL), gettext("<interface>"));
1112 1112 (void) fprintf(fp, gettext("See ifconfig(1M) for "
1113 1113 "details of the <interface> string.\n"));
1114 1114 (void) fprintf(fp, gettext("%s %s is valid "
1115 1115 "if the %s property is set to %s, otherwise it "
1116 1116 "must not be set.\n"),
1117 1117 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
1118 1118 pt_to_str(PT_IPTYPE), gettext("shared"));
1119 1119 (void) fprintf(fp, gettext("%s %s is valid "
1120 1120 "if the %s property is set to %s, otherwise it "
1121 1121 "must not be set.\n"),
1122 1122 cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
1123 1123 pt_to_str(PT_IPTYPE), gettext("exclusive"));
1124 1124 (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
1125 1125 "is valid if the %s or %s property is set, "
1126 1126 "otherwise it must not be set\n"),
1127 1127 cmd_to_str(CMD_SET),
1128 1128 pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
1129 1129 cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
1130 1130 gettext(pt_to_str(PT_ADDRESS)),
1131 1131 gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
1132 1132 break;
1133 1133 case RT_DEVICE:
1134 1134 (void) fprintf(fp, gettext("The '%s' resource scope is "
1135 1135 "used to configure a device node.\n"),
1136 1136 rt_to_str(resource_scope));
1137 1137 (void) fprintf(fp, gettext("Valid commands:\n"));
1138 1138 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1139 1139 pt_to_str(PT_MATCH), gettext("<device-path>"));
1140 1140 break;
1141 1141 case RT_RCTL:
1142 1142 (void) fprintf(fp, gettext("The '%s' resource scope is "
1143 1143 "used to configure a resource control.\n"),
1144 1144 rt_to_str(resource_scope));
1145 1145 (void) fprintf(fp, gettext("Valid commands:\n"));
1146 1146 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1147 1147 pt_to_str(PT_NAME), gettext("<string>"));
1148 1148 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1149 1149 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
1150 1150 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1151 1151 pt_to_str(PT_LIMIT), gettext("<number>"),
1152 1152 pt_to_str(PT_ACTION), gettext("<action-value>"));
1153 1153 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1154 1154 cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
1155 1155 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1156 1156 pt_to_str(PT_LIMIT), gettext("<number>"),
1157 1157 pt_to_str(PT_ACTION), gettext("<action-value>"));
1158 1158 (void) fprintf(fp, "%s\n\t%s := privileged\n"
1159 1159 "\t%s := none | deny\n", gettext("Where"),
1160 1160 gettext("<priv-value>"), gettext("<action-value>"));
1161 1161 break;
1162 1162 case RT_ATTR:
1163 1163 (void) fprintf(fp, gettext("The '%s' resource scope is "
1164 1164 "used to configure a generic attribute.\n"),
1165 1165 rt_to_str(resource_scope));
1166 1166 (void) fprintf(fp, gettext("Valid commands:\n"));
1167 1167 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1168 1168 pt_to_str(PT_NAME), gettext("<name>"));
1169 1169 (void) fprintf(fp, "\t%s %s=boolean\n",
1170 1170 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1171 1171 (void) fprintf(fp, "\t%s %s=true | false\n",
1172 1172 cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
1173 1173 (void) fprintf(fp, gettext("or\n"));
1174 1174 (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
1175 1175 pt_to_str(PT_TYPE));
1176 1176 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1177 1177 pt_to_str(PT_VALUE), gettext("<integer>"));
1178 1178 (void) fprintf(fp, gettext("or\n"));
1179 1179 (void) fprintf(fp, "\t%s %s=string\n",
1180 1180 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1181 1181 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1182 1182 pt_to_str(PT_VALUE), gettext("<string>"));
1183 1183 (void) fprintf(fp, gettext("or\n"));
1184 1184 (void) fprintf(fp, "\t%s %s=uint\n",
1185 1185 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1186 1186 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1187 1187 pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
1188 1188 break;
1189 1189 case RT_DATASET:
1190 1190 (void) fprintf(fp, gettext("The '%s' resource scope is "
1191 1191 "used to export ZFS datasets.\n"),
1192 1192 rt_to_str(resource_scope));
1193 1193 (void) fprintf(fp, gettext("Valid commands:\n"));
1194 1194 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1195 1195 pt_to_str(PT_NAME), gettext("<name>"));
1196 1196 break;
1197 1197 case RT_DCPU:
1198 1198 (void) fprintf(fp, gettext("The '%s' resource scope "
1199 1199 "configures the 'pools' facility to dedicate\na "
1200 1200 "subset of the system's processors to this zone "
1201 1201 "while it is running.\n"),
1202 1202 rt_to_str(resource_scope));
1203 1203 (void) fprintf(fp, gettext("Valid commands:\n"));
1204 1204 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1205 1205 pt_to_str(PT_NCPUS),
1206 1206 gettext("<unsigned integer | range>"));
1207 1207 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1208 1208 pt_to_str(PT_IMPORTANCE),
1209 1209 gettext("<unsigned integer>"));
1210 1210 break;
1211 1211 case RT_PCAP:
1212 1212 (void) fprintf(fp, gettext("The '%s' resource scope is "
1213 1213 "used to set an upper limit (a cap) on the\n"
1214 1214 "percentage of CPU that can be used by this zone. "
1215 1215 "A '%s' value of 1\ncorresponds to one cpu. The "
1216 1216 "value can be set higher than 1, up to the total\n"
1217 1217 "number of CPUs on the system. The value can "
1218 1218 "also be less than 1,\nrepresenting a fraction of "
1219 1219 "a cpu.\n"),
1220 1220 rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
1221 1221 (void) fprintf(fp, gettext("Valid commands:\n"));
1222 1222 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1223 1223 pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
1224 1224 break;
1225 1225 case RT_MCAP:
1226 1226 (void) fprintf(fp, gettext("The '%s' resource scope is "
1227 1227 "used to set an upper limit (a cap) on the\n"
1228 1228 "amount of physical memory, swap space and locked "
1229 1229 "memory that can be used by\nthis zone.\n"),
1230 1230 rt_to_str(resource_scope));
1231 1231 (void) fprintf(fp, gettext("Valid commands:\n"));
1232 1232 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1233 1233 pt_to_str(PT_PHYSICAL),
1234 1234 gettext("<qualified unsigned decimal>"));
1235 1235 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1236 1236 pt_to_str(PT_SWAP),
1237 1237 gettext("<qualified unsigned decimal>"));
1238 1238 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1239 1239 pt_to_str(PT_LOCKED),
1240 1240 gettext("<qualified unsigned decimal>"));
1241 1241 break;
1242 1242 case RT_ADMIN:
1243 1243 (void) fprintf(fp, gettext("The '%s' resource scope is "
1244 1244 "used to delegate specific zone management\n"
1245 1245 "rights to users and roles. These rights are "
1246 1246 "only applicable to this zone.\n"),
1247 1247 rt_to_str(resource_scope));
1248 1248 (void) fprintf(fp, gettext("Valid commands:\n"));
1249 1249 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1250 1250 pt_to_str(PT_USER),
1251 1251 gettext("<single user or role name>"));
1252 1252 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1253 1253 pt_to_str(PT_AUTHS),
1254 1254 gettext("<comma separated list>"));
1255 1255 break;
1256 1256 case RT_SECFLAGS:
1257 1257 (void) fprintf(fp, gettext("The '%s' resource scope is "
1258 1258 "used to specify the default security-flags\n"
1259 1259 "of this zone, and their upper and lower bound.\n"),
1260 1260 rt_to_str(resource_scope));
1261 1261 (void) fprintf(fp, "\t%s %s=%s\n",
1262 1262 cmd_to_str(CMD_SET), pt_to_str(PT_DEFAULT),
1263 1263 gettext("<security flags>"));
1264 1264 (void) fprintf(fp, "\t%s %s=%s\n",
1265 1265 cmd_to_str(CMD_SET), pt_to_str(PT_LOWER),
1266 1266 gettext("<security flags>"));
1267 1267 (void) fprintf(fp, "\t%s %s=%s\n",
1268 1268 cmd_to_str(CMD_SET), pt_to_str(PT_UPPER),
1269 1269 gettext("<security flags>"));
1270 1270 break;
1271 1271 }
1272 1272 (void) fprintf(fp, gettext("And from any resource scope, you "
1273 1273 "can:\n"));
1274 1274 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1275 1275 gettext("(to conclude this operation)"));
1276 1276 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1277 1277 gettext("(to cancel this operation)"));
1278 1278 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1279 1279 gettext("(to exit the zonecfg utility)"));
1280 1280 }
1281 1281 if (flags & HELP_USAGE) {
1282 1282 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1283 1283 execname, cmd_to_str(CMD_HELP));
1284 1284 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1285 1285 execname, gettext("interactive"));
1286 1286 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1287 1287 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1288 1288 execname);
1289 1289 }
1290 1290 if (flags & HELP_SUBCMDS) {
1291 1291 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1292 1292 for (i = 0; i <= CMD_MAX; i++) {
1293 1293 (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1294 1294 if (verbose)
1295 1295 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1296 1296 }
1297 1297 }
1298 1298 if (flags & HELP_SYNTAX) {
1299 1299 if (!verbose)
1300 1300 (void) fprintf(fp, "\n");
1301 1301 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1302 1302 (void) fprintf(fp, gettext("\t(except the reserved words "
1303 1303 "'%s' and anything starting with '%s')\n"), "global",
1304 1304 "SUNW");
1305 1305 (void) fprintf(fp,
1306 1306 gettext("\tName must be less than %d characters.\n"),
1307 1307 ZONENAME_MAX);
1308 1308 if (verbose)
1309 1309 (void) fprintf(fp, "\n");
1310 1310 }
1311 1311 if (flags & HELP_NETADDR) {
1312 1312 (void) fprintf(fp, gettext("\n<net-addr> :="));
1313 1313 (void) fprintf(fp,
1314 1314 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
1315 1315 (void) fprintf(fp,
1316 1316 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1317 1317 (void) fprintf(fp,
1318 1318 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1319 1319 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1320 1320 "IPv6 address syntax.\n"));
1321 1321 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1322 1322 (void) fprintf(fp,
1323 1323 gettext("<IPv6-prefix-length> := [0-128]\n"));
1324 1324 (void) fprintf(fp,
1325 1325 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1326 1326 }
1327 1327 if (flags & HELP_RESOURCES) {
1328 1328 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1329 1329 "%s | %s | %s | %s | %s\n\n",
1330 1330 gettext("resource type"), rt_to_str(RT_FS),
1331 1331 rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1332 1332 rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1333 1333 rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1334 1334 rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1335 1335 rt_to_str(RT_ADMIN), rt_to_str(RT_SECFLAGS));
1336 1336 }
1337 1337 if (flags & HELP_PROPS) {
1338 1338 (void) fprintf(fp, gettext("For resource type ... there are "
1339 1339 "property types ...:\n"));
1340 1340 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1341 1341 pt_to_str(PT_ZONENAME));
1342 1342 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1343 1343 pt_to_str(PT_ZONEPATH));
1344 1344 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1345 1345 pt_to_str(PT_BRAND));
1346 1346 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1347 1347 pt_to_str(PT_AUTOBOOT));
1348 1348 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1349 1349 pt_to_str(PT_BOOTARGS));
1350 1350 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1351 1351 pt_to_str(PT_POOL));
1352 1352 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1353 1353 pt_to_str(PT_LIMITPRIV));
1354 1354 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1355 1355 pt_to_str(PT_SCHED));
1356 1356 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1357 1357 pt_to_str(PT_IPTYPE));
1358 1358 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1359 1359 pt_to_str(PT_HOSTID));
1360 1360 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1361 1361 pt_to_str(PT_FS_ALLOWED));
1362 1362 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1363 1363 pt_to_str(PT_MAXLWPS));
1364 1364 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1365 1365 pt_to_str(PT_MAXPROCS));
1366 1366 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1367 1367 pt_to_str(PT_MAXSHMMEM));
1368 1368 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1369 1369 pt_to_str(PT_MAXSHMIDS));
1370 1370 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1371 1371 pt_to_str(PT_MAXMSGIDS));
1372 1372 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1373 1373 pt_to_str(PT_MAXSEMIDS));
1374 1374 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1375 1375 pt_to_str(PT_SHARES));
1376 1376 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1377 1377 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1378 1378 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1379 1379 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1380 1380 (void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
1381 1381 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1382 1382 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1383 1383 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1384 1384 pt_to_str(PT_MATCH));
1385 1385 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1386 1386 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1387 1387 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1388 1388 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1389 1389 pt_to_str(PT_VALUE));
1390 1390 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1391 1391 pt_to_str(PT_NAME));
1392 1392 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1393 1393 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1394 1394 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1395 1395 pt_to_str(PT_NCPUS));
1396 1396 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1397 1397 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1398 1398 pt_to_str(PT_LOCKED));
1399 1399 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1400 1400 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1401 1401 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n",
1402 1402 rt_to_str(RT_SECFLAGS), pt_to_str(PT_DEFAULT),
1403 1403 pt_to_str(PT_LOWER), pt_to_str(PT_UPPER));
1404 1404 }
1405 1405 if (need_to_close)
1406 1406 (void) pager_close(fp);
1407 1407 }
1408 1408
1409 1409 static void
1410 1410 zone_perror(char *prefix, int err, boolean_t set_saw)
1411 1411 {
1412 1412 zerr("%s: %s", prefix, zonecfg_strerror(err));
1413 1413 if (set_saw)
1414 1414 saw_error = B_TRUE;
1415 1415 }
1416 1416
1417 1417 /*
1418 1418 * zone_perror() expects a single string, but for remove and select
1419 1419 * we have both the command and the resource type, so this wrapper
1420 1420 * function serves the same purpose in a slightly different way.
1421 1421 */
1422 1422
1423 1423 static void
1424 1424 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1425 1425 {
1426 1426 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
1427 1427 zonecfg_strerror(err));
1428 1428 if (set_saw)
1429 1429 saw_error = B_TRUE;
1430 1430 }
1431 1431
1432 1432 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1433 1433 static int
1434 1434 initialize(boolean_t handle_expected)
1435 1435 {
1436 1436 int err;
1437 1437 char brandname[MAXNAMELEN];
1438 1438
1439 1439 if (zonecfg_check_handle(handle) != Z_OK) {
1440 1440 if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
1441 1441 got_handle = B_TRUE;
1442 1442 if (zonecfg_get_brand(handle, brandname,
1443 1443 sizeof (brandname)) != Z_OK) {
1444 1444 zerr("Zone %s is inconsistent: missing "
1445 1445 "brand attribute", zone);
1446 1446 exit(Z_ERR);
1447 1447 }
1448 1448 if ((brand = brand_open(brandname)) == NULL) {
1449 1449 zerr("Zone %s uses non-existent brand \"%s\"."
1450 1450 " Unable to continue", zone, brandname);
1451 1451 exit(Z_ERR);
1452 1452 }
1453 1453 /*
1454 1454 * If the user_attr file is newer than
1455 1455 * the zone config file, the admins
1456 1456 * may need to be updated since the
1457 1457 * RBAC files are authoritative for
1458 1458 * authorization checks.
1459 1459 */
1460 1460 err = zonecfg_update_userauths(handle, zone);
1461 1461 if (err == Z_OK) {
1462 1462 zerr(gettext("The administrative rights "
1463 1463 "were updated to match "
1464 1464 "the current RBAC configuration.\n"
1465 1465 "Use \"info admin\" and \"revert\" to "
1466 1466 "compare with the previous settings."));
1467 1467 need_to_commit = B_TRUE;
1468 1468 } else if (err != Z_NO_ENTRY) {
1469 1469 zerr(gettext("failed to update "
1470 1470 "admin rights."));
1471 1471 exit(Z_ERR);
1472 1472 } else if (need_to_commit) {
1473 1473 zerr(gettext("admin rights were updated "
1474 1474 "to match RBAC configuration."));
1475 1475 }
1476 1476
1477 1477 } else if (global_zone && err == Z_NO_ZONE && !got_handle &&
1478 1478 !read_only_mode) {
1479 1479 /*
1480 1480 * We implicitly create the global zone config if it
1481 1481 * doesn't exist.
1482 1482 */
1483 1483 zone_dochandle_t tmphandle;
1484 1484
1485 1485 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1486 1486 zone_perror(execname, Z_NOMEM, B_TRUE);
1487 1487 exit(Z_ERR);
1488 1488 }
1489 1489
1490 1490 err = zonecfg_get_template_handle("SUNWblank", zone,
1491 1491 tmphandle);
1492 1492
1493 1493 if (err != Z_OK) {
1494 1494 zonecfg_fini_handle(tmphandle);
1495 1495 zone_perror("SUNWblank", err, B_TRUE);
1496 1496 return (err);
1497 1497 }
1498 1498
1499 1499 need_to_commit = B_TRUE;
1500 1500 zonecfg_fini_handle(handle);
1501 1501 handle = tmphandle;
1502 1502 got_handle = B_TRUE;
1503 1503
1504 1504 } else {
1505 1505 zone_perror(zone, err, handle_expected || got_handle);
1506 1506 if (err == Z_NO_ZONE && !got_handle &&
1507 1507 interactive_mode && !read_only_mode)
1508 1508 (void) printf(gettext("Use '%s' to begin "
1509 1509 "configuring a new zone.\n"),
1510 1510 cmd_to_str(CMD_CREATE));
1511 1511 return (err);
1512 1512 }
1513 1513 }
1514 1514 return (Z_OK);
1515 1515 }
1516 1516
1517 1517 static boolean_t
1518 1518 state_atleast(zone_state_t state)
1519 1519 {
1520 1520 zone_state_t state_num;
1521 1521 int err;
1522 1522
1523 1523 if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
1524 1524 /* all states are greater than "non-existent" */
1525 1525 if (err == Z_NO_ZONE)
1526 1526 return (B_FALSE);
1527 1527 zerr(gettext("Unexpectedly failed to determine state "
1528 1528 "of zone %s: %s"), zone, zonecfg_strerror(err));
1529 1529 exit(Z_ERR);
1530 1530 }
1531 1531 return (state_num >= state);
1532 1532 }
1533 1533
1534 1534 /*
1535 1535 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
1536 1536 */
1537 1537
1538 1538 void
1539 1539 short_usage(int command)
1540 1540 {
1541 1541 /* lex_lineno has already been incremented in the lexer; compensate */
1542 1542 if (cmd_file_mode) {
1543 1543 if (strcmp(cmd_file_name, "-") == 0)
1544 1544 (void) fprintf(stderr,
1545 1545 gettext("syntax error on line %d\n"),
1546 1546 lex_lineno - 1);
1547 1547 else
1548 1548 (void) fprintf(stderr,
1549 1549 gettext("syntax error on line %d of %s\n"),
1550 1550 lex_lineno - 1, cmd_file_name);
1551 1551 }
1552 1552 (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
1553 1553 helptab[command].short_usage);
1554 1554 saw_error = B_TRUE;
1555 1555 }
1556 1556
1557 1557 /*
1558 1558 * long_usage() is for bad semantics: e.g., wrong property type for a given
1559 1559 * resource type. It is also used by longer_usage() below.
1560 1560 */
1561 1561
1562 1562 void
1563 1563 long_usage(uint_t cmd_num, boolean_t set_saw)
1564 1564 {
1565 1565 (void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
1566 1566 helptab[cmd_num].short_usage);
1567 1567 (void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
1568 1568 if (set_saw)
1569 1569 saw_error = B_TRUE;
1570 1570 }
1571 1571
1572 1572 /*
1573 1573 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
1574 1574 * any extra usage() flags as appropriate for whatever command.
1575 1575 */
1576 1576
1577 1577 void
1578 1578 longer_usage(uint_t cmd_num)
1579 1579 {
1580 1580 long_usage(cmd_num, B_FALSE);
1581 1581 if (helptab[cmd_num].flags != 0) {
1582 1582 (void) printf("\n");
1583 1583 usage(B_TRUE, helptab[cmd_num].flags);
1584 1584 }
1585 1585 }
1586 1586
1587 1587 /*
1588 1588 * scope_usage() is simply used when a command is called from the wrong scope.
1589 1589 */
1590 1590
1591 1591 static void
1592 1592 scope_usage(uint_t cmd_num)
1593 1593 {
1594 1594 zerr(gettext("The %s command only makes sense in the %s scope."),
1595 1595 cmd_to_str(cmd_num),
1596 1596 global_scope ? gettext("resource") : gettext("global"));
1597 1597 saw_error = B_TRUE;
1598 1598 }
1599 1599
1600 1600 /*
1601 1601 * On input, B_TRUE => yes, B_FALSE => no.
1602 1602 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
1603 1603 */
1604 1604
1605 1605 static int
1606 1606 ask_yesno(boolean_t default_answer, const char *question)
1607 1607 {
1608 1608 char line[64]; /* should be enough to answer yes or no */
1609 1609
1610 1610 if (!ok_to_prompt) {
1611 1611 saw_error = B_TRUE;
1612 1612 return (-1);
1613 1613 }
1614 1614 for (;;) {
1615 1615 if (printf("%s (%s)? ", question,
1616 1616 default_answer ? "[y]/n" : "y/[n]") < 0)
1617 1617 return (-1);
1618 1618 if (fgets(line, sizeof (line), stdin) == NULL)
1619 1619 return (-1);
1620 1620
1621 1621 if (line[0] == '\n')
1622 1622 return (default_answer ? 1 : 0);
1623 1623 if (tolower(line[0]) == 'y')
1624 1624 return (1);
1625 1625 if (tolower(line[0]) == 'n')
1626 1626 return (0);
1627 1627 }
1628 1628 }
1629 1629
1630 1630 /*
1631 1631 * Prints warning if zone already exists.
1632 1632 * In interactive mode, prompts if we should continue anyway and returns Z_OK
1633 1633 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
1634 1634 *
1635 1635 * Note that if a zone exists and its state is >= INSTALLED, an error message
1636 1636 * will be printed and this function will return Z_ERR regardless of mode.
1637 1637 */
1638 1638
1639 1639 static int
1640 1640 check_if_zone_already_exists(boolean_t force)
1641 1641 {
1642 1642 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
1643 1643 zone_dochandle_t tmphandle;
1644 1644 int res, answer;
1645 1645
1646 1646 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1647 1647 zone_perror(execname, Z_NOMEM, B_TRUE);
1648 1648 exit(Z_ERR);
1649 1649 }
1650 1650 res = zonecfg_get_handle(zone, tmphandle);
1651 1651 zonecfg_fini_handle(tmphandle);
1652 1652 if (res != Z_OK)
1653 1653 return (Z_OK);
1654 1654
1655 1655 if (state_atleast(ZONE_STATE_INSTALLED)) {
1656 1656 zerr(gettext("Zone %s already installed; %s not allowed."),
1657 1657 zone, cmd_to_str(CMD_CREATE));
1658 1658 return (Z_ERR);
1659 1659 }
1660 1660
1661 1661 if (force) {
1662 1662 (void) printf(gettext("Zone %s already exists; overwriting.\n"),
1663 1663 zone);
1664 1664 return (Z_OK);
1665 1665 }
1666 1666 (void) snprintf(line, sizeof (line),
1667 1667 gettext("Zone %s already exists; %s anyway"), zone,
1668 1668 cmd_to_str(CMD_CREATE));
1669 1669 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
1670 1670 zerr(gettext("Zone exists, input not from terminal and -F not "
1671 1671 "specified:\n%s command ignored, exiting."),
1672 1672 cmd_to_str(CMD_CREATE));
1673 1673 exit(Z_ERR);
1674 1674 }
1675 1675 return (answer == 1 ? Z_OK : Z_ERR);
1676 1676 }
1677 1677
1678 1678 static boolean_t
1679 1679 zone_is_read_only(int cmd_num)
1680 1680 {
1681 1681 if (strncmp(zone, "SUNW", 4) == 0) {
1682 1682 zerr(gettext("%s: zones beginning with SUNW are read-only."),
1683 1683 zone);
1684 1684 saw_error = B_TRUE;
1685 1685 return (B_TRUE);
1686 1686 }
1687 1687 if (read_only_mode) {
1688 1688 zerr(gettext("%s: cannot %s in read-only mode."), zone,
1689 1689 cmd_to_str(cmd_num));
1690 1690 saw_error = B_TRUE;
1691 1691 return (B_TRUE);
1692 1692 }
1693 1693 return (B_FALSE);
1694 1694 }
1695 1695
1696 1696 /*
1697 1697 * Create a new configuration.
1698 1698 */
1699 1699 void
1700 1700 create_func(cmd_t *cmd)
1701 1701 {
1702 1702 int err, arg;
1703 1703 char zone_template[ZONENAME_MAX];
1704 1704 char attach_path[MAXPATHLEN];
1705 1705 zone_dochandle_t tmphandle;
1706 1706 boolean_t force = B_FALSE;
1707 1707 boolean_t attach = B_FALSE;
1708 1708 boolean_t arg_err = B_FALSE;
1709 1709
1710 1710 assert(cmd != NULL);
1711 1711
1712 1712 /* This is the default if no arguments are given. */
1713 1713 (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1714 1714
1715 1715 optind = 0;
1716 1716 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
1717 1717 != EOF) {
1718 1718 switch (arg) {
1719 1719 case '?':
1720 1720 if (optopt == '?')
1721 1721 longer_usage(CMD_CREATE);
1722 1722 else
1723 1723 short_usage(CMD_CREATE);
1724 1724 arg_err = B_TRUE;
1725 1725 break;
1726 1726 case 'a':
1727 1727 (void) strlcpy(attach_path, optarg,
1728 1728 sizeof (attach_path));
1729 1729 attach = B_TRUE;
1730 1730 break;
1731 1731 case 'b':
1732 1732 (void) strlcpy(zone_template, "SUNWblank",
1733 1733 sizeof (zone_template));
1734 1734 break;
1735 1735 case 'F':
1736 1736 force = B_TRUE;
1737 1737 break;
1738 1738 case 't':
1739 1739 (void) strlcpy(zone_template, optarg,
1740 1740 sizeof (zone_template));
1741 1741 break;
1742 1742 default:
1743 1743 short_usage(CMD_CREATE);
1744 1744 arg_err = B_TRUE;
1745 1745 break;
1746 1746 }
1747 1747 }
1748 1748 if (arg_err)
1749 1749 return;
1750 1750
1751 1751 if (optind != cmd->cmd_argc) {
1752 1752 short_usage(CMD_CREATE);
1753 1753 return;
1754 1754 }
1755 1755
1756 1756 if (zone_is_read_only(CMD_CREATE))
1757 1757 return;
1758 1758
1759 1759 if (check_if_zone_already_exists(force) != Z_OK)
1760 1760 return;
1761 1761
1762 1762 /*
1763 1763 * Get a temporary handle first. If that fails, the old handle
1764 1764 * will not be lost. Then finish whichever one we don't need,
1765 1765 * to avoid leaks. Then get the handle for zone_template, and
1766 1766 * set the name to zone: this "copy, rename" method is how
1767 1767 * create -[b|t] works.
1768 1768 */
1769 1769 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1770 1770 zone_perror(execname, Z_NOMEM, B_TRUE);
1771 1771 exit(Z_ERR);
1772 1772 }
1773 1773
1774 1774 if (attach)
1775 1775 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1776 1776 zone, B_FALSE, tmphandle);
1777 1777 else
1778 1778 err = zonecfg_get_template_handle(zone_template, zone,
1779 1779 tmphandle);
1780 1780
1781 1781 if (err != Z_OK) {
1782 1782 zonecfg_fini_handle(tmphandle);
1783 1783 if (attach && err == Z_NO_ZONE)
1784 1784 (void) fprintf(stderr, gettext("invalid path to "
1785 1785 "detached zone\n"));
1786 1786 else if (attach && err == Z_INVALID_DOCUMENT)
1787 1787 (void) fprintf(stderr, gettext("Cannot attach to an "
1788 1788 "earlier release of the operating system\n"));
1789 1789 else
1790 1790 zone_perror(zone_template, err, B_TRUE);
1791 1791 return;
1792 1792 }
1793 1793
1794 1794 need_to_commit = B_TRUE;
1795 1795 zonecfg_fini_handle(handle);
1796 1796 handle = tmphandle;
1797 1797 got_handle = B_TRUE;
1798 1798 }
1799 1799
1800 1800 /*
1801 1801 * This malloc()'s memory, which must be freed by the caller.
1802 1802 */
1803 1803 static char *
1804 1804 quoteit(char *instr)
1805 1805 {
1806 1806 char *outstr;
1807 1807 size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
1808 1808
1809 1809 if ((outstr = malloc(outstrsize)) == NULL) {
1810 1810 zone_perror(zone, Z_NOMEM, B_FALSE);
1811 1811 exit(Z_ERR);
1812 1812 }
1813 1813 if (strchr(instr, ' ') == NULL) {
1814 1814 (void) strlcpy(outstr, instr, outstrsize);
1815 1815 return (outstr);
1816 1816 }
1817 1817 (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
1818 1818 return (outstr);
1819 1819 }
1820 1820
1821 1821 static void
1822 1822 export_prop(FILE *of, int prop_num, char *prop_id)
1823 1823 {
1824 1824 char *quote_str;
1825 1825
1826 1826 if (strlen(prop_id) == 0)
1827 1827 return;
1828 1828 quote_str = quoteit(prop_id);
1829 1829 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1830 1830 pt_to_str(prop_num), quote_str);
1831 1831 free(quote_str);
1832 1832 }
1833 1833
1834 1834 void
1835 1835 export_func(cmd_t *cmd)
1836 1836 {
1837 1837 struct zone_nwiftab nwiftab;
1838 1838 struct zone_fstab fstab;
1839 1839 struct zone_devtab devtab;
1840 1840 struct zone_attrtab attrtab;
1841 1841 struct zone_rctltab rctltab;
1842 1842 struct zone_dstab dstab;
1843 1843 struct zone_psettab psettab;
1844 1844 struct zone_mcaptab mcaptab;
1845 1845 struct zone_rctlvaltab *valptr;
1846 1846 struct zone_admintab admintab;
1847 1847 struct zone_secflagstab secflagstab;
1848 1848 int err, arg;
1849 1849 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1850 1850 char bootargs[BOOTARGS_MAX];
1851 1851 char sched[MAXNAMELEN];
1852 1852 char brand[MAXNAMELEN];
1853 1853 char hostidp[HW_HOSTID_LEN];
1854 1854 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1855 1855 char *limitpriv;
1856 1856 FILE *of;
1857 1857 boolean_t autoboot;
1858 1858 zone_iptype_t iptype;
1859 1859 boolean_t need_to_close = B_FALSE;
1860 1860 boolean_t arg_err = B_FALSE;
1861 1861
1862 1862 assert(cmd != NULL);
1863 1863
1864 1864 outfile[0] = '\0';
1865 1865 optind = 0;
1866 1866 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1867 1867 switch (arg) {
1868 1868 case '?':
1869 1869 if (optopt == '?')
1870 1870 longer_usage(CMD_EXPORT);
1871 1871 else
1872 1872 short_usage(CMD_EXPORT);
1873 1873 arg_err = B_TRUE;
1874 1874 break;
1875 1875 case 'f':
1876 1876 (void) strlcpy(outfile, optarg, sizeof (outfile));
1877 1877 break;
1878 1878 default:
1879 1879 short_usage(CMD_EXPORT);
1880 1880 arg_err = B_TRUE;
1881 1881 break;
1882 1882 }
1883 1883 }
1884 1884 if (arg_err)
1885 1885 return;
1886 1886
1887 1887 if (optind != cmd->cmd_argc) {
1888 1888 short_usage(CMD_EXPORT);
1889 1889 return;
1890 1890 }
1891 1891 if (strlen(outfile) == 0) {
1892 1892 of = stdout;
1893 1893 } else {
1894 1894 if ((of = fopen(outfile, "w")) == NULL) {
1895 1895 zerr(gettext("opening file %s: %s"),
1896 1896 outfile, strerror(errno));
1897 1897 goto done;
1898 1898 }
1899 1899 setbuf(of, NULL);
1900 1900 need_to_close = B_TRUE;
1901 1901 }
1902 1902
1903 1903 if ((err = initialize(B_TRUE)) != Z_OK)
1904 1904 goto done;
1905 1905
1906 1906 (void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
1907 1907
1908 1908 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
1909 1909 strlen(zonepath) > 0)
1910 1910 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1911 1911 pt_to_str(PT_ZONEPATH), zonepath);
1912 1912
1913 1913 if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
1914 1914 (strcmp(brand, NATIVE_BRAND_NAME) != 0))
1915 1915 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1916 1916 pt_to_str(PT_BRAND), brand);
1917 1917
1918 1918 if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
1919 1919 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1920 1920 pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
1921 1921
1922 1922 if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
1923 1923 strlen(bootargs) > 0) {
1924 1924 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1925 1925 pt_to_str(PT_BOOTARGS), bootargs);
1926 1926 }
1927 1927
1928 1928 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
1929 1929 strlen(pool) > 0)
1930 1930 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1931 1931 pt_to_str(PT_POOL), pool);
1932 1932
1933 1933 if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
1934 1934 strlen(limitpriv) > 0) {
1935 1935 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1936 1936 pt_to_str(PT_LIMITPRIV), limitpriv);
1937 1937 free(limitpriv);
1938 1938 }
1939 1939
1940 1940 if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
1941 1941 strlen(sched) > 0)
1942 1942 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1943 1943 pt_to_str(PT_SCHED), sched);
1944 1944
1945 1945 if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
1946 1946 switch (iptype) {
1947 1947 case ZS_SHARED:
1948 1948 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1949 1949 pt_to_str(PT_IPTYPE), "shared");
1950 1950 break;
1951 1951 case ZS_EXCLUSIVE:
1952 1952 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1953 1953 pt_to_str(PT_IPTYPE), "exclusive");
1954 1954 break;
1955 1955 }
1956 1956 }
1957 1957
1958 1958 if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1959 1959 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1960 1960 pt_to_str(PT_HOSTID), hostidp);
1961 1961 }
1962 1962
1963 1963 if (zonecfg_get_fs_allowed(handle, fsallowedp,
1964 1964 sizeof (fsallowedp)) == Z_OK) {
1965 1965 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1966 1966 pt_to_str(PT_FS_ALLOWED), fsallowedp);
1967 1967 }
1968 1968
1969 1969 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
1970 1970 zone_perror(zone, err, B_FALSE);
1971 1971 goto done;
1972 1972 }
1973 1973 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
1974 1974 zone_fsopt_t *optptr;
1975 1975
1976 1976 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1977 1977 rt_to_str(RT_FS));
1978 1978 export_prop(of, PT_DIR, fstab.zone_fs_dir);
1979 1979 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
1980 1980 export_prop(of, PT_RAW, fstab.zone_fs_raw);
1981 1981 export_prop(of, PT_TYPE, fstab.zone_fs_type);
1982 1982 for (optptr = fstab.zone_fs_options; optptr != NULL;
1983 1983 optptr = optptr->zone_fsopt_next) {
1984 1984 /*
1985 1985 * Simple property values with embedded equal signs
1986 1986 * need to be quoted to prevent the lexer from
1987 1987 * mis-parsing them as complex name=value pairs.
1988 1988 */
1989 1989 if (strchr(optptr->zone_fsopt_opt, '='))
1990 1990 (void) fprintf(of, "%s %s \"%s\"\n",
1991 1991 cmd_to_str(CMD_ADD),
1992 1992 pt_to_str(PT_OPTIONS),
1993 1993 optptr->zone_fsopt_opt);
1994 1994 else
1995 1995 (void) fprintf(of, "%s %s %s\n",
1996 1996 cmd_to_str(CMD_ADD),
1997 1997 pt_to_str(PT_OPTIONS),
1998 1998 optptr->zone_fsopt_opt);
1999 1999 }
2000 2000 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2001 2001 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2002 2002 }
2003 2003 (void) zonecfg_endfsent(handle);
2004 2004
2005 2005 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2006 2006 zone_perror(zone, err, B_FALSE);
2007 2007 goto done;
2008 2008 }
2009 2009 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2010 2010 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2011 2011 rt_to_str(RT_NET));
2012 2012 export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
2013 2013 export_prop(of, PT_ALLOWED_ADDRESS,
2014 2014 nwiftab.zone_nwif_allowed_address);
2015 2015 export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
2016 2016 export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
2017 2017 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2018 2018 }
2019 2019 (void) zonecfg_endnwifent(handle);
2020 2020
2021 2021 if ((err = zonecfg_setdevent(handle)) != Z_OK) {
2022 2022 zone_perror(zone, err, B_FALSE);
2023 2023 goto done;
2024 2024 }
2025 2025 while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
2026 2026 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2027 2027 rt_to_str(RT_DEVICE));
2028 2028 export_prop(of, PT_MATCH, devtab.zone_dev_match);
2029 2029 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2030 2030 }
2031 2031 (void) zonecfg_enddevent(handle);
2032 2032
2033 2033 if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
2034 2034 char buf[128];
2035 2035
2036 2036 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2037 2037 rt_to_str(RT_MCAP));
2038 2038 bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
2039 2039 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2040 2040 pt_to_str(PT_PHYSICAL), buf);
2041 2041 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2042 2042 }
2043 2043
2044 2044 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
2045 2045 zone_perror(zone, err, B_FALSE);
2046 2046 goto done;
2047 2047 }
2048 2048 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2049 2049 (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
2050 2050 export_prop(of, PT_NAME, rctltab.zone_rctl_name);
2051 2051 for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
2052 2052 valptr = valptr->zone_rctlval_next) {
2053 2053 fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2054 2054 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
2055 2055 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
2056 2056 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
2057 2057 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
2058 2058 }
2059 2059 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2060 2060 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2061 2061 }
2062 2062 (void) zonecfg_endrctlent(handle);
2063 2063
2064 2064 if ((err = zonecfg_setattrent(handle)) != Z_OK) {
2065 2065 zone_perror(zone, err, B_FALSE);
2066 2066 goto done;
2067 2067 }
2068 2068 while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
2069 2069 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2070 2070 rt_to_str(RT_ATTR));
2071 2071 export_prop(of, PT_NAME, attrtab.zone_attr_name);
2072 2072 export_prop(of, PT_TYPE, attrtab.zone_attr_type);
2073 2073 export_prop(of, PT_VALUE, attrtab.zone_attr_value);
2074 2074 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2075 2075 }
2076 2076 (void) zonecfg_endattrent(handle);
2077 2077
2078 2078 if ((err = zonecfg_setdsent(handle)) != Z_OK) {
2079 2079 zone_perror(zone, err, B_FALSE);
2080 2080 goto done;
2081 2081 }
2082 2082 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
2083 2083 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2084 2084 rt_to_str(RT_DATASET));
2085 2085 export_prop(of, PT_NAME, dstab.zone_dataset_name);
2086 2086 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2087 2087 }
2088 2088 (void) zonecfg_enddsent(handle);
2089 2089
2090 2090 if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
2091 2091 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2092 2092 rt_to_str(RT_DCPU));
2093 2093 if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
2094 2094 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2095 2095 pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
2096 2096 else
2097 2097 (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
2098 2098 pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
2099 2099 psettab.zone_ncpu_max);
2100 2100 if (psettab.zone_importance[0] != '\0')
2101 2101 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2102 2102 pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
2103 2103 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2104 2104 }
2105 2105
2106 2106 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
2107 2107 zone_perror(zone, err, B_FALSE);
2108 2108 goto done;
2109 2109 }
↓ open down ↓ |
2109 lines elided |
↑ open up ↑ |
2110 2110 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
2111 2111 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2112 2112 rt_to_str(RT_ADMIN));
2113 2113 export_prop(of, PT_USER, admintab.zone_admin_user);
2114 2114 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
2115 2115 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2116 2116 }
2117 2117
2118 2118 (void) zonecfg_endadminent(handle);
2119 2119
2120 - if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
2121 - zone_perror(zone, err, B_FALSE);
2122 - goto done;
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));
2123 2127 }
2124 2128
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 2129 /*
2133 2130 * There is nothing to export for pcap since this resource is just
2134 2131 * a container for an rctl alias.
2135 2132 */
2136 2133
2137 2134 done:
2138 2135 if (need_to_close)
2139 2136 (void) fclose(of);
2140 2137 }
2141 2138
2142 2139 void
2143 2140 exit_func(cmd_t *cmd)
2144 2141 {
2145 2142 int arg, answer;
2146 2143 boolean_t arg_err = B_FALSE;
2147 2144
2148 2145 optind = 0;
2149 2146 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2150 2147 switch (arg) {
2151 2148 case '?':
2152 2149 longer_usage(CMD_EXIT);
2153 2150 arg_err = B_TRUE;
2154 2151 break;
2155 2152 case 'F':
2156 2153 force_exit = B_TRUE;
2157 2154 break;
2158 2155 default:
2159 2156 short_usage(CMD_EXIT);
2160 2157 arg_err = B_TRUE;
2161 2158 break;
2162 2159 }
2163 2160 }
2164 2161 if (arg_err)
2165 2162 return;
2166 2163
2167 2164 if (optind < cmd->cmd_argc) {
2168 2165 short_usage(CMD_EXIT);
2169 2166 return;
2170 2167 }
2171 2168
2172 2169 if (global_scope || force_exit) {
2173 2170 time_to_exit = B_TRUE;
2174 2171 return;
2175 2172 }
2176 2173
2177 2174 answer = ask_yesno(B_FALSE, "Resource incomplete; really quit");
2178 2175 if (answer == -1) {
2179 2176 zerr(gettext("Resource incomplete, input "
2180 2177 "not from terminal and -F not specified:\n%s command "
2181 2178 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
2182 2179 exit(Z_ERR);
2183 2180 } else if (answer == 1) {
2184 2181 time_to_exit = B_TRUE;
2185 2182 }
2186 2183 /* (answer == 0) => just return */
2187 2184 }
2188 2185
2189 2186 static int
2190 2187 validate_zonepath_syntax(char *path)
2191 2188 {
2192 2189 if (path[0] != '/') {
2193 2190 zerr(gettext("%s is not an absolute path."), path);
2194 2191 return (Z_ERR);
2195 2192 }
2196 2193 /* If path is all slashes, then fail */
2197 2194 if (strspn(path, "/") == strlen(path)) {
2198 2195 zerr(gettext("/ is not allowed as a %s."),
2199 2196 pt_to_str(PT_ZONEPATH));
2200 2197 return (Z_ERR);
2201 2198 }
2202 2199 return (Z_OK);
2203 2200 }
2204 2201
2205 2202 static void
2206 2203 add_resource(cmd_t *cmd)
2207 2204 {
2208 2205 int type;
2209 2206 struct zone_psettab tmp_psettab;
2210 2207 struct zone_mcaptab tmp_mcaptab;
2211 2208 struct zone_secflagstab tmp_secflagstab;
2212 2209 uint64_t tmp;
2213 2210 uint64_t tmp_mcap;
2214 2211 char pool[MAXNAMELEN];
2215 2212
2216 2213 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2217 2214 long_usage(CMD_ADD, B_TRUE);
2218 2215 goto bad;
2219 2216 }
2220 2217
2221 2218 switch (type) {
2222 2219 case RT_FS:
2223 2220 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2224 2221 return;
2225 2222 case RT_NET:
2226 2223 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2227 2224 return;
2228 2225 case RT_DEVICE:
2229 2226 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2230 2227 return;
2231 2228 case RT_RCTL:
2232 2229 if (global_zone)
2233 2230 zerr(gettext("WARNING: Setting a global zone resource "
2234 2231 "control too low could deny\nservice "
2235 2232 "to even the root user; "
2236 2233 "this could render the system impossible\n"
2237 2234 "to administer. Please use caution."));
2238 2235 bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
2239 2236 return;
2240 2237 case RT_ATTR:
2241 2238 bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
2242 2239 return;
2243 2240 case RT_DATASET:
2244 2241 bzero(&in_progress_dstab, sizeof (in_progress_dstab));
2245 2242 return;
2246 2243 case RT_DCPU:
2247 2244 /* Make sure there isn't already a cpu-set or cpu-cap entry. */
2248 2245 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
2249 2246 zerr(gettext("The %s resource already exists."),
2250 2247 rt_to_str(RT_DCPU));
2251 2248 goto bad;
2252 2249 }
2253 2250 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
2254 2251 Z_NO_ENTRY) {
2255 2252 zerr(gettext("The %s resource already exists."),
2256 2253 rt_to_str(RT_PCAP));
2257 2254 goto bad;
2258 2255 }
2259 2256
2260 2257 /* Make sure the pool property isn't set. */
2261 2258 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
2262 2259 strlen(pool) > 0) {
2263 2260 zerr(gettext("The %s property is already set. "
2264 2261 "A persistent pool is incompatible with\nthe %s "
2265 2262 "resource."),
2266 2263 pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
2267 2264 goto bad;
2268 2265 }
2269 2266
2270 2267 bzero(&in_progress_psettab, sizeof (in_progress_psettab));
2271 2268 return;
2272 2269 case RT_PCAP:
2273 2270 /*
2274 2271 * Make sure there isn't already a cpu-set or incompatible
2275 2272 * cpu-cap rctls.
2276 2273 */
2277 2274 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
2278 2275 zerr(gettext("The %s resource already exists."),
2279 2276 rt_to_str(RT_DCPU));
2280 2277 goto bad;
2281 2278 }
2282 2279
2283 2280 switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
2284 2281 case Z_ALIAS_DISALLOW:
2285 2282 zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
2286 2283 B_FALSE);
2287 2284 goto bad;
2288 2285
2289 2286 case Z_OK:
2290 2287 zerr(gettext("The %s resource already exists."),
2291 2288 rt_to_str(RT_PCAP));
2292 2289 goto bad;
2293 2290
2294 2291 default:
2295 2292 break;
2296 2293 }
2297 2294 return;
2298 2295 case RT_MCAP:
2299 2296 /*
2300 2297 * Make sure there isn't already a mem-cap entry or max-swap
2301 2298 * or max-locked rctl.
2302 2299 */
2303 2300 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2304 2301 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2305 2302 == Z_OK ||
2306 2303 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2307 2304 &tmp_mcap) == Z_OK) {
2308 2305 zerr(gettext("The %s resource or a related resource "
2309 2306 "control already exists."), rt_to_str(RT_MCAP));
2310 2307 goto bad;
2311 2308 }
2312 2309 if (global_zone)
2313 2310 zerr(gettext("WARNING: Setting a global zone memory "
2314 2311 "cap too low could deny\nservice "
2315 2312 "to even the root user; "
2316 2313 "this could render the system impossible\n"
2317 2314 "to administer. Please use caution."));
2318 2315 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2319 2316 return;
2320 2317 case RT_ADMIN:
2321 2318 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2322 2319 return;
2323 2320 case RT_SECFLAGS:
2324 2321 /* Make sure we haven't already set this */
2325 2322 if (zonecfg_lookup_secflags(handle, &tmp_secflagstab) == Z_OK)
2326 2323 zerr(gettext("The %s resource already exists."),
2327 2324 rt_to_str(RT_SECFLAGS));
2328 2325 bzero(&in_progress_secflagstab,
2329 2326 sizeof (in_progress_secflagstab));
2330 2327 return;
2331 2328 default:
2332 2329 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2333 2330 long_usage(CMD_ADD, B_TRUE);
2334 2331 usage(B_FALSE, HELP_RESOURCES);
2335 2332 }
2336 2333 bad:
2337 2334 global_scope = B_TRUE;
2338 2335 end_op = -1;
2339 2336 }
2340 2337
2341 2338 static void
2342 2339 do_complex_rctl_val(complex_property_ptr_t cp)
2343 2340 {
2344 2341 struct zone_rctlvaltab *rctlvaltab;
2345 2342 complex_property_ptr_t cx;
2346 2343 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2347 2344 seen_action = B_FALSE;
2348 2345 rctlblk_t *rctlblk;
2349 2346 int err;
2350 2347
2351 2348 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
2352 2349 zone_perror(zone, Z_NOMEM, B_TRUE);
2353 2350 exit(Z_ERR);
2354 2351 }
2355 2352 for (cx = cp; cx != NULL; cx = cx->cp_next) {
2356 2353 switch (cx->cp_type) {
2357 2354 case PT_PRIV:
2358 2355 if (seen_priv) {
2359 2356 zerr(gettext("%s already specified"),
2360 2357 pt_to_str(PT_PRIV));
2361 2358 goto bad;
2362 2359 }
2363 2360 (void) strlcpy(rctlvaltab->zone_rctlval_priv,
2364 2361 cx->cp_value,
2365 2362 sizeof (rctlvaltab->zone_rctlval_priv));
2366 2363 seen_priv = B_TRUE;
2367 2364 break;
2368 2365 case PT_LIMIT:
2369 2366 if (seen_limit) {
2370 2367 zerr(gettext("%s already specified"),
2371 2368 pt_to_str(PT_LIMIT));
2372 2369 goto bad;
2373 2370 }
2374 2371 (void) strlcpy(rctlvaltab->zone_rctlval_limit,
2375 2372 cx->cp_value,
2376 2373 sizeof (rctlvaltab->zone_rctlval_limit));
2377 2374 seen_limit = B_TRUE;
2378 2375 break;
2379 2376 case PT_ACTION:
2380 2377 if (seen_action) {
2381 2378 zerr(gettext("%s already specified"),
2382 2379 pt_to_str(PT_ACTION));
2383 2380 goto bad;
2384 2381 }
2385 2382 (void) strlcpy(rctlvaltab->zone_rctlval_action,
2386 2383 cx->cp_value,
2387 2384 sizeof (rctlvaltab->zone_rctlval_action));
2388 2385 seen_action = B_TRUE;
2389 2386 break;
2390 2387 default:
2391 2388 zone_perror(pt_to_str(PT_VALUE),
2392 2389 Z_NO_PROPERTY_TYPE, B_TRUE);
2393 2390 long_usage(CMD_ADD, B_TRUE);
2394 2391 usage(B_FALSE, HELP_PROPS);
2395 2392 zonecfg_free_rctl_value_list(rctlvaltab);
2396 2393 return;
2397 2394 }
2398 2395 }
2399 2396 if (!seen_priv)
2400 2397 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
2401 2398 if (!seen_limit)
2402 2399 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
2403 2400 if (!seen_action)
2404 2401 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
2405 2402 if (!seen_priv || !seen_limit || !seen_action)
2406 2403 goto bad;
2407 2404 rctlvaltab->zone_rctlval_next = NULL;
2408 2405 rctlblk = alloca(rctlblk_size());
2409 2406 /*
2410 2407 * Make sure the rctl value looks roughly correct; we won't know if
2411 2408 * it's truly OK until we verify the configuration on the target
2412 2409 * system.
2413 2410 */
2414 2411 if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
2415 2412 !zonecfg_valid_rctlblk(rctlblk)) {
2416 2413 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
2417 2414 pt_to_str(PT_VALUE));
2418 2415 goto bad;
2419 2416 }
2420 2417 err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
2421 2418 if (err != Z_OK)
2422 2419 zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
2423 2420 return;
2424 2421
2425 2422 bad:
2426 2423 zonecfg_free_rctl_value_list(rctlvaltab);
2427 2424 }
2428 2425
2429 2426 static void
2430 2427 add_property(cmd_t *cmd)
2431 2428 {
2432 2429 char *prop_id;
2433 2430 int err, res_type, prop_type;
2434 2431 property_value_ptr_t pp;
2435 2432 list_property_ptr_t l;
2436 2433
2437 2434 res_type = resource_scope;
2438 2435 prop_type = cmd->cmd_prop_name[0];
2439 2436 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
2440 2437 long_usage(CMD_ADD, B_TRUE);
2441 2438 return;
2442 2439 }
2443 2440
2444 2441 if (cmd->cmd_prop_nv_pairs != 1) {
2445 2442 long_usage(CMD_ADD, B_TRUE);
2446 2443 return;
2447 2444 }
2448 2445
2449 2446 if (initialize(B_TRUE) != Z_OK)
2450 2447 return;
2451 2448
2452 2449 switch (res_type) {
2453 2450 case RT_FS:
2454 2451 if (prop_type != PT_OPTIONS) {
2455 2452 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2456 2453 B_TRUE);
2457 2454 long_usage(CMD_ADD, B_TRUE);
2458 2455 usage(B_FALSE, HELP_PROPS);
2459 2456 return;
2460 2457 }
2461 2458 pp = cmd->cmd_property_ptr[0];
2462 2459 if (pp->pv_type != PROP_VAL_SIMPLE &&
2463 2460 pp->pv_type != PROP_VAL_LIST) {
2464 2461 zerr(gettext("A %s or %s value was expected here."),
2465 2462 pvt_to_str(PROP_VAL_SIMPLE),
2466 2463 pvt_to_str(PROP_VAL_LIST));
2467 2464 saw_error = B_TRUE;
2468 2465 return;
2469 2466 }
2470 2467 if (pp->pv_type == PROP_VAL_SIMPLE) {
2471 2468 if (pp->pv_simple == NULL) {
2472 2469 long_usage(CMD_ADD, B_TRUE);
2473 2470 return;
2474 2471 }
2475 2472 prop_id = pp->pv_simple;
2476 2473 err = zonecfg_add_fs_option(&in_progress_fstab,
2477 2474 prop_id);
2478 2475 if (err != Z_OK)
2479 2476 zone_perror(pt_to_str(prop_type), err, B_TRUE);
2480 2477 } else {
2481 2478 list_property_ptr_t list;
2482 2479
2483 2480 for (list = pp->pv_list; list != NULL;
2484 2481 list = list->lp_next) {
2485 2482 prop_id = list->lp_simple;
2486 2483 if (prop_id == NULL)
2487 2484 break;
2488 2485 err = zonecfg_add_fs_option(
2489 2486 &in_progress_fstab, prop_id);
2490 2487 if (err != Z_OK)
2491 2488 zone_perror(pt_to_str(prop_type), err,
2492 2489 B_TRUE);
2493 2490 }
2494 2491 }
2495 2492 return;
2496 2493 case RT_RCTL:
2497 2494 if (prop_type != PT_VALUE) {
2498 2495 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2499 2496 B_TRUE);
2500 2497 long_usage(CMD_ADD, B_TRUE);
2501 2498 usage(B_FALSE, HELP_PROPS);
2502 2499 return;
2503 2500 }
2504 2501 pp = cmd->cmd_property_ptr[0];
2505 2502 if (pp->pv_type != PROP_VAL_COMPLEX &&
2506 2503 pp->pv_type != PROP_VAL_LIST) {
2507 2504 zerr(gettext("A %s or %s value was expected here."),
2508 2505 pvt_to_str(PROP_VAL_COMPLEX),
2509 2506 pvt_to_str(PROP_VAL_LIST));
2510 2507 saw_error = B_TRUE;
2511 2508 return;
2512 2509 }
2513 2510 if (pp->pv_type == PROP_VAL_COMPLEX) {
2514 2511 do_complex_rctl_val(pp->pv_complex);
2515 2512 return;
2516 2513 }
2517 2514 for (l = pp->pv_list; l != NULL; l = l->lp_next)
2518 2515 do_complex_rctl_val(l->lp_complex);
2519 2516 return;
2520 2517 default:
2521 2518 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2522 2519 long_usage(CMD_ADD, B_TRUE);
2523 2520 usage(B_FALSE, HELP_RESOURCES);
2524 2521 return;
2525 2522 }
2526 2523 }
2527 2524
2528 2525 static boolean_t
2529 2526 gz_invalid_resource(int type)
2530 2527 {
2531 2528 return (global_zone && (type == RT_FS ||
2532 2529 type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2533 2530 type == RT_DATASET));
2534 2531 }
2535 2532
2536 2533 static boolean_t
2537 2534 gz_invalid_rt_property(int type)
2538 2535 {
2539 2536 return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2540 2537 type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
2541 2538 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2542 2539 type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2543 2540 }
2544 2541
2545 2542 static boolean_t
2546 2543 gz_invalid_property(int type)
2547 2544 {
2548 2545 return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2549 2546 type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
2550 2547 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2551 2548 type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2552 2549 }
2553 2550
2554 2551 void
2555 2552 add_func(cmd_t *cmd)
2556 2553 {
2557 2554 int arg;
2558 2555 boolean_t arg_err = B_FALSE;
2559 2556
2560 2557 assert(cmd != NULL);
2561 2558
2562 2559 optind = 0;
2563 2560 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2564 2561 switch (arg) {
2565 2562 case '?':
2566 2563 longer_usage(CMD_ADD);
2567 2564 arg_err = B_TRUE;
2568 2565 break;
2569 2566 default:
2570 2567 short_usage(CMD_ADD);
2571 2568 arg_err = B_TRUE;
2572 2569 break;
2573 2570 }
2574 2571 }
2575 2572 if (arg_err)
2576 2573 return;
2577 2574
2578 2575 if (optind != cmd->cmd_argc) {
2579 2576 short_usage(CMD_ADD);
2580 2577 return;
2581 2578 }
2582 2579
2583 2580 if (zone_is_read_only(CMD_ADD))
2584 2581 return;
2585 2582
2586 2583 if (initialize(B_TRUE) != Z_OK)
2587 2584 return;
2588 2585 if (global_scope) {
2589 2586 if (gz_invalid_resource(cmd->cmd_res_type)) {
2590 2587 zerr(gettext("Cannot add a %s resource to the "
2591 2588 "global zone."), rt_to_str(cmd->cmd_res_type));
2592 2589 saw_error = B_TRUE;
2593 2590 return;
2594 2591 }
2595 2592
2596 2593 global_scope = B_FALSE;
2597 2594 resource_scope = cmd->cmd_res_type;
2598 2595 end_op = CMD_ADD;
2599 2596 add_resource(cmd);
2600 2597 } else
2601 2598 add_property(cmd);
2602 2599 }
2603 2600
2604 2601 /*
2605 2602 * This routine has an unusual implementation, because it tries very
2606 2603 * hard to succeed in the face of a variety of failure modes.
2607 2604 * The most common and most vexing occurs when the index file and
2608 2605 * the /etc/zones/<zonename.xml> file are not both present. In
2609 2606 * this case, delete must eradicate as much of the zone state as is left
2610 2607 * so that the user can later create a new zone with the same name.
2611 2608 */
2612 2609 void
2613 2610 delete_func(cmd_t *cmd)
2614 2611 {
2615 2612 int err, arg, answer;
2616 2613 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
2617 2614 boolean_t force = B_FALSE;
2618 2615 boolean_t arg_err = B_FALSE;
2619 2616
2620 2617 optind = 0;
2621 2618 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2622 2619 switch (arg) {
2623 2620 case '?':
2624 2621 longer_usage(CMD_DELETE);
2625 2622 arg_err = B_TRUE;
2626 2623 break;
2627 2624 case 'F':
2628 2625 force = B_TRUE;
2629 2626 break;
2630 2627 default:
2631 2628 short_usage(CMD_DELETE);
2632 2629 arg_err = B_TRUE;
2633 2630 break;
2634 2631 }
2635 2632 }
2636 2633 if (arg_err)
2637 2634 return;
2638 2635
2639 2636 if (optind != cmd->cmd_argc) {
2640 2637 short_usage(CMD_DELETE);
2641 2638 return;
2642 2639 }
2643 2640
2644 2641 if (zone_is_read_only(CMD_DELETE))
2645 2642 return;
2646 2643
2647 2644 if (!force) {
2648 2645 /*
2649 2646 * Initialize sets up the global called "handle" and warns the
2650 2647 * user if the zone is not configured. In force mode, we don't
2651 2648 * trust that evaluation, and hence skip it. (We don't need the
2652 2649 * handle to be loaded anyway, since zonecfg_destroy is done by
2653 2650 * zonename). However, we also have to take care to emulate the
2654 2651 * messages spit out by initialize; see below.
2655 2652 */
2656 2653 if (initialize(B_TRUE) != Z_OK)
2657 2654 return;
2658 2655
2659 2656 (void) snprintf(line, sizeof (line),
2660 2657 gettext("Are you sure you want to delete zone %s"), zone);
2661 2658 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
2662 2659 zerr(gettext("Input not from terminal and -F not "
2663 2660 "specified:\n%s command ignored, exiting."),
2664 2661 cmd_to_str(CMD_DELETE));
2665 2662 exit(Z_ERR);
2666 2663 }
2667 2664 if (answer != 1)
2668 2665 return;
2669 2666 }
2670 2667
2671 2668 /*
2672 2669 * This function removes the authorizations from user_attr
2673 2670 * that correspond to those specified in the configuration
2674 2671 */
2675 2672 if (initialize(B_TRUE) == Z_OK) {
2676 2673 (void) zonecfg_deauthorize_users(handle, zone);
2677 2674 }
2678 2675 if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
2679 2676 if ((err == Z_BAD_ZONE_STATE) && !force) {
2680 2677 zerr(gettext("Zone %s not in %s state; %s not "
2681 2678 "allowed. Use -F to force %s."),
2682 2679 zone, zone_state_str(ZONE_STATE_CONFIGURED),
2683 2680 cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
2684 2681 } else {
2685 2682 zone_perror(zone, err, B_TRUE);
2686 2683 }
2687 2684 }
2688 2685 need_to_commit = B_FALSE;
2689 2686
2690 2687 /*
2691 2688 * Emulate initialize's messaging; if there wasn't a valid handle to
2692 2689 * begin with, then user had typed delete (or delete -F) multiple
2693 2690 * times. So we emit a message.
2694 2691 *
2695 2692 * We only do this in the 'force' case because normally, initialize()
2696 2693 * takes care of this for us.
2697 2694 */
2698 2695 if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
2699 2696 (void) printf(gettext("Use '%s' to begin "
2700 2697 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
2701 2698
2702 2699 /*
2703 2700 * Time for a new handle: finish the old one off first
2704 2701 * then get a new one properly to avoid leaks.
2705 2702 */
2706 2703 if (got_handle) {
2707 2704 zonecfg_fini_handle(handle);
2708 2705 if ((handle = zonecfg_init_handle()) == NULL) {
2709 2706 zone_perror(execname, Z_NOMEM, B_TRUE);
2710 2707 exit(Z_ERR);
2711 2708 }
2712 2709 if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
2713 2710 /* If there was no zone before, that's OK */
2714 2711 if (err != Z_NO_ZONE)
2715 2712 zone_perror(zone, err, B_TRUE);
2716 2713 got_handle = B_FALSE;
2717 2714 }
2718 2715 }
2719 2716 }
2720 2717
2721 2718 static int
2722 2719 fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only)
2723 2720 {
2724 2721 int err, i;
2725 2722 property_value_ptr_t pp;
2726 2723
2727 2724 if ((err = initialize(B_TRUE)) != Z_OK)
2728 2725 return (err);
2729 2726
2730 2727 bzero(fstab, sizeof (*fstab));
2731 2728 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2732 2729 pp = cmd->cmd_property_ptr[i];
2733 2730 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2734 2731 zerr(gettext("A simple value was expected here."));
2735 2732 saw_error = B_TRUE;
2736 2733 return (Z_INSUFFICIENT_SPEC);
2737 2734 }
2738 2735 switch (cmd->cmd_prop_name[i]) {
2739 2736 case PT_DIR:
2740 2737 (void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
2741 2738 sizeof (fstab->zone_fs_dir));
2742 2739 break;
2743 2740 case PT_SPECIAL:
2744 2741 (void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
2745 2742 sizeof (fstab->zone_fs_special));
2746 2743 break;
2747 2744 case PT_RAW:
2748 2745 (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2749 2746 sizeof (fstab->zone_fs_raw));
2750 2747 break;
2751 2748 case PT_TYPE:
2752 2749 (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2753 2750 sizeof (fstab->zone_fs_type));
2754 2751 break;
2755 2752 default:
2756 2753 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2757 2754 Z_NO_PROPERTY_TYPE, B_TRUE);
2758 2755 return (Z_INSUFFICIENT_SPEC);
2759 2756 }
2760 2757 }
2761 2758 if (fill_in_only)
2762 2759 return (Z_OK);
2763 2760 return (zonecfg_lookup_filesystem(handle, fstab));
2764 2761 }
2765 2762
2766 2763 static int
2767 2764 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2768 2765 boolean_t fill_in_only)
2769 2766 {
2770 2767 int err, i;
2771 2768 property_value_ptr_t pp;
2772 2769
2773 2770 if ((err = initialize(B_TRUE)) != Z_OK)
2774 2771 return (err);
2775 2772
2776 2773 bzero(nwiftab, sizeof (*nwiftab));
2777 2774 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2778 2775 pp = cmd->cmd_property_ptr[i];
2779 2776 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2780 2777 zerr(gettext("A simple value was expected here."));
2781 2778 saw_error = B_TRUE;
2782 2779 return (Z_INSUFFICIENT_SPEC);
2783 2780 }
2784 2781 switch (cmd->cmd_prop_name[i]) {
2785 2782 case PT_ADDRESS:
2786 2783 (void) strlcpy(nwiftab->zone_nwif_address,
2787 2784 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2788 2785 break;
2789 2786 case PT_ALLOWED_ADDRESS:
2790 2787 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2791 2788 pp->pv_simple,
2792 2789 sizeof (nwiftab->zone_nwif_allowed_address));
2793 2790 break;
2794 2791 case PT_PHYSICAL:
2795 2792 (void) strlcpy(nwiftab->zone_nwif_physical,
2796 2793 pp->pv_simple,
2797 2794 sizeof (nwiftab->zone_nwif_physical));
2798 2795 break;
2799 2796 case PT_DEFROUTER:
2800 2797 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2801 2798 pp->pv_simple,
2802 2799 sizeof (nwiftab->zone_nwif_defrouter));
2803 2800 break;
2804 2801 default:
2805 2802 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2806 2803 Z_NO_PROPERTY_TYPE, B_TRUE);
2807 2804 return (Z_INSUFFICIENT_SPEC);
2808 2805 }
2809 2806 }
2810 2807 if (fill_in_only)
2811 2808 return (Z_OK);
2812 2809 err = zonecfg_lookup_nwif(handle, nwiftab);
2813 2810 return (err);
2814 2811 }
2815 2812
2816 2813 static int
2817 2814 fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
2818 2815 {
2819 2816 int err, i;
2820 2817 property_value_ptr_t pp;
2821 2818
2822 2819 if ((err = initialize(B_TRUE)) != Z_OK)
2823 2820 return (err);
2824 2821
2825 2822 bzero(devtab, sizeof (*devtab));
2826 2823 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2827 2824 pp = cmd->cmd_property_ptr[i];
2828 2825 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2829 2826 zerr(gettext("A simple value was expected here."));
2830 2827 saw_error = B_TRUE;
2831 2828 return (Z_INSUFFICIENT_SPEC);
2832 2829 }
2833 2830 switch (cmd->cmd_prop_name[i]) {
2834 2831 case PT_MATCH:
2835 2832 (void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
2836 2833 sizeof (devtab->zone_dev_match));
2837 2834 break;
2838 2835 default:
2839 2836 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2840 2837 Z_NO_PROPERTY_TYPE, B_TRUE);
2841 2838 return (Z_INSUFFICIENT_SPEC);
2842 2839 }
2843 2840 }
2844 2841 if (fill_in_only)
2845 2842 return (Z_OK);
2846 2843 err = zonecfg_lookup_dev(handle, devtab);
2847 2844 return (err);
2848 2845 }
2849 2846
2850 2847 static int
2851 2848 fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab,
2852 2849 boolean_t fill_in_only)
2853 2850 {
2854 2851 int err, i;
2855 2852 property_value_ptr_t pp;
2856 2853
2857 2854 if ((err = initialize(B_TRUE)) != Z_OK)
2858 2855 return (err);
2859 2856
2860 2857 bzero(rctltab, sizeof (*rctltab));
2861 2858 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2862 2859 pp = cmd->cmd_property_ptr[i];
2863 2860 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2864 2861 zerr(gettext("A simple value was expected here."));
2865 2862 saw_error = B_TRUE;
2866 2863 return (Z_INSUFFICIENT_SPEC);
2867 2864 }
2868 2865 switch (cmd->cmd_prop_name[i]) {
2869 2866 case PT_NAME:
2870 2867 (void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
2871 2868 sizeof (rctltab->zone_rctl_name));
2872 2869 break;
2873 2870 default:
2874 2871 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2875 2872 Z_NO_PROPERTY_TYPE, B_TRUE);
2876 2873 return (Z_INSUFFICIENT_SPEC);
2877 2874 }
2878 2875 }
2879 2876 if (fill_in_only)
2880 2877 return (Z_OK);
2881 2878 err = zonecfg_lookup_rctl(handle, rctltab);
2882 2879 return (err);
2883 2880 }
2884 2881
2885 2882 static int
2886 2883 fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab,
2887 2884 boolean_t fill_in_only)
2888 2885 {
2889 2886 int err, i;
2890 2887 property_value_ptr_t pp;
2891 2888
2892 2889 if ((err = initialize(B_TRUE)) != Z_OK)
2893 2890 return (err);
2894 2891
2895 2892 bzero(attrtab, sizeof (*attrtab));
2896 2893 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2897 2894 pp = cmd->cmd_property_ptr[i];
2898 2895 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2899 2896 zerr(gettext("A simple value was expected here."));
2900 2897 saw_error = B_TRUE;
2901 2898 return (Z_INSUFFICIENT_SPEC);
2902 2899 }
2903 2900 switch (cmd->cmd_prop_name[i]) {
2904 2901 case PT_NAME:
2905 2902 (void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
2906 2903 sizeof (attrtab->zone_attr_name));
2907 2904 break;
2908 2905 case PT_TYPE:
2909 2906 (void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
2910 2907 sizeof (attrtab->zone_attr_type));
2911 2908 break;
2912 2909 case PT_VALUE:
2913 2910 (void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
2914 2911 sizeof (attrtab->zone_attr_value));
2915 2912 break;
2916 2913 default:
2917 2914 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2918 2915 Z_NO_PROPERTY_TYPE, B_TRUE);
2919 2916 return (Z_INSUFFICIENT_SPEC);
2920 2917 }
2921 2918 }
2922 2919 if (fill_in_only)
2923 2920 return (Z_OK);
2924 2921 err = zonecfg_lookup_attr(handle, attrtab);
2925 2922 return (err);
2926 2923 }
2927 2924
2928 2925 static int
2929 2926 fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
2930 2927 {
2931 2928 int err, i;
2932 2929 property_value_ptr_t pp;
2933 2930
2934 2931 if ((err = initialize(B_TRUE)) != Z_OK)
2935 2932 return (err);
2936 2933
2937 2934 dstab->zone_dataset_name[0] = '\0';
2938 2935 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2939 2936 pp = cmd->cmd_property_ptr[i];
2940 2937 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2941 2938 zerr(gettext("A simple value was expected here."));
2942 2939 saw_error = B_TRUE;
2943 2940 return (Z_INSUFFICIENT_SPEC);
2944 2941 }
2945 2942 switch (cmd->cmd_prop_name[i]) {
2946 2943 case PT_NAME:
2947 2944 (void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
2948 2945 sizeof (dstab->zone_dataset_name));
2949 2946 break;
2950 2947 default:
2951 2948 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2952 2949 Z_NO_PROPERTY_TYPE, B_TRUE);
2953 2950 return (Z_INSUFFICIENT_SPEC);
2954 2951 }
2955 2952 }
2956 2953 if (fill_in_only)
2957 2954 return (Z_OK);
2958 2955 return (zonecfg_lookup_ds(handle, dstab));
2959 2956 }
2960 2957
2961 2958 static int
2962 2959 fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
2963 2960 boolean_t fill_in_only)
2964 2961 {
2965 2962 int err, i;
2966 2963 property_value_ptr_t pp;
2967 2964
2968 2965 if ((err = initialize(B_TRUE)) != Z_OK)
2969 2966 return (err);
2970 2967
2971 2968 bzero(admintab, sizeof (*admintab));
2972 2969 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2973 2970 pp = cmd->cmd_property_ptr[i];
2974 2971 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2975 2972 zerr(gettext("A simple value was expected here."));
2976 2973 saw_error = B_TRUE;
2977 2974 return (Z_INSUFFICIENT_SPEC);
2978 2975 }
2979 2976 switch (cmd->cmd_prop_name[i]) {
2980 2977 case PT_USER:
2981 2978 (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2982 2979 sizeof (admintab->zone_admin_user));
2983 2980 break;
2984 2981 case PT_AUTHS:
2985 2982 (void) strlcpy(admintab->zone_admin_auths,
2986 2983 pp->pv_simple, sizeof (admintab->zone_admin_auths));
2987 2984 break;
2988 2985 default:
2989 2986 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2990 2987 Z_NO_PROPERTY_TYPE, B_TRUE);
2991 2988 return (Z_INSUFFICIENT_SPEC);
2992 2989 }
2993 2990 }
2994 2991 if (fill_in_only)
2995 2992 return (Z_OK);
2996 2993 err = zonecfg_lookup_admin(handle, admintab);
2997 2994 return (err);
2998 2995 }
2999 2996
3000 2997 static int
3001 2998 fill_in_secflagstab(cmd_t *cmd, struct zone_secflagstab *secflagstab,
3002 2999 boolean_t fill_in_only)
3003 3000 {
3004 3001 int err, i;
3005 3002 property_value_ptr_t pp;
3006 3003
3007 3004 if ((err = initialize(B_TRUE)) != Z_OK)
3008 3005 return (err);
3009 3006
3010 3007 bzero(secflagstab, sizeof (*secflagstab));
3011 3008 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
3012 3009 pp = cmd->cmd_property_ptr[i];
3013 3010 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
3014 3011 zerr(gettext("A simple value was expected here."));
3015 3012 saw_error = B_TRUE;
3016 3013 return (Z_INSUFFICIENT_SPEC);
3017 3014 }
3018 3015 switch (cmd->cmd_prop_name[i]) {
3019 3016 case PT_DEFAULT:
3020 3017 (void) strlcpy(secflagstab->zone_secflags_default,
3021 3018 pp->pv_simple,
3022 3019 sizeof (secflagstab->zone_secflags_default));
3023 3020 break;
3024 3021 case PT_LOWER:
3025 3022 (void) strlcpy(secflagstab->zone_secflags_lower,
3026 3023 pp->pv_simple,
3027 3024 sizeof (secflagstab->zone_secflags_lower));
3028 3025 break;
3029 3026 case PT_UPPER:
3030 3027 (void) strlcpy(secflagstab->zone_secflags_upper,
3031 3028 pp->pv_simple,
3032 3029 sizeof (secflagstab->zone_secflags_upper));
3033 3030 break;
3034 3031 default:
3035 3032 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3036 3033 Z_NO_PROPERTY_TYPE, B_TRUE);
3037 3034 return (Z_INSUFFICIENT_SPEC);
3038 3035 }
3039 3036 }
3040 3037 if (fill_in_only)
3041 3038 return (Z_OK);
3042 3039
3043 3040 err = zonecfg_lookup_secflags(handle, secflagstab);
3044 3041
3045 3042 return (err);
3046 3043 }
3047 3044
3048 3045 static void
3049 3046 remove_aliased_rctl(int type, char *name)
3050 3047 {
3051 3048 int err;
3052 3049 uint64_t tmp;
3053 3050
3054 3051 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
3055 3052 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3056 3053 zonecfg_strerror(err));
3057 3054 saw_error = B_TRUE;
3058 3055 return;
3059 3056 }
3060 3057 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
3061 3058 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3062 3059 zonecfg_strerror(err));
3063 3060 saw_error = B_TRUE;
3064 3061 } else {
3065 3062 need_to_commit = B_TRUE;
3066 3063 }
3067 3064 }
3068 3065
3069 3066 static boolean_t
3070 3067 prompt_remove_resource(cmd_t *cmd, char *rsrc)
3071 3068 {
3072 3069 int num;
3073 3070 int answer;
3074 3071 int arg;
3075 3072 boolean_t force = B_FALSE;
3076 3073 char prompt[128];
3077 3074 boolean_t arg_err = B_FALSE;
3078 3075
3079 3076 optind = 0;
3080 3077 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3081 3078 switch (arg) {
3082 3079 case 'F':
3083 3080 force = B_TRUE;
3084 3081 break;
3085 3082 default:
3086 3083 arg_err = B_TRUE;
3087 3084 break;
3088 3085 }
3089 3086 }
3090 3087 if (arg_err)
3091 3088 return (B_FALSE);
3092 3089
3093 3090
3094 3091 num = zonecfg_num_resources(handle, rsrc);
3095 3092
3096 3093 if (num == 0) {
3097 3094 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
3098 3095 B_TRUE);
3099 3096 return (B_FALSE);
3100 3097 }
3101 3098 if (num > 1 && !force) {
3102 3099 if (!interactive_mode) {
3103 3100 zerr(gettext("There are multiple instances of this "
3104 3101 "resource. Either qualify the resource to\n"
3105 3102 "remove a single instance or use the -F option to "
3106 3103 "remove all instances."));
3107 3104 saw_error = B_TRUE;
3108 3105 return (B_FALSE);
3109 3106 }
3110 3107 (void) snprintf(prompt, sizeof (prompt), gettext(
3111 3108 "Are you sure you want to remove ALL '%s' resources"),
3112 3109 rsrc);
3113 3110 answer = ask_yesno(B_FALSE, prompt);
3114 3111 if (answer == -1) {
3115 3112 zerr(gettext("Resource incomplete."));
3116 3113 return (B_FALSE);
3117 3114 }
3118 3115 if (answer != 1)
3119 3116 return (B_FALSE);
3120 3117 }
3121 3118 return (B_TRUE);
3122 3119 }
3123 3120
3124 3121 static void
3125 3122 remove_fs(cmd_t *cmd)
3126 3123 {
3127 3124 int err;
3128 3125
3129 3126 /* traditional, qualified fs removal */
3130 3127 if (cmd->cmd_prop_nv_pairs > 0) {
3131 3128 struct zone_fstab fstab;
3132 3129
3133 3130 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
3134 3131 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3135 3132 return;
3136 3133 }
3137 3134 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
3138 3135 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3139 3136 else
3140 3137 need_to_commit = B_TRUE;
3141 3138 zonecfg_free_fs_option_list(fstab.zone_fs_options);
3142 3139 return;
3143 3140 }
3144 3141
3145 3142 /*
3146 3143 * unqualified fs removal. remove all fs's but prompt if more
3147 3144 * than one.
3148 3145 */
3149 3146 if (!prompt_remove_resource(cmd, "fs"))
3150 3147 return;
3151 3148
3152 3149 if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
3153 3150 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3154 3151 else
3155 3152 need_to_commit = B_TRUE;
3156 3153 }
3157 3154
3158 3155 static void
3159 3156 remove_net(cmd_t *cmd)
3160 3157 {
3161 3158 int err;
3162 3159
3163 3160 /* traditional, qualified net removal */
3164 3161 if (cmd->cmd_prop_nv_pairs > 0) {
3165 3162 struct zone_nwiftab nwiftab;
3166 3163
3167 3164 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
3168 3165 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3169 3166 return;
3170 3167 }
3171 3168 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
3172 3169 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3173 3170 else
3174 3171 need_to_commit = B_TRUE;
3175 3172 return;
3176 3173 }
3177 3174
3178 3175 /*
3179 3176 * unqualified net removal. remove all nets but prompt if more
3180 3177 * than one.
3181 3178 */
3182 3179 if (!prompt_remove_resource(cmd, "net"))
3183 3180 return;
3184 3181
3185 3182 if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
3186 3183 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3187 3184 else
3188 3185 need_to_commit = B_TRUE;
3189 3186 }
3190 3187
3191 3188 static void
3192 3189 remove_device(cmd_t *cmd)
3193 3190 {
3194 3191 int err;
3195 3192
3196 3193 /* traditional, qualified device removal */
3197 3194 if (cmd->cmd_prop_nv_pairs > 0) {
3198 3195 struct zone_devtab devtab;
3199 3196
3200 3197 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3201 3198 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3202 3199 return;
3203 3200 }
3204 3201 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
3205 3202 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3206 3203 else
3207 3204 need_to_commit = B_TRUE;
3208 3205 return;
3209 3206 }
3210 3207
3211 3208 /*
3212 3209 * unqualified device removal. remove all devices but prompt if more
3213 3210 * than one.
3214 3211 */
3215 3212 if (!prompt_remove_resource(cmd, "device"))
3216 3213 return;
3217 3214
3218 3215 if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3219 3216 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3220 3217 else
3221 3218 need_to_commit = B_TRUE;
3222 3219 }
3223 3220
3224 3221 static void
3225 3222 remove_attr(cmd_t *cmd)
3226 3223 {
3227 3224 int err;
3228 3225
3229 3226 /* traditional, qualified attr removal */
3230 3227 if (cmd->cmd_prop_nv_pairs > 0) {
3231 3228 struct zone_attrtab attrtab;
3232 3229
3233 3230 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3234 3231 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3235 3232 return;
3236 3233 }
3237 3234 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
3238 3235 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3239 3236 else
3240 3237 need_to_commit = B_TRUE;
3241 3238 return;
3242 3239 }
3243 3240
3244 3241 /*
3245 3242 * unqualified attr removal. remove all attrs but prompt if more
3246 3243 * than one.
3247 3244 */
3248 3245 if (!prompt_remove_resource(cmd, "attr"))
3249 3246 return;
3250 3247
3251 3248 if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3252 3249 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3253 3250 else
3254 3251 need_to_commit = B_TRUE;
3255 3252 }
3256 3253
3257 3254 static void
3258 3255 remove_dataset(cmd_t *cmd)
3259 3256 {
3260 3257 int err;
3261 3258
3262 3259 /* traditional, qualified dataset removal */
3263 3260 if (cmd->cmd_prop_nv_pairs > 0) {
3264 3261 struct zone_dstab dstab;
3265 3262
3266 3263 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3267 3264 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3268 3265 return;
3269 3266 }
3270 3267 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
3271 3268 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3272 3269 else
3273 3270 need_to_commit = B_TRUE;
3274 3271 return;
3275 3272 }
3276 3273
3277 3274 /*
3278 3275 * unqualified dataset removal. remove all datasets but prompt if more
3279 3276 * than one.
3280 3277 */
3281 3278 if (!prompt_remove_resource(cmd, "dataset"))
3282 3279 return;
3283 3280
3284 3281 if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3285 3282 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3286 3283 else
3287 3284 need_to_commit = B_TRUE;
3288 3285 }
3289 3286
3290 3287 static void
3291 3288 remove_rctl(cmd_t *cmd)
3292 3289 {
3293 3290 int err;
3294 3291
3295 3292 /* traditional, qualified rctl removal */
3296 3293 if (cmd->cmd_prop_nv_pairs > 0) {
3297 3294 struct zone_rctltab rctltab;
3298 3295
3299 3296 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3300 3297 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3301 3298 return;
3302 3299 }
3303 3300 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
3304 3301 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3305 3302 else
3306 3303 need_to_commit = B_TRUE;
3307 3304 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3308 3305 return;
3309 3306 }
3310 3307
3311 3308 /*
3312 3309 * unqualified rctl removal. remove all rctls but prompt if more
3313 3310 * than one.
3314 3311 */
3315 3312 if (!prompt_remove_resource(cmd, "rctl"))
3316 3313 return;
3317 3314
3318 3315 if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3319 3316 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3320 3317 else
3321 3318 need_to_commit = B_TRUE;
3322 3319 }
3323 3320
3324 3321 static void
3325 3322 remove_pset()
3326 3323 {
3327 3324 int err;
3328 3325 struct zone_psettab psettab;
3329 3326
3330 3327 if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3331 3328 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3332 3329 return;
3333 3330 }
3334 3331 if ((err = zonecfg_delete_pset(handle)) != Z_OK)
3335 3332 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3336 3333 else
3337 3334 need_to_commit = B_TRUE;
3338 3335 }
3339 3336
3340 3337 static void
3341 3338 remove_pcap()
3342 3339 {
3343 3340 int err;
3344 3341 uint64_t tmp;
3345 3342
3346 3343 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3347 3344 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
3348 3345 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3349 3346 saw_error = B_TRUE;
3350 3347 return;
3351 3348 }
3352 3349
3353 3350 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
3354 3351 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3355 3352 else
3356 3353 need_to_commit = B_TRUE;
3357 3354 }
3358 3355
3359 3356 static void
3360 3357 remove_mcap()
3361 3358 {
3362 3359 int err, res1, res2, res3;
3363 3360 uint64_t tmp;
3364 3361 struct zone_mcaptab mcaptab;
3365 3362 boolean_t revert = B_FALSE;
3366 3363
3367 3364 res1 = zonecfg_lookup_mcap(handle, &mcaptab);
3368 3365 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3369 3366 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3370 3367
3371 3368 /* if none of these exist, there is no resource to remove */
3372 3369 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3373 3370 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
3374 3371 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3375 3372 saw_error = B_TRUE;
3376 3373 return;
3377 3374 }
3378 3375 if (res1 == Z_OK) {
3379 3376 if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
3380 3377 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3381 3378 revert = B_TRUE;
3382 3379 } else {
3383 3380 need_to_commit = B_TRUE;
3384 3381 }
3385 3382 }
3386 3383 if (res2 == Z_OK) {
3387 3384 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3388 3385 != Z_OK) {
3389 3386 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3390 3387 revert = B_TRUE;
3391 3388 } else {
3392 3389 need_to_commit = B_TRUE;
3393 3390 }
3394 3391 }
3395 3392 if (res3 == Z_OK) {
3396 3393 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3397 3394 != Z_OK) {
3398 3395 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3399 3396 revert = B_TRUE;
3400 3397 } else {
3401 3398 need_to_commit = B_TRUE;
3402 3399 }
3403 3400 }
3404 3401
3405 3402 if (revert)
3406 3403 need_to_commit = B_FALSE;
3407 3404 }
3408 3405
3409 3406 static void
3410 3407 remove_admin(cmd_t *cmd)
3411 3408 {
3412 3409 int err;
3413 3410
3414 3411 /* traditional, qualified attr removal */
3415 3412 if (cmd->cmd_prop_nv_pairs > 0) {
3416 3413 struct zone_admintab admintab;
3417 3414
3418 3415 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3419 3416 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3420 3417 err, B_TRUE);
3421 3418 return;
3422 3419 }
3423 3420 if ((err = zonecfg_delete_admin(handle, &admintab,
3424 3421 zone))
3425 3422 != Z_OK)
3426 3423 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3427 3424 err, B_TRUE);
3428 3425 else
3429 3426 need_to_commit = B_TRUE;
3430 3427 return;
3431 3428 } else {
3432 3429 /*
3433 3430 * unqualified admin removal.
3434 3431 * remove all admins but prompt if more
3435 3432 * than one.
3436 3433 */
3437 3434 if (!prompt_remove_resource(cmd, "admin"))
3438 3435 return;
3439 3436
3440 3437 if ((err = zonecfg_delete_admins(handle, zone))
3441 3438 != Z_OK)
3442 3439 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3443 3440 err, B_TRUE);
3444 3441 else
3445 3442 need_to_commit = B_TRUE;
3446 3443 }
3447 3444 }
3448 3445
3449 3446 static void
3450 3447 remove_secflags()
3451 3448 {
3452 3449 int err;
3453 3450 struct zone_secflagstab sectab = { 0 };
3454 3451
3455 3452 if (zonecfg_lookup_secflags(handle, §ab) != Z_OK) {
3456 3453 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3457 3454 rt_to_str(RT_SECFLAGS),
3458 3455 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3459 3456 return;
3460 3457 }
3461 3458
3462 3459 if ((err = zonecfg_delete_secflags(handle, §ab)) != Z_OK) {
3463 3460 z_cmd_rt_perror(CMD_REMOVE, RT_SECFLAGS, err, B_TRUE);
3464 3461 return;
3465 3462 }
3466 3463
3467 3464 need_to_commit = B_TRUE;
3468 3465 }
3469 3466
3470 3467 static void
3471 3468 remove_resource(cmd_t *cmd)
3472 3469 {
3473 3470 int type;
3474 3471 int arg;
3475 3472 boolean_t arg_err = B_FALSE;
3476 3473
3477 3474 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3478 3475 long_usage(CMD_REMOVE, B_TRUE);
3479 3476 return;
3480 3477 }
3481 3478
3482 3479 optind = 0;
3483 3480 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3484 3481 switch (arg) {
3485 3482 case '?':
3486 3483 longer_usage(CMD_REMOVE);
3487 3484 arg_err = B_TRUE;
3488 3485 break;
3489 3486 case 'F':
3490 3487 break;
3491 3488 default:
3492 3489 short_usage(CMD_REMOVE);
3493 3490 arg_err = B_TRUE;
3494 3491 break;
3495 3492 }
3496 3493 }
3497 3494 if (arg_err)
3498 3495 return;
3499 3496
3500 3497 if (initialize(B_TRUE) != Z_OK)
3501 3498 return;
3502 3499
3503 3500 switch (type) {
3504 3501 case RT_FS:
3505 3502 remove_fs(cmd);
3506 3503 return;
3507 3504 case RT_NET:
3508 3505 remove_net(cmd);
3509 3506 return;
3510 3507 case RT_DEVICE:
3511 3508 remove_device(cmd);
3512 3509 return;
3513 3510 case RT_RCTL:
3514 3511 remove_rctl(cmd);
3515 3512 return;
3516 3513 case RT_ATTR:
3517 3514 remove_attr(cmd);
3518 3515 return;
3519 3516 case RT_DATASET:
3520 3517 remove_dataset(cmd);
3521 3518 return;
3522 3519 case RT_DCPU:
3523 3520 remove_pset();
3524 3521 return;
3525 3522 case RT_PCAP:
3526 3523 remove_pcap();
3527 3524 return;
3528 3525 case RT_MCAP:
3529 3526 remove_mcap();
3530 3527 return;
3531 3528 case RT_ADMIN:
3532 3529 remove_admin(cmd);
3533 3530 return;
3534 3531 case RT_SECFLAGS:
3535 3532 remove_secflags();
3536 3533 return;
3537 3534 default:
3538 3535 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3539 3536 long_usage(CMD_REMOVE, B_TRUE);
3540 3537 usage(B_FALSE, HELP_RESOURCES);
3541 3538 return;
3542 3539 }
3543 3540 }
3544 3541
3545 3542 static void
3546 3543 remove_property(cmd_t *cmd)
3547 3544 {
3548 3545 char *prop_id;
3549 3546 int err, res_type, prop_type;
3550 3547 property_value_ptr_t pp;
3551 3548 struct zone_rctlvaltab *rctlvaltab;
3552 3549 complex_property_ptr_t cx;
3553 3550
3554 3551 res_type = resource_scope;
3555 3552 prop_type = cmd->cmd_prop_name[0];
3556 3553 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3557 3554 long_usage(CMD_REMOVE, B_TRUE);
3558 3555 return;
3559 3556 }
3560 3557
3561 3558 if (cmd->cmd_prop_nv_pairs != 1) {
3562 3559 long_usage(CMD_ADD, B_TRUE);
3563 3560 return;
3564 3561 }
3565 3562
3566 3563 if (initialize(B_TRUE) != Z_OK)
3567 3564 return;
3568 3565
3569 3566 switch (res_type) {
3570 3567 case RT_FS:
3571 3568 if (prop_type != PT_OPTIONS) {
3572 3569 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3573 3570 B_TRUE);
3574 3571 long_usage(CMD_REMOVE, B_TRUE);
3575 3572 usage(B_FALSE, HELP_PROPS);
3576 3573 return;
3577 3574 }
3578 3575 pp = cmd->cmd_property_ptr[0];
3579 3576 if (pp->pv_type == PROP_VAL_COMPLEX) {
3580 3577 zerr(gettext("A %s or %s value was expected here."),
3581 3578 pvt_to_str(PROP_VAL_SIMPLE),
3582 3579 pvt_to_str(PROP_VAL_LIST));
3583 3580 saw_error = B_TRUE;
3584 3581 return;
3585 3582 }
3586 3583 if (pp->pv_type == PROP_VAL_SIMPLE) {
3587 3584 if (pp->pv_simple == NULL) {
3588 3585 long_usage(CMD_ADD, B_TRUE);
3589 3586 return;
3590 3587 }
3591 3588 prop_id = pp->pv_simple;
3592 3589 err = zonecfg_remove_fs_option(&in_progress_fstab,
3593 3590 prop_id);
3594 3591 if (err != Z_OK)
3595 3592 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3596 3593 } else {
3597 3594 list_property_ptr_t list;
3598 3595
3599 3596 for (list = pp->pv_list; list != NULL;
3600 3597 list = list->lp_next) {
3601 3598 prop_id = list->lp_simple;
3602 3599 if (prop_id == NULL)
3603 3600 break;
3604 3601 err = zonecfg_remove_fs_option(
3605 3602 &in_progress_fstab, prop_id);
3606 3603 if (err != Z_OK)
3607 3604 zone_perror(pt_to_str(prop_type), err,
3608 3605 B_TRUE);
3609 3606 }
3610 3607 }
3611 3608 return;
3612 3609 case RT_RCTL:
3613 3610 if (prop_type != PT_VALUE) {
3614 3611 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3615 3612 B_TRUE);
3616 3613 long_usage(CMD_REMOVE, B_TRUE);
3617 3614 usage(B_FALSE, HELP_PROPS);
3618 3615 return;
3619 3616 }
3620 3617 pp = cmd->cmd_property_ptr[0];
3621 3618 if (pp->pv_type != PROP_VAL_COMPLEX) {
3622 3619 zerr(gettext("A %s value was expected here."),
3623 3620 pvt_to_str(PROP_VAL_COMPLEX));
3624 3621 saw_error = B_TRUE;
3625 3622 return;
3626 3623 }
3627 3624 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3628 3625 zone_perror(zone, Z_NOMEM, B_TRUE);
3629 3626 exit(Z_ERR);
3630 3627 }
3631 3628 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
3632 3629 switch (cx->cp_type) {
3633 3630 case PT_PRIV:
3634 3631 (void) strlcpy(rctlvaltab->zone_rctlval_priv,
3635 3632 cx->cp_value,
3636 3633 sizeof (rctlvaltab->zone_rctlval_priv));
3637 3634 break;
3638 3635 case PT_LIMIT:
3639 3636 (void) strlcpy(rctlvaltab->zone_rctlval_limit,
3640 3637 cx->cp_value,
3641 3638 sizeof (rctlvaltab->zone_rctlval_limit));
3642 3639 break;
3643 3640 case PT_ACTION:
3644 3641 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3645 3642 cx->cp_value,
3646 3643 sizeof (rctlvaltab->zone_rctlval_action));
3647 3644 break;
3648 3645 default:
3649 3646 zone_perror(pt_to_str(prop_type),
3650 3647 Z_NO_PROPERTY_TYPE, B_TRUE);
3651 3648 long_usage(CMD_ADD, B_TRUE);
3652 3649 usage(B_FALSE, HELP_PROPS);
3653 3650 zonecfg_free_rctl_value_list(rctlvaltab);
3654 3651 return;
3655 3652 }
3656 3653 }
3657 3654 rctlvaltab->zone_rctlval_next = NULL;
3658 3655 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3659 3656 rctlvaltab);
3660 3657 if (err != Z_OK)
3661 3658 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3662 3659 zonecfg_free_rctl_value_list(rctlvaltab);
3663 3660 return;
3664 3661 case RT_NET:
3665 3662 if (prop_type != PT_DEFROUTER) {
3666 3663 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3667 3664 B_TRUE);
3668 3665 long_usage(CMD_REMOVE, B_TRUE);
3669 3666 usage(B_FALSE, HELP_PROPS);
3670 3667 return;
3671 3668 } else {
3672 3669 bzero(&in_progress_nwiftab.zone_nwif_defrouter,
3673 3670 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
3674 3671 return;
3675 3672 }
3676 3673 default:
3677 3674 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3678 3675 long_usage(CMD_REMOVE, B_TRUE);
3679 3676 usage(B_FALSE, HELP_RESOURCES);
3680 3677 return;
3681 3678 }
3682 3679 }
3683 3680
3684 3681 void
3685 3682 remove_func(cmd_t *cmd)
3686 3683 {
3687 3684 if (zone_is_read_only(CMD_REMOVE))
3688 3685 return;
3689 3686
3690 3687 assert(cmd != NULL);
3691 3688
3692 3689 if (global_scope) {
3693 3690 if (gz_invalid_resource(cmd->cmd_res_type)) {
3694 3691 zerr(gettext("%s is not a valid resource for the "
3695 3692 "global zone."), rt_to_str(cmd->cmd_res_type));
3696 3693 saw_error = B_TRUE;
3697 3694 return;
3698 3695 }
3699 3696 remove_resource(cmd);
3700 3697 } else {
3701 3698 remove_property(cmd);
3702 3699 }
3703 3700 }
3704 3701
3705 3702 static void
3706 3703 clear_property(cmd_t *cmd)
3707 3704 {
3708 3705 int res_type, prop_type;
3709 3706
3710 3707 res_type = resource_scope;
3711 3708 prop_type = cmd->cmd_res_type;
3712 3709 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3713 3710 long_usage(CMD_CLEAR, B_TRUE);
3714 3711 return;
3715 3712 }
3716 3713
3717 3714 if (initialize(B_TRUE) != Z_OK)
3718 3715 return;
3719 3716
3720 3717 switch (res_type) {
3721 3718 case RT_FS:
3722 3719 if (prop_type == PT_RAW) {
3723 3720 in_progress_fstab.zone_fs_raw[0] = '\0';
3724 3721 need_to_commit = B_TRUE;
3725 3722 return;
3726 3723 }
3727 3724 break;
3728 3725 case RT_DCPU:
3729 3726 if (prop_type == PT_IMPORTANCE) {
3730 3727 in_progress_psettab.zone_importance[0] = '\0';
3731 3728 need_to_commit = B_TRUE;
3732 3729 return;
3733 3730 }
3734 3731 break;
3735 3732 case RT_MCAP:
3736 3733 switch (prop_type) {
3737 3734 case PT_PHYSICAL:
3738 3735 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3739 3736 need_to_commit = B_TRUE;
3740 3737 return;
3741 3738 case PT_SWAP:
3742 3739 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3743 3740 return;
3744 3741 case PT_LOCKED:
3745 3742 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3746 3743 return;
3747 3744 }
3748 3745 break;
3749 3746 case RT_SECFLAGS:
3750 3747 switch (prop_type) {
3751 3748 case PT_LOWER:
3752 3749 in_progress_secflagstab.zone_secflags_lower[0] = '\0';
3753 3750 need_to_commit = B_TRUE;
3754 3751 return;
3755 3752 case PT_DEFAULT:
3756 3753 in_progress_secflagstab.zone_secflags_default[0] = '\0';
3757 3754 need_to_commit = B_TRUE;
3758 3755 return;
3759 3756 case PT_UPPER:
3760 3757 in_progress_secflagstab.zone_secflags_upper[0] = '\0';
3761 3758 need_to_commit = B_TRUE;
3762 3759 return;
3763 3760 }
3764 3761 break;
3765 3762 default:
3766 3763 break;
3767 3764 }
3768 3765
3769 3766 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3770 3767 }
3771 3768
3772 3769 static void
3773 3770 clear_global(cmd_t *cmd)
3774 3771 {
3775 3772 int err, type;
3776 3773
3777 3774 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3778 3775 long_usage(CMD_CLEAR, B_TRUE);
3779 3776 return;
3780 3777 }
3781 3778
3782 3779 if (initialize(B_TRUE) != Z_OK)
3783 3780 return;
3784 3781
3785 3782 switch (type) {
3786 3783 case PT_ZONENAME:
3787 3784 /* FALLTHRU */
3788 3785 case PT_ZONEPATH:
3789 3786 /* FALLTHRU */
3790 3787 case PT_BRAND:
3791 3788 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
3792 3789 return;
3793 3790 case PT_AUTOBOOT:
3794 3791 /* false is default; we'll treat as equivalent to clearing */
3795 3792 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
3796 3793 z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
3797 3794 else
3798 3795 need_to_commit = B_TRUE;
3799 3796 return;
3800 3797 case PT_POOL:
3801 3798 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
3802 3799 z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
3803 3800 else
3804 3801 need_to_commit = B_TRUE;
3805 3802 return;
3806 3803 case PT_LIMITPRIV:
3807 3804 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
3808 3805 z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
3809 3806 else
3810 3807 need_to_commit = B_TRUE;
3811 3808 return;
3812 3809 case PT_BOOTARGS:
3813 3810 if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK)
3814 3811 z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, B_TRUE);
3815 3812 else
3816 3813 need_to_commit = B_TRUE;
3817 3814 return;
3818 3815 case PT_SCHED:
3819 3816 if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK)
3820 3817 z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, B_TRUE);
3821 3818 else
3822 3819 need_to_commit = B_TRUE;
3823 3820 return;
3824 3821 case PT_IPTYPE:
3825 3822 /* shared is default; we'll treat as equivalent to clearing */
3826 3823 if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
3827 3824 z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, B_TRUE);
3828 3825 else
3829 3826 need_to_commit = B_TRUE;
3830 3827 return;
3831 3828 case PT_MAXLWPS:
3832 3829 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
3833 3830 return;
3834 3831 case PT_MAXPROCS:
3835 3832 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
3836 3833 return;
3837 3834 case PT_MAXSHMMEM:
3838 3835 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
3839 3836 return;
3840 3837 case PT_MAXSHMIDS:
3841 3838 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
3842 3839 return;
3843 3840 case PT_MAXMSGIDS:
3844 3841 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
3845 3842 return;
3846 3843 case PT_MAXSEMIDS:
3847 3844 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
3848 3845 return;
3849 3846 case PT_SHARES:
3850 3847 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
3851 3848 return;
3852 3849 case PT_HOSTID:
3853 3850 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
3854 3851 z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
3855 3852 else
3856 3853 need_to_commit = B_TRUE;
3857 3854 return;
3858 3855 case PT_FS_ALLOWED:
3859 3856 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
3860 3857 z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
3861 3858 else
3862 3859 need_to_commit = B_TRUE;
3863 3860 return;
3864 3861 default:
3865 3862 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
3866 3863 long_usage(CMD_CLEAR, B_TRUE);
3867 3864 usage(B_FALSE, HELP_PROPS);
3868 3865 return;
3869 3866 }
3870 3867 }
3871 3868
3872 3869 void
3873 3870 clear_func(cmd_t *cmd)
3874 3871 {
3875 3872 if (zone_is_read_only(CMD_CLEAR))
3876 3873 return;
3877 3874
3878 3875 assert(cmd != NULL);
3879 3876
3880 3877 if (global_scope) {
3881 3878 if (gz_invalid_property(cmd->cmd_res_type)) {
3882 3879 zerr(gettext("%s is not a valid property for the "
3883 3880 "global zone."), pt_to_str(cmd->cmd_res_type));
3884 3881 saw_error = B_TRUE;
3885 3882 return;
3886 3883 }
3887 3884
3888 3885 clear_global(cmd);
3889 3886 } else {
3890 3887 clear_property(cmd);
3891 3888 }
3892 3889 }
3893 3890
3894 3891 void
3895 3892 select_func(cmd_t *cmd)
3896 3893 {
3897 3894 int type, err, res;
3898 3895 uint64_t limit;
3899 3896 uint64_t tmp;
3900 3897
3901 3898 if (zone_is_read_only(CMD_SELECT))
3902 3899 return;
3903 3900
3904 3901 assert(cmd != NULL);
3905 3902
3906 3903 if (global_scope) {
3907 3904 global_scope = B_FALSE;
3908 3905 resource_scope = cmd->cmd_res_type;
3909 3906 end_op = CMD_SELECT;
3910 3907 } else {
3911 3908 scope_usage(CMD_SELECT);
3912 3909 return;
3913 3910 }
3914 3911
3915 3912 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3916 3913 long_usage(CMD_SELECT, B_TRUE);
3917 3914 return;
3918 3915 }
3919 3916
3920 3917 if (initialize(B_TRUE) != Z_OK)
3921 3918 return;
3922 3919
3923 3920 switch (type) {
3924 3921 case RT_FS:
3925 3922 if ((err = fill_in_fstab(cmd, &old_fstab, B_FALSE)) != Z_OK) {
3926 3923 z_cmd_rt_perror(CMD_SELECT, RT_FS, err, B_TRUE);
3927 3924 global_scope = B_TRUE;
3928 3925 }
3929 3926 bcopy(&old_fstab, &in_progress_fstab,
3930 3927 sizeof (struct zone_fstab));
3931 3928 return;
3932 3929 case RT_NET:
3933 3930 if ((err = fill_in_nwiftab(cmd, &old_nwiftab, B_FALSE))
3934 3931 != Z_OK) {
3935 3932 z_cmd_rt_perror(CMD_SELECT, RT_NET, err, B_TRUE);
3936 3933 global_scope = B_TRUE;
3937 3934 }
3938 3935 bcopy(&old_nwiftab, &in_progress_nwiftab,
3939 3936 sizeof (struct zone_nwiftab));
3940 3937 return;
3941 3938 case RT_DEVICE:
3942 3939 if ((err = fill_in_devtab(cmd, &old_devtab, B_FALSE)) != Z_OK) {
3943 3940 z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, B_TRUE);
3944 3941 global_scope = B_TRUE;
3945 3942 }
3946 3943 bcopy(&old_devtab, &in_progress_devtab,
3947 3944 sizeof (struct zone_devtab));
3948 3945 return;
3949 3946 case RT_RCTL:
3950 3947 if ((err = fill_in_rctltab(cmd, &old_rctltab, B_FALSE))
3951 3948 != Z_OK) {
3952 3949 z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, B_TRUE);
3953 3950 global_scope = B_TRUE;
3954 3951 }
3955 3952 bcopy(&old_rctltab, &in_progress_rctltab,
3956 3953 sizeof (struct zone_rctltab));
3957 3954 return;
3958 3955 case RT_ATTR:
3959 3956 if ((err = fill_in_attrtab(cmd, &old_attrtab, B_FALSE))
3960 3957 != Z_OK) {
3961 3958 z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, B_TRUE);
3962 3959 global_scope = B_TRUE;
3963 3960 }
3964 3961 bcopy(&old_attrtab, &in_progress_attrtab,
3965 3962 sizeof (struct zone_attrtab));
3966 3963 return;
3967 3964 case RT_DATASET:
3968 3965 if ((err = fill_in_dstab(cmd, &old_dstab, B_FALSE)) != Z_OK) {
3969 3966 z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, B_TRUE);
3970 3967 global_scope = B_TRUE;
3971 3968 }
3972 3969 bcopy(&old_dstab, &in_progress_dstab,
3973 3970 sizeof (struct zone_dstab));
3974 3971 return;
3975 3972 case RT_DCPU:
3976 3973 if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
3977 3974 z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
3978 3975 global_scope = B_TRUE;
3979 3976 }
3980 3977 bcopy(&old_psettab, &in_progress_psettab,
3981 3978 sizeof (struct zone_psettab));
3982 3979 return;
3983 3980 case RT_PCAP:
3984 3981 if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
3985 3982 != Z_OK) {
3986 3983 z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
3987 3984 global_scope = B_TRUE;
3988 3985 }
3989 3986 return;
3990 3987 case RT_MCAP:
3991 3988 /* if none of these exist, there is no resource to select */
3992 3989 if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
3993 3990 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
3994 3991 != Z_OK &&
3995 3992 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
3996 3993 != Z_OK) {
3997 3994 z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
3998 3995 B_TRUE);
3999 3996 global_scope = B_TRUE;
4000 3997 }
4001 3998 if (res == Z_OK)
4002 3999 bcopy(&old_mcaptab, &in_progress_mcaptab,
4003 4000 sizeof (struct zone_mcaptab));
4004 4001 else
4005 4002 bzero(&in_progress_mcaptab,
4006 4003 sizeof (in_progress_mcaptab));
4007 4004 return;
4008 4005 case RT_ADMIN:
4009 4006 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
4010 4007 != Z_OK) {
4011 4008 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
4012 4009 B_TRUE);
4013 4010 global_scope = B_TRUE;
4014 4011 }
4015 4012 bcopy(&old_admintab, &in_progress_admintab,
4016 4013 sizeof (struct zone_admintab));
4017 4014 return;
4018 4015 case RT_SECFLAGS:
4019 4016 if ((err = fill_in_secflagstab(cmd, &old_secflagstab, B_FALSE))
4020 4017 != Z_OK) {
4021 4018 z_cmd_rt_perror(CMD_SELECT, RT_SECFLAGS, err,
4022 4019 B_TRUE);
4023 4020 global_scope = B_TRUE;
4024 4021 }
4025 4022 bcopy(&old_secflagstab, &in_progress_secflagstab,
4026 4023 sizeof (struct zone_secflagstab));
4027 4024 return;
4028 4025 default:
4029 4026 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
4030 4027 long_usage(CMD_SELECT, B_TRUE);
4031 4028 usage(B_FALSE, HELP_RESOURCES);
4032 4029 return;
4033 4030 }
4034 4031 }
4035 4032
4036 4033 /*
4037 4034 * Network "addresses" can be one of the following forms:
4038 4035 * <IPv4 address>
4039 4036 * <IPv4 address>/<prefix length>
4040 4037 * <IPv6 address>/<prefix length>
4041 4038 * <host name>
4042 4039 * <host name>/<prefix length>
4043 4040 * In other words, the "/" followed by a prefix length is allowed but not
4044 4041 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4045 4042 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4046 4043 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4047 4044 * Host names must start with an alpha-numeric character, and all subsequent
4048 4045 * characters must be either alpha-numeric or "-".
4049 4046 *
4050 4047 * In some cases, e.g., the nexthop for the defrouter, the context indicates
4051 4048 * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
4052 4049 * require the /<prefix length> (and should ignore it if provided).
4053 4050 */
4054 4051
4055 4052 static int
4056 4053 validate_net_address_syntax(char *address, boolean_t ishost)
4057 4054 {
4058 4055 char *slashp, part1[MAXHOSTNAMELEN];
4059 4056 struct in6_addr in6;
4060 4057 struct in_addr in4;
4061 4058 int prefixlen, i;
4062 4059
4063 4060 /*
4064 4061 * Copy the part before any '/' into part1 or copy the whole
4065 4062 * thing if there is no '/'.
4066 4063 */
4067 4064 if ((slashp = strchr(address, '/')) != NULL) {
4068 4065 *slashp = '\0';
4069 4066 (void) strlcpy(part1, address, sizeof (part1));
4070 4067 *slashp = '/';
4071 4068 prefixlen = atoi(++slashp);
4072 4069 } else {
4073 4070 (void) strlcpy(part1, address, sizeof (part1));
4074 4071 }
4075 4072
4076 4073 if (ishost && slashp != NULL) {
4077 4074 zerr(gettext("Warning: prefix length in %s is not required and "
4078 4075 "will be ignored. The default host-prefix length "
4079 4076 "will be used"), address);
4080 4077 }
4081 4078
4082 4079
4083 4080 if (inet_pton(AF_INET6, part1, &in6) == 1) {
4084 4081 if (ishost) {
4085 4082 prefixlen = IPV6_ABITS;
4086 4083 } else if (slashp == NULL) {
4087 4084 zerr(gettext("%s: IPv6 addresses "
4088 4085 "require /prefix-length suffix."), address);
4089 4086 return (Z_ERR);
4090 4087 }
4091 4088 if (prefixlen < 0 || prefixlen > 128) {
4092 4089 zerr(gettext("%s: IPv6 address "
4093 4090 "prefix lengths must be 0 - 128."), address);
4094 4091 return (Z_ERR);
4095 4092 }
4096 4093 return (Z_OK);
4097 4094 }
4098 4095
4099 4096 /* At this point, any /prefix must be for IPv4. */
4100 4097 if (ishost)
4101 4098 prefixlen = IPV4_ABITS;
4102 4099 else if (slashp != NULL) {
4103 4100 if (prefixlen < 0 || prefixlen > 32) {
4104 4101 zerr(gettext("%s: IPv4 address "
4105 4102 "prefix lengths must be 0 - 32."), address);
4106 4103 return (Z_ERR);
4107 4104 }
4108 4105 }
4109 4106
4110 4107 if (inet_pton(AF_INET, part1, &in4) == 1)
4111 4108 return (Z_OK);
4112 4109
4113 4110 /* address may also be a host name */
4114 4111 if (!isalnum(part1[0])) {
4115 4112 zerr(gettext("%s: bogus host name or network address syntax"),
4116 4113 part1);
4117 4114 saw_error = B_TRUE;
4118 4115 usage(B_FALSE, HELP_NETADDR);
4119 4116 return (Z_ERR);
4120 4117 }
4121 4118 for (i = 1; part1[i]; i++)
4122 4119 if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
4123 4120 zerr(gettext("%s: bogus host name or "
4124 4121 "network address syntax"), part1);
4125 4122 saw_error = B_TRUE;
4126 4123 usage(B_FALSE, HELP_NETADDR);
4127 4124 return (Z_ERR);
4128 4125 }
4129 4126 return (Z_OK);
4130 4127 }
4131 4128
4132 4129 static int
4133 4130 validate_net_physical_syntax(const char *ifname)
4134 4131 {
4135 4132 ifspec_t ifnameprop;
4136 4133 zone_iptype_t iptype;
4137 4134
4138 4135 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
4139 4136 zerr(gettext("zone configuration has an invalid or nonexistent "
4140 4137 "ip-type property"));
4141 4138 return (Z_ERR);
4142 4139 }
4143 4140 switch (iptype) {
4144 4141 case ZS_SHARED:
4145 4142 if (ifparse_ifspec(ifname, &ifnameprop) == B_FALSE) {
4146 4143 zerr(gettext("%s: invalid physical interface name"),
4147 4144 ifname);
4148 4145 return (Z_ERR);
4149 4146 }
4150 4147 if (ifnameprop.ifsp_lunvalid) {
4151 4148 zerr(gettext("%s: LUNs not allowed in physical "
4152 4149 "interface names"), ifname);
4153 4150 return (Z_ERR);
4154 4151 }
4155 4152 break;
4156 4153 case ZS_EXCLUSIVE:
4157 4154 if (dladm_valid_linkname(ifname) == B_FALSE) {
4158 4155 if (strchr(ifname, ':') != NULL)
4159 4156 zerr(gettext("%s: physical interface name "
4160 4157 "required; logical interface name not "
4161 4158 "allowed"), ifname);
4162 4159 else
4163 4160 zerr(gettext("%s: invalid physical interface "
4164 4161 "name"), ifname);
4165 4162 return (Z_ERR);
4166 4163 }
4167 4164 break;
4168 4165 }
4169 4166 return (Z_OK);
4170 4167 }
4171 4168
4172 4169 static boolean_t
4173 4170 valid_fs_type(const char *type)
4174 4171 {
4175 4172 /*
4176 4173 * Is this a valid path component?
4177 4174 */
4178 4175 if (strlen(type) + 1 > MAXNAMELEN)
4179 4176 return (B_FALSE);
4180 4177 /*
4181 4178 * Make sure a bad value for "type" doesn't make
4182 4179 * /usr/lib/fs/<type>/mount turn into something else.
4183 4180 */
4184 4181 if (strchr(type, '/') != NULL || type[0] == '\0' ||
4185 4182 strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
4186 4183 return (B_FALSE);
4187 4184 /*
4188 4185 * More detailed verification happens later by zoneadm(1m).
4189 4186 */
4190 4187 return (B_TRUE);
4191 4188 }
4192 4189
4193 4190 static boolean_t
4194 4191 allow_exclusive()
4195 4192 {
4196 4193 brand_handle_t bh;
4197 4194 char brand[MAXNAMELEN];
4198 4195 boolean_t ret;
4199 4196
4200 4197 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
4201 4198 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
4202 4199 return (B_FALSE);
4203 4200 }
4204 4201 if ((bh = brand_open(brand)) == NULL) {
4205 4202 zerr("%s: %s\n", zone, gettext("unknown brand."));
4206 4203 return (B_FALSE);
4207 4204 }
4208 4205 ret = brand_allow_exclusive_ip(bh);
4209 4206 brand_close(bh);
4210 4207 if (!ret)
4211 4208 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
4212 4209 pt_to_str(PT_IPTYPE), "exclusive",
4213 4210 pt_to_str(PT_BRAND), brand);
4214 4211 return (ret);
4215 4212 }
4216 4213
4217 4214 static void
4218 4215 set_aliased_rctl(char *alias, int prop_type, char *s)
4219 4216 {
4220 4217 uint64_t limit;
4221 4218 int err;
4222 4219 char tmp[128];
4223 4220
4224 4221 if (global_zone && strcmp(alias, ALIAS_SHARES) != 0)
4225 4222 zerr(gettext("WARNING: Setting a global zone resource "
4226 4223 "control too low could deny\nservice "
4227 4224 "to even the root user; "
4228 4225 "this could render the system impossible\n"
4229 4226 "to administer. Please use caution."));
4230 4227
4231 4228 /* convert memory based properties */
4232 4229 if (prop_type == PT_MAXSHMMEM) {
4233 4230 if (!zonecfg_valid_memlimit(s, &limit)) {
4234 4231 zerr(gettext("A non-negative number with a required "
4235 4232 "scale suffix (K, M, G or T) was expected\nhere."));
4236 4233 saw_error = B_TRUE;
4237 4234 return;
4238 4235 }
4239 4236
4240 4237 (void) snprintf(tmp, sizeof (tmp), "%llu", limit);
4241 4238 s = tmp;
4242 4239 }
4243 4240
4244 4241 if (!zonecfg_aliased_rctl_ok(handle, alias)) {
4245 4242 zone_perror(pt_to_str(prop_type), Z_ALIAS_DISALLOW, B_FALSE);
4246 4243 saw_error = B_TRUE;
4247 4244 } else if (!zonecfg_valid_alias_limit(alias, s, &limit)) {
4248 4245 zerr(gettext("%s property is out of range."),
4249 4246 pt_to_str(prop_type));
4250 4247 saw_error = B_TRUE;
4251 4248 } else if ((err = zonecfg_set_aliased_rctl(handle, alias, limit))
4252 4249 != Z_OK) {
4253 4250 zone_perror(zone, err, B_TRUE);
4254 4251 saw_error = B_TRUE;
4255 4252 } else {
4256 4253 need_to_commit = B_TRUE;
4257 4254 }
4258 4255 }
4259 4256
4260 4257 static void
4261 4258 set_in_progress_nwiftab_address(char *prop_id, int prop_type)
4262 4259 {
4263 4260 if (prop_type == PT_ADDRESS) {
4264 4261 (void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
4265 4262 sizeof (in_progress_nwiftab.zone_nwif_address));
4266 4263 } else {
4267 4264 assert(prop_type == PT_ALLOWED_ADDRESS);
4268 4265 (void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
4269 4266 prop_id,
4270 4267 sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
4271 4268 }
4272 4269 }
4273 4270
4274 4271 void
4275 4272 set_func(cmd_t *cmd)
4276 4273 {
4277 4274 char *prop_id;
4278 4275 int arg, err, res_type, prop_type;
4279 4276 property_value_ptr_t pp;
4280 4277 boolean_t autoboot;
4281 4278 zone_iptype_t iptype;
4282 4279 boolean_t force_set = B_FALSE;
4283 4280 size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
4284 4281 uint64_t mem_cap, mem_limit;
4285 4282 float cap;
4286 4283 char *unitp;
4287 4284 struct zone_psettab tmp_psettab;
4288 4285 boolean_t arg_err = B_FALSE;
4289 4286
4290 4287 if (zone_is_read_only(CMD_SET))
4291 4288 return;
4292 4289
4293 4290 assert(cmd != NULL);
4294 4291
4295 4292 optind = opterr = 0;
4296 4293 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
4297 4294 switch (arg) {
4298 4295 case 'F':
4299 4296 force_set = B_TRUE;
4300 4297 break;
4301 4298 default:
4302 4299 if (optopt == '?')
4303 4300 longer_usage(CMD_SET);
4304 4301 else
4305 4302 short_usage(CMD_SET);
4306 4303 arg_err = B_TRUE;
4307 4304 break;
4308 4305 }
4309 4306 }
4310 4307 if (arg_err)
4311 4308 return;
4312 4309
4313 4310 prop_type = cmd->cmd_prop_name[0];
4314 4311 if (global_scope) {
4315 4312 if (gz_invalid_property(prop_type)) {
4316 4313 zerr(gettext("%s is not a valid property for the "
4317 4314 "global zone."), pt_to_str(prop_type));
4318 4315 saw_error = B_TRUE;
4319 4316 return;
4320 4317 }
4321 4318
4322 4319 if (prop_type == PT_ZONENAME) {
4323 4320 res_type = RT_ZONENAME;
4324 4321 } else if (prop_type == PT_ZONEPATH) {
4325 4322 res_type = RT_ZONEPATH;
4326 4323 } else if (prop_type == PT_AUTOBOOT) {
4327 4324 res_type = RT_AUTOBOOT;
4328 4325 } else if (prop_type == PT_BRAND) {
4329 4326 res_type = RT_BRAND;
4330 4327 } else if (prop_type == PT_POOL) {
4331 4328 res_type = RT_POOL;
4332 4329 } else if (prop_type == PT_LIMITPRIV) {
4333 4330 res_type = RT_LIMITPRIV;
4334 4331 } else if (prop_type == PT_BOOTARGS) {
4335 4332 res_type = RT_BOOTARGS;
4336 4333 } else if (prop_type == PT_SCHED) {
4337 4334 res_type = RT_SCHED;
4338 4335 } else if (prop_type == PT_IPTYPE) {
4339 4336 res_type = RT_IPTYPE;
4340 4337 } else if (prop_type == PT_MAXLWPS) {
4341 4338 res_type = RT_MAXLWPS;
4342 4339 } else if (prop_type == PT_MAXPROCS) {
4343 4340 res_type = RT_MAXPROCS;
4344 4341 } else if (prop_type == PT_MAXSHMMEM) {
4345 4342 res_type = RT_MAXSHMMEM;
4346 4343 } else if (prop_type == PT_MAXSHMIDS) {
4347 4344 res_type = RT_MAXSHMIDS;
4348 4345 } else if (prop_type == PT_MAXMSGIDS) {
4349 4346 res_type = RT_MAXMSGIDS;
4350 4347 } else if (prop_type == PT_MAXSEMIDS) {
4351 4348 res_type = RT_MAXSEMIDS;
4352 4349 } else if (prop_type == PT_SHARES) {
4353 4350 res_type = RT_SHARES;
4354 4351 } else if (prop_type == PT_HOSTID) {
4355 4352 res_type = RT_HOSTID;
4356 4353 } else if (prop_type == PT_FS_ALLOWED) {
4357 4354 res_type = RT_FS_ALLOWED;
4358 4355 } else {
4359 4356 zerr(gettext("Cannot set a resource-specific property "
4360 4357 "from the global scope."));
4361 4358 saw_error = B_TRUE;
4362 4359 return;
4363 4360 }
4364 4361 } else {
4365 4362 res_type = resource_scope;
4366 4363 }
4367 4364
4368 4365 if (force_set) {
4369 4366 if (res_type != RT_ZONEPATH) {
4370 4367 zerr(gettext("Only zonepath setting can be forced."));
4371 4368 saw_error = B_TRUE;
4372 4369 return;
4373 4370 }
4374 4371 if (!zonecfg_in_alt_root()) {
4375 4372 zerr(gettext("Zonepath is changeable only in an "
4376 4373 "alternate root."));
4377 4374 saw_error = B_TRUE;
4378 4375 return;
4379 4376 }
4380 4377 }
4381 4378
4382 4379 pp = cmd->cmd_property_ptr[0];
4383 4380 /*
4384 4381 * A nasty expression but not that complicated:
4385 4382 * 1. fs options are simple or list (tested below)
4386 4383 * 2. rctl value's are complex or list (tested below)
4387 4384 * Anything else should be simple.
4388 4385 */
4389 4386 if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
4390 4387 !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
4391 4388 (pp->pv_type != PROP_VAL_SIMPLE ||
4392 4389 (prop_id = pp->pv_simple) == NULL)) {
4393 4390 zerr(gettext("A %s value was expected here."),
4394 4391 pvt_to_str(PROP_VAL_SIMPLE));
4395 4392 saw_error = B_TRUE;
4396 4393 return;
4397 4394 }
4398 4395 if (prop_type == PT_UNKNOWN) {
4399 4396 long_usage(CMD_SET, B_TRUE);
4400 4397 return;
4401 4398 }
4402 4399
4403 4400 /*
4404 4401 * Special case: the user can change the zone name prior to 'create';
4405 4402 * if the zone already exists, we fall through letting initialize()
4406 4403 * and the rest of the logic run.
4407 4404 */
4408 4405 if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4409 4406 !state_atleast(ZONE_STATE_CONFIGURED)) {
4410 4407 if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
4411 4408 zone_perror(prop_id, err, B_TRUE);
4412 4409 usage(B_FALSE, HELP_SYNTAX);
4413 4410 return;
4414 4411 }
4415 4412 (void) strlcpy(zone, prop_id, sizeof (zone));
4416 4413 return;
4417 4414 }
4418 4415
4419 4416 if (initialize(B_TRUE) != Z_OK)
4420 4417 return;
4421 4418
4422 4419 switch (res_type) {
4423 4420 case RT_ZONENAME:
4424 4421 if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
4425 4422 /*
4426 4423 * Use prop_id instead of 'zone' here, since we're
4427 4424 * reporting a problem about the *new* zonename.
4428 4425 */
4429 4426 zone_perror(prop_id, err, B_TRUE);
4430 4427 usage(B_FALSE, HELP_SYNTAX);
4431 4428 } else {
4432 4429 need_to_commit = B_TRUE;
4433 4430 (void) strlcpy(zone, prop_id, sizeof (zone));
4434 4431 }
4435 4432 return;
4436 4433 case RT_ZONEPATH:
4437 4434 if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
4438 4435 zerr(gettext("Zone %s already installed; %s %s not "
4439 4436 "allowed."), zone, cmd_to_str(CMD_SET),
4440 4437 rt_to_str(RT_ZONEPATH));
4441 4438 return;
4442 4439 }
4443 4440 if (validate_zonepath_syntax(prop_id) != Z_OK) {
4444 4441 saw_error = B_TRUE;
4445 4442 return;
4446 4443 }
4447 4444 if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
4448 4445 zone_perror(zone, err, B_TRUE);
4449 4446 else
4450 4447 need_to_commit = B_TRUE;
4451 4448 return;
4452 4449 case RT_BRAND:
4453 4450 if (state_atleast(ZONE_STATE_INSTALLED)) {
4454 4451 zerr(gettext("Zone %s already installed; %s %s not "
4455 4452 "allowed."), zone, cmd_to_str(CMD_SET),
4456 4453 rt_to_str(RT_BRAND));
4457 4454 return;
4458 4455 }
4459 4456 if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
4460 4457 zone_perror(zone, err, B_TRUE);
4461 4458 else
4462 4459 need_to_commit = B_TRUE;
4463 4460 return;
4464 4461 case RT_AUTOBOOT:
4465 4462 if (strcmp(prop_id, "true") == 0) {
4466 4463 autoboot = B_TRUE;
4467 4464 } else if (strcmp(prop_id, "false") == 0) {
4468 4465 autoboot = B_FALSE;
4469 4466 } else {
4470 4467 zerr(gettext("%s value must be '%s' or '%s'."),
4471 4468 pt_to_str(PT_AUTOBOOT), "true", "false");
4472 4469 saw_error = B_TRUE;
4473 4470 return;
4474 4471 }
4475 4472 if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
4476 4473 zone_perror(zone, err, B_TRUE);
4477 4474 else
4478 4475 need_to_commit = B_TRUE;
4479 4476 return;
4480 4477 case RT_POOL:
4481 4478 /* don't allow use of the reserved temporary pool names */
4482 4479 if (strncmp("SUNW", prop_id, 4) == 0) {
4483 4480 zerr(gettext("pool names starting with SUNW are "
4484 4481 "reserved."));
4485 4482 saw_error = B_TRUE;
4486 4483 return;
4487 4484 }
4488 4485
4489 4486 /* can't set pool if dedicated-cpu exists */
4490 4487 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
4491 4488 zerr(gettext("The %s resource already exists. "
4492 4489 "A persistent pool is incompatible\nwith the %s "
4493 4490 "resource."), rt_to_str(RT_DCPU),
4494 4491 rt_to_str(RT_DCPU));
4495 4492 saw_error = B_TRUE;
4496 4493 return;
4497 4494 }
4498 4495
4499 4496 if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
4500 4497 zone_perror(zone, err, B_TRUE);
4501 4498 else
4502 4499 need_to_commit = B_TRUE;
4503 4500 return;
4504 4501 case RT_LIMITPRIV:
4505 4502 if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
4506 4503 zone_perror(zone, err, B_TRUE);
4507 4504 else
4508 4505 need_to_commit = B_TRUE;
4509 4506 return;
4510 4507 case RT_BOOTARGS:
4511 4508 if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
4512 4509 zone_perror(zone, err, B_TRUE);
4513 4510 else
4514 4511 need_to_commit = B_TRUE;
4515 4512 return;
4516 4513 case RT_SCHED:
4517 4514 if ((err = zonecfg_set_sched(handle, prop_id)) != Z_OK)
4518 4515 zone_perror(zone, err, B_TRUE);
4519 4516 else
4520 4517 need_to_commit = B_TRUE;
4521 4518 return;
4522 4519 case RT_IPTYPE:
4523 4520 if (strcmp(prop_id, "shared") == 0) {
4524 4521 iptype = ZS_SHARED;
4525 4522 } else if (strcmp(prop_id, "exclusive") == 0) {
4526 4523 iptype = ZS_EXCLUSIVE;
4527 4524 } else {
4528 4525 zerr(gettext("%s value must be '%s' or '%s'."),
4529 4526 pt_to_str(PT_IPTYPE), "shared", "exclusive");
4530 4527 saw_error = B_TRUE;
4531 4528 return;
4532 4529 }
4533 4530 if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
4534 4531 saw_error = B_TRUE;
4535 4532 return;
4536 4533 }
4537 4534 if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
4538 4535 zone_perror(zone, err, B_TRUE);
4539 4536 else
4540 4537 need_to_commit = B_TRUE;
4541 4538 return;
4542 4539 case RT_MAXLWPS:
4543 4540 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4544 4541 return;
4545 4542 case RT_MAXPROCS:
4546 4543 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4547 4544 return;
4548 4545 case RT_MAXSHMMEM:
4549 4546 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4550 4547 return;
4551 4548 case RT_MAXSHMIDS:
4552 4549 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4553 4550 return;
4554 4551 case RT_MAXMSGIDS:
4555 4552 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4556 4553 return;
4557 4554 case RT_MAXSEMIDS:
4558 4555 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4559 4556 return;
4560 4557 case RT_SHARES:
4561 4558 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4562 4559 return;
4563 4560 case RT_HOSTID:
4564 4561 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4565 4562 if (err == Z_TOO_BIG) {
4566 4563 zerr(gettext("hostid string is too large: %s"),
4567 4564 prop_id);
4568 4565 saw_error = B_TRUE;
4569 4566 } else {
4570 4567 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4571 4568 }
4572 4569 return;
4573 4570 }
4574 4571 need_to_commit = B_TRUE;
4575 4572 return;
4576 4573 case RT_FS_ALLOWED:
4577 4574 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4578 4575 zone_perror(zone, err, B_TRUE);
4579 4576 else
4580 4577 need_to_commit = B_TRUE;
4581 4578 return;
4582 4579 case RT_FS:
4583 4580 switch (prop_type) {
4584 4581 case PT_DIR:
4585 4582 (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4586 4583 sizeof (in_progress_fstab.zone_fs_dir));
4587 4584 return;
4588 4585 case PT_SPECIAL:
4589 4586 (void) strlcpy(in_progress_fstab.zone_fs_special,
4590 4587 prop_id,
4591 4588 sizeof (in_progress_fstab.zone_fs_special));
4592 4589 return;
4593 4590 case PT_RAW:
4594 4591 (void) strlcpy(in_progress_fstab.zone_fs_raw,
4595 4592 prop_id, sizeof (in_progress_fstab.zone_fs_raw));
4596 4593 return;
4597 4594 case PT_TYPE:
4598 4595 if (!valid_fs_type(prop_id)) {
4599 4596 zerr(gettext("\"%s\" is not a valid %s."),
4600 4597 prop_id, pt_to_str(PT_TYPE));
4601 4598 saw_error = B_TRUE;
4602 4599 return;
4603 4600 }
4604 4601 (void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
4605 4602 sizeof (in_progress_fstab.zone_fs_type));
4606 4603 return;
4607 4604 case PT_OPTIONS:
4608 4605 if (pp->pv_type != PROP_VAL_SIMPLE &&
4609 4606 pp->pv_type != PROP_VAL_LIST) {
4610 4607 zerr(gettext("A %s or %s value was expected "
4611 4608 "here."), pvt_to_str(PROP_VAL_SIMPLE),
4612 4609 pvt_to_str(PROP_VAL_LIST));
4613 4610 saw_error = B_TRUE;
4614 4611 return;
4615 4612 }
4616 4613 zonecfg_free_fs_option_list(
4617 4614 in_progress_fstab.zone_fs_options);
4618 4615 in_progress_fstab.zone_fs_options = NULL;
4619 4616 if (!(pp->pv_type == PROP_VAL_LIST &&
4620 4617 pp->pv_list == NULL))
4621 4618 add_property(cmd);
4622 4619 return;
4623 4620 default:
4624 4621 break;
4625 4622 }
4626 4623 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4627 4624 long_usage(CMD_SET, B_TRUE);
4628 4625 usage(B_FALSE, HELP_PROPS);
4629 4626 return;
4630 4627 case RT_NET:
4631 4628 switch (prop_type) {
4632 4629 case PT_ADDRESS:
4633 4630 case PT_ALLOWED_ADDRESS:
4634 4631 if (validate_net_address_syntax(prop_id, B_FALSE)
4635 4632 != Z_OK) {
4636 4633 saw_error = B_TRUE;
4637 4634 return;
4638 4635 }
4639 4636 set_in_progress_nwiftab_address(prop_id, prop_type);
4640 4637 break;
4641 4638 case PT_PHYSICAL:
4642 4639 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4643 4640 saw_error = B_TRUE;
4644 4641 return;
4645 4642 }
4646 4643 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4647 4644 prop_id,
4648 4645 sizeof (in_progress_nwiftab.zone_nwif_physical));
4649 4646 break;
4650 4647 case PT_DEFROUTER:
4651 4648 if (validate_net_address_syntax(prop_id, B_TRUE)
4652 4649 != Z_OK) {
4653 4650 saw_error = B_TRUE;
4654 4651 return;
4655 4652 }
4656 4653 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
4657 4654 prop_id,
4658 4655 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
4659 4656 break;
4660 4657 default:
4661 4658 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4662 4659 B_TRUE);
4663 4660 long_usage(CMD_SET, B_TRUE);
4664 4661 usage(B_FALSE, HELP_PROPS);
4665 4662 return;
4666 4663 }
4667 4664 return;
4668 4665 case RT_DEVICE:
4669 4666 switch (prop_type) {
4670 4667 case PT_MATCH:
4671 4668 (void) strlcpy(in_progress_devtab.zone_dev_match,
4672 4669 prop_id,
4673 4670 sizeof (in_progress_devtab.zone_dev_match));
4674 4671 break;
4675 4672 default:
4676 4673 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4677 4674 B_TRUE);
4678 4675 long_usage(CMD_SET, B_TRUE);
4679 4676 usage(B_FALSE, HELP_PROPS);
4680 4677 return;
4681 4678 }
4682 4679 return;
4683 4680 case RT_RCTL:
4684 4681 switch (prop_type) {
4685 4682 case PT_NAME:
4686 4683 if (!zonecfg_valid_rctlname(prop_id)) {
4687 4684 zerr(gettext("'%s' is not a valid zone %s "
4688 4685 "name."), prop_id, rt_to_str(RT_RCTL));
4689 4686 return;
4690 4687 }
4691 4688 (void) strlcpy(in_progress_rctltab.zone_rctl_name,
4692 4689 prop_id,
4693 4690 sizeof (in_progress_rctltab.zone_rctl_name));
4694 4691 break;
4695 4692 case PT_VALUE:
4696 4693 if (pp->pv_type != PROP_VAL_COMPLEX &&
4697 4694 pp->pv_type != PROP_VAL_LIST) {
4698 4695 zerr(gettext("A %s or %s value was expected "
4699 4696 "here."), pvt_to_str(PROP_VAL_COMPLEX),
4700 4697 pvt_to_str(PROP_VAL_LIST));
4701 4698 saw_error = B_TRUE;
4702 4699 return;
4703 4700 }
4704 4701 zonecfg_free_rctl_value_list(
4705 4702 in_progress_rctltab.zone_rctl_valptr);
4706 4703 in_progress_rctltab.zone_rctl_valptr = NULL;
4707 4704 if (!(pp->pv_type == PROP_VAL_LIST &&
4708 4705 pp->pv_list == NULL))
4709 4706 add_property(cmd);
4710 4707 break;
4711 4708 default:
4712 4709 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4713 4710 B_TRUE);
4714 4711 long_usage(CMD_SET, B_TRUE);
4715 4712 usage(B_FALSE, HELP_PROPS);
4716 4713 return;
4717 4714 }
4718 4715 return;
4719 4716 case RT_ATTR:
4720 4717 switch (prop_type) {
4721 4718 case PT_NAME:
4722 4719 (void) strlcpy(in_progress_attrtab.zone_attr_name,
4723 4720 prop_id,
4724 4721 sizeof (in_progress_attrtab.zone_attr_name));
4725 4722 break;
4726 4723 case PT_TYPE:
4727 4724 (void) strlcpy(in_progress_attrtab.zone_attr_type,
4728 4725 prop_id,
4729 4726 sizeof (in_progress_attrtab.zone_attr_type));
4730 4727 break;
4731 4728 case PT_VALUE:
4732 4729 (void) strlcpy(in_progress_attrtab.zone_attr_value,
4733 4730 prop_id,
4734 4731 sizeof (in_progress_attrtab.zone_attr_value));
4735 4732 break;
4736 4733 default:
4737 4734 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4738 4735 B_TRUE);
4739 4736 long_usage(CMD_SET, B_TRUE);
4740 4737 usage(B_FALSE, HELP_PROPS);
4741 4738 return;
4742 4739 }
4743 4740 return;
4744 4741 case RT_DATASET:
4745 4742 switch (prop_type) {
4746 4743 case PT_NAME:
4747 4744 (void) strlcpy(in_progress_dstab.zone_dataset_name,
4748 4745 prop_id,
4749 4746 sizeof (in_progress_dstab.zone_dataset_name));
4750 4747 return;
4751 4748 default:
4752 4749 break;
4753 4750 }
4754 4751 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4755 4752 long_usage(CMD_SET, B_TRUE);
4756 4753 usage(B_FALSE, HELP_PROPS);
4757 4754 return;
4758 4755 case RT_DCPU:
4759 4756 switch (prop_type) {
4760 4757 char *lowp, *highp;
4761 4758
4762 4759 case PT_NCPUS:
4763 4760 lowp = prop_id;
4764 4761 if ((highp = strchr(prop_id, '-')) != NULL)
4765 4762 *highp++ = '\0';
4766 4763 else
4767 4764 highp = lowp;
4768 4765
4769 4766 /* Make sure the input makes sense. */
4770 4767 if (!zonecfg_valid_ncpus(lowp, highp)) {
4771 4768 zerr(gettext("%s property is out of range."),
4772 4769 pt_to_str(PT_NCPUS));
4773 4770 saw_error = B_TRUE;
4774 4771 return;
4775 4772 }
4776 4773
4777 4774 (void) strlcpy(
4778 4775 in_progress_psettab.zone_ncpu_min, lowp,
4779 4776 sizeof (in_progress_psettab.zone_ncpu_min));
4780 4777 (void) strlcpy(
4781 4778 in_progress_psettab.zone_ncpu_max, highp,
4782 4779 sizeof (in_progress_psettab.zone_ncpu_max));
4783 4780 return;
4784 4781 case PT_IMPORTANCE:
4785 4782 /* Make sure the value makes sense. */
4786 4783 if (!zonecfg_valid_importance(prop_id)) {
4787 4784 zerr(gettext("%s property is out of range."),
4788 4785 pt_to_str(PT_IMPORTANCE));
4789 4786 saw_error = B_TRUE;
4790 4787 return;
4791 4788 }
4792 4789
4793 4790 (void) strlcpy(in_progress_psettab.zone_importance,
4794 4791 prop_id,
4795 4792 sizeof (in_progress_psettab.zone_importance));
4796 4793 return;
4797 4794 default:
4798 4795 break;
4799 4796 }
4800 4797 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4801 4798 long_usage(CMD_SET, B_TRUE);
4802 4799 usage(B_FALSE, HELP_PROPS);
4803 4800 return;
4804 4801 case RT_PCAP:
4805 4802 if (prop_type != PT_NCPUS) {
4806 4803 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4807 4804 B_TRUE);
4808 4805 long_usage(CMD_SET, B_TRUE);
4809 4806 usage(B_FALSE, HELP_PROPS);
4810 4807 return;
4811 4808 }
4812 4809
4813 4810 /*
4814 4811 * We already checked that an rctl alias is allowed in
4815 4812 * the add_resource() function.
4816 4813 */
4817 4814
4818 4815 if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
4819 4816 (int)(cap * 100) < 1) {
4820 4817 zerr(gettext("%s property is out of range."),
4821 4818 pt_to_str(PT_NCPUS));
4822 4819 saw_error = B_TRUE;
4823 4820 return;
4824 4821 }
4825 4822
4826 4823 if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
4827 4824 (int)(cap * 100))) != Z_OK)
4828 4825 zone_perror(zone, err, B_TRUE);
4829 4826 else
4830 4827 need_to_commit = B_TRUE;
4831 4828 return;
4832 4829 case RT_MCAP:
4833 4830 switch (prop_type) {
4834 4831 case PT_PHYSICAL:
4835 4832 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4836 4833 zerr(gettext("A positive number with a "
4837 4834 "required scale suffix (K, M, G or T) was "
4838 4835 "expected here."));
4839 4836 saw_error = B_TRUE;
4840 4837 } else if (mem_cap < ONE_MB) {
4841 4838 zerr(gettext("%s value is too small. It must "
4842 4839 "be at least 1M."), pt_to_str(PT_PHYSICAL));
4843 4840 saw_error = B_TRUE;
4844 4841 } else {
4845 4842 snprintf(in_progress_mcaptab.zone_physmem_cap,
4846 4843 physmem_size, "%llu", mem_cap);
4847 4844 }
4848 4845 break;
4849 4846 case PT_SWAP:
4850 4847 /*
4851 4848 * We have to check if an rctl is allowed here since
4852 4849 * there might already be a rctl defined that blocks
4853 4850 * the alias.
4854 4851 */
4855 4852 if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
4856 4853 zone_perror(pt_to_str(PT_MAXSWAP),
4857 4854 Z_ALIAS_DISALLOW, B_FALSE);
4858 4855 saw_error = B_TRUE;
4859 4856 return;
4860 4857 }
4861 4858
4862 4859 if (global_zone)
4863 4860 mem_limit = ONE_MB * 100;
4864 4861 else
4865 4862 mem_limit = ONE_MB * 50;
4866 4863
4867 4864 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4868 4865 zerr(gettext("A positive number with a "
4869 4866 "required scale suffix (K, M, G or T) was "
4870 4867 "expected here."));
4871 4868 saw_error = B_TRUE;
4872 4869 } else if (mem_cap < mem_limit) {
4873 4870 char buf[128];
4874 4871
4875 4872 (void) snprintf(buf, sizeof (buf), "%llu",
4876 4873 mem_limit);
4877 4874 bytes_to_units(buf, buf, sizeof (buf));
4878 4875 zerr(gettext("%s value is too small. It must "
4879 4876 "be at least %s."), pt_to_str(PT_SWAP),
4880 4877 buf);
4881 4878 saw_error = B_TRUE;
4882 4879 } else {
4883 4880 if ((err = zonecfg_set_aliased_rctl(handle,
4884 4881 ALIAS_MAXSWAP, mem_cap)) != Z_OK)
4885 4882 zone_perror(zone, err, B_TRUE);
4886 4883 else
4887 4884 need_to_commit = B_TRUE;
4888 4885 }
4889 4886 break;
4890 4887 case PT_LOCKED:
4891 4888 /*
4892 4889 * We have to check if an rctl is allowed here since
4893 4890 * there might already be a rctl defined that blocks
4894 4891 * the alias.
4895 4892 */
4896 4893 if (!zonecfg_aliased_rctl_ok(handle,
4897 4894 ALIAS_MAXLOCKEDMEM)) {
4898 4895 zone_perror(pt_to_str(PT_LOCKED),
4899 4896 Z_ALIAS_DISALLOW, B_FALSE);
4900 4897 saw_error = B_TRUE;
4901 4898 return;
4902 4899 }
4903 4900
4904 4901 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4905 4902 zerr(gettext("A non-negative number with a "
4906 4903 "required scale suffix (K, M, G or T) was "
4907 4904 "expected\nhere."));
4908 4905 saw_error = B_TRUE;
4909 4906 } else {
4910 4907 if ((err = zonecfg_set_aliased_rctl(handle,
4911 4908 ALIAS_MAXLOCKEDMEM, mem_cap)) != Z_OK)
4912 4909 zone_perror(zone, err, B_TRUE);
4913 4910 else
4914 4911 need_to_commit = B_TRUE;
4915 4912 }
4916 4913 break;
4917 4914 default:
4918 4915 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4919 4916 B_TRUE);
4920 4917 long_usage(CMD_SET, B_TRUE);
4921 4918 usage(B_FALSE, HELP_PROPS);
4922 4919 return;
4923 4920 }
4924 4921 return;
4925 4922 case RT_ADMIN:
4926 4923 switch (prop_type) {
4927 4924 case PT_USER:
4928 4925 (void) strlcpy(in_progress_admintab.zone_admin_user,
4929 4926 prop_id,
4930 4927 sizeof (in_progress_admintab.zone_admin_user));
4931 4928 return;
4932 4929 case PT_AUTHS:
4933 4930 (void) strlcpy(in_progress_admintab.zone_admin_auths,
4934 4931 prop_id,
4935 4932 sizeof (in_progress_admintab.zone_admin_auths));
4936 4933 return;
4937 4934 default:
4938 4935 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4939 4936 B_TRUE);
4940 4937 long_usage(CMD_SET, B_TRUE);
4941 4938 usage(B_FALSE, HELP_PROPS);
4942 4939 return;
4943 4940 }
4944 4941 case RT_SECFLAGS: {
4945 4942 char *propstr;
4946 4943
4947 4944 switch (prop_type) {
4948 4945 case PT_DEFAULT:
4949 4946 propstr = in_progress_secflagstab.zone_secflags_default;
4950 4947 break;
4951 4948 case PT_UPPER:
4952 4949 propstr = in_progress_secflagstab.zone_secflags_upper;
4953 4950 break;
4954 4951 case PT_LOWER:
4955 4952 propstr = in_progress_secflagstab.zone_secflags_lower;
4956 4953 break;
4957 4954 default:
4958 4955 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4959 4956 B_TRUE);
4960 4957 long_usage(CMD_SET, B_TRUE);
4961 4958 usage(B_FALSE, HELP_PROPS);
4962 4959 return;
4963 4960 }
4964 4961 (void) strlcpy(propstr, prop_id, ZONECFG_SECFLAGS_MAX);
4965 4962 return;
4966 4963 }
4967 4964 default:
4968 4965 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4969 4966 long_usage(CMD_SET, B_TRUE);
4970 4967 usage(B_FALSE, HELP_RESOURCES);
4971 4968 return;
4972 4969 }
4973 4970 }
4974 4971
4975 4972 static void
4976 4973 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4977 4974 {
4978 4975 char *qstr;
4979 4976
4980 4977 if (*pval != '\0') {
4981 4978 qstr = quoteit(pval);
4982 4979 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4983 4980 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4984 4981 qstr);
4985 4982 else
4986 4983 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
4987 4984 free(qstr);
4988 4985 } else if (print_notspec)
4989 4986 (void) fprintf(fp, gettext("\t%s not specified\n"),
4990 4987 pt_to_str(pnum));
4991 4988 }
4992 4989
4993 4990 static void
4994 4991 info_zonename(zone_dochandle_t handle, FILE *fp)
4995 4992 {
4996 4993 char zonename[ZONENAME_MAX];
4997 4994
4998 4995 if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
4999 4996 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
5000 4997 zonename);
5001 4998 else
5002 4999 (void) fprintf(fp, gettext("%s not specified\n"),
5003 5000 pt_to_str(PT_ZONENAME));
5004 5001 }
5005 5002
5006 5003 static void
5007 5004 info_zonepath(zone_dochandle_t handle, FILE *fp)
5008 5005 {
5009 5006 char zonepath[MAXPATHLEN];
5010 5007
5011 5008 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
5012 5009 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
5013 5010 zonepath);
5014 5011 else {
5015 5012 (void) fprintf(fp, gettext("%s not specified\n"),
5016 5013 pt_to_str(PT_ZONEPATH));
5017 5014 }
5018 5015 }
5019 5016
5020 5017 static void
5021 5018 info_brand(zone_dochandle_t handle, FILE *fp)
5022 5019 {
5023 5020 char brand[MAXNAMELEN];
5024 5021
5025 5022 if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
5026 5023 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
5027 5024 brand);
5028 5025 else
5029 5026 (void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
5030 5027 gettext("not specified"));
5031 5028 }
5032 5029
5033 5030 static void
5034 5031 info_autoboot(zone_dochandle_t handle, FILE *fp)
5035 5032 {
5036 5033 boolean_t autoboot;
5037 5034 int err;
5038 5035
5039 5036 if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
5040 5037 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
5041 5038 autoboot ? "true" : "false");
5042 5039 else
5043 5040 zone_perror(zone, err, B_TRUE);
5044 5041 }
5045 5042
5046 5043 static void
5047 5044 info_pool(zone_dochandle_t handle, FILE *fp)
5048 5045 {
5049 5046 char pool[MAXNAMELEN];
5050 5047 int err;
5051 5048
5052 5049 if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
5053 5050 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
5054 5051 else
5055 5052 zone_perror(zone, err, B_TRUE);
5056 5053 }
5057 5054
5058 5055 static void
5059 5056 info_limitpriv(zone_dochandle_t handle, FILE *fp)
5060 5057 {
5061 5058 char *limitpriv;
5062 5059 int err;
5063 5060
5064 5061 if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
5065 5062 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
5066 5063 limitpriv);
5067 5064 free(limitpriv);
5068 5065 } else {
5069 5066 zone_perror(zone, err, B_TRUE);
5070 5067 }
5071 5068 }
5072 5069
5073 5070 static void
5074 5071 info_bootargs(zone_dochandle_t handle, FILE *fp)
5075 5072 {
5076 5073 char bootargs[BOOTARGS_MAX];
5077 5074 int err;
5078 5075
5079 5076 if ((err = zonecfg_get_bootargs(handle, bootargs,
5080 5077 sizeof (bootargs))) == Z_OK) {
5081 5078 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
5082 5079 bootargs);
5083 5080 } else {
5084 5081 zone_perror(zone, err, B_TRUE);
5085 5082 }
5086 5083 }
5087 5084
5088 5085 static void
5089 5086 info_sched(zone_dochandle_t handle, FILE *fp)
5090 5087 {
5091 5088 char sched[MAXNAMELEN];
5092 5089 int err;
5093 5090
5094 5091 if ((err = zonecfg_get_sched_class(handle, sched, sizeof (sched)))
5095 5092 == Z_OK) {
5096 5093 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_SCHED), sched);
5097 5094 } else {
5098 5095 zone_perror(zone, err, B_TRUE);
5099 5096 }
5100 5097 }
5101 5098
5102 5099 static void
5103 5100 info_iptype(zone_dochandle_t handle, FILE *fp)
5104 5101 {
5105 5102 zone_iptype_t iptype;
5106 5103 int err;
5107 5104
5108 5105 if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
5109 5106 switch (iptype) {
5110 5107 case ZS_SHARED:
5111 5108 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
5112 5109 "shared");
5113 5110 break;
5114 5111 case ZS_EXCLUSIVE:
5115 5112 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
5116 5113 "exclusive");
5117 5114 break;
5118 5115 }
5119 5116 } else {
5120 5117 zone_perror(zone, err, B_TRUE);
5121 5118 }
5122 5119 }
5123 5120
5124 5121 static void
5125 5122 info_hostid(zone_dochandle_t handle, FILE *fp)
5126 5123 {
5127 5124 char hostidp[HW_HOSTID_LEN];
5128 5125 int err;
5129 5126
5130 5127 if ((err = zonecfg_get_hostid(handle, hostidp,
5131 5128 sizeof (hostidp))) == Z_OK) {
5132 5129 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
5133 5130 } else if (err == Z_BAD_PROPERTY) {
5134 5131 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
5135 5132 } else {
5136 5133 zone_perror(zone, err, B_TRUE);
5137 5134 }
5138 5135 }
5139 5136
5140 5137 static void
5141 5138 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
5142 5139 {
5143 5140 char fsallowedp[ZONE_FS_ALLOWED_MAX];
5144 5141 int err;
5145 5142
5146 5143 if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
5147 5144 sizeof (fsallowedp))) == Z_OK) {
5148 5145 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
5149 5146 fsallowedp);
5150 5147 } else if (err == Z_BAD_PROPERTY) {
5151 5148 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
5152 5149 } else {
5153 5150 zone_perror(zone, err, B_TRUE);
5154 5151 }
5155 5152 }
5156 5153
5157 5154 static void
5158 5155 output_fs(FILE *fp, struct zone_fstab *fstab)
5159 5156 {
5160 5157 zone_fsopt_t *this;
5161 5158
5162 5159 (void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
5163 5160 output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
5164 5161 output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
5165 5162 output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
5166 5163 output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
5167 5164 (void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
5168 5165 for (this = fstab->zone_fs_options; this != NULL;
5169 5166 this = this->zone_fsopt_next) {
5170 5167 if (strchr(this->zone_fsopt_opt, '='))
5171 5168 (void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
5172 5169 else
5173 5170 (void) fprintf(fp, "%s", this->zone_fsopt_opt);
5174 5171 if (this->zone_fsopt_next != NULL)
5175 5172 (void) fprintf(fp, ",");
5176 5173 }
5177 5174 (void) fprintf(fp, "]\n");
5178 5175 }
5179 5176
5180 5177 static void
5181 5178 info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5182 5179 {
5183 5180 struct zone_fstab lookup, user;
5184 5181 boolean_t output = B_FALSE;
5185 5182
5186 5183 if (zonecfg_setfsent(handle) != Z_OK)
5187 5184 return;
5188 5185 while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
5189 5186 if (cmd->cmd_prop_nv_pairs == 0) {
5190 5187 output_fs(fp, &lookup);
5191 5188 goto loopend;
5192 5189 }
5193 5190 if (fill_in_fstab(cmd, &user, B_TRUE) != Z_OK)
5194 5191 goto loopend;
5195 5192 if (strlen(user.zone_fs_dir) > 0 &&
5196 5193 strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
5197 5194 goto loopend; /* no match */
5198 5195 if (strlen(user.zone_fs_special) > 0 &&
5199 5196 strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
5200 5197 goto loopend; /* no match */
5201 5198 if (strlen(user.zone_fs_type) > 0 &&
5202 5199 strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
5203 5200 goto loopend; /* no match */
5204 5201 output_fs(fp, &lookup);
5205 5202 output = B_TRUE;
5206 5203 loopend:
5207 5204 zonecfg_free_fs_option_list(lookup.zone_fs_options);
5208 5205 }
5209 5206 (void) zonecfg_endfsent(handle);
5210 5207 /*
5211 5208 * If a property n/v pair was specified, warn the user if there was
5212 5209 * nothing to output.
5213 5210 */
5214 5211 if (!output && cmd->cmd_prop_nv_pairs > 0)
5215 5212 (void) printf(gettext("No such %s resource.\n"),
5216 5213 rt_to_str(RT_FS));
5217 5214 }
5218 5215
5219 5216 static void
5220 5217 output_net(FILE *fp, struct zone_nwiftab *nwiftab)
5221 5218 {
5222 5219 (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
5223 5220 output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
5224 5221 output_prop(fp, PT_ALLOWED_ADDRESS,
5225 5222 nwiftab->zone_nwif_allowed_address, B_TRUE);
5226 5223 output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
5227 5224 output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
5228 5225 }
5229 5226
5230 5227 static void
5231 5228 info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5232 5229 {
5233 5230 struct zone_nwiftab lookup, user;
5234 5231 boolean_t output = B_FALSE;
5235 5232
5236 5233 if (zonecfg_setnwifent(handle) != Z_OK)
5237 5234 return;
5238 5235 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
5239 5236 if (cmd->cmd_prop_nv_pairs == 0) {
5240 5237 output_net(fp, &lookup);
5241 5238 continue;
5242 5239 }
5243 5240 if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
5244 5241 continue;
5245 5242 if (strlen(user.zone_nwif_physical) > 0 &&
5246 5243 strcmp(user.zone_nwif_physical,
5247 5244 lookup.zone_nwif_physical) != 0)
5248 5245 continue; /* no match */
5249 5246 /* If present make sure it matches */
5250 5247 if (strlen(user.zone_nwif_address) > 0 &&
5251 5248 !zonecfg_same_net_address(user.zone_nwif_address,
5252 5249 lookup.zone_nwif_address))
5253 5250 continue; /* no match */
5254 5251 output_net(fp, &lookup);
5255 5252 output = B_TRUE;
5256 5253 }
5257 5254 (void) zonecfg_endnwifent(handle);
5258 5255 /*
5259 5256 * If a property n/v pair was specified, warn the user if there was
5260 5257 * nothing to output.
5261 5258 */
5262 5259 if (!output && cmd->cmd_prop_nv_pairs > 0)
5263 5260 (void) printf(gettext("No such %s resource.\n"),
5264 5261 rt_to_str(RT_NET));
5265 5262 }
5266 5263
5267 5264 static void
5268 5265 output_dev(FILE *fp, struct zone_devtab *devtab)
5269 5266 {
5270 5267 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
5271 5268 output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
5272 5269 }
5273 5270
5274 5271 static void
5275 5272 info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5276 5273 {
5277 5274 struct zone_devtab lookup, user;
5278 5275 boolean_t output = B_FALSE;
5279 5276
5280 5277 if (zonecfg_setdevent(handle) != Z_OK)
5281 5278 return;
5282 5279 while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
5283 5280 if (cmd->cmd_prop_nv_pairs == 0) {
5284 5281 output_dev(fp, &lookup);
5285 5282 continue;
5286 5283 }
5287 5284 if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
5288 5285 continue;
5289 5286 if (strlen(user.zone_dev_match) > 0 &&
5290 5287 strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
5291 5288 continue; /* no match */
5292 5289 output_dev(fp, &lookup);
5293 5290 output = B_TRUE;
5294 5291 }
5295 5292 (void) zonecfg_enddevent(handle);
5296 5293 /*
5297 5294 * If a property n/v pair was specified, warn the user if there was
5298 5295 * nothing to output.
5299 5296 */
5300 5297 if (!output && cmd->cmd_prop_nv_pairs > 0)
5301 5298 (void) printf(gettext("No such %s resource.\n"),
5302 5299 rt_to_str(RT_DEVICE));
5303 5300 }
5304 5301
5305 5302 static void
5306 5303 output_rctl(FILE *fp, struct zone_rctltab *rctltab)
5307 5304 {
5308 5305 struct zone_rctlvaltab *valptr;
5309 5306
5310 5307 (void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
5311 5308 output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
5312 5309 for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
5313 5310 valptr = valptr->zone_rctlval_next) {
5314 5311 fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
5315 5312 pt_to_str(PT_VALUE),
5316 5313 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
5317 5314 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
5318 5315 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
5319 5316 }
5320 5317 }
5321 5318
5322 5319 static void
5323 5320 info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5324 5321 {
5325 5322 struct zone_rctltab lookup, user;
5326 5323 boolean_t output = B_FALSE;
5327 5324
5328 5325 if (zonecfg_setrctlent(handle) != Z_OK)
5329 5326 return;
5330 5327 while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
5331 5328 if (cmd->cmd_prop_nv_pairs == 0) {
5332 5329 output_rctl(fp, &lookup);
5333 5330 } else if (fill_in_rctltab(cmd, &user, B_TRUE) == Z_OK &&
5334 5331 (strlen(user.zone_rctl_name) == 0 ||
5335 5332 strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
5336 5333 output_rctl(fp, &lookup);
5337 5334 output = B_TRUE;
5338 5335 }
5339 5336 zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
5340 5337 }
5341 5338 (void) zonecfg_endrctlent(handle);
5342 5339 /*
5343 5340 * If a property n/v pair was specified, warn the user if there was
5344 5341 * nothing to output.
5345 5342 */
5346 5343 if (!output && cmd->cmd_prop_nv_pairs > 0)
5347 5344 (void) printf(gettext("No such %s resource.\n"),
5348 5345 rt_to_str(RT_RCTL));
5349 5346 }
5350 5347
5351 5348 static void
5352 5349 output_attr(FILE *fp, struct zone_attrtab *attrtab)
5353 5350 {
5354 5351 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
5355 5352 output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
5356 5353 output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
5357 5354 output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
5358 5355 }
5359 5356
5360 5357 static void
5361 5358 info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5362 5359 {
5363 5360 struct zone_attrtab lookup, user;
5364 5361 boolean_t output = B_FALSE;
5365 5362
5366 5363 if (zonecfg_setattrent(handle) != Z_OK)
5367 5364 return;
5368 5365 while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
5369 5366 if (cmd->cmd_prop_nv_pairs == 0) {
5370 5367 output_attr(fp, &lookup);
5371 5368 continue;
5372 5369 }
5373 5370 if (fill_in_attrtab(cmd, &user, B_TRUE) != Z_OK)
5374 5371 continue;
5375 5372 if (strlen(user.zone_attr_name) > 0 &&
5376 5373 strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
5377 5374 continue; /* no match */
5378 5375 if (strlen(user.zone_attr_type) > 0 &&
5379 5376 strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
5380 5377 continue; /* no match */
5381 5378 if (strlen(user.zone_attr_value) > 0 &&
5382 5379 strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
5383 5380 continue; /* no match */
5384 5381 output_attr(fp, &lookup);
5385 5382 output = B_TRUE;
5386 5383 }
5387 5384 (void) zonecfg_endattrent(handle);
5388 5385 /*
5389 5386 * If a property n/v pair was specified, warn the user if there was
5390 5387 * nothing to output.
5391 5388 */
5392 5389 if (!output && cmd->cmd_prop_nv_pairs > 0)
5393 5390 (void) printf(gettext("No such %s resource.\n"),
5394 5391 rt_to_str(RT_ATTR));
5395 5392 }
5396 5393
5397 5394 static void
5398 5395 output_ds(FILE *fp, struct zone_dstab *dstab)
5399 5396 {
5400 5397 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
5401 5398 output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
5402 5399 }
5403 5400
5404 5401 static void
5405 5402 info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5406 5403 {
5407 5404 struct zone_dstab lookup, user;
5408 5405 boolean_t output = B_FALSE;
5409 5406
5410 5407 if (zonecfg_setdsent(handle) != Z_OK)
5411 5408 return;
5412 5409 while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
5413 5410 if (cmd->cmd_prop_nv_pairs == 0) {
5414 5411 output_ds(fp, &lookup);
5415 5412 continue;
5416 5413 }
5417 5414 if (fill_in_dstab(cmd, &user, B_TRUE) != Z_OK)
5418 5415 continue;
5419 5416 if (strlen(user.zone_dataset_name) > 0 &&
5420 5417 strcmp(user.zone_dataset_name,
5421 5418 lookup.zone_dataset_name) != 0)
5422 5419 continue; /* no match */
5423 5420 output_ds(fp, &lookup);
5424 5421 output = B_TRUE;
5425 5422 }
5426 5423 (void) zonecfg_enddsent(handle);
5427 5424 /*
5428 5425 * If a property n/v pair was specified, warn the user if there was
5429 5426 * nothing to output.
5430 5427 */
5431 5428 if (!output && cmd->cmd_prop_nv_pairs > 0)
5432 5429 (void) printf(gettext("No such %s resource.\n"),
5433 5430 rt_to_str(RT_DATASET));
5434 5431 }
5435 5432
5436 5433 static void
5437 5434 output_pset(FILE *fp, struct zone_psettab *psettab)
5438 5435 {
5439 5436 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DCPU));
5440 5437 if (strcmp(psettab->zone_ncpu_min, psettab->zone_ncpu_max) == 0)
5441 5438 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_NCPUS),
5442 5439 psettab->zone_ncpu_max);
5443 5440 else
5444 5441 (void) fprintf(fp, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS),
5445 5442 psettab->zone_ncpu_min, psettab->zone_ncpu_max);
5446 5443 if (psettab->zone_importance[0] != '\0')
5447 5444 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE),
5448 5445 psettab->zone_importance);
5449 5446 }
5450 5447
5451 5448 static void
5452 5449 info_pset(zone_dochandle_t handle, FILE *fp)
5453 5450 {
5454 5451 struct zone_psettab lookup;
5455 5452
5456 5453 if (zonecfg_getpsetent(handle, &lookup) == Z_OK)
5457 5454 output_pset(fp, &lookup);
5458 5455 }
5459 5456
5460 5457 static void
5461 5458 output_pcap(FILE *fp)
5462 5459 {
5463 5460 uint64_t cap;
5464 5461
5465 5462 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &cap) == Z_OK) {
5466 5463 float scaled = (float)cap / 100;
5467 5464 (void) fprintf(fp, "%s:\n", rt_to_str(RT_PCAP));
5468 5465 (void) fprintf(fp, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS),
5469 5466 scaled);
5470 5467 }
5471 5468 }
5472 5469
5473 5470 static void
5474 5471 info_pcap(FILE *fp)
5475 5472 {
5476 5473 output_pcap(fp);
5477 5474 }
5478 5475
5479 5476
5480 5477 static void
5481 5478 info_aliased_rctl(zone_dochandle_t handle, FILE *fp, char *alias)
5482 5479 {
5483 5480 uint64_t limit;
5484 5481
5485 5482 if (zonecfg_get_aliased_rctl(handle, alias, &limit) == Z_OK) {
5486 5483 /* convert memory based properties */
5487 5484 if (strcmp(alias, ALIAS_MAXSHMMEM) == 0) {
5488 5485 char buf[128];
5489 5486
5490 5487 (void) snprintf(buf, sizeof (buf), "%llu", limit);
5491 5488 bytes_to_units(buf, buf, sizeof (buf));
5492 5489 (void) fprintf(fp, "[%s: %s]\n", alias, buf);
5493 5490 return;
5494 5491 }
5495 5492
5496 5493 (void) fprintf(fp, "[%s: %llu]\n", alias, limit);
5497 5494 }
5498 5495 }
5499 5496
5500 5497 static void
5501 5498 bytes_to_units(char *str, char *buf, int bufsize)
5502 5499 {
5503 5500 unsigned long long num;
5504 5501 unsigned long long save = 0;
5505 5502 char *units = "BKMGT";
5506 5503 char *up = units;
5507 5504
5508 5505 num = strtoll(str, NULL, 10);
5509 5506
5510 5507 if (num < 1024) {
5511 5508 (void) snprintf(buf, bufsize, "%llu", num);
5512 5509 return;
5513 5510 }
5514 5511
5515 5512 while ((num >= 1024) && (*up != 'T')) {
5516 5513 up++; /* next unit of measurement */
5517 5514 save = num;
5518 5515 num = (num + 512) >> 10;
5519 5516 }
5520 5517
5521 5518 /* check if we should output a fraction. snprintf will round for us */
5522 5519 if (save % 1024 != 0 && ((save >> 10) < 10))
5523 5520 (void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
5524 5521 *up);
5525 5522 else
5526 5523 (void) snprintf(buf, bufsize, "%llu%c", num, *up);
5527 5524 }
5528 5525
5529 5526 static void
5530 5527 output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
5531 5528 uint64_t maxswap, int showlocked, uint64_t maxlocked)
5532 5529 {
5533 5530 char buf[128];
5534 5531
5535 5532 (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
5536 5533 if (mcaptab->zone_physmem_cap[0] != '\0') {
5537 5534 bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
5538 5535 output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
5539 5536 }
5540 5537
5541 5538 if (showswap == Z_OK) {
5542 5539 (void) snprintf(buf, sizeof (buf), "%llu", maxswap);
5543 5540 bytes_to_units(buf, buf, sizeof (buf));
5544 5541 output_prop(fp, PT_SWAP, buf, B_TRUE);
5545 5542 }
5546 5543
5547 5544 if (showlocked == Z_OK) {
5548 5545 (void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
5549 5546 bytes_to_units(buf, buf, sizeof (buf));
5550 5547 output_prop(fp, PT_LOCKED, buf, B_TRUE);
5551 5548 }
5552 5549 }
5553 5550
5554 5551 static void
5555 5552 info_mcap(zone_dochandle_t handle, FILE *fp)
5556 5553 {
5557 5554 int res1, res2, res3;
5558 5555 uint64_t swap_limit;
5559 5556 uint64_t locked_limit;
5560 5557 struct zone_mcaptab lookup;
5561 5558
5562 5559 bzero(&lookup, sizeof (lookup));
5563 5560 res1 = zonecfg_getmcapent(handle, &lookup);
5564 5561 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5565 5562 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5566 5563 &locked_limit);
5567 5564
5568 5565 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5569 5566 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5570 5567 }
5571 5568
5572 5569 static void
5573 5570 output_auth(FILE *fp, struct zone_admintab *admintab)
5574 5571 {
5575 5572 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5576 5573 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5577 5574 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5578 5575 }
5579 5576
5580 5577 static void
5581 5578 output_secflags(FILE *fp, struct zone_secflagstab *sftab)
5582 5579 {
5583 5580 (void) fprintf(fp, "%s:\n", rt_to_str(RT_SECFLAGS));
5584 5581 output_prop(fp, PT_DEFAULT, sftab->zone_secflags_default, B_TRUE);
5585 5582 output_prop(fp, PT_LOWER, sftab->zone_secflags_lower, B_TRUE);
5586 5583 output_prop(fp, PT_UPPER, sftab->zone_secflags_upper, B_TRUE);
5587 5584 }
5588 5585
5589 5586 static void
5590 5587 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5591 5588 {
5592 5589 struct zone_admintab lookup, user;
5593 5590 boolean_t output = B_FALSE;
5594 5591 int err;
5595 5592
5596 5593 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5597 5594 zone_perror(zone, err, B_TRUE);
5598 5595 return;
5599 5596 }
5600 5597 while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5601 5598 if (cmd->cmd_prop_nv_pairs == 0) {
5602 5599 output_auth(fp, &lookup);
5603 5600 continue;
5604 5601 }
5605 5602 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5606 5603 continue;
5607 5604 if (strlen(user.zone_admin_user) > 0 &&
5608 5605 strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5609 5606 continue; /* no match */
5610 5607 output_auth(fp, &lookup);
5611 5608 output = B_TRUE;
5612 5609 }
5613 5610 (void) zonecfg_endadminent(handle);
5614 5611 /*
5615 5612 * If a property n/v pair was specified, warn the user if there was
5616 5613 * nothing to output.
↓ open down ↓ |
3475 lines elided |
↑ open up ↑ |
5617 5614 */
5618 5615 if (!output && cmd->cmd_prop_nv_pairs > 0)
5619 5616 (void) printf(gettext("No such %s resource.\n"),
5620 5617 rt_to_str(RT_ADMIN));
5621 5618 }
5622 5619
5623 5620 static void
5624 5621 info_secflags(zone_dochandle_t handle, FILE *fp)
5625 5622 {
5626 5623 struct zone_secflagstab sftab;
5627 - int err;
5628 5624
5629 - if ((err = zonecfg_lookup_secflags(handle, &sftab)) != Z_OK) {
5630 - zone_perror(zone, err, B_TRUE);
5631 - return;
5625 + if (zonecfg_lookup_secflags(handle, &sftab) == Z_OK) {
5626 + output_secflags(fp, &sftab);
5632 5627 }
5633 -
5634 - output_secflags(fp, &sftab);
5635 5628 }
5636 5629
5637 5630 void
5638 5631 info_func(cmd_t *cmd)
5639 5632 {
5640 5633 FILE *fp = stdout;
5641 5634 boolean_t need_to_close = B_FALSE;
5642 5635 int type;
5643 5636 int res1, res2;
5644 5637 uint64_t swap_limit;
5645 5638 uint64_t locked_limit;
5646 5639
5647 5640 assert(cmd != NULL);
5648 5641
5649 5642 if (initialize(B_TRUE) != Z_OK)
5650 5643 return;
5651 5644
5652 5645 /* don't page error output */
5653 5646 if (interactive_mode) {
5654 5647 if ((fp = pager_open()) != NULL)
5655 5648 need_to_close = B_TRUE;
5656 5649 else
5657 5650 fp = stdout;
5658 5651
5659 5652 setbuf(fp, NULL);
5660 5653 }
5661 5654
5662 5655 if (!global_scope) {
5663 5656 switch (resource_scope) {
5664 5657 case RT_FS:
5665 5658 output_fs(fp, &in_progress_fstab);
5666 5659 break;
5667 5660 case RT_NET:
5668 5661 output_net(fp, &in_progress_nwiftab);
5669 5662 break;
5670 5663 case RT_DEVICE:
5671 5664 output_dev(fp, &in_progress_devtab);
5672 5665 break;
5673 5666 case RT_RCTL:
5674 5667 output_rctl(fp, &in_progress_rctltab);
5675 5668 break;
5676 5669 case RT_ATTR:
5677 5670 output_attr(fp, &in_progress_attrtab);
5678 5671 break;
5679 5672 case RT_DATASET:
5680 5673 output_ds(fp, &in_progress_dstab);
5681 5674 break;
5682 5675 case RT_DCPU:
5683 5676 output_pset(fp, &in_progress_psettab);
5684 5677 break;
5685 5678 case RT_PCAP:
5686 5679 output_pcap(fp);
5687 5680 break;
5688 5681 case RT_MCAP:
5689 5682 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5690 5683 &swap_limit);
5691 5684 res2 = zonecfg_get_aliased_rctl(handle,
5692 5685 ALIAS_MAXLOCKEDMEM, &locked_limit);
5693 5686 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5694 5687 res2, locked_limit);
5695 5688 break;
5696 5689 case RT_ADMIN:
5697 5690 output_auth(fp, &in_progress_admintab);
5698 5691 break;
5699 5692 case RT_SECFLAGS:
5700 5693 output_secflags(fp, &in_progress_secflagstab);
5701 5694 break;
5702 5695 }
5703 5696 goto cleanup;
5704 5697 }
5705 5698
5706 5699 type = cmd->cmd_res_type;
5707 5700
5708 5701 if (gz_invalid_rt_property(type)) {
5709 5702 zerr(gettext("%s is not a valid property for the global zone."),
5710 5703 rt_to_str(type));
5711 5704 goto cleanup;
5712 5705 }
5713 5706
5714 5707 if (gz_invalid_resource(type)) {
5715 5708 zerr(gettext("%s is not a valid resource for the global zone."),
5716 5709 rt_to_str(type));
5717 5710 goto cleanup;
5718 5711 }
5719 5712
5720 5713 switch (cmd->cmd_res_type) {
5721 5714 case RT_UNKNOWN:
5722 5715 info_zonename(handle, fp);
5723 5716 if (!global_zone) {
5724 5717 info_zonepath(handle, fp);
5725 5718 info_brand(handle, fp);
5726 5719 info_autoboot(handle, fp);
5727 5720 info_bootargs(handle, fp);
5728 5721 }
5729 5722 info_pool(handle, fp);
5730 5723 if (!global_zone) {
5731 5724 info_limitpriv(handle, fp);
5732 5725 info_sched(handle, fp);
5733 5726 info_iptype(handle, fp);
5734 5727 info_hostid(handle, fp);
5735 5728 info_fs_allowed(handle, fp);
5736 5729 }
5737 5730 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5738 5731 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5739 5732 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5740 5733 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5741 5734 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5742 5735 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5743 5736 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5744 5737 if (!global_zone) {
5745 5738 info_fs(handle, fp, cmd);
5746 5739 info_net(handle, fp, cmd);
5747 5740 info_dev(handle, fp, cmd);
5748 5741 }
5749 5742 info_pset(handle, fp);
5750 5743 info_pcap(fp);
5751 5744 info_mcap(handle, fp);
5752 5745 if (!global_zone) {
5753 5746 info_attr(handle, fp, cmd);
5754 5747 info_ds(handle, fp, cmd);
5755 5748 info_auth(handle, fp, cmd);
5756 5749 }
5757 5750 info_rctl(handle, fp, cmd);
5758 5751 info_secflags(handle, fp);
5759 5752 break;
5760 5753 case RT_ZONENAME:
5761 5754 info_zonename(handle, fp);
5762 5755 break;
5763 5756 case RT_ZONEPATH:
5764 5757 info_zonepath(handle, fp);
5765 5758 break;
5766 5759 case RT_BRAND:
5767 5760 info_brand(handle, fp);
5768 5761 break;
5769 5762 case RT_AUTOBOOT:
5770 5763 info_autoboot(handle, fp);
5771 5764 break;
5772 5765 case RT_POOL:
5773 5766 info_pool(handle, fp);
5774 5767 break;
5775 5768 case RT_LIMITPRIV:
5776 5769 info_limitpriv(handle, fp);
5777 5770 break;
5778 5771 case RT_BOOTARGS:
5779 5772 info_bootargs(handle, fp);
5780 5773 break;
5781 5774 case RT_SCHED:
5782 5775 info_sched(handle, fp);
5783 5776 break;
5784 5777 case RT_IPTYPE:
5785 5778 info_iptype(handle, fp);
5786 5779 break;
5787 5780 case RT_MAXLWPS:
5788 5781 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5789 5782 break;
5790 5783 case RT_MAXPROCS:
5791 5784 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5792 5785 break;
5793 5786 case RT_MAXSHMMEM:
5794 5787 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5795 5788 break;
5796 5789 case RT_MAXSHMIDS:
5797 5790 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5798 5791 break;
5799 5792 case RT_MAXMSGIDS:
5800 5793 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5801 5794 break;
5802 5795 case RT_MAXSEMIDS:
5803 5796 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5804 5797 break;
5805 5798 case RT_SHARES:
5806 5799 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5807 5800 break;
5808 5801 case RT_FS:
5809 5802 info_fs(handle, fp, cmd);
5810 5803 break;
5811 5804 case RT_NET:
5812 5805 info_net(handle, fp, cmd);
5813 5806 break;
5814 5807 case RT_DEVICE:
5815 5808 info_dev(handle, fp, cmd);
5816 5809 break;
5817 5810 case RT_RCTL:
5818 5811 info_rctl(handle, fp, cmd);
5819 5812 break;
5820 5813 case RT_ATTR:
5821 5814 info_attr(handle, fp, cmd);
5822 5815 break;
5823 5816 case RT_DATASET:
5824 5817 info_ds(handle, fp, cmd);
5825 5818 break;
5826 5819 case RT_DCPU:
5827 5820 info_pset(handle, fp);
5828 5821 break;
5829 5822 case RT_PCAP:
5830 5823 info_pcap(fp);
5831 5824 break;
5832 5825 case RT_MCAP:
5833 5826 info_mcap(handle, fp);
5834 5827 break;
5835 5828 case RT_HOSTID:
5836 5829 info_hostid(handle, fp);
5837 5830 break;
5838 5831 case RT_ADMIN:
5839 5832 info_auth(handle, fp, cmd);
5840 5833 break;
5841 5834 case RT_FS_ALLOWED:
5842 5835 info_fs_allowed(handle, fp);
5843 5836 break;
5844 5837 case RT_SECFLAGS:
5845 5838 info_secflags(handle, fp);
5846 5839 break;
5847 5840 default:
5848 5841 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5849 5842 B_TRUE);
5850 5843 }
5851 5844
5852 5845 cleanup:
5853 5846 if (need_to_close)
5854 5847 (void) pager_close(fp);
5855 5848 }
5856 5849
5857 5850 /*
5858 5851 * Helper function for verify-- checks that a required string property
5859 5852 * exists.
5860 5853 */
5861 5854 static void
5862 5855 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5863 5856 {
5864 5857 if (strlen(attr) == 0) {
5865 5858 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5866 5859 pt_to_str(pt));
5867 5860 saw_error = B_TRUE;
5868 5861 if (*ret_val == Z_OK)
5869 5862 *ret_val = Z_REQD_PROPERTY_MISSING;
5870 5863 }
5871 5864 }
5872 5865
5873 5866 static int
5874 5867 do_subproc(char *cmdbuf)
5875 5868 {
5876 5869 char inbuf[MAX_CMD_LEN];
5877 5870 FILE *file;
5878 5871 int status;
5879 5872
5880 5873 file = popen(cmdbuf, "r");
5881 5874 if (file == NULL) {
5882 5875 zerr(gettext("Could not launch: %s"), cmdbuf);
5883 5876 return (-1);
5884 5877 }
5885 5878
5886 5879 while (fgets(inbuf, sizeof (inbuf), file) != NULL)
5887 5880 fprintf(stderr, "%s", inbuf);
5888 5881 status = pclose(file);
5889 5882
5890 5883 if (WIFSIGNALED(status)) {
5891 5884 zerr(gettext("%s unexpectedly terminated due to signal %d"),
5892 5885 cmdbuf, WTERMSIG(status));
5893 5886 return (-1);
5894 5887 }
5895 5888 assert(WIFEXITED(status));
5896 5889 return (WEXITSTATUS(status));
5897 5890 }
5898 5891
5899 5892 static int
5900 5893 brand_verify(zone_dochandle_t handle)
5901 5894 {
5902 5895 char xml_file[32];
5903 5896 char cmdbuf[MAX_CMD_LEN];
5904 5897 brand_handle_t bh;
5905 5898 char brand[MAXNAMELEN];
5906 5899 int err;
5907 5900
5908 5901 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
5909 5902 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
5910 5903 return (Z_INVALID_DOCUMENT);
5911 5904 }
5912 5905 if ((bh = brand_open(brand)) == NULL) {
5913 5906 zerr("%s: %s\n", zone, gettext("unknown brand."));
5914 5907 return (Z_INVALID_DOCUMENT);
5915 5908 }
5916 5909
5917 5910 /*
5918 5911 * Fetch the verify command, if any, from the brand configuration
5919 5912 * and build the command line to execute it.
5920 5913 */
5921 5914 strcpy(cmdbuf, EXEC_PREFIX);
5922 5915 err = brand_get_verify_cfg(bh, cmdbuf + EXEC_LEN,
5923 5916 sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
5924 5917 brand_close(bh);
5925 5918 if (err != Z_OK) {
5926 5919 zerr("%s: %s\n", zone,
5927 5920 gettext("could not get brand verification command"));
5928 5921 return (Z_INVALID_DOCUMENT);
5929 5922 }
5930 5923
5931 5924 /*
5932 5925 * If the brand doesn't provide a verification routine, we just
5933 5926 * return success.
5934 5927 */
5935 5928 if (strlen(cmdbuf) == EXEC_LEN)
5936 5929 return (Z_OK);
5937 5930
5938 5931 /*
5939 5932 * Dump the current config information for this zone to a file.
5940 5933 */
5941 5934 strcpy(xml_file, "/tmp/zonecfg_verify.XXXXXX");
5942 5935 if (mkstemp(xml_file) == NULL)
5943 5936 return (Z_TEMP_FILE);
5944 5937 if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
5945 5938 (void) unlink(xml_file);
5946 5939 return (err);
5947 5940 }
5948 5941
5949 5942 /*
5950 5943 * Execute the verification command.
5951 5944 */
5952 5945 if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
5953 5946 (strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
5954 5947 err = Z_BRAND_ERROR;
5955 5948 } else {
5956 5949 err = do_subproc(cmdbuf);
5957 5950 }
5958 5951
5959 5952 (void) unlink(xml_file);
5960 5953 return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
5961 5954 }
5962 5955
5963 5956 /*
5964 5957 * Track the network interfaces listed in zonecfg(1m) in a linked list
5965 5958 * so that we can later check that defrouter is specified for an exclusive IP
5966 5959 * zone if and only if at least one allowed-address has been specified.
5967 5960 */
5968 5961 static boolean_t
5969 5962 add_nwif(struct zone_nwiftab *nwif)
5970 5963 {
5971 5964 struct xif *tmp;
5972 5965
5973 5966 for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
5974 5967 if (strcmp(tmp->xif_name, nwif->zone_nwif_physical) == 0) {
5975 5968 if (strlen(nwif->zone_nwif_allowed_address) > 0)
5976 5969 tmp->xif_has_address = B_TRUE;
5977 5970 if (strlen(nwif->zone_nwif_defrouter) > 0)
5978 5971 tmp->xif_has_defrouter = B_TRUE;
5979 5972 return (B_TRUE);
5980 5973 }
5981 5974 }
5982 5975
5983 5976 tmp = malloc(sizeof (*tmp));
5984 5977 if (tmp == NULL) {
5985 5978 zerr(gettext("memory allocation failed for %s"),
5986 5979 nwif->zone_nwif_physical);
5987 5980 return (B_FALSE);
5988 5981 }
5989 5982 strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5990 5983 sizeof (tmp->xif_name));
5991 5984 tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5992 5985 tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5993 5986 tmp->xif_next = xif;
5994 5987 xif = tmp;
5995 5988 return (B_TRUE);
5996 5989 }
5997 5990
5998 5991 boolean_t
5999 5992 verify_secflags(struct zone_secflagstab *tab)
6000 5993 {
6001 5994 secflagdelta_t def = {0};
6002 5995 secflagdelta_t upper = {0};
6003 5996 secflagdelta_t lower = {0};
6004 5997 boolean_t def_set = B_FALSE;
6005 5998 boolean_t upper_set = B_FALSE;
6006 5999 boolean_t lower_set = B_FALSE;
6007 6000 boolean_t ret = B_TRUE;
6008 6001
6009 6002 if (strlen(tab->zone_secflags_default) > 0) {
6010 6003 def_set = B_TRUE;
6011 6004 if (secflags_parse(NULL, tab->zone_secflags_default,
6012 6005 &def) == -1) {
6013 6006 zerr(gettext("default security flags '%s' are invalid"),
6014 6007 tab->zone_secflags_default);
6015 6008 ret = B_FALSE;
6016 6009 }
6017 6010 } else {
6018 6011 secflags_zero(&def.psd_assign);
6019 6012 def.psd_ass_active = B_TRUE;
6020 6013 }
6021 6014
6022 6015 if (strlen(tab->zone_secflags_upper) > 0) {
6023 6016 upper_set = B_TRUE;
6024 6017 if (secflags_parse(NULL, tab->zone_secflags_upper,
6025 6018 &upper) == -1) {
6026 6019 zerr(gettext("upper security flags '%s' are invalid"),
6027 6020 tab->zone_secflags_upper);
6028 6021 ret = B_FALSE;
6029 6022 }
6030 6023 } else {
6031 6024 secflags_fullset(&upper.psd_assign);
6032 6025 upper.psd_ass_active = B_TRUE;
6033 6026 }
6034 6027
6035 6028 if (strlen(tab->zone_secflags_lower) > 0) {
6036 6029 lower_set = B_TRUE;
6037 6030 if (secflags_parse(NULL, tab->zone_secflags_lower,
6038 6031 &lower) == -1) {
6039 6032 zerr(gettext("lower security flags '%s' are invalid"),
6040 6033 tab->zone_secflags_lower);
6041 6034 ret = B_FALSE;
6042 6035 }
6043 6036 } else {
6044 6037 secflags_zero(&lower.psd_assign);
6045 6038 lower.psd_ass_active = B_TRUE;
6046 6039 }
6047 6040
6048 6041 if (def_set && !def.psd_ass_active) {
6049 6042 zerr(gettext("only assignment of security flags is "
6050 6043 "allowed (default: %s)"), tab->zone_secflags_default);
6051 6044 }
6052 6045
6053 6046 if (lower_set && !lower.psd_ass_active) {
6054 6047 zerr(gettext("only assignment of security flags is "
6055 6048 "allowed (lower: %s)"), tab->zone_secflags_lower);
6056 6049 }
6057 6050
6058 6051 if (upper_set && !upper.psd_ass_active) {
6059 6052 zerr(gettext("only assignment of security flags is "
6060 6053 "allowed (upper: %s)"), tab->zone_secflags_upper);
6061 6054 }
6062 6055
6063 6056 if (def.psd_assign & ~upper.psd_assign) { /* In default but not upper */
6064 6057 zerr(gettext("default secflags must be within the "
6065 6058 "upper limit"));
6066 6059 ret = B_FALSE;
6067 6060 }
6068 6061 if (lower.psd_assign & ~def.psd_assign) { /* In lower but not default */
6069 6062 zerr(gettext("default secflags must be above the lower limit"));
6070 6063 ret = B_FALSE;
6071 6064 }
6072 6065 if (lower.psd_assign & ~upper.psd_assign) { /* In lower but not upper */
6073 6066 zerr(gettext("lower secflags must be within the upper limit"));
6074 6067 ret = B_FALSE;
6075 6068 }
6076 6069
6077 6070 return (ret);
6078 6071 }
6079 6072
6080 6073 /*
6081 6074 * See the DTD for which attributes are required for which resources.
6082 6075 *
6083 6076 * This function can be called by commit_func(), which needs to save things,
6084 6077 * in addition to the general call from parse_and_run(), which doesn't need
6085 6078 * things saved. Since the parameters are standardized, we distinguish by
6086 6079 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6087 6080 * that a save is needed.
6088 6081 */
6089 6082 void
6090 6083 verify_func(cmd_t *cmd)
6091 6084 {
6092 6085 struct zone_nwiftab nwiftab;
6093 6086 struct zone_fstab fstab;
6094 6087 struct zone_attrtab attrtab;
6095 6088 struct zone_rctltab rctltab;
6096 6089 struct zone_dstab dstab;
6097 6090 struct zone_psettab psettab;
6098 6091 struct zone_admintab admintab;
6099 6092 struct zone_secflagstab secflagstab;
6100 6093 char zonepath[MAXPATHLEN];
6101 6094 char sched[MAXNAMELEN];
6102 6095 char brand[MAXNAMELEN];
6103 6096 char hostidp[HW_HOSTID_LEN];
6104 6097 char fsallowedp[ZONE_FS_ALLOWED_MAX];
6105 6098 priv_set_t *privs;
6106 6099 char *privname = NULL;
6107 6100 int err, ret_val = Z_OK, arg;
6108 6101 int pset_res;
6109 6102 boolean_t save = B_FALSE;
6110 6103 boolean_t arg_err = B_FALSE;
6111 6104 zone_iptype_t iptype;
6112 6105 boolean_t has_cpu_shares = B_FALSE;
6113 6106 boolean_t has_cpu_cap = B_FALSE;
6114 6107 struct xif *tmp;
6115 6108
6116 6109 optind = 0;
6117 6110 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6118 6111 switch (arg) {
6119 6112 case '?':
6120 6113 longer_usage(CMD_VERIFY);
6121 6114 arg_err = B_TRUE;
6122 6115 break;
6123 6116 default:
6124 6117 short_usage(CMD_VERIFY);
6125 6118 arg_err = B_TRUE;
6126 6119 break;
6127 6120 }
6128 6121 }
6129 6122 if (arg_err)
6130 6123 return;
6131 6124
6132 6125 if (optind > cmd->cmd_argc) {
6133 6126 short_usage(CMD_VERIFY);
6134 6127 return;
6135 6128 }
6136 6129
6137 6130 if (zone_is_read_only(CMD_VERIFY))
6138 6131 return;
6139 6132
6140 6133 assert(cmd != NULL);
6141 6134
6142 6135 if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
6143 6136 save = B_TRUE;
6144 6137 if (initialize(B_TRUE) != Z_OK)
6145 6138 return;
6146 6139
6147 6140 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK &&
6148 6141 !global_zone) {
6149 6142 zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
6150 6143 ret_val = Z_REQD_RESOURCE_MISSING;
6151 6144 saw_error = B_TRUE;
6152 6145 }
6153 6146 if (strlen(zonepath) == 0 && !global_zone) {
6154 6147 zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
6155 6148 ret_val = Z_REQD_RESOURCE_MISSING;
6156 6149 saw_error = B_TRUE;
6157 6150 }
6158 6151
6159 6152 if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
6160 6153 zone_perror(zone, err, B_TRUE);
6161 6154 return;
6162 6155 }
6163 6156 if ((err = brand_verify(handle)) != Z_OK) {
6164 6157 zone_perror(zone, err, B_TRUE);
6165 6158 return;
6166 6159 }
6167 6160
6168 6161 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
6169 6162 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
6170 6163 ret_val = Z_REQD_RESOURCE_MISSING;
6171 6164 saw_error = B_TRUE;
6172 6165 }
6173 6166
6174 6167 if ((privs = priv_allocset()) == NULL) {
6175 6168 zerr(gettext("%s: priv_allocset failed"), zone);
6176 6169 return;
6177 6170 }
6178 6171 if (zonecfg_get_privset(handle, privs, &privname) != Z_OK) {
6179 6172 zerr(gettext("%s: invalid privilege: %s"), zone, privname);
6180 6173 priv_freeset(privs);
6181 6174 free(privname);
6182 6175 return;
6183 6176 }
6184 6177 priv_freeset(privs);
6185 6178
6186 6179 if (zonecfg_get_hostid(handle, hostidp,
6187 6180 sizeof (hostidp)) == Z_INVALID_PROPERTY) {
6188 6181 zerr(gettext("%s: invalid hostid: %s"),
6189 6182 zone, hostidp);
6190 6183 return;
6191 6184 }
6192 6185
6193 6186 if (zonecfg_get_fs_allowed(handle, fsallowedp,
6194 6187 sizeof (fsallowedp)) == Z_INVALID_PROPERTY) {
6195 6188 zerr(gettext("%s: invalid fs-allowed: %s"),
6196 6189 zone, fsallowedp);
6197 6190 return;
6198 6191 }
6199 6192
6200 6193 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
6201 6194 zone_perror(zone, err, B_TRUE);
6202 6195 return;
6203 6196 }
6204 6197 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
6205 6198 check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
6206 6199 check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
6207 6200 &ret_val);
6208 6201 check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
6209 6202
6210 6203 zonecfg_free_fs_option_list(fstab.zone_fs_options);
6211 6204 }
6212 6205 (void) zonecfg_endfsent(handle);
6213 6206
6214 6207 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
6215 6208 zone_perror(zone, err, B_TRUE);
6216 6209 return;
6217 6210 }
6218 6211 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
6219 6212 /*
6220 6213 * physical is required in all cases.
6221 6214 * A shared IP requires an address,
6222 6215 * and may include a default router, while
6223 6216 * an exclusive IP must have neither an address
6224 6217 * nor a default router.
6225 6218 * The physical interface name must be valid in all cases.
6226 6219 */
6227 6220 check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
6228 6221 PT_PHYSICAL, &ret_val);
6229 6222 if (validate_net_physical_syntax(nwiftab.zone_nwif_physical) !=
6230 6223 Z_OK) {
6231 6224 saw_error = B_TRUE;
6232 6225 if (ret_val == Z_OK)
6233 6226 ret_val = Z_INVAL;
6234 6227 }
6235 6228
6236 6229 switch (iptype) {
6237 6230 case ZS_SHARED:
6238 6231 check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
6239 6232 PT_ADDRESS, &ret_val);
6240 6233 if (strlen(nwiftab.zone_nwif_allowed_address) > 0) {
6241 6234 zerr(gettext("%s: %s cannot be specified "
6242 6235 "for a shared IP type"),
6243 6236 rt_to_str(RT_NET),
6244 6237 pt_to_str(PT_ALLOWED_ADDRESS));
6245 6238 saw_error = B_TRUE;
6246 6239 if (ret_val == Z_OK)
6247 6240 ret_val = Z_INVAL;
6248 6241 }
6249 6242 break;
6250 6243 case ZS_EXCLUSIVE:
6251 6244 if (strlen(nwiftab.zone_nwif_address) > 0) {
6252 6245 zerr(gettext("%s: %s cannot be specified "
6253 6246 "for an exclusive IP type"),
6254 6247 rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
6255 6248 saw_error = B_TRUE;
6256 6249 if (ret_val == Z_OK)
6257 6250 ret_val = Z_INVAL;
6258 6251 } else {
6259 6252 if (!add_nwif(&nwiftab)) {
6260 6253 saw_error = B_TRUE;
6261 6254 if (ret_val == Z_OK)
6262 6255 ret_val = Z_INVAL;
6263 6256 }
6264 6257 }
6265 6258 break;
6266 6259 }
6267 6260 }
6268 6261 for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
6269 6262 if (!tmp->xif_has_address && tmp->xif_has_defrouter) {
6270 6263 zerr(gettext("%s: %s for %s cannot be specified "
6271 6264 "without %s for an exclusive IP type"),
6272 6265 rt_to_str(RT_NET), pt_to_str(PT_DEFROUTER),
6273 6266 tmp->xif_name, pt_to_str(PT_ALLOWED_ADDRESS));
6274 6267 saw_error = B_TRUE;
6275 6268 ret_val = Z_INVAL;
6276 6269 }
6277 6270 }
6278 6271 free(xif);
6279 6272 xif = NULL;
6280 6273 (void) zonecfg_endnwifent(handle);
6281 6274
6282 6275 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
6283 6276 zone_perror(zone, err, B_TRUE);
6284 6277 return;
6285 6278 }
6286 6279 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
6287 6280 check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
6288 6281 &ret_val);
6289 6282
6290 6283 if (strcmp(rctltab.zone_rctl_name, "zone.cpu-shares") == 0)
6291 6284 has_cpu_shares = B_TRUE;
6292 6285
6293 6286 if (strcmp(rctltab.zone_rctl_name, "zone.cpu-cap") == 0)
6294 6287 has_cpu_cap = B_TRUE;
6295 6288
6296 6289 if (rctltab.zone_rctl_valptr == NULL) {
6297 6290 zerr(gettext("%s: no %s specified"),
6298 6291 rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
6299 6292 saw_error = B_TRUE;
6300 6293 if (ret_val == Z_OK)
6301 6294 ret_val = Z_REQD_PROPERTY_MISSING;
6302 6295 } else {
6303 6296 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
6304 6297 }
6305 6298 }
6306 6299 (void) zonecfg_endrctlent(handle);
6307 6300
6308 6301 if ((pset_res = zonecfg_lookup_pset(handle, &psettab)) == Z_OK &&
6309 6302 has_cpu_shares) {
6310 6303 zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
6311 6304 rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
6312 6305 saw_error = B_TRUE;
6313 6306 if (ret_val == Z_OK)
6314 6307 ret_val = Z_INCOMPATIBLE;
6315 6308 }
6316 6309
6317 6310 if (has_cpu_shares && zonecfg_get_sched_class(handle, sched,
6318 6311 sizeof (sched)) == Z_OK && strlen(sched) > 0 &&
6319 6312 strcmp(sched, "FSS") != 0) {
6320 6313 zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
6321 6314 "incompatible"),
6322 6315 rt_to_str(RT_RCTL), rt_to_str(RT_SCHED), sched);
6323 6316 saw_error = B_TRUE;
6324 6317 if (ret_val == Z_OK)
6325 6318 ret_val = Z_INCOMPATIBLE;
6326 6319 }
6327 6320
6328 6321 if (pset_res == Z_OK && has_cpu_cap) {
6329 6322 zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
6330 6323 rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
6331 6324 saw_error = B_TRUE;
6332 6325 if (ret_val == Z_OK)
6333 6326 ret_val = Z_INCOMPATIBLE;
6334 6327 }
6335 6328
6336 6329 if ((err = zonecfg_setattrent(handle)) != Z_OK) {
6337 6330 zone_perror(zone, err, B_TRUE);
6338 6331 return;
6339 6332 }
6340 6333 while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
6341 6334 check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
6342 6335 &ret_val);
6343 6336 check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
6344 6337 &ret_val);
6345 6338 check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
6346 6339 &ret_val);
6347 6340 }
6348 6341 (void) zonecfg_endattrent(handle);
6349 6342
6350 6343 if ((err = zonecfg_setdsent(handle)) != Z_OK) {
6351 6344 zone_perror(zone, err, B_TRUE);
6352 6345 return;
6353 6346 }
6354 6347 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
6355 6348 if (strlen(dstab.zone_dataset_name) == 0) {
6356 6349 zerr("%s: %s %s", rt_to_str(RT_DATASET),
6357 6350 pt_to_str(PT_NAME), gettext("not specified"));
6358 6351 saw_error = B_TRUE;
6359 6352 if (ret_val == Z_OK)
6360 6353 ret_val = Z_REQD_PROPERTY_MISSING;
6361 6354 } else if (!zfs_name_valid(dstab.zone_dataset_name,
6362 6355 ZFS_TYPE_FILESYSTEM)) {
6363 6356 zerr("%s: %s %s", rt_to_str(RT_DATASET),
6364 6357 pt_to_str(PT_NAME), gettext("invalid"));
6365 6358 saw_error = B_TRUE;
6366 6359 if (ret_val == Z_OK)
6367 6360 ret_val = Z_BAD_PROPERTY;
6368 6361 }
6369 6362
6370 6363 }
6371 6364 (void) zonecfg_enddsent(handle);
6372 6365
6373 6366 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
6374 6367 zone_perror(zone, err, B_TRUE);
6375 6368 return;
6376 6369 }
6377 6370 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6378 6371 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6379 6372 PT_USER, &ret_val);
6380 6373 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6381 6374 PT_AUTHS, &ret_val);
6382 6375 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6383 6376 == NULL)) {
6384 6377 zerr(gettext("%s %s is not a valid username"),
6385 6378 pt_to_str(PT_USER),
↓ open down ↓ |
741 lines elided |
↑ open up ↑ |
6386 6379 admintab.zone_admin_user);
6387 6380 ret_val = Z_BAD_PROPERTY;
6388 6381 }
6389 6382 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6390 6383 admintab.zone_admin_auths, zone))) {
6391 6384 ret_val = Z_BAD_PROPERTY;
6392 6385 }
6393 6386 }
6394 6387 (void) zonecfg_endadminent(handle);
6395 6388
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;
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 + }
6408 6398 }
6409 6399
6410 6400 if (!global_scope) {
6411 6401 zerr(gettext("resource specification incomplete"));
6412 6402 saw_error = B_TRUE;
6413 6403 if (ret_val == Z_OK)
6414 6404 ret_val = Z_INSUFFICIENT_SPEC;
6415 6405 }
6416 6406
6417 6407 if (save) {
6418 6408 if (ret_val == Z_OK) {
6419 6409 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6420 6410 need_to_commit = B_FALSE;
6421 6411 (void) strlcpy(revert_zone, zone,
6422 6412 sizeof (revert_zone));
6423 6413 }
6424 6414 } else {
6425 6415 zerr(gettext("Zone %s failed to verify"), zone);
6426 6416 }
6427 6417 }
6428 6418 if (ret_val != Z_OK)
6429 6419 zone_perror(zone, ret_val, B_TRUE);
6430 6420 }
6431 6421
6432 6422 void
6433 6423 cancel_func(cmd_t *cmd)
6434 6424 {
6435 6425 int arg;
6436 6426 boolean_t arg_err = B_FALSE;
6437 6427
6438 6428 assert(cmd != NULL);
6439 6429
6440 6430 optind = 0;
6441 6431 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6442 6432 switch (arg) {
6443 6433 case '?':
6444 6434 longer_usage(CMD_CANCEL);
6445 6435 arg_err = B_TRUE;
6446 6436 break;
6447 6437 default:
6448 6438 short_usage(CMD_CANCEL);
6449 6439 arg_err = B_TRUE;
6450 6440 break;
6451 6441 }
6452 6442 }
6453 6443 if (arg_err)
6454 6444 return;
6455 6445
6456 6446 if (optind != cmd->cmd_argc) {
6457 6447 short_usage(CMD_CANCEL);
6458 6448 return;
6459 6449 }
6460 6450
6461 6451 if (global_scope)
6462 6452 scope_usage(CMD_CANCEL);
6463 6453 global_scope = B_TRUE;
6464 6454 zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
6465 6455 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
6466 6456 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
6467 6457 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
6468 6458 zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
6469 6459 bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
6470 6460 bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
6471 6461 bzero(&in_progress_dstab, sizeof (in_progress_dstab));
6472 6462 }
6473 6463
6474 6464 static int
6475 6465 validate_attr_name(char *name)
6476 6466 {
6477 6467 int i;
6478 6468
6479 6469 if (!isalnum(name[0])) {
6480 6470 zerr(gettext("Invalid %s %s %s: must start with an alpha-"
6481 6471 "numeric character."), rt_to_str(RT_ATTR),
6482 6472 pt_to_str(PT_NAME), name);
6483 6473 return (Z_INVAL);
6484 6474 }
6485 6475 for (i = 1; name[i]; i++)
6486 6476 if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
6487 6477 zerr(gettext("Invalid %s %s %s: can only contain "
6488 6478 "alpha-numeric characters, plus '-' and '.'."),
6489 6479 rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
6490 6480 return (Z_INVAL);
6491 6481 }
6492 6482 return (Z_OK);
6493 6483 }
6494 6484
6495 6485 static int
6496 6486 validate_attr_type_val(struct zone_attrtab *attrtab)
6497 6487 {
6498 6488 boolean_t boolval;
6499 6489 int64_t intval;
6500 6490 char strval[MAXNAMELEN];
6501 6491 uint64_t uintval;
6502 6492
6503 6493 if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
6504 6494 if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
6505 6495 return (Z_OK);
6506 6496 zerr(gettext("invalid %s value for %s=%s"),
6507 6497 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
6508 6498 return (Z_ERR);
6509 6499 }
6510 6500
6511 6501 if (strcmp(attrtab->zone_attr_type, "int") == 0) {
6512 6502 if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
6513 6503 return (Z_OK);
6514 6504 zerr(gettext("invalid %s value for %s=%s"),
6515 6505 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
6516 6506 return (Z_ERR);
6517 6507 }
6518 6508
6519 6509 if (strcmp(attrtab->zone_attr_type, "string") == 0) {
6520 6510 if (zonecfg_get_attr_string(attrtab, strval,
6521 6511 sizeof (strval)) == Z_OK)
6522 6512 return (Z_OK);
6523 6513 zerr(gettext("invalid %s value for %s=%s"),
6524 6514 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
6525 6515 return (Z_ERR);
6526 6516 }
6527 6517
6528 6518 if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
6529 6519 if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
6530 6520 return (Z_OK);
6531 6521 zerr(gettext("invalid %s value for %s=%s"),
6532 6522 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
6533 6523 return (Z_ERR);
6534 6524 }
6535 6525
6536 6526 zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
6537 6527 pt_to_str(PT_TYPE), attrtab->zone_attr_type);
6538 6528 return (Z_ERR);
6539 6529 }
6540 6530
6541 6531 /*
6542 6532 * Helper function for end_func-- checks the existence of a given property
6543 6533 * and emits a message if not specified.
6544 6534 */
6545 6535 static int
6546 6536 end_check_reqd(char *attr, int pt, boolean_t *validation_failed)
6547 6537 {
6548 6538 if (strlen(attr) == 0) {
6549 6539 *validation_failed = B_TRUE;
6550 6540 zerr(gettext("%s not specified"), pt_to_str(pt));
6551 6541 return (Z_ERR);
6552 6542 }
6553 6543 return (Z_OK);
6554 6544 }
6555 6545
6556 6546 static void
6557 6547 net_exists_error(struct zone_nwiftab nwif)
6558 6548 {
6559 6549 if (strlen(nwif.zone_nwif_address) > 0) {
6560 6550 zerr(gettext("A %s resource with the %s '%s', "
6561 6551 "and %s '%s' already exists."),
6562 6552 rt_to_str(RT_NET),
6563 6553 pt_to_str(PT_PHYSICAL),
6564 6554 nwif.zone_nwif_physical,
6565 6555 pt_to_str(PT_ADDRESS),
6566 6556 in_progress_nwiftab.zone_nwif_address);
6567 6557 } else {
6568 6558 zerr(gettext("A %s resource with the %s '%s', "
6569 6559 "and %s '%s' already exists."),
6570 6560 rt_to_str(RT_NET),
6571 6561 pt_to_str(PT_PHYSICAL),
6572 6562 nwif.zone_nwif_physical,
6573 6563 pt_to_str(PT_ALLOWED_ADDRESS),
6574 6564 nwif.zone_nwif_allowed_address);
6575 6565 }
6576 6566 }
6577 6567
6578 6568 void
6579 6569 end_func(cmd_t *cmd)
6580 6570 {
6581 6571 boolean_t validation_failed = B_FALSE;
6582 6572 boolean_t arg_err = B_FALSE;
6583 6573 struct zone_fstab tmp_fstab;
6584 6574 struct zone_nwiftab tmp_nwiftab;
6585 6575 struct zone_devtab tmp_devtab;
6586 6576 struct zone_rctltab tmp_rctltab;
6587 6577 struct zone_attrtab tmp_attrtab;
6588 6578 struct zone_dstab tmp_dstab;
6589 6579 struct zone_admintab tmp_admintab;
6590 6580 int err, arg, res1, res2, res3;
6591 6581 uint64_t swap_limit;
6592 6582 uint64_t locked_limit;
6593 6583 uint64_t proc_cap;
6594 6584
6595 6585 assert(cmd != NULL);
6596 6586
6597 6587 optind = 0;
6598 6588 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6599 6589 switch (arg) {
6600 6590 case '?':
6601 6591 longer_usage(CMD_END);
6602 6592 arg_err = B_TRUE;
6603 6593 break;
6604 6594 default:
6605 6595 short_usage(CMD_END);
6606 6596 arg_err = B_TRUE;
6607 6597 break;
6608 6598 }
6609 6599 }
6610 6600 if (arg_err)
6611 6601 return;
6612 6602
6613 6603 if (optind != cmd->cmd_argc) {
6614 6604 short_usage(CMD_END);
6615 6605 return;
6616 6606 }
6617 6607
6618 6608 if (global_scope) {
6619 6609 scope_usage(CMD_END);
6620 6610 return;
6621 6611 }
6622 6612
6623 6613 assert(end_op == CMD_ADD || end_op == CMD_SELECT);
6624 6614
6625 6615 switch (resource_scope) {
6626 6616 case RT_FS:
6627 6617 /* First make sure everything was filled in. */
6628 6618 if (end_check_reqd(in_progress_fstab.zone_fs_dir,
6629 6619 PT_DIR, &validation_failed) == Z_OK) {
6630 6620 if (in_progress_fstab.zone_fs_dir[0] != '/') {
6631 6621 zerr(gettext("%s %s is not an absolute path."),
6632 6622 pt_to_str(PT_DIR),
6633 6623 in_progress_fstab.zone_fs_dir);
6634 6624 validation_failed = B_TRUE;
6635 6625 }
6636 6626 }
6637 6627
6638 6628 (void) end_check_reqd(in_progress_fstab.zone_fs_special,
6639 6629 PT_SPECIAL, &validation_failed);
6640 6630
6641 6631 if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
6642 6632 in_progress_fstab.zone_fs_raw[0] != '/') {
6643 6633 zerr(gettext("%s %s is not an absolute path."),
6644 6634 pt_to_str(PT_RAW),
6645 6635 in_progress_fstab.zone_fs_raw);
6646 6636 validation_failed = B_TRUE;
6647 6637 }
6648 6638
6649 6639 (void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
6650 6640 &validation_failed);
6651 6641
6652 6642 if (validation_failed) {
6653 6643 saw_error = B_TRUE;
6654 6644 return;
6655 6645 }
6656 6646
6657 6647 if (end_op == CMD_ADD) {
6658 6648 /* Make sure there isn't already one like this. */
6659 6649 bzero(&tmp_fstab, sizeof (tmp_fstab));
6660 6650 (void) strlcpy(tmp_fstab.zone_fs_dir,
6661 6651 in_progress_fstab.zone_fs_dir,
6662 6652 sizeof (tmp_fstab.zone_fs_dir));
6663 6653 err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
6664 6654 zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
6665 6655 if (err == Z_OK) {
6666 6656 zerr(gettext("A %s resource "
6667 6657 "with the %s '%s' already exists."),
6668 6658 rt_to_str(RT_FS), pt_to_str(PT_DIR),
6669 6659 in_progress_fstab.zone_fs_dir);
6670 6660 saw_error = B_TRUE;
6671 6661 return;
6672 6662 }
6673 6663 err = zonecfg_add_filesystem(handle,
6674 6664 &in_progress_fstab);
6675 6665 } else {
6676 6666 err = zonecfg_modify_filesystem(handle, &old_fstab,
6677 6667 &in_progress_fstab);
6678 6668 }
6679 6669 zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
6680 6670 in_progress_fstab.zone_fs_options = NULL;
6681 6671 break;
6682 6672
6683 6673 case RT_NET:
6684 6674 /*
6685 6675 * First make sure everything was filled in.
6686 6676 * Since we don't know whether IP will be shared
6687 6677 * or exclusive here, some checks are deferred until
6688 6678 * the verify command.
6689 6679 */
6690 6680 (void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
6691 6681 PT_PHYSICAL, &validation_failed);
6692 6682
6693 6683 if (validation_failed) {
6694 6684 saw_error = B_TRUE;
6695 6685 return;
6696 6686 }
6697 6687 if (end_op == CMD_ADD) {
6698 6688 /* Make sure there isn't already one like this. */
6699 6689 bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
6700 6690 (void) strlcpy(tmp_nwiftab.zone_nwif_physical,
6701 6691 in_progress_nwiftab.zone_nwif_physical,
6702 6692 sizeof (tmp_nwiftab.zone_nwif_physical));
6703 6693 (void) strlcpy(tmp_nwiftab.zone_nwif_address,
6704 6694 in_progress_nwiftab.zone_nwif_address,
6705 6695 sizeof (tmp_nwiftab.zone_nwif_address));
6706 6696 (void) strlcpy(tmp_nwiftab.zone_nwif_allowed_address,
6707 6697 in_progress_nwiftab.zone_nwif_allowed_address,
6708 6698 sizeof (tmp_nwiftab.zone_nwif_allowed_address));
6709 6699 (void) strlcpy(tmp_nwiftab.zone_nwif_defrouter,
6710 6700 in_progress_nwiftab.zone_nwif_defrouter,
6711 6701 sizeof (tmp_nwiftab.zone_nwif_defrouter));
6712 6702 if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
6713 6703 net_exists_error(in_progress_nwiftab);
6714 6704 saw_error = B_TRUE;
6715 6705 return;
6716 6706 }
6717 6707 err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
6718 6708 } else {
6719 6709 err = zonecfg_modify_nwif(handle, &old_nwiftab,
6720 6710 &in_progress_nwiftab);
6721 6711 }
6722 6712 break;
6723 6713
6724 6714 case RT_DEVICE:
6725 6715 /* First make sure everything was filled in. */
6726 6716 (void) end_check_reqd(in_progress_devtab.zone_dev_match,
6727 6717 PT_MATCH, &validation_failed);
6728 6718
6729 6719 if (validation_failed) {
6730 6720 saw_error = B_TRUE;
6731 6721 return;
6732 6722 }
6733 6723
6734 6724 if (end_op == CMD_ADD) {
6735 6725 /* Make sure there isn't already one like this. */
6736 6726 (void) strlcpy(tmp_devtab.zone_dev_match,
6737 6727 in_progress_devtab.zone_dev_match,
6738 6728 sizeof (tmp_devtab.zone_dev_match));
6739 6729 if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
6740 6730 zerr(gettext("A %s resource with the %s '%s' "
6741 6731 "already exists."), rt_to_str(RT_DEVICE),
6742 6732 pt_to_str(PT_MATCH),
6743 6733 in_progress_devtab.zone_dev_match);
6744 6734 saw_error = B_TRUE;
6745 6735 return;
6746 6736 }
6747 6737 err = zonecfg_add_dev(handle, &in_progress_devtab);
6748 6738 } else {
6749 6739 err = zonecfg_modify_dev(handle, &old_devtab,
6750 6740 &in_progress_devtab);
6751 6741 }
6752 6742 break;
6753 6743
6754 6744 case RT_RCTL:
6755 6745 /* First make sure everything was filled in. */
6756 6746 (void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
6757 6747 PT_NAME, &validation_failed);
6758 6748
6759 6749 if (in_progress_rctltab.zone_rctl_valptr == NULL) {
6760 6750 zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
6761 6751 validation_failed = B_TRUE;
6762 6752 }
6763 6753
6764 6754 if (validation_failed) {
6765 6755 saw_error = B_TRUE;
6766 6756 return;
6767 6757 }
6768 6758
6769 6759 if (end_op == CMD_ADD) {
6770 6760 /* Make sure there isn't already one like this. */
6771 6761 (void) strlcpy(tmp_rctltab.zone_rctl_name,
6772 6762 in_progress_rctltab.zone_rctl_name,
6773 6763 sizeof (tmp_rctltab.zone_rctl_name));
6774 6764 tmp_rctltab.zone_rctl_valptr = NULL;
6775 6765 err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
6776 6766 zonecfg_free_rctl_value_list(
6777 6767 tmp_rctltab.zone_rctl_valptr);
6778 6768 if (err == Z_OK) {
6779 6769 zerr(gettext("A %s resource "
6780 6770 "with the %s '%s' already exists."),
6781 6771 rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
6782 6772 in_progress_rctltab.zone_rctl_name);
6783 6773 saw_error = B_TRUE;
6784 6774 return;
6785 6775 }
6786 6776 err = zonecfg_add_rctl(handle, &in_progress_rctltab);
6787 6777 } else {
6788 6778 err = zonecfg_modify_rctl(handle, &old_rctltab,
6789 6779 &in_progress_rctltab);
6790 6780 }
6791 6781 if (err == Z_OK) {
6792 6782 zonecfg_free_rctl_value_list(
6793 6783 in_progress_rctltab.zone_rctl_valptr);
6794 6784 in_progress_rctltab.zone_rctl_valptr = NULL;
6795 6785 }
6796 6786 break;
6797 6787
6798 6788 case RT_ATTR:
6799 6789 /* First make sure everything was filled in. */
6800 6790 (void) end_check_reqd(in_progress_attrtab.zone_attr_name,
6801 6791 PT_NAME, &validation_failed);
6802 6792 (void) end_check_reqd(in_progress_attrtab.zone_attr_type,
6803 6793 PT_TYPE, &validation_failed);
6804 6794 (void) end_check_reqd(in_progress_attrtab.zone_attr_value,
6805 6795 PT_VALUE, &validation_failed);
6806 6796
6807 6797 if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
6808 6798 Z_OK)
6809 6799 validation_failed = B_TRUE;
6810 6800
6811 6801 if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
6812 6802 validation_failed = B_TRUE;
6813 6803
6814 6804 if (validation_failed) {
6815 6805 saw_error = B_TRUE;
6816 6806 return;
6817 6807 }
6818 6808 if (end_op == CMD_ADD) {
6819 6809 /* Make sure there isn't already one like this. */
6820 6810 bzero(&tmp_attrtab, sizeof (tmp_attrtab));
6821 6811 (void) strlcpy(tmp_attrtab.zone_attr_name,
6822 6812 in_progress_attrtab.zone_attr_name,
6823 6813 sizeof (tmp_attrtab.zone_attr_name));
6824 6814 if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
6825 6815 zerr(gettext("An %s resource "
6826 6816 "with the %s '%s' already exists."),
6827 6817 rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
6828 6818 in_progress_attrtab.zone_attr_name);
6829 6819 saw_error = B_TRUE;
6830 6820 return;
6831 6821 }
6832 6822 err = zonecfg_add_attr(handle, &in_progress_attrtab);
6833 6823 } else {
6834 6824 err = zonecfg_modify_attr(handle, &old_attrtab,
6835 6825 &in_progress_attrtab);
6836 6826 }
6837 6827 break;
6838 6828 case RT_DATASET:
6839 6829 /* First make sure everything was filled in. */
6840 6830 if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
6841 6831 zerr("%s %s", pt_to_str(PT_NAME),
6842 6832 gettext("not specified"));
6843 6833 saw_error = B_TRUE;
6844 6834 validation_failed = B_TRUE;
6845 6835 }
6846 6836 if (validation_failed)
6847 6837 return;
6848 6838 if (end_op == CMD_ADD) {
6849 6839 /* Make sure there isn't already one like this. */
6850 6840 bzero(&tmp_dstab, sizeof (tmp_dstab));
6851 6841 (void) strlcpy(tmp_dstab.zone_dataset_name,
6852 6842 in_progress_dstab.zone_dataset_name,
6853 6843 sizeof (tmp_dstab.zone_dataset_name));
6854 6844 err = zonecfg_lookup_ds(handle, &tmp_dstab);
6855 6845 if (err == Z_OK) {
6856 6846 zerr(gettext("A %s resource "
6857 6847 "with the %s '%s' already exists."),
6858 6848 rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
6859 6849 in_progress_dstab.zone_dataset_name);
6860 6850 saw_error = B_TRUE;
6861 6851 return;
6862 6852 }
6863 6853 err = zonecfg_add_ds(handle, &in_progress_dstab);
6864 6854 } else {
6865 6855 err = zonecfg_modify_ds(handle, &old_dstab,
6866 6856 &in_progress_dstab);
6867 6857 }
6868 6858 break;
6869 6859 case RT_DCPU:
6870 6860 /* Make sure everything was filled in. */
6871 6861 if (end_check_reqd(in_progress_psettab.zone_ncpu_min,
6872 6862 PT_NCPUS, &validation_failed) != Z_OK) {
6873 6863 saw_error = B_TRUE;
6874 6864 return;
6875 6865 }
6876 6866
6877 6867 if (end_op == CMD_ADD) {
6878 6868 err = zonecfg_add_pset(handle, &in_progress_psettab);
6879 6869 } else {
6880 6870 err = zonecfg_modify_pset(handle, &in_progress_psettab);
6881 6871 }
6882 6872 break;
6883 6873 case RT_PCAP:
6884 6874 /* Make sure everything was filled in. */
6885 6875 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
6886 6876 != Z_OK) {
6887 6877 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
6888 6878 saw_error = B_TRUE;
6889 6879 validation_failed = B_TRUE;
6890 6880 return;
6891 6881 }
6892 6882 err = Z_OK;
6893 6883 break;
6894 6884 case RT_MCAP:
6895 6885 /* Make sure everything was filled in. */
6896 6886 res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
6897 6887 Z_ERR : Z_OK;
6898 6888 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
6899 6889 &swap_limit);
6900 6890 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
6901 6891 &locked_limit);
6902 6892
6903 6893 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
6904 6894 zerr(gettext("No property was specified. One of %s, "
6905 6895 "%s or %s is required."), pt_to_str(PT_PHYSICAL),
6906 6896 pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
6907 6897 saw_error = B_TRUE;
6908 6898 return;
6909 6899 }
6910 6900
6911 6901 /* if phys & locked are both set, verify locked <= phys */
6912 6902 if (res1 == Z_OK && res3 == Z_OK) {
6913 6903 uint64_t phys_limit;
6914 6904 char *endp;
6915 6905
6916 6906 phys_limit = strtoull(
6917 6907 in_progress_mcaptab.zone_physmem_cap, &endp, 10);
6918 6908 if (phys_limit < locked_limit) {
6919 6909 zerr(gettext("The %s cap must be less than or "
6920 6910 "equal to the %s cap."),
6921 6911 pt_to_str(PT_LOCKED),
6922 6912 pt_to_str(PT_PHYSICAL));
6923 6913 saw_error = B_TRUE;
6924 6914 return;
6925 6915 }
6926 6916 }
6927 6917
6928 6918 err = Z_OK;
6929 6919 if (res1 == Z_OK) {
6930 6920 /*
6931 6921 * We could be ending from either an add operation
6932 6922 * or a select operation. Since all of the properties
6933 6923 * within this resource are optional, we always use
6934 6924 * modify on the mcap entry. zonecfg_modify_mcap()
6935 6925 * will handle both adding and modifying a memory cap.
6936 6926 */
6937 6927 err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
6938 6928 } else if (end_op == CMD_SELECT) {
6939 6929 /*
6940 6930 * If we're ending from a select and the physical
6941 6931 * memory cap is empty then the user could have cleared
6942 6932 * the physical cap value, so try to delete the entry.
6943 6933 */
6944 6934 (void) zonecfg_delete_mcap(handle);
6945 6935 }
6946 6936 break;
6947 6937 case RT_ADMIN:
6948 6938 /* First make sure everything was filled in. */
6949 6939 if (end_check_reqd(in_progress_admintab.zone_admin_user,
6950 6940 PT_USER, &validation_failed) == Z_OK) {
6951 6941 if (getpwnam(in_progress_admintab.zone_admin_user)
6952 6942 == NULL) {
6953 6943 zerr(gettext("%s %s is not a valid username"),
6954 6944 pt_to_str(PT_USER),
6955 6945 in_progress_admintab.zone_admin_user);
6956 6946 validation_failed = B_TRUE;
6957 6947 }
6958 6948 }
6959 6949
6960 6950 if (end_check_reqd(in_progress_admintab.zone_admin_auths,
6961 6951 PT_AUTHS, &validation_failed) == Z_OK) {
6962 6952 if (!zonecfg_valid_auths(
6963 6953 in_progress_admintab.zone_admin_auths,
6964 6954 zone)) {
6965 6955 validation_failed = B_TRUE;
6966 6956 }
6967 6957 }
6968 6958
6969 6959 if (validation_failed) {
6970 6960 saw_error = B_TRUE;
6971 6961 return;
6972 6962 }
6973 6963
6974 6964 if (end_op == CMD_ADD) {
6975 6965 /* Make sure there isn't already one like this. */
6976 6966 bzero(&tmp_admintab, sizeof (tmp_admintab));
6977 6967 (void) strlcpy(tmp_admintab.zone_admin_user,
6978 6968 in_progress_admintab.zone_admin_user,
6979 6969 sizeof (tmp_admintab.zone_admin_user));
6980 6970 err = zonecfg_lookup_admin(
6981 6971 handle, &tmp_admintab);
6982 6972 if (err == Z_OK) {
6983 6973 zerr(gettext("A %s resource "
6984 6974 "with the %s '%s' already exists."),
6985 6975 rt_to_str(RT_ADMIN),
6986 6976 pt_to_str(PT_USER),
6987 6977 in_progress_admintab.zone_admin_user);
6988 6978 saw_error = B_TRUE;
6989 6979 return;
6990 6980 }
6991 6981 err = zonecfg_add_admin(handle,
6992 6982 &in_progress_admintab, zone);
6993 6983 } else {
6994 6984 err = zonecfg_modify_admin(handle,
6995 6985 &old_admintab, &in_progress_admintab,
6996 6986 zone);
6997 6987 }
6998 6988 break;
6999 6989 case RT_SECFLAGS:
7000 6990 if (verify_secflags(&in_progress_secflagstab) != B_TRUE) {
7001 6991 saw_error = B_TRUE;
7002 6992 return;
7003 6993 }
7004 6994
7005 6995 if (end_op == CMD_ADD) {
7006 6996 err = zonecfg_add_secflags(handle,
7007 6997 &in_progress_secflagstab);
7008 6998 } else {
7009 6999 err = zonecfg_modify_secflags(handle,
7010 7000 &old_secflagstab, &in_progress_secflagstab);
7011 7001 }
7012 7002 break;
7013 7003 default:
7014 7004 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
7015 7005 B_TRUE);
7016 7006 saw_error = B_TRUE;
7017 7007 return;
7018 7008 }
7019 7009
7020 7010 if (err != Z_OK) {
7021 7011 zone_perror(zone, err, B_TRUE);
7022 7012 } else {
7023 7013 need_to_commit = B_TRUE;
7024 7014 global_scope = B_TRUE;
7025 7015 end_op = -1;
7026 7016 }
7027 7017 }
7028 7018
7029 7019 void
7030 7020 commit_func(cmd_t *cmd)
7031 7021 {
7032 7022 int arg;
7033 7023 boolean_t arg_err = B_FALSE;
7034 7024
7035 7025 optind = 0;
7036 7026 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
7037 7027 switch (arg) {
7038 7028 case '?':
7039 7029 longer_usage(CMD_COMMIT);
7040 7030 arg_err = B_TRUE;
7041 7031 break;
7042 7032 default:
7043 7033 short_usage(CMD_COMMIT);
7044 7034 arg_err = B_TRUE;
7045 7035 break;
7046 7036 }
7047 7037 }
7048 7038 if (arg_err)
7049 7039 return;
7050 7040
7051 7041 if (optind != cmd->cmd_argc) {
7052 7042 short_usage(CMD_COMMIT);
7053 7043 return;
7054 7044 }
7055 7045
7056 7046 if (zone_is_read_only(CMD_COMMIT))
7057 7047 return;
7058 7048
7059 7049 assert(cmd != NULL);
7060 7050
7061 7051 cmd->cmd_argc = 1;
7062 7052 /*
7063 7053 * cmd_arg normally comes from a strdup() in the lexer, and the
7064 7054 * whole cmd structure and its (char *) attributes are freed at
7065 7055 * the completion of each command, so the strdup() below is needed
7066 7056 * to match this and prevent a core dump from trying to free()
7067 7057 * something that can't be.
7068 7058 */
7069 7059 if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
7070 7060 zone_perror(zone, Z_NOMEM, B_TRUE);
7071 7061 exit(Z_ERR);
7072 7062 }
7073 7063 cmd->cmd_argv[1] = NULL;
7074 7064 verify_func(cmd);
7075 7065 }
7076 7066
7077 7067 void
7078 7068 revert_func(cmd_t *cmd)
7079 7069 {
7080 7070 char line[128]; /* enough to ask a question */
7081 7071 boolean_t force = B_FALSE;
7082 7072 boolean_t arg_err = B_FALSE;
7083 7073 int err, arg, answer;
7084 7074
7085 7075 optind = 0;
7086 7076 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
7087 7077 switch (arg) {
7088 7078 case '?':
7089 7079 longer_usage(CMD_REVERT);
7090 7080 arg_err = B_TRUE;
7091 7081 break;
7092 7082 case 'F':
7093 7083 force = B_TRUE;
7094 7084 break;
7095 7085 default:
7096 7086 short_usage(CMD_REVERT);
7097 7087 arg_err = B_TRUE;
7098 7088 break;
7099 7089 }
7100 7090 }
7101 7091 if (arg_err)
7102 7092 return;
7103 7093
7104 7094 if (optind != cmd->cmd_argc) {
7105 7095 short_usage(CMD_REVERT);
7106 7096 return;
7107 7097 }
7108 7098
7109 7099 if (zone_is_read_only(CMD_REVERT))
7110 7100 return;
7111 7101
7112 7102 if (!global_scope) {
7113 7103 zerr(gettext("You can only use %s in the global scope.\nUse"
7114 7104 " '%s' to cancel changes to a resource specification."),
7115 7105 cmd_to_str(CMD_REVERT), cmd_to_str(CMD_CANCEL));
7116 7106 saw_error = B_TRUE;
7117 7107 return;
7118 7108 }
7119 7109
7120 7110 if (zonecfg_check_handle(handle) != Z_OK) {
7121 7111 zerr(gettext("No changes to revert."));
7122 7112 saw_error = B_TRUE;
7123 7113 return;
7124 7114 }
7125 7115
7126 7116 if (!force) {
7127 7117 (void) snprintf(line, sizeof (line),
7128 7118 gettext("Are you sure you want to revert"));
7129 7119 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
7130 7120 zerr(gettext("Input not from terminal and -F not "
7131 7121 "specified:\n%s command ignored, exiting."),
7132 7122 cmd_to_str(CMD_REVERT));
7133 7123 exit(Z_ERR);
7134 7124 }
7135 7125 if (answer != 1)
7136 7126 return;
7137 7127 }
7138 7128
7139 7129 /*
7140 7130 * Reset any pending admins that were
7141 7131 * removed from the previous zone
7142 7132 */
7143 7133 zonecfg_remove_userauths(handle, "", zone, B_FALSE);
7144 7134
7145 7135 /*
7146 7136 * Time for a new handle: finish the old one off first
7147 7137 * then get a new one properly to avoid leaks.
7148 7138 */
7149 7139 zonecfg_fini_handle(handle);
7150 7140 if ((handle = zonecfg_init_handle()) == NULL) {
7151 7141 zone_perror(execname, Z_NOMEM, B_TRUE);
7152 7142 exit(Z_ERR);
7153 7143 }
7154 7144
7155 7145 if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
7156 7146 saw_error = B_TRUE;
7157 7147 got_handle = B_FALSE;
7158 7148 if (err == Z_NO_ZONE)
7159 7149 zerr(gettext("%s: no such saved zone to revert to."),
7160 7150 revert_zone);
7161 7151 else
7162 7152 zone_perror(zone, err, B_TRUE);
7163 7153 }
7164 7154 (void) strlcpy(zone, revert_zone, sizeof (zone));
7165 7155 }
7166 7156
7167 7157 void
7168 7158 help_func(cmd_t *cmd)
7169 7159 {
7170 7160 int i;
7171 7161
7172 7162 assert(cmd != NULL);
7173 7163
7174 7164 if (cmd->cmd_argc == 0) {
7175 7165 usage(B_TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
7176 7166 return;
7177 7167 }
7178 7168 if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
7179 7169 usage(B_TRUE, HELP_USAGE);
7180 7170 return;
7181 7171 }
7182 7172 if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
7183 7173 usage(B_TRUE, HELP_SUBCMDS);
7184 7174 return;
7185 7175 }
7186 7176 if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
7187 7177 usage(B_TRUE, HELP_SYNTAX | HELP_RES_PROPS);
7188 7178 return;
7189 7179 }
7190 7180 if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
7191 7181 longer_usage(CMD_HELP);
7192 7182 return;
7193 7183 }
7194 7184
7195 7185 for (i = 0; i <= CMD_MAX; i++) {
7196 7186 if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
7197 7187 longer_usage(i);
7198 7188 return;
7199 7189 }
7200 7190 }
7201 7191 /* We do not use zerr() here because we do not want its extra \n. */
7202 7192 (void) fprintf(stderr, gettext("Unknown help subject %s. "),
7203 7193 cmd->cmd_argv[0]);
7204 7194 usage(B_FALSE, HELP_META);
7205 7195 }
7206 7196
7207 7197 static int
7208 7198 string_to_yyin(char *string)
7209 7199 {
7210 7200 if ((yyin = tmpfile()) == NULL) {
7211 7201 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
7212 7202 return (Z_ERR);
7213 7203 }
7214 7204 if (fwrite(string, strlen(string), 1, yyin) != 1) {
7215 7205 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
7216 7206 return (Z_ERR);
7217 7207 }
7218 7208 if (fseek(yyin, 0, SEEK_SET) != 0) {
7219 7209 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
7220 7210 return (Z_ERR);
7221 7211 }
7222 7212 return (Z_OK);
7223 7213 }
7224 7214
7225 7215 /* This is the back-end helper function for read_input() below. */
7226 7216
7227 7217 static int
7228 7218 cleanup()
7229 7219 {
7230 7220 int answer;
7231 7221 cmd_t *cmd;
7232 7222
7233 7223 if (!interactive_mode && !cmd_file_mode) {
7234 7224 /*
7235 7225 * If we're not in interactive mode, and we're not in command
7236 7226 * file mode, then we must be in commands-from-the-command-line
7237 7227 * mode. As such, we can't loop back and ask for more input.
7238 7228 * It was OK to prompt for such things as whether or not to
7239 7229 * really delete a zone in the command handler called from
7240 7230 * yyparse() above, but "really quit?" makes no sense in this
7241 7231 * context. So disable prompting.
7242 7232 */
7243 7233 ok_to_prompt = B_FALSE;
7244 7234 }
7245 7235 if (!global_scope) {
7246 7236 if (!time_to_exit) {
7247 7237 /*
7248 7238 * Just print a simple error message in the -1 case,
7249 7239 * since exit_func() already handles that case, and
7250 7240 * EOF means we are finished anyway.
7251 7241 */
7252 7242 answer = ask_yesno(B_FALSE,
7253 7243 gettext("Resource incomplete; really quit"));
7254 7244 if (answer == -1) {
7255 7245 zerr(gettext("Resource incomplete."));
7256 7246 return (Z_ERR);
7257 7247 }
7258 7248 if (answer != 1) {
7259 7249 yyin = stdin;
7260 7250 return (Z_REPEAT);
7261 7251 }
7262 7252 } else {
7263 7253 saw_error = B_TRUE;
7264 7254 }
7265 7255 }
7266 7256 /*
7267 7257 * Make sure we tried something and that the handle checks
7268 7258 * out, or we would get a false error trying to commit.
7269 7259 */
7270 7260 if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
7271 7261 if ((cmd = alloc_cmd()) == NULL) {
7272 7262 zone_perror(zone, Z_NOMEM, B_TRUE);
7273 7263 return (Z_ERR);
7274 7264 }
7275 7265 cmd->cmd_argc = 0;
7276 7266 cmd->cmd_argv[0] = NULL;
7277 7267 commit_func(cmd);
7278 7268 free_cmd(cmd);
7279 7269 /*
7280 7270 * need_to_commit will get set back to FALSE if the
7281 7271 * configuration is saved successfully.
7282 7272 */
7283 7273 if (need_to_commit) {
7284 7274 if (force_exit) {
7285 7275 zerr(gettext("Configuration not saved."));
7286 7276 return (Z_ERR);
7287 7277 }
7288 7278 answer = ask_yesno(B_FALSE,
7289 7279 gettext("Configuration not saved; really quit"));
7290 7280 if (answer == -1) {
7291 7281 zerr(gettext("Configuration not saved."));
7292 7282 return (Z_ERR);
7293 7283 }
7294 7284 if (answer != 1) {
7295 7285 time_to_exit = B_FALSE;
7296 7286 yyin = stdin;
7297 7287 return (Z_REPEAT);
7298 7288 }
7299 7289 }
7300 7290 }
7301 7291 return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
7302 7292 }
7303 7293
7304 7294 /*
7305 7295 * read_input() is the driver of this program. It is a wrapper around
7306 7296 * yyparse(), printing appropriate prompts when needed, checking for
7307 7297 * exit conditions and reacting appropriately [the latter in its cleanup()
7308 7298 * helper function].
7309 7299 *
7310 7300 * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
7311 7301 * so do_interactive() knows that we are not really done (i.e, we asked
7312 7302 * the user if we should really quit and the user said no).
7313 7303 */
7314 7304 static int
7315 7305 read_input()
7316 7306 {
7317 7307 boolean_t yyin_is_a_tty = isatty(fileno(yyin));
7318 7308 /*
7319 7309 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
7320 7310 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
7321 7311 */
7322 7312 char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
7323 7313
7324 7314 /* yyin should have been set to the appropriate (FILE *) if not stdin */
7325 7315 newline_terminated = B_TRUE;
7326 7316 for (;;) {
7327 7317 if (yyin_is_a_tty) {
7328 7318 if (newline_terminated) {
7329 7319 if (global_scope)
7330 7320 (void) snprintf(prompt, sizeof (prompt),
7331 7321 "%s:%s> ", execname, zone);
7332 7322 else
7333 7323 (void) snprintf(prompt, sizeof (prompt),
7334 7324 "%s:%s:%s> ", execname, zone,
7335 7325 rt_to_str(resource_scope));
7336 7326 }
7337 7327 /*
7338 7328 * If the user hits ^C then we want to catch it and
7339 7329 * start over. If the user hits EOF then we want to
7340 7330 * bail out.
7341 7331 */
7342 7332 line = gl_get_line(gl, prompt, NULL, -1);
7343 7333 if (gl_return_status(gl) == GLR_SIGNAL) {
7344 7334 gl_abandon_line(gl);
7345 7335 continue;
7346 7336 }
7347 7337 if (line == NULL)
7348 7338 break;
7349 7339 (void) string_to_yyin(line);
7350 7340 while (!feof(yyin))
7351 7341 yyparse();
7352 7342 } else {
7353 7343 yyparse();
7354 7344 }
7355 7345 /* Bail out on an error in command file mode. */
7356 7346 if (saw_error && cmd_file_mode && !interactive_mode)
7357 7347 time_to_exit = B_TRUE;
7358 7348 if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
7359 7349 break;
7360 7350 }
7361 7351 return (cleanup());
7362 7352 }
7363 7353
7364 7354 /*
7365 7355 * This function is used in the zonecfg-interactive-mode scenario: it just
7366 7356 * calls read_input() until we are done.
7367 7357 */
7368 7358
7369 7359 static int
7370 7360 do_interactive(void)
7371 7361 {
7372 7362 int err;
7373 7363
7374 7364 interactive_mode = B_TRUE;
7375 7365 if (!read_only_mode) {
7376 7366 /*
7377 7367 * Try to set things up proactively in interactive mode, so
7378 7368 * that if the zone in question does not exist yet, we can
7379 7369 * provide the user with a clue.
7380 7370 */
7381 7371 (void) initialize(B_FALSE);
7382 7372 }
7383 7373 do {
7384 7374 err = read_input();
7385 7375 } while (err == Z_REPEAT);
7386 7376 return (err);
7387 7377 }
7388 7378
7389 7379 /*
7390 7380 * cmd_file is slightly more complicated, as it has to open the command file
7391 7381 * and set yyin appropriately. Once that is done, though, it just calls
7392 7382 * read_input(), and only once, since prompting is not possible.
7393 7383 */
7394 7384
7395 7385 static int
7396 7386 cmd_file(char *file)
7397 7387 {
7398 7388 FILE *infile;
7399 7389 int err;
7400 7390 struct stat statbuf;
7401 7391 boolean_t using_real_file = (strcmp(file, "-") != 0);
7402 7392
7403 7393 if (using_real_file) {
7404 7394 /*
7405 7395 * zerr() prints a line number in cmd_file_mode, which we do
7406 7396 * not want here, so temporarily unset it.
7407 7397 */
7408 7398 cmd_file_mode = B_FALSE;
7409 7399 if ((infile = fopen(file, "r")) == NULL) {
7410 7400 zerr(gettext("could not open file %s: %s"),
7411 7401 file, strerror(errno));
7412 7402 return (Z_ERR);
7413 7403 }
7414 7404 if ((err = fstat(fileno(infile), &statbuf)) != 0) {
7415 7405 zerr(gettext("could not stat file %s: %s"),
7416 7406 file, strerror(errno));
7417 7407 err = Z_ERR;
7418 7408 goto done;
7419 7409 }
7420 7410 if (!S_ISREG(statbuf.st_mode)) {
7421 7411 zerr(gettext("%s is not a regular file."), file);
7422 7412 err = Z_ERR;
7423 7413 goto done;
7424 7414 }
7425 7415 yyin = infile;
7426 7416 cmd_file_mode = B_TRUE;
7427 7417 ok_to_prompt = B_FALSE;
7428 7418 } else {
7429 7419 /*
7430 7420 * "-f -" is essentially the same as interactive mode,
7431 7421 * so treat it that way.
7432 7422 */
7433 7423 interactive_mode = B_TRUE;
7434 7424 }
7435 7425 /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
7436 7426 if ((err = read_input()) == Z_REPEAT)
7437 7427 err = Z_ERR;
7438 7428 done:
7439 7429 if (using_real_file)
7440 7430 (void) fclose(infile);
7441 7431 return (err);
7442 7432 }
7443 7433
7444 7434 /*
7445 7435 * Since yacc is based on reading from a (FILE *) whereas what we get from
7446 7436 * the command line is in argv format, we need to convert when the user
7447 7437 * gives us commands directly from the command line. That is done here by
7448 7438 * concatenating the argv list into a space-separated string, writing it
7449 7439 * to a temp file, and rewinding the file so yyin can be set to it. Then
7450 7440 * we call read_input(), and only once, since prompting about whether to
7451 7441 * continue or quit would make no sense in this context.
7452 7442 */
7453 7443
7454 7444 static int
7455 7445 one_command_at_a_time(int argc, char *argv[])
7456 7446 {
7457 7447 char *command;
7458 7448 size_t len = 2; /* terminal \n\0 */
7459 7449 int i, err;
7460 7450
7461 7451 for (i = 0; i < argc; i++)
7462 7452 len += strlen(argv[i]) + 1;
7463 7453 if ((command = malloc(len)) == NULL) {
7464 7454 zone_perror(execname, Z_NOMEM, B_TRUE);
7465 7455 return (Z_ERR);
7466 7456 }
7467 7457 (void) strlcpy(command, argv[0], len);
7468 7458 for (i = 1; i < argc; i++) {
7469 7459 (void) strlcat(command, " ", len);
7470 7460 (void) strlcat(command, argv[i], len);
7471 7461 }
7472 7462 (void) strlcat(command, "\n", len);
7473 7463 err = string_to_yyin(command);
7474 7464 free(command);
7475 7465 if (err != Z_OK)
7476 7466 return (err);
7477 7467 while (!feof(yyin))
7478 7468 yyparse();
7479 7469 return (cleanup());
7480 7470 }
7481 7471
7482 7472 static char *
7483 7473 get_execbasename(char *execfullname)
7484 7474 {
7485 7475 char *last_slash, *execbasename;
7486 7476
7487 7477 /* guard against '/' at end of command invocation */
7488 7478 for (;;) {
7489 7479 last_slash = strrchr(execfullname, '/');
7490 7480 if (last_slash == NULL) {
7491 7481 execbasename = execfullname;
7492 7482 break;
7493 7483 } else {
7494 7484 execbasename = last_slash + 1;
7495 7485 if (*execbasename == '\0') {
7496 7486 *last_slash = '\0';
7497 7487 continue;
7498 7488 }
7499 7489 break;
7500 7490 }
7501 7491 }
7502 7492 return (execbasename);
7503 7493 }
7504 7494
7505 7495 int
7506 7496 main(int argc, char *argv[])
7507 7497 {
7508 7498 int err, arg;
7509 7499 struct stat st;
7510 7500
7511 7501 /* This must be before anything goes to stdout. */
7512 7502 setbuf(stdout, NULL);
7513 7503
7514 7504 saw_error = B_FALSE;
7515 7505 cmd_file_mode = B_FALSE;
7516 7506 execname = get_execbasename(argv[0]);
7517 7507
7518 7508 (void) setlocale(LC_ALL, "");
7519 7509 (void) textdomain(TEXT_DOMAIN);
7520 7510
7521 7511 if (getzoneid() != GLOBAL_ZONEID) {
7522 7512 zerr(gettext("%s can only be run from the global zone."),
7523 7513 execname);
7524 7514 exit(Z_ERR);
7525 7515 }
7526 7516
7527 7517 if (argc < 2) {
7528 7518 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7529 7519 exit(Z_USAGE);
7530 7520 }
7531 7521 if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7532 7522 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7533 7523 exit(Z_OK);
7534 7524 }
7535 7525
7536 7526 while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
7537 7527 switch (arg) {
7538 7528 case '?':
7539 7529 if (optopt == '?')
7540 7530 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7541 7531 else
7542 7532 usage(B_FALSE, HELP_USAGE);
7543 7533 exit(Z_USAGE);
7544 7534 /* NOTREACHED */
7545 7535 case 'f':
7546 7536 cmd_file_name = optarg;
7547 7537 cmd_file_mode = B_TRUE;
7548 7538 break;
7549 7539 case 'R':
7550 7540 if (*optarg != '/') {
7551 7541 zerr(gettext("root path must be absolute: %s"),
7552 7542 optarg);
7553 7543 exit(Z_USAGE);
7554 7544 }
7555 7545 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7556 7546 zerr(gettext(
7557 7547 "root path must be a directory: %s"),
7558 7548 optarg);
7559 7549 exit(Z_USAGE);
7560 7550 }
7561 7551 zonecfg_set_root(optarg);
7562 7552 break;
7563 7553 case 'z':
7564 7554 if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7565 7555 global_zone = B_TRUE;
7566 7556 } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7567 7557 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7568 7558 usage(B_FALSE, HELP_SYNTAX);
7569 7559 exit(Z_USAGE);
7570 7560 }
7571 7561 (void) strlcpy(zone, optarg, sizeof (zone));
7572 7562 (void) strlcpy(revert_zone, optarg, sizeof (zone));
7573 7563 break;
7574 7564 default:
7575 7565 usage(B_FALSE, HELP_USAGE);
7576 7566 exit(Z_USAGE);
7577 7567 }
7578 7568 }
7579 7569
7580 7570 if (optind > argc || strcmp(zone, "") == 0) {
7581 7571 usage(B_FALSE, HELP_USAGE);
7582 7572 exit(Z_USAGE);
7583 7573 }
7584 7574
7585 7575 if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7586 7576 read_only_mode = B_FALSE;
7587 7577 } else if (err == Z_ACCES) {
7588 7578 read_only_mode = B_TRUE;
7589 7579 /* skip this message in one-off from command line mode */
7590 7580 if (optind == argc)
7591 7581 (void) fprintf(stderr, gettext("WARNING: you do not "
7592 7582 "have write access to this zone's configuration "
7593 7583 "file;\ngoing into read-only mode.\n"));
7594 7584 } else {
7595 7585 fprintf(stderr, "%s: Could not access zone configuration "
7596 7586 "store: %s\n", execname, zonecfg_strerror(err));
7597 7587 exit(Z_ERR);
7598 7588 }
7599 7589
7600 7590 if ((handle = zonecfg_init_handle()) == NULL) {
7601 7591 zone_perror(execname, Z_NOMEM, B_TRUE);
7602 7592 exit(Z_ERR);
7603 7593 }
7604 7594
7605 7595 /*
7606 7596 * This may get set back to FALSE again in cmd_file() if cmd_file_name
7607 7597 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
7608 7598 */
7609 7599 if (isatty(STDIN_FILENO))
7610 7600 ok_to_prompt = B_TRUE;
7611 7601 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
7612 7602 exit(Z_ERR);
7613 7603 if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
7614 7604 exit(Z_ERR);
7615 7605 (void) sigset(SIGINT, SIG_IGN);
7616 7606 if (optind == argc) {
7617 7607 if (!cmd_file_mode)
7618 7608 err = do_interactive();
7619 7609 else
7620 7610 err = cmd_file(cmd_file_name);
7621 7611 } else {
7622 7612 err = one_command_at_a_time(argc - optind, &(argv[optind]));
7623 7613 }
7624 7614 zonecfg_fini_handle(handle);
7625 7615 if (brand != NULL)
7626 7616 brand_close(brand);
7627 7617 (void) del_GetLine(gl);
7628 7618 return (err);
7629 7619 }
↓ open down ↓ |
1212 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX