1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * zonecfg is a lex/yacc based command interpreter used to manage zone 29 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which 30 * the grammar (see zonecfg_grammar.y) builds up into commands, some of 31 * which takes resources and/or properties as arguments. See the block 32 * comments near the end of zonecfg_grammar.y for how the data structures 33 * which keep track of these resources and properties are built up. 34 * 35 * The resource/property data structures are inserted into a command 36 * structure (see zonecfg.h), which also keeps track of command names, 37 * miscellaneous arguments, and function handlers. The grammar selects 38 * the appropriate function handler, each of which takes a pointer to a 39 * command structure as its sole argument, and invokes it. The grammar 40 * itself is "entered" (a la the Matrix) by yyparse(), which is called 41 * from read_input(), our main driving function. That in turn is called 42 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each 43 * of which is called from main() depending on how the program was invoked. 44 * 45 * The rest of this module consists of the various function handlers and 46 * their helper functions. Some of these functions, particularly the 47 * X_to_str() functions, which maps command, resource and property numbers 48 * to strings, are used quite liberally, as doing so results in a better 49 * program w/rt I18N, reducing the need for translation notes. 50 */ 51 52 #include <sys/mntent.h> 53 #include <sys/varargs.h> 54 #include <sys/sysmacros.h> 55 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <strings.h> 59 #include <unistd.h> 60 #include <ctype.h> 61 #include <stdlib.h> 62 #include <assert.h> 63 #include <sys/stat.h> 64 #include <zone.h> 65 #include <arpa/inet.h> 66 #include <netdb.h> 67 #include <locale.h> 68 #include <libintl.h> 69 #include <alloca.h> 70 #include <signal.h> 71 #include <wait.h> 72 #include <libtecla.h> 73 #include <libzfs.h> 74 #include <sys/brand.h> 75 #include <libbrand.h> 76 #include <sys/systeminfo.h> 77 #include <libdladm.h> 78 #include <libinetutil.h> 79 80 #include <libzonecfg.h> 81 #include "zonecfg.h" 82 83 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 84 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 85 #endif 86 87 #define PAGER "/usr/bin/more" 88 #define EXEC_PREFIX "exec " 89 #define EXEC_LEN (strlen(EXEC_PREFIX)) 90 91 struct help { 92 uint_t cmd_num; 93 char *cmd_name; 94 uint_t flags; 95 char *short_usage; 96 }; 97 98 extern int yyparse(void); 99 extern int lex_lineno; 100 101 #define MAX_LINE_LEN 1024 102 #define MAX_CMD_HIST 1024 103 #define MAX_CMD_LEN 1024 104 105 #define ONE_MB 1048576 106 107 /* 108 * Each SHELP_ should be a simple string. 109 */ 110 111 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \ 112 "add <property-name> <property-value>\n\t(resource scope)" 113 #define SHELP_CANCEL "cancel" 114 #define SHELP_CLEAR "clear <property-name>" 115 #define SHELP_COMMIT "commit" 116 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]" 117 #define SHELP_DELETE "delete [-F]" 118 #define SHELP_END "end" 119 #define SHELP_EXIT "exit [-F]" 120 #define SHELP_EXPORT "export [-f output-file]" 121 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]" 122 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]" 123 #define SHELP_REMOVE "remove [-F] <resource-type> " \ 124 "[ <property-name>=<property-value> ]*\n" \ 125 "\t(global scope)\n" \ 126 "remove <property-name> <property-value>\n" \ 127 "\t(resource scope)" 128 #define SHELP_REVERT "revert [-F]" 129 #define SHELP_SELECT "select <resource-type> { <property-name>=" \ 130 "<property-value> }" 131 #define SHELP_SET "set <property-name>=<property-value>" 132 #define SHELP_VERIFY "verify" 133 134 static struct help helptab[] = { 135 { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, }, 136 { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, }, 137 { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, }, 138 { CMD_COMMIT, "commit", 0, SHELP_COMMIT, }, 139 { CMD_CREATE, "create", 0, SHELP_CREATE, }, 140 { CMD_DELETE, "delete", 0, SHELP_DELETE, }, 141 { CMD_END, "end", 0, SHELP_END, }, 142 { CMD_EXIT, "exit", 0, SHELP_EXIT, }, 143 { CMD_EXPORT, "export", 0, SHELP_EXPORT, }, 144 { CMD_HELP, "help", 0, SHELP_HELP }, 145 { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, }, 146 { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, }, 147 { CMD_REVERT, "revert", 0, SHELP_REVERT, }, 148 { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, }, 149 { CMD_SET, "set", HELP_PROPS, SHELP_SET, }, 150 { CMD_VERIFY, "verify", 0, SHELP_VERIFY, }, 151 { 0 }, 152 }; 153 154 #define MAX_RT_STRLEN 16 155 156 /* These *must* match the order of the RT_ define's from zonecfg.h */ 157 static char *res_types[] = { 158 "unknown", 159 "zonename", 160 "zonepath", 161 "autoboot", 162 "pool", 163 "fs", 164 "inherit-pkg-dir", 165 "net", 166 "device", 167 "rctl", 168 "attr", 169 "dataset", 170 "limitpriv", 171 "bootargs", 172 "brand", 173 "dedicated-cpu", 174 "capped-memory", 175 ALIAS_MAXLWPS, 176 ALIAS_MAXSHMMEM, 177 ALIAS_MAXSHMIDS, 178 ALIAS_MAXMSGIDS, 179 ALIAS_MAXSEMIDS, 180 ALIAS_SHARES, 181 "scheduling-class", 182 "ip-type", 183 "capped-cpu", 184 "hostid", 185 NULL 186 }; 187 188 /* These *must* match the order of the PT_ define's from zonecfg.h */ 189 static char *prop_types[] = { 190 "unknown", 191 "zonename", 192 "zonepath", 193 "autoboot", 194 "pool", 195 "dir", 196 "special", 197 "type", 198 "options", 199 "address", 200 "physical", 201 "name", 202 "value", 203 "match", 204 "priv", 205 "limit", 206 "action", 207 "raw", 208 "limitpriv", 209 "bootargs", 210 "brand", 211 "ncpus", 212 "importance", 213 "swap", 214 "locked", 215 ALIAS_SHARES, 216 ALIAS_MAXLWPS, 217 ALIAS_MAXSHMMEM, 218 ALIAS_MAXSHMIDS, 219 ALIAS_MAXMSGIDS, 220 ALIAS_MAXSEMIDS, 221 ALIAS_MAXLOCKEDMEM, 222 ALIAS_MAXSWAP, 223 "scheduling-class", 224 "ip-type", 225 "defrouter", 226 "hostid", 227 NULL 228 }; 229 230 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */ 231 static char *prop_val_types[] = { 232 "simple", 233 "complex", 234 "list", 235 }; 236 237 /* 238 * The various _cmds[] lists below are for command tab-completion. 239 */ 240 241 /* 242 * remove has a space afterwards because it has qualifiers; the other commands 243 * that have qualifiers (add, select, etc.) don't need a space here because 244 * they have their own _cmds[] lists below. 245 */ 246 static const char *global_scope_cmds[] = { 247 "add", 248 "clear", 249 "commit", 250 "create", 251 "delete", 252 "exit", 253 "export", 254 "help", 255 "info", 256 "remove ", 257 "revert", 258 "select", 259 "set", 260 "verify", 261 NULL 262 }; 263 264 static const char *add_cmds[] = { 265 "add fs", 266 "add inherit-pkg-dir", 267 "add net", 268 "add device", 269 "add rctl", 270 "add attr", 271 "add dataset", 272 "add dedicated-cpu", 273 "add capped-cpu", 274 "add capped-memory", 275 NULL 276 }; 277 278 static const char *clear_cmds[] = { 279 "clear autoboot", 280 "clear pool", 281 "clear limitpriv", 282 "clear bootargs", 283 "clear scheduling-class", 284 "clear ip-type", 285 "clear " ALIAS_MAXLWPS, 286 "clear " ALIAS_MAXSHMMEM, 287 "clear " ALIAS_MAXSHMIDS, 288 "clear " ALIAS_MAXMSGIDS, 289 "clear " ALIAS_MAXSEMIDS, 290 "clear " ALIAS_SHARES, 291 NULL 292 }; 293 294 static const char *remove_cmds[] = { 295 "remove fs ", 296 "remove inherit-pkg-dir ", 297 "remove net ", 298 "remove device ", 299 "remove rctl ", 300 "remove attr ", 301 "remove dataset ", 302 "remove dedicated-cpu ", 303 "remove capped-cpu ", 304 "remove capped-memory ", 305 NULL 306 }; 307 308 static const char *select_cmds[] = { 309 "select fs ", 310 "select inherit-pkg-dir ", 311 "select net ", 312 "select device ", 313 "select rctl ", 314 "select attr ", 315 "select dataset ", 316 "select dedicated-cpu", 317 "select capped-cpu", 318 "select capped-memory", 319 NULL 320 }; 321 322 static const char *set_cmds[] = { 323 "set zonename=", 324 "set zonepath=", 325 "set brand=", 326 "set autoboot=", 327 "set pool=", 328 "set limitpriv=", 329 "set bootargs=", 330 "set scheduling-class=", 331 "set ip-type=", 332 "set " ALIAS_MAXLWPS "=", 333 "set " ALIAS_MAXSHMMEM "=", 334 "set " ALIAS_MAXSHMIDS "=", 335 "set " ALIAS_MAXMSGIDS "=", 336 "set " ALIAS_MAXSEMIDS "=", 337 "set " ALIAS_SHARES "=", 338 "set hostid=", 339 NULL 340 }; 341 342 static const char *info_cmds[] = { 343 "info fs ", 344 "info inherit-pkg-dir ", 345 "info net ", 346 "info device ", 347 "info rctl ", 348 "info attr ", 349 "info dataset ", 350 "info capped-memory", 351 "info dedicated-cpu", 352 "info capped-cpu", 353 "info zonename", 354 "info zonepath", 355 "info autoboot", 356 "info pool", 357 "info limitpriv", 358 "info bootargs", 359 "info brand", 360 "info scheduling-class", 361 "info ip-type", 362 "info max-lwps", 363 "info max-shm-memory", 364 "info max-shm-ids", 365 "info max-msg-ids", 366 "info max-sem-ids", 367 "info cpu-shares", 368 "info hostid", 369 NULL 370 }; 371 372 static const char *fs_res_scope_cmds[] = { 373 "add options ", 374 "cancel", 375 "end", 376 "exit", 377 "help", 378 "info", 379 "remove options ", 380 "set dir=", 381 "set raw=", 382 "set special=", 383 "set type=", 384 "clear raw", 385 NULL 386 }; 387 388 static const char *net_res_scope_cmds[] = { 389 "cancel", 390 "end", 391 "exit", 392 "help", 393 "info", 394 "set address=", 395 "set physical=", 396 NULL 397 }; 398 399 static const char *ipd_res_scope_cmds[] = { 400 "cancel", 401 "end", 402 "exit", 403 "help", 404 "info", 405 "set dir=", 406 NULL 407 }; 408 409 static const char *device_res_scope_cmds[] = { 410 "cancel", 411 "end", 412 "exit", 413 "help", 414 "info", 415 "set match=", 416 NULL 417 }; 418 419 static const char *attr_res_scope_cmds[] = { 420 "cancel", 421 "end", 422 "exit", 423 "help", 424 "info", 425 "set name=", 426 "set type=", 427 "set value=", 428 NULL 429 }; 430 431 static const char *rctl_res_scope_cmds[] = { 432 "add value ", 433 "cancel", 434 "end", 435 "exit", 436 "help", 437 "info", 438 "remove value ", 439 "set name=", 440 NULL 441 }; 442 443 static const char *dataset_res_scope_cmds[] = { 444 "cancel", 445 "end", 446 "exit", 447 "help", 448 "info", 449 "set name=", 450 NULL 451 }; 452 453 static const char *pset_res_scope_cmds[] = { 454 "cancel", 455 "end", 456 "exit", 457 "help", 458 "info", 459 "set ncpus=", 460 "set importance=", 461 "clear importance", 462 NULL 463 }; 464 465 static const char *pcap_res_scope_cmds[] = { 466 "cancel", 467 "end", 468 "exit", 469 "help", 470 "info", 471 "set ncpus=", 472 NULL 473 }; 474 475 static const char *mcap_res_scope_cmds[] = { 476 "cancel", 477 "end", 478 "exit", 479 "help", 480 "info", 481 "set physical=", 482 "set swap=", 483 "set locked=", 484 "clear physical", 485 "clear swap", 486 "clear locked", 487 NULL 488 }; 489 490 /* Global variables */ 491 492 /* set early in main(), never modified thereafter, used all over the place */ 493 static char *execname; 494 495 /* set in main(), used all over the place */ 496 static zone_dochandle_t handle; 497 498 /* used all over the place */ 499 static char zone[ZONENAME_MAX]; 500 static char revert_zone[ZONENAME_MAX]; 501 502 /* global brand operations */ 503 static brand_handle_t brand; 504 505 /* set in modifying functions, checked in read_input() */ 506 static boolean_t need_to_commit = B_FALSE; 507 boolean_t saw_error; 508 509 /* set in yacc parser, checked in read_input() */ 510 boolean_t newline_terminated; 511 512 /* set in main(), checked in lex error handler */ 513 boolean_t cmd_file_mode; 514 515 /* set in exit_func(), checked in read_input() */ 516 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE; 517 518 /* used in short_usage() and zerr() */ 519 static char *cmd_file_name = NULL; 520 521 /* checked in read_input() and other places */ 522 static boolean_t ok_to_prompt = B_FALSE; 523 524 /* set and checked in initialize() */ 525 static boolean_t got_handle = B_FALSE; 526 527 /* initialized in do_interactive(), checked in initialize() */ 528 static boolean_t interactive_mode; 529 530 /* set if configuring the global zone */ 531 static boolean_t global_zone = B_FALSE; 532 533 /* set in main(), checked in multiple places */ 534 static boolean_t read_only_mode; 535 536 /* scope is outer/global or inner/resource */ 537 static boolean_t global_scope = B_TRUE; 538 static int resource_scope; /* should be in the RT_ list from zonecfg.h */ 539 static int end_op = -1; /* operation on end is either add or modify */ 540 541 int num_prop_vals; /* for grammar */ 542 543 /* 544 * These are for keeping track of resources as they are specified as part of 545 * the multi-step process. They should be initialized by add_resource() or 546 * select_func() and filled in by add_property() or set_func(). 547 */ 548 static struct zone_fstab old_fstab, in_progress_fstab; 549 static struct zone_fstab old_ipdtab, in_progress_ipdtab; 550 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab; 551 static struct zone_devtab old_devtab, in_progress_devtab; 552 static struct zone_rctltab old_rctltab, in_progress_rctltab; 553 static struct zone_attrtab old_attrtab, in_progress_attrtab; 554 static struct zone_dstab old_dstab, in_progress_dstab; 555 static struct zone_psettab old_psettab, in_progress_psettab; 556 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab; 557 558 static GetLine *gl; /* The gl_get_line() resource object */ 559 560 static void bytes_to_units(char *str, char *buf, int bufsize); 561 562 /* Functions begin here */ 563 564 static boolean_t 565 initial_match(const char *line1, const char *line2, int word_end) 566 { 567 if (word_end <= 0) 568 return (B_TRUE); 569 return (strncmp(line1, line2, word_end) == 0); 570 } 571 572 static int 573 add_stuff(WordCompletion *cpl, const char *line1, const char **list, 574 int word_end) 575 { 576 int i, err; 577 578 for (i = 0; list[i] != NULL; i++) { 579 if (initial_match(line1, list[i], word_end)) { 580 err = cpl_add_completion(cpl, line1, 0, word_end, 581 list[i] + word_end, "", ""); 582 if (err != 0) 583 return (err); 584 } 585 } 586 return (0); 587 } 588 589 static 590 /* ARGSUSED */ 591 CPL_MATCH_FN(cmd_cpl_fn) 592 { 593 if (global_scope) { 594 /* 595 * The MAX/MIN tests below are to make sure we have at least 596 * enough characters to distinguish from other prefixes (MAX) 597 * but only check MIN(what we have, what we're checking). 598 */ 599 if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0) 600 return (add_stuff(cpl, line, add_cmds, word_end)); 601 if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0) 602 return (add_stuff(cpl, line, clear_cmds, word_end)); 603 if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0) 604 return (add_stuff(cpl, line, select_cmds, word_end)); 605 if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0) 606 return (add_stuff(cpl, line, set_cmds, word_end)); 607 if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0) 608 return (add_stuff(cpl, line, remove_cmds, word_end)); 609 if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0) 610 return (add_stuff(cpl, line, info_cmds, word_end)); 611 return (add_stuff(cpl, line, global_scope_cmds, word_end)); 612 } 613 switch (resource_scope) { 614 case RT_FS: 615 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end)); 616 case RT_IPD: 617 return (add_stuff(cpl, line, ipd_res_scope_cmds, word_end)); 618 case RT_NET: 619 return (add_stuff(cpl, line, net_res_scope_cmds, word_end)); 620 case RT_DEVICE: 621 return (add_stuff(cpl, line, device_res_scope_cmds, word_end)); 622 case RT_RCTL: 623 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end)); 624 case RT_ATTR: 625 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end)); 626 case RT_DATASET: 627 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end)); 628 case RT_DCPU: 629 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end)); 630 case RT_PCAP: 631 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end)); 632 case RT_MCAP: 633 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end)); 634 } 635 return (0); 636 } 637 638 /* 639 * For the main CMD_func() functions below, several of them call getopt() 640 * then check optind against argc to make sure an extra parameter was not 641 * passed in. The reason this is not caught in the grammar is that the 642 * grammar just checks for a miscellaneous TOKEN, which is *expected* to 643 * be "-F" (for example), but could be anything. So (for example) this 644 * check will prevent "create bogus". 645 */ 646 647 cmd_t * 648 alloc_cmd(void) 649 { 650 return (calloc(1, sizeof (cmd_t))); 651 } 652 653 void 654 free_cmd(cmd_t *cmd) 655 { 656 int i; 657 658 for (i = 0; i < MAX_EQ_PROP_PAIRS; i++) 659 if (cmd->cmd_property_ptr[i] != NULL) { 660 property_value_ptr_t pp = cmd->cmd_property_ptr[i]; 661 662 switch (pp->pv_type) { 663 case PROP_VAL_SIMPLE: 664 free(pp->pv_simple); 665 break; 666 case PROP_VAL_COMPLEX: 667 free_complex(pp->pv_complex); 668 break; 669 case PROP_VAL_LIST: 670 free_list(pp->pv_list); 671 break; 672 } 673 } 674 for (i = 0; i < cmd->cmd_argc; i++) 675 free(cmd->cmd_argv[i]); 676 free(cmd); 677 } 678 679 complex_property_ptr_t 680 alloc_complex(void) 681 { 682 return (calloc(1, sizeof (complex_property_t))); 683 } 684 685 void 686 free_complex(complex_property_ptr_t complex) 687 { 688 if (complex == NULL) 689 return; 690 free_complex(complex->cp_next); 691 if (complex->cp_value != NULL) 692 free(complex->cp_value); 693 free(complex); 694 } 695 696 list_property_ptr_t 697 alloc_list(void) 698 { 699 return (calloc(1, sizeof (list_property_t))); 700 } 701 702 void 703 free_list(list_property_ptr_t list) 704 { 705 if (list == NULL) 706 return; 707 if (list->lp_simple != NULL) 708 free(list->lp_simple); 709 free_complex(list->lp_complex); 710 free_list(list->lp_next); 711 free(list); 712 } 713 714 void 715 free_outer_list(list_property_ptr_t list) 716 { 717 if (list == NULL) 718 return; 719 free_outer_list(list->lp_next); 720 free(list); 721 } 722 723 static struct zone_rctlvaltab * 724 alloc_rctlvaltab(void) 725 { 726 return (calloc(1, sizeof (struct zone_rctlvaltab))); 727 } 728 729 static char * 730 rt_to_str(int res_type) 731 { 732 assert(res_type >= RT_MIN && res_type <= RT_MAX); 733 return (res_types[res_type]); 734 } 735 736 static char * 737 pt_to_str(int prop_type) 738 { 739 assert(prop_type >= PT_MIN && prop_type <= PT_MAX); 740 return (prop_types[prop_type]); 741 } 742 743 static char * 744 pvt_to_str(int pv_type) 745 { 746 assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX); 747 return (prop_val_types[pv_type]); 748 } 749 750 static char * 751 cmd_to_str(int cmd_num) 752 { 753 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 754 return (helptab[cmd_num].cmd_name); 755 } 756 757 /* 758 * This is a separate function rather than a set of define's because of the 759 * gettext() wrapping. 760 */ 761 762 /* 763 * TRANSLATION_NOTE 764 * Each string below should have \t follow \n whenever needed; the 765 * initial \t and the terminal \n will be provided by the calling function. 766 */ 767 768 static char * 769 long_help(int cmd_num) 770 { 771 static char line[1024]; /* arbitrary large amount */ 772 773 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 774 switch (cmd_num) { 775 case CMD_HELP: 776 return (gettext("Prints help message.")); 777 case CMD_CREATE: 778 (void) snprintf(line, sizeof (line), 779 gettext("Creates a configuration for the " 780 "specified zone. %s should be\n\tused to " 781 "begin configuring a new zone. If overwriting an " 782 "existing\n\tconfiguration, the -F flag can be " 783 "used to force the action. If\n\t-t template is " 784 "given, creates a configuration identical to the\n" 785 "\tspecified template, except that the zone name " 786 "is changed from\n\ttemplate to zonename. '%s -a' " 787 "creates a configuration from a\n\tdetached " 788 "zonepath. '%s -b' results in a blank " 789 "configuration.\n\t'%s' with no arguments applies " 790 "the Sun default settings."), 791 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE), 792 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE)); 793 return (line); 794 case CMD_EXIT: 795 return (gettext("Exits the program. The -F flag can " 796 "be used to force the action.")); 797 case CMD_EXPORT: 798 return (gettext("Prints configuration to standard " 799 "output, or to output-file if\n\tspecified, in " 800 "a form suitable for use in a command-file.")); 801 case CMD_ADD: 802 return (gettext("Add specified resource to " 803 "configuration.")); 804 case CMD_DELETE: 805 return (gettext("Deletes the specified zone. The -F " 806 "flag can be used to force the\n\taction.")); 807 case CMD_REMOVE: 808 return (gettext("Remove specified resource from " 809 "configuration. The -F flag can be used\n\tto " 810 "force the action.")); 811 case CMD_SELECT: 812 (void) snprintf(line, sizeof (line), 813 gettext("Selects a resource to modify. " 814 "Resource modification is completed\n\twith the " 815 "command \"%s\". The property name/value pairs " 816 "must uniquely\n\tidentify a resource. Note that " 817 "the curly braces ('{', '}') mean one\n\tor more " 818 "of whatever is between them."), 819 cmd_to_str(CMD_END)); 820 return (line); 821 case CMD_SET: 822 return (gettext("Sets property values.")); 823 case CMD_CLEAR: 824 return (gettext("Clears property values.")); 825 case CMD_INFO: 826 return (gettext("Displays information about the " 827 "current configuration. If resource\n\ttype is " 828 "specified, displays only information about " 829 "resources of\n\tthe relevant type. If resource " 830 "id is specified, displays only\n\tinformation " 831 "about that resource.")); 832 case CMD_VERIFY: 833 return (gettext("Verifies current configuration " 834 "for correctness (some resource types\n\thave " 835 "required properties).")); 836 case CMD_COMMIT: 837 (void) snprintf(line, sizeof (line), 838 gettext("Commits current configuration. " 839 "Configuration must be committed to\n\tbe used by " 840 "%s. Until the configuration is committed, " 841 "changes \n\tcan be removed with the %s " 842 "command. This operation is\n\tattempted " 843 "automatically upon completion of a %s " 844 "session."), "zoneadm", cmd_to_str(CMD_REVERT), 845 "zonecfg"); 846 return (line); 847 case CMD_REVERT: 848 return (gettext("Reverts configuration back to the " 849 "last committed state. The -F flag\n\tcan be " 850 "used to force the action.")); 851 case CMD_CANCEL: 852 return (gettext("Cancels resource/property " 853 "specification.")); 854 case CMD_END: 855 return (gettext("Ends resource/property " 856 "specification.")); 857 } 858 /* NOTREACHED */ 859 return (NULL); 860 } 861 862 /* 863 * Called with verbose TRUE when help is explicitly requested, FALSE for 864 * unexpected errors. 865 */ 866 867 void 868 usage(boolean_t verbose, uint_t flags) 869 { 870 FILE *fp = verbose ? stdout : stderr, *newfp; 871 boolean_t need_to_close = B_FALSE; 872 char *pager; 873 int i; 874 875 /* don't page error output */ 876 if (verbose && interactive_mode) { 877 if ((pager = getenv("PAGER")) == NULL) 878 pager = PAGER; 879 if ((newfp = popen(pager, "w")) != NULL) { 880 need_to_close = B_TRUE; 881 fp = newfp; 882 } 883 } 884 if (flags & HELP_META) { 885 (void) fprintf(fp, gettext("More help is available for the " 886 "following:\n")); 887 (void) fprintf(fp, "\n\tcommands ('%s commands')\n", 888 cmd_to_str(CMD_HELP)); 889 (void) fprintf(fp, "\tsyntax ('%s syntax')\n", 890 cmd_to_str(CMD_HELP)); 891 (void) fprintf(fp, "\tusage ('%s usage')\n\n", 892 cmd_to_str(CMD_HELP)); 893 (void) fprintf(fp, gettext("You may also obtain help on any " 894 "command by typing '%s <command-name>.'\n"), 895 cmd_to_str(CMD_HELP)); 896 } 897 if (flags & HELP_RES_SCOPE) { 898 switch (resource_scope) { 899 case RT_FS: 900 (void) fprintf(fp, gettext("The '%s' resource scope is " 901 "used to configure a file-system.\n"), 902 rt_to_str(resource_scope)); 903 (void) fprintf(fp, gettext("Valid commands:\n")); 904 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 905 pt_to_str(PT_DIR), gettext("<path>")); 906 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 907 pt_to_str(PT_SPECIAL), gettext("<path>")); 908 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 909 pt_to_str(PT_RAW), gettext("<raw-device>")); 910 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 911 pt_to_str(PT_TYPE), gettext("<file-system type>")); 912 (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD), 913 pt_to_str(PT_OPTIONS), 914 gettext("<file-system options>")); 915 (void) fprintf(fp, "\t%s %s %s\n", 916 cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS), 917 gettext("<file-system options>")); 918 (void) fprintf(fp, gettext("Consult the file-system " 919 "specific manual page, such as mount_ufs(1M), " 920 "for\ndetails about file-system options. Note " 921 "that any file-system options with an\nembedded " 922 "'=' character must be enclosed in double quotes, " 923 /*CSTYLED*/ 924 "such as \"%s=5\".\n"), MNTOPT_RETRY); 925 break; 926 case RT_IPD: 927 (void) fprintf(fp, gettext("The '%s' resource scope is " 928 "used to configure a directory\ninherited from the " 929 "global zone into a non-global zone in read-only " 930 "mode.\n"), rt_to_str(resource_scope)); 931 (void) fprintf(fp, gettext("Valid commands:\n")); 932 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 933 pt_to_str(PT_DIR), gettext("<path>")); 934 break; 935 case RT_NET: 936 (void) fprintf(fp, gettext("The '%s' resource scope is " 937 "used to configure a network interface.\n"), 938 rt_to_str(resource_scope)); 939 (void) fprintf(fp, gettext("Valid commands:\n")); 940 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 941 pt_to_str(PT_ADDRESS), gettext("<IP-address>")); 942 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 943 pt_to_str(PT_PHYSICAL), gettext("<interface>")); 944 (void) fprintf(fp, gettext("See ifconfig(1M) for " 945 "details of the <interface> string.\n")); 946 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 947 pt_to_str(PT_DEFROUTER), gettext("<IP-address>")); 948 (void) fprintf(fp, gettext("%s %s and %s %s are valid " 949 "if the %s property is set to %s, otherwise they " 950 "must not be set.\n"), 951 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS), 952 cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER), 953 pt_to_str(PT_IPTYPE), "shared"); 954 break; 955 case RT_DEVICE: 956 (void) fprintf(fp, gettext("The '%s' resource scope is " 957 "used to configure a device node.\n"), 958 rt_to_str(resource_scope)); 959 (void) fprintf(fp, gettext("Valid commands:\n")); 960 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 961 pt_to_str(PT_MATCH), gettext("<device-path>")); 962 break; 963 case RT_RCTL: 964 (void) fprintf(fp, gettext("The '%s' resource scope is " 965 "used to configure a resource control.\n"), 966 rt_to_str(resource_scope)); 967 (void) fprintf(fp, gettext("Valid commands:\n")); 968 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 969 pt_to_str(PT_NAME), gettext("<string>")); 970 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n", 971 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE), 972 pt_to_str(PT_PRIV), gettext("<priv-value>"), 973 pt_to_str(PT_LIMIT), gettext("<number>"), 974 pt_to_str(PT_ACTION), gettext("<action-value>")); 975 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n", 976 cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE), 977 pt_to_str(PT_PRIV), gettext("<priv-value>"), 978 pt_to_str(PT_LIMIT), gettext("<number>"), 979 pt_to_str(PT_ACTION), gettext("<action-value>")); 980 (void) fprintf(fp, "%s\n\t%s := privileged\n" 981 "\t%s := none | deny\n", gettext("Where"), 982 gettext("<priv-value>"), gettext("<action-value>")); 983 break; 984 case RT_ATTR: 985 (void) fprintf(fp, gettext("The '%s' resource scope is " 986 "used to configure a generic attribute.\n"), 987 rt_to_str(resource_scope)); 988 (void) fprintf(fp, gettext("Valid commands:\n")); 989 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 990 pt_to_str(PT_NAME), gettext("<name>")); 991 (void) fprintf(fp, "\t%s %s=boolean\n", 992 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 993 (void) fprintf(fp, "\t%s %s=true | false\n", 994 cmd_to_str(CMD_SET), pt_to_str(PT_VALUE)); 995 (void) fprintf(fp, gettext("or\n")); 996 (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET), 997 pt_to_str(PT_TYPE)); 998 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 999 pt_to_str(PT_VALUE), gettext("<integer>")); 1000 (void) fprintf(fp, gettext("or\n")); 1001 (void) fprintf(fp, "\t%s %s=string\n", 1002 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 1003 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1004 pt_to_str(PT_VALUE), gettext("<string>")); 1005 (void) fprintf(fp, gettext("or\n")); 1006 (void) fprintf(fp, "\t%s %s=uint\n", 1007 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 1008 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1009 pt_to_str(PT_VALUE), gettext("<unsigned integer>")); 1010 break; 1011 case RT_DATASET: 1012 (void) fprintf(fp, gettext("The '%s' resource scope is " 1013 "used to export ZFS datasets.\n"), 1014 rt_to_str(resource_scope)); 1015 (void) fprintf(fp, gettext("Valid commands:\n")); 1016 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1017 pt_to_str(PT_NAME), gettext("<name>")); 1018 break; 1019 case RT_DCPU: 1020 (void) fprintf(fp, gettext("The '%s' resource scope " 1021 "configures the 'pools' facility to dedicate\na " 1022 "subset of the system's processors to this zone " 1023 "while it is running.\n"), 1024 rt_to_str(resource_scope)); 1025 (void) fprintf(fp, gettext("Valid commands:\n")); 1026 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1027 pt_to_str(PT_NCPUS), 1028 gettext("<unsigned integer | range>")); 1029 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1030 pt_to_str(PT_IMPORTANCE), 1031 gettext("<unsigned integer>")); 1032 break; 1033 case RT_PCAP: 1034 (void) fprintf(fp, gettext("The '%s' resource scope is " 1035 "used to set an upper limit (a cap) on the\n" 1036 "percentage of CPU that can be used by this zone. " 1037 "A '%s' value of 1\ncorresponds to one cpu. The " 1038 "value can be set higher than 1, up to the total\n" 1039 "number of CPUs on the system. The value can " 1040 "also be less than 1,\nrepresenting a fraction of " 1041 "a cpu.\n"), 1042 rt_to_str(resource_scope), pt_to_str(PT_NCPUS)); 1043 (void) fprintf(fp, gettext("Valid commands:\n")); 1044 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1045 pt_to_str(PT_NCPUS), gettext("<unsigned decimal>")); 1046 break; 1047 case RT_MCAP: 1048 (void) fprintf(fp, gettext("The '%s' resource scope is " 1049 "used to set an upper limit (a cap) on the\n" 1050 "amount of physical memory, swap space and locked " 1051 "memory that can be used by\nthis zone.\n"), 1052 rt_to_str(resource_scope)); 1053 (void) fprintf(fp, gettext("Valid commands:\n")); 1054 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1055 pt_to_str(PT_PHYSICAL), 1056 gettext("<qualified unsigned decimal>")); 1057 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1058 pt_to_str(PT_SWAP), 1059 gettext("<qualified unsigned decimal>")); 1060 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 1061 pt_to_str(PT_LOCKED), 1062 gettext("<qualified unsigned decimal>")); 1063 break; 1064 } 1065 (void) fprintf(fp, gettext("And from any resource scope, you " 1066 "can:\n")); 1067 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END), 1068 gettext("(to conclude this operation)")); 1069 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL), 1070 gettext("(to cancel this operation)")); 1071 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT), 1072 gettext("(to exit the zonecfg utility)")); 1073 } 1074 if (flags & HELP_USAGE) { 1075 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"), 1076 execname, cmd_to_str(CMD_HELP)); 1077 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n", 1078 execname, gettext("interactive")); 1079 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname); 1080 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n", 1081 execname); 1082 } 1083 if (flags & HELP_SUBCMDS) { 1084 (void) fprintf(fp, "%s:\n\n", gettext("Commands")); 1085 for (i = 0; i <= CMD_MAX; i++) { 1086 (void) fprintf(fp, "%s\n", helptab[i].short_usage); 1087 if (verbose) 1088 (void) fprintf(fp, "\t%s\n\n", long_help(i)); 1089 } 1090 } 1091 if (flags & HELP_SYNTAX) { 1092 if (!verbose) 1093 (void) fprintf(fp, "\n"); 1094 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n"); 1095 (void) fprintf(fp, gettext("\t(except the reserved words " 1096 "'%s' and anything starting with '%s')\n"), "global", 1097 "SUNW"); 1098 (void) fprintf(fp, 1099 gettext("\tName must be less than %d characters.\n"), 1100 ZONENAME_MAX); 1101 if (verbose) 1102 (void) fprintf(fp, "\n"); 1103 } 1104 if (flags & HELP_NETADDR) { 1105 (void) fprintf(fp, gettext("\n<net-addr> :=")); 1106 (void) fprintf(fp, 1107 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n")); 1108 (void) fprintf(fp, 1109 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n")); 1110 (void) fprintf(fp, 1111 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n")); 1112 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and " 1113 "IPv6 address syntax.\n")); 1114 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n")); 1115 (void) fprintf(fp, 1116 gettext("<IPv6-prefix-length> := [0-128]\n")); 1117 (void) fprintf(fp, 1118 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n")); 1119 } 1120 if (flags & HELP_RESOURCES) { 1121 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s |\n\t" 1122 "%s | %s | %s | %s\n\n", 1123 gettext("resource type"), rt_to_str(RT_FS), 1124 rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE), 1125 rt_to_str(RT_RCTL), rt_to_str(RT_ATTR), 1126 rt_to_str(RT_DATASET), rt_to_str(RT_DCPU), 1127 rt_to_str(RT_PCAP), rt_to_str(RT_MCAP)); 1128 } 1129 if (flags & HELP_PROPS) { 1130 (void) fprintf(fp, gettext("For resource type ... there are " 1131 "property types ...:\n")); 1132 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1133 pt_to_str(PT_ZONENAME)); 1134 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1135 pt_to_str(PT_ZONEPATH)); 1136 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1137 pt_to_str(PT_BRAND)); 1138 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1139 pt_to_str(PT_AUTOBOOT)); 1140 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1141 pt_to_str(PT_BOOTARGS)); 1142 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1143 pt_to_str(PT_POOL)); 1144 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1145 pt_to_str(PT_LIMITPRIV)); 1146 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1147 pt_to_str(PT_SCHED)); 1148 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1149 pt_to_str(PT_IPTYPE)); 1150 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1151 pt_to_str(PT_HOSTID)); 1152 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1153 pt_to_str(PT_MAXLWPS)); 1154 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1155 pt_to_str(PT_MAXSHMMEM)); 1156 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1157 pt_to_str(PT_MAXSHMIDS)); 1158 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1159 pt_to_str(PT_MAXMSGIDS)); 1160 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1161 pt_to_str(PT_MAXSEMIDS)); 1162 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 1163 pt_to_str(PT_SHARES)); 1164 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s\n", rt_to_str(RT_FS), 1165 pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL), 1166 pt_to_str(PT_RAW), pt_to_str(PT_TYPE), 1167 pt_to_str(PT_OPTIONS)); 1168 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_IPD), 1169 pt_to_str(PT_DIR)); 1170 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_NET), 1171 pt_to_str(PT_ADDRESS), pt_to_str(PT_PHYSICAL), 1172 pt_to_str(PT_DEFROUTER)); 1173 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE), 1174 pt_to_str(PT_MATCH)); 1175 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL), 1176 pt_to_str(PT_NAME), pt_to_str(PT_VALUE)); 1177 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR), 1178 pt_to_str(PT_NAME), pt_to_str(PT_TYPE), 1179 pt_to_str(PT_VALUE)); 1180 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET), 1181 pt_to_str(PT_NAME)); 1182 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU), 1183 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE)); 1184 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP), 1185 pt_to_str(PT_NCPUS)); 1186 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP), 1187 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP), 1188 pt_to_str(PT_LOCKED)); 1189 } 1190 if (need_to_close) 1191 (void) pclose(fp); 1192 } 1193 1194 /* PRINTFLIKE1 */ 1195 static void 1196 zerr(const char *fmt, ...) 1197 { 1198 va_list alist; 1199 static int last_lineno; 1200 1201 /* lex_lineno has already been incremented in the lexer; compensate */ 1202 if (cmd_file_mode && lex_lineno > last_lineno) { 1203 if (strcmp(cmd_file_name, "-") == 0) 1204 (void) fprintf(stderr, gettext("On line %d:\n"), 1205 lex_lineno - 1); 1206 else 1207 (void) fprintf(stderr, gettext("On line %d of %s:\n"), 1208 lex_lineno - 1, cmd_file_name); 1209 last_lineno = lex_lineno; 1210 } 1211 va_start(alist, fmt); 1212 (void) vfprintf(stderr, fmt, alist); 1213 (void) fprintf(stderr, "\n"); 1214 va_end(alist); 1215 } 1216 1217 static void 1218 zone_perror(char *prefix, int err, boolean_t set_saw) 1219 { 1220 zerr("%s: %s", prefix, zonecfg_strerror(err)); 1221 if (set_saw) 1222 saw_error = B_TRUE; 1223 } 1224 1225 /* 1226 * zone_perror() expects a single string, but for remove and select 1227 * we have both the command and the resource type, so this wrapper 1228 * function serves the same purpose in a slightly different way. 1229 */ 1230 1231 static void 1232 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw) 1233 { 1234 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num), 1235 zonecfg_strerror(err)); 1236 if (set_saw) 1237 saw_error = B_TRUE; 1238 } 1239 1240 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */ 1241 static int 1242 initialize(boolean_t handle_expected) 1243 { 1244 int err; 1245 char brandname[MAXNAMELEN]; 1246 1247 if (zonecfg_check_handle(handle) != Z_OK) { 1248 if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) { 1249 got_handle = B_TRUE; 1250 if (zonecfg_get_brand(handle, brandname, 1251 sizeof (brandname)) != Z_OK) { 1252 zerr("Zone %s is inconsistent: missing " 1253 "brand attribute", zone); 1254 exit(Z_ERR); 1255 } 1256 if ((brand = brand_open(brandname)) == NULL) { 1257 zerr("Zone %s uses non-existent brand \"%s\"." 1258 " Unable to continue", zone, brandname); 1259 exit(Z_ERR); 1260 } 1261 } else if (global_zone && err == Z_NO_ZONE && !got_handle && 1262 !read_only_mode) { 1263 /* 1264 * We implicitly create the global zone config if it 1265 * doesn't exist. 1266 */ 1267 zone_dochandle_t tmphandle; 1268 1269 if ((tmphandle = zonecfg_init_handle()) == NULL) { 1270 zone_perror(execname, Z_NOMEM, B_TRUE); 1271 exit(Z_ERR); 1272 } 1273 1274 err = zonecfg_get_template_handle("SUNWblank", zone, 1275 tmphandle); 1276 1277 if (err != Z_OK) { 1278 zonecfg_fini_handle(tmphandle); 1279 zone_perror("SUNWblank", err, B_TRUE); 1280 return (err); 1281 } 1282 1283 need_to_commit = B_TRUE; 1284 zonecfg_fini_handle(handle); 1285 handle = tmphandle; 1286 got_handle = B_TRUE; 1287 1288 } else { 1289 zone_perror(zone, err, handle_expected || got_handle); 1290 if (err == Z_NO_ZONE && !got_handle && 1291 interactive_mode && !read_only_mode) 1292 (void) printf(gettext("Use '%s' to begin " 1293 "configuring a new zone.\n"), 1294 cmd_to_str(CMD_CREATE)); 1295 return (err); 1296 } 1297 } 1298 return (Z_OK); 1299 } 1300 1301 static boolean_t 1302 state_atleast(zone_state_t state) 1303 { 1304 zone_state_t state_num; 1305 int err; 1306 1307 if ((err = zone_get_state(zone, &state_num)) != Z_OK) { 1308 /* all states are greater than "non-existent" */ 1309 if (err == Z_NO_ZONE) 1310 return (B_FALSE); 1311 zerr(gettext("Unexpectedly failed to determine state " 1312 "of zone %s: %s"), zone, zonecfg_strerror(err)); 1313 exit(Z_ERR); 1314 } 1315 return (state_num >= state); 1316 } 1317 1318 /* 1319 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc. 1320 */ 1321 1322 void 1323 short_usage(int command) 1324 { 1325 /* lex_lineno has already been incremented in the lexer; compensate */ 1326 if (cmd_file_mode) { 1327 if (strcmp(cmd_file_name, "-") == 0) 1328 (void) fprintf(stderr, 1329 gettext("syntax error on line %d\n"), 1330 lex_lineno - 1); 1331 else 1332 (void) fprintf(stderr, 1333 gettext("syntax error on line %d of %s\n"), 1334 lex_lineno - 1, cmd_file_name); 1335 } 1336 (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"), 1337 helptab[command].short_usage); 1338 saw_error = B_TRUE; 1339 } 1340 1341 /* 1342 * long_usage() is for bad semantics: e.g., wrong property type for a given 1343 * resource type. It is also used by longer_usage() below. 1344 */ 1345 1346 void 1347 long_usage(uint_t cmd_num, boolean_t set_saw) 1348 { 1349 (void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"), 1350 helptab[cmd_num].short_usage); 1351 (void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num)); 1352 if (set_saw) 1353 saw_error = B_TRUE; 1354 } 1355 1356 /* 1357 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also 1358 * any extra usage() flags as appropriate for whatever command. 1359 */ 1360 1361 void 1362 longer_usage(uint_t cmd_num) 1363 { 1364 long_usage(cmd_num, B_FALSE); 1365 if (helptab[cmd_num].flags != 0) { 1366 (void) printf("\n"); 1367 usage(B_TRUE, helptab[cmd_num].flags); 1368 } 1369 } 1370 1371 /* 1372 * scope_usage() is simply used when a command is called from the wrong scope. 1373 */ 1374 1375 static void 1376 scope_usage(uint_t cmd_num) 1377 { 1378 zerr(gettext("The %s command only makes sense in the %s scope."), 1379 cmd_to_str(cmd_num), 1380 global_scope ? gettext("resource") : gettext("global")); 1381 saw_error = B_TRUE; 1382 } 1383 1384 /* 1385 * On input, B_TRUE => yes, B_FALSE => no. 1386 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1. 1387 */ 1388 1389 static int 1390 ask_yesno(boolean_t default_answer, const char *question) 1391 { 1392 char line[64]; /* should be enough to answer yes or no */ 1393 1394 if (!ok_to_prompt) { 1395 saw_error = B_TRUE; 1396 return (-1); 1397 } 1398 for (;;) { 1399 if (printf("%s (%s)? ", question, 1400 default_answer ? "[y]/n" : "y/[n]") < 0) 1401 return (-1); 1402 if (fgets(line, sizeof (line), stdin) == NULL) 1403 return (-1); 1404 1405 if (line[0] == '\n') 1406 return (default_answer ? 1 : 0); 1407 if (tolower(line[0]) == 'y') 1408 return (1); 1409 if (tolower(line[0]) == 'n') 1410 return (0); 1411 } 1412 } 1413 1414 /* 1415 * Prints warning if zone already exists. 1416 * In interactive mode, prompts if we should continue anyway and returns Z_OK 1417 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR. 1418 * 1419 * Note that if a zone exists and its state is >= INSTALLED, an error message 1420 * will be printed and this function will return Z_ERR regardless of mode. 1421 */ 1422 1423 static int 1424 check_if_zone_already_exists(boolean_t force) 1425 { 1426 char line[ZONENAME_MAX + 128]; /* enough to ask a question */ 1427 zone_dochandle_t tmphandle; 1428 int res, answer; 1429 1430 if ((tmphandle = zonecfg_init_handle()) == NULL) { 1431 zone_perror(execname, Z_NOMEM, B_TRUE); 1432 exit(Z_ERR); 1433 } 1434 res = zonecfg_get_handle(zone, tmphandle); 1435 zonecfg_fini_handle(tmphandle); 1436 if (res != Z_OK) 1437 return (Z_OK); 1438 1439 if (state_atleast(ZONE_STATE_INSTALLED)) { 1440 zerr(gettext("Zone %s already installed; %s not allowed."), 1441 zone, cmd_to_str(CMD_CREATE)); 1442 return (Z_ERR); 1443 } 1444 1445 if (force) { 1446 (void) printf(gettext("Zone %s already exists; overwriting.\n"), 1447 zone); 1448 return (Z_OK); 1449 } 1450 (void) snprintf(line, sizeof (line), 1451 gettext("Zone %s already exists; %s anyway"), zone, 1452 cmd_to_str(CMD_CREATE)); 1453 if ((answer = ask_yesno(B_FALSE, line)) == -1) { 1454 zerr(gettext("Zone exists, input not from terminal and -F not " 1455 "specified:\n%s command ignored, exiting."), 1456 cmd_to_str(CMD_CREATE)); 1457 exit(Z_ERR); 1458 } 1459 return (answer == 1 ? Z_OK : Z_ERR); 1460 } 1461 1462 static boolean_t 1463 zone_is_read_only(int cmd_num) 1464 { 1465 if (strncmp(zone, "SUNW", 4) == 0) { 1466 zerr(gettext("%s: zones beginning with SUNW are read-only."), 1467 zone); 1468 saw_error = B_TRUE; 1469 return (B_TRUE); 1470 } 1471 if (read_only_mode) { 1472 zerr(gettext("%s: cannot %s in read-only mode."), zone, 1473 cmd_to_str(cmd_num)); 1474 saw_error = B_TRUE; 1475 return (B_TRUE); 1476 } 1477 return (B_FALSE); 1478 } 1479 1480 /* 1481 * Create a new configuration. 1482 */ 1483 void 1484 create_func(cmd_t *cmd) 1485 { 1486 int err, arg; 1487 char zone_template[ZONENAME_MAX]; 1488 char attach_path[MAXPATHLEN]; 1489 zone_dochandle_t tmphandle; 1490 boolean_t force = B_FALSE; 1491 boolean_t attach = B_FALSE; 1492 boolean_t arg_err = B_FALSE; 1493 1494 assert(cmd != NULL); 1495 1496 /* This is the default if no arguments are given. */ 1497 (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template)); 1498 1499 optind = 0; 1500 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:")) 1501 != EOF) { 1502 switch (arg) { 1503 case '?': 1504 if (optopt == '?') 1505 longer_usage(CMD_CREATE); 1506 else 1507 short_usage(CMD_CREATE); 1508 arg_err = B_TRUE; 1509 break; 1510 case 'a': 1511 (void) strlcpy(attach_path, optarg, 1512 sizeof (attach_path)); 1513 attach = B_TRUE; 1514 break; 1515 case 'b': 1516 (void) strlcpy(zone_template, "SUNWblank", 1517 sizeof (zone_template)); 1518 break; 1519 case 'F': 1520 force = B_TRUE; 1521 break; 1522 case 't': 1523 (void) strlcpy(zone_template, optarg, 1524 sizeof (zone_template)); 1525 break; 1526 default: 1527 short_usage(CMD_CREATE); 1528 arg_err = B_TRUE; 1529 break; 1530 } 1531 } 1532 if (arg_err) 1533 return; 1534 1535 if (optind != cmd->cmd_argc) { 1536 short_usage(CMD_CREATE); 1537 return; 1538 } 1539 1540 if (zone_is_read_only(CMD_CREATE)) 1541 return; 1542 1543 if (check_if_zone_already_exists(force) != Z_OK) 1544 return; 1545 1546 /* 1547 * Get a temporary handle first. If that fails, the old handle 1548 * will not be lost. Then finish whichever one we don't need, 1549 * to avoid leaks. Then get the handle for zone_template, and 1550 * set the name to zone: this "copy, rename" method is how 1551 * create -[b|t] works. 1552 */ 1553 if ((tmphandle = zonecfg_init_handle()) == NULL) { 1554 zone_perror(execname, Z_NOMEM, B_TRUE); 1555 exit(Z_ERR); 1556 } 1557 1558 if (attach) 1559 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED, 1560 zone, B_FALSE, tmphandle); 1561 else 1562 err = zonecfg_get_template_handle(zone_template, zone, 1563 tmphandle); 1564 1565 if (err != Z_OK) { 1566 zonecfg_fini_handle(tmphandle); 1567 if (attach && err == Z_NO_ZONE) 1568 (void) fprintf(stderr, gettext("invalid path to " 1569 "detached zone\n")); 1570 else if (attach && err == Z_INVALID_DOCUMENT) 1571 (void) fprintf(stderr, gettext("Cannot attach to an " 1572 "earlier release of the operating system\n")); 1573 else 1574 zone_perror(zone_template, err, B_TRUE); 1575 return; 1576 } 1577 1578 need_to_commit = B_TRUE; 1579 zonecfg_fini_handle(handle); 1580 handle = tmphandle; 1581 got_handle = B_TRUE; 1582 } 1583 1584 /* 1585 * This malloc()'s memory, which must be freed by the caller. 1586 */ 1587 static char * 1588 quoteit(char *instr) 1589 { 1590 char *outstr; 1591 size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */ 1592 1593 if ((outstr = malloc(outstrsize)) == NULL) { 1594 zone_perror(zone, Z_NOMEM, B_FALSE); 1595 exit(Z_ERR); 1596 } 1597 if (strchr(instr, ' ') == NULL) { 1598 (void) strlcpy(outstr, instr, outstrsize); 1599 return (outstr); 1600 } 1601 (void) snprintf(outstr, outstrsize, "\"%s\"", instr); 1602 return (outstr); 1603 } 1604 1605 static void 1606 export_prop(FILE *of, int prop_num, char *prop_id) 1607 { 1608 char *quote_str; 1609 1610 if (strlen(prop_id) == 0) 1611 return; 1612 quote_str = quoteit(prop_id); 1613 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1614 pt_to_str(prop_num), quote_str); 1615 free(quote_str); 1616 } 1617 1618 void 1619 export_func(cmd_t *cmd) 1620 { 1621 struct zone_nwiftab nwiftab; 1622 struct zone_fstab fstab; 1623 struct zone_devtab devtab; 1624 struct zone_attrtab attrtab; 1625 struct zone_rctltab rctltab; 1626 struct zone_dstab dstab; 1627 struct zone_psettab psettab; 1628 struct zone_mcaptab mcaptab; 1629 struct zone_rctlvaltab *valptr; 1630 int err, arg; 1631 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN]; 1632 char bootargs[BOOTARGS_MAX]; 1633 char sched[MAXNAMELEN]; 1634 char brand[MAXNAMELEN]; 1635 char hostidp[HW_HOSTID_LEN]; 1636 char *limitpriv; 1637 FILE *of; 1638 boolean_t autoboot; 1639 zone_iptype_t iptype; 1640 boolean_t need_to_close = B_FALSE; 1641 boolean_t arg_err = B_FALSE; 1642 1643 assert(cmd != NULL); 1644 1645 outfile[0] = '\0'; 1646 optind = 0; 1647 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) { 1648 switch (arg) { 1649 case '?': 1650 if (optopt == '?') 1651 longer_usage(CMD_EXPORT); 1652 else 1653 short_usage(CMD_EXPORT); 1654 arg_err = B_TRUE; 1655 break; 1656 case 'f': 1657 (void) strlcpy(outfile, optarg, sizeof (outfile)); 1658 break; 1659 default: 1660 short_usage(CMD_EXPORT); 1661 arg_err = B_TRUE; 1662 break; 1663 } 1664 } 1665 if (arg_err) 1666 return; 1667 1668 if (optind != cmd->cmd_argc) { 1669 short_usage(CMD_EXPORT); 1670 return; 1671 } 1672 if (strlen(outfile) == 0) { 1673 of = stdout; 1674 } else { 1675 if ((of = fopen(outfile, "w")) == NULL) { 1676 zerr(gettext("opening file %s: %s"), 1677 outfile, strerror(errno)); 1678 goto done; 1679 } 1680 setbuf(of, NULL); 1681 need_to_close = B_TRUE; 1682 } 1683 1684 if ((err = initialize(B_TRUE)) != Z_OK) 1685 goto done; 1686 1687 (void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE)); 1688 1689 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK && 1690 strlen(zonepath) > 0) 1691 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1692 pt_to_str(PT_ZONEPATH), zonepath); 1693 1694 if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) && 1695 (strcmp(brand, NATIVE_BRAND_NAME) != 0)) 1696 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1697 pt_to_str(PT_BRAND), brand); 1698 1699 if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK) 1700 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1701 pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false"); 1702 1703 if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK && 1704 strlen(bootargs) > 0) { 1705 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1706 pt_to_str(PT_BOOTARGS), bootargs); 1707 } 1708 1709 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK && 1710 strlen(pool) > 0) 1711 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1712 pt_to_str(PT_POOL), pool); 1713 1714 if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK && 1715 strlen(limitpriv) > 0) { 1716 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1717 pt_to_str(PT_LIMITPRIV), limitpriv); 1718 free(limitpriv); 1719 } 1720 1721 if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK && 1722 strlen(sched) > 0) 1723 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1724 pt_to_str(PT_SCHED), sched); 1725 1726 if (zonecfg_get_iptype(handle, &iptype) == Z_OK) { 1727 switch (iptype) { 1728 case ZS_SHARED: 1729 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1730 pt_to_str(PT_IPTYPE), "shared"); 1731 break; 1732 case ZS_EXCLUSIVE: 1733 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1734 pt_to_str(PT_IPTYPE), "exclusive"); 1735 break; 1736 } 1737 } 1738 1739 if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) { 1740 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1741 pt_to_str(PT_HOSTID), hostidp); 1742 } 1743 1744 if ((err = zonecfg_setipdent(handle)) != Z_OK) { 1745 zone_perror(zone, err, B_FALSE); 1746 goto done; 1747 } 1748 while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 1749 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1750 rt_to_str(RT_IPD)); 1751 export_prop(of, PT_DIR, fstab.zone_fs_dir); 1752 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1753 } 1754 (void) zonecfg_endipdent(handle); 1755 1756 if ((err = zonecfg_setfsent(handle)) != Z_OK) { 1757 zone_perror(zone, err, B_FALSE); 1758 goto done; 1759 } 1760 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 1761 zone_fsopt_t *optptr; 1762 1763 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1764 rt_to_str(RT_FS)); 1765 export_prop(of, PT_DIR, fstab.zone_fs_dir); 1766 export_prop(of, PT_SPECIAL, fstab.zone_fs_special); 1767 export_prop(of, PT_RAW, fstab.zone_fs_raw); 1768 export_prop(of, PT_TYPE, fstab.zone_fs_type); 1769 for (optptr = fstab.zone_fs_options; optptr != NULL; 1770 optptr = optptr->zone_fsopt_next) { 1771 /* 1772 * Simple property values with embedded equal signs 1773 * need to be quoted to prevent the lexer from 1774 * mis-parsing them as complex name=value pairs. 1775 */ 1776 if (strchr(optptr->zone_fsopt_opt, '=')) 1777 (void) fprintf(of, "%s %s \"%s\"\n", 1778 cmd_to_str(CMD_ADD), 1779 pt_to_str(PT_OPTIONS), 1780 optptr->zone_fsopt_opt); 1781 else 1782 (void) fprintf(of, "%s %s %s\n", 1783 cmd_to_str(CMD_ADD), 1784 pt_to_str(PT_OPTIONS), 1785 optptr->zone_fsopt_opt); 1786 } 1787 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1788 zonecfg_free_fs_option_list(fstab.zone_fs_options); 1789 } 1790 (void) zonecfg_endfsent(handle); 1791 1792 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 1793 zone_perror(zone, err, B_FALSE); 1794 goto done; 1795 } 1796 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 1797 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1798 rt_to_str(RT_NET)); 1799 export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address); 1800 export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical); 1801 export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter); 1802 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1803 } 1804 (void) zonecfg_endnwifent(handle); 1805 1806 if ((err = zonecfg_setdevent(handle)) != Z_OK) { 1807 zone_perror(zone, err, B_FALSE); 1808 goto done; 1809 } 1810 while (zonecfg_getdevent(handle, &devtab) == Z_OK) { 1811 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1812 rt_to_str(RT_DEVICE)); 1813 export_prop(of, PT_MATCH, devtab.zone_dev_match); 1814 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1815 } 1816 (void) zonecfg_enddevent(handle); 1817 1818 if ((err = zonecfg_setrctlent(handle)) != Z_OK) { 1819 zone_perror(zone, err, B_FALSE); 1820 goto done; 1821 } 1822 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1823 (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD)); 1824 export_prop(of, PT_NAME, rctltab.zone_rctl_name); 1825 for (valptr = rctltab.zone_rctl_valptr; valptr != NULL; 1826 valptr = valptr->zone_rctlval_next) { 1827 fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n", 1828 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE), 1829 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv, 1830 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit, 1831 pt_to_str(PT_ACTION), valptr->zone_rctlval_action); 1832 } 1833 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1834 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1835 } 1836 (void) zonecfg_endrctlent(handle); 1837 1838 if ((err = zonecfg_setattrent(handle)) != Z_OK) { 1839 zone_perror(zone, err, B_FALSE); 1840 goto done; 1841 } 1842 while (zonecfg_getattrent(handle, &attrtab) == Z_OK) { 1843 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1844 rt_to_str(RT_ATTR)); 1845 export_prop(of, PT_NAME, attrtab.zone_attr_name); 1846 export_prop(of, PT_TYPE, attrtab.zone_attr_type); 1847 export_prop(of, PT_VALUE, attrtab.zone_attr_value); 1848 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1849 } 1850 (void) zonecfg_endattrent(handle); 1851 1852 if ((err = zonecfg_setdsent(handle)) != Z_OK) { 1853 zone_perror(zone, err, B_FALSE); 1854 goto done; 1855 } 1856 while (zonecfg_getdsent(handle, &dstab) == Z_OK) { 1857 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1858 rt_to_str(RT_DATASET)); 1859 export_prop(of, PT_NAME, dstab.zone_dataset_name); 1860 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1861 } 1862 (void) zonecfg_enddsent(handle); 1863 1864 if (zonecfg_getpsetent(handle, &psettab) == Z_OK) { 1865 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1866 rt_to_str(RT_DCPU)); 1867 if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0) 1868 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1869 pt_to_str(PT_NCPUS), psettab.zone_ncpu_max); 1870 else 1871 (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET), 1872 pt_to_str(PT_NCPUS), psettab.zone_ncpu_min, 1873 psettab.zone_ncpu_max); 1874 if (psettab.zone_importance[0] != '\0') 1875 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1876 pt_to_str(PT_IMPORTANCE), psettab.zone_importance); 1877 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1878 } 1879 1880 if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) { 1881 char buf[128]; 1882 1883 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1884 rt_to_str(RT_MCAP)); 1885 bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf)); 1886 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1887 pt_to_str(PT_PHYSICAL), buf); 1888 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1889 } 1890 1891 /* 1892 * There is nothing to export for pcap since this resource is just 1893 * a container for an rctl alias. 1894 */ 1895 1896 done: 1897 if (need_to_close) 1898 (void) fclose(of); 1899 } 1900 1901 void 1902 exit_func(cmd_t *cmd) 1903 { 1904 int arg, answer; 1905 boolean_t arg_err = B_FALSE; 1906 1907 optind = 0; 1908 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 1909 switch (arg) { 1910 case '?': 1911 longer_usage(CMD_EXIT); 1912 arg_err = B_TRUE; 1913 break; 1914 case 'F': 1915 force_exit = B_TRUE; 1916 break; 1917 default: 1918 short_usage(CMD_EXIT); 1919 arg_err = B_TRUE; 1920 break; 1921 } 1922 } 1923 if (arg_err) 1924 return; 1925 1926 if (optind < cmd->cmd_argc) { 1927 short_usage(CMD_EXIT); 1928 return; 1929 } 1930 1931 if (global_scope || force_exit) { 1932 time_to_exit = B_TRUE; 1933 return; 1934 } 1935 1936 answer = ask_yesno(B_FALSE, "Resource incomplete; really quit"); 1937 if (answer == -1) { 1938 zerr(gettext("Resource incomplete, input " 1939 "not from terminal and -F not specified:\n%s command " 1940 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT)); 1941 exit(Z_ERR); 1942 } else if (answer == 1) { 1943 time_to_exit = B_TRUE; 1944 } 1945 /* (answer == 0) => just return */ 1946 } 1947 1948 static int 1949 validate_zonepath_syntax(char *path) 1950 { 1951 if (path[0] != '/') { 1952 zerr(gettext("%s is not an absolute path."), path); 1953 return (Z_ERR); 1954 } 1955 if (strcmp(path, "/") == 0) { 1956 zerr(gettext("/ is not allowed as a %s."), 1957 pt_to_str(PT_ZONEPATH)); 1958 return (Z_ERR); 1959 } 1960 return (Z_OK); 1961 } 1962 1963 static void 1964 add_resource(cmd_t *cmd) 1965 { 1966 int type; 1967 struct zone_psettab tmp_psettab; 1968 struct zone_mcaptab tmp_mcaptab; 1969 uint64_t tmp; 1970 uint64_t tmp_mcap; 1971 char pool[MAXNAMELEN]; 1972 1973 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 1974 long_usage(CMD_ADD, B_TRUE); 1975 goto bad; 1976 } 1977 1978 switch (type) { 1979 case RT_FS: 1980 bzero(&in_progress_fstab, sizeof (in_progress_fstab)); 1981 return; 1982 case RT_IPD: 1983 if (state_atleast(ZONE_STATE_INSTALLED)) { 1984 zerr(gettext("Zone %s already installed; %s %s not " 1985 "allowed."), zone, cmd_to_str(CMD_ADD), 1986 rt_to_str(RT_IPD)); 1987 goto bad; 1988 } 1989 bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab)); 1990 return; 1991 case RT_NET: 1992 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab)); 1993 return; 1994 case RT_DEVICE: 1995 bzero(&in_progress_devtab, sizeof (in_progress_devtab)); 1996 return; 1997 case RT_RCTL: 1998 if (global_zone) 1999 zerr(gettext("WARNING: Setting a global zone resource " 2000 "control too low could deny\nservice " 2001 "to even the root user; " 2002 "this could render the system impossible\n" 2003 "to administer. Please use caution.")); 2004 bzero(&in_progress_rctltab, sizeof (in_progress_rctltab)); 2005 return; 2006 case RT_ATTR: 2007 bzero(&in_progress_attrtab, sizeof (in_progress_attrtab)); 2008 return; 2009 case RT_DATASET: 2010 bzero(&in_progress_dstab, sizeof (in_progress_dstab)); 2011 return; 2012 case RT_DCPU: 2013 /* Make sure there isn't already a cpu-set or cpu-cap entry. */ 2014 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) { 2015 zerr(gettext("The %s resource already exists."), 2016 rt_to_str(RT_DCPU)); 2017 goto bad; 2018 } 2019 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != 2020 Z_NO_ENTRY) { 2021 zerr(gettext("The %s resource already exists."), 2022 rt_to_str(RT_PCAP)); 2023 goto bad; 2024 } 2025 2026 /* Make sure the pool property isn't set. */ 2027 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK && 2028 strlen(pool) > 0) { 2029 zerr(gettext("The %s property is already set. " 2030 "A persistent pool is incompatible with\nthe %s " 2031 "resource."), 2032 pt_to_str(PT_POOL), rt_to_str(RT_DCPU)); 2033 goto bad; 2034 } 2035 2036 bzero(&in_progress_psettab, sizeof (in_progress_psettab)); 2037 return; 2038 case RT_PCAP: 2039 /* 2040 * Make sure there isn't already a cpu-set or incompatible 2041 * cpu-cap rctls. 2042 */ 2043 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) { 2044 zerr(gettext("The %s resource already exists."), 2045 rt_to_str(RT_DCPU)); 2046 goto bad; 2047 } 2048 2049 switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) { 2050 case Z_ALIAS_DISALLOW: 2051 zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW, 2052 B_FALSE); 2053 goto bad; 2054 2055 case Z_OK: 2056 zerr(gettext("The %s resource already exists."), 2057 rt_to_str(RT_PCAP)); 2058 goto bad; 2059 2060 default: 2061 break; 2062 } 2063 return; 2064 case RT_MCAP: 2065 /* 2066 * Make sure there isn't already a mem-cap entry or max-swap 2067 * or max-locked rctl. 2068 */ 2069 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK || 2070 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap) 2071 == Z_OK || 2072 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, 2073 &tmp_mcap) == Z_OK) { 2074 zerr(gettext("The %s resource or a related resource " 2075 "control already exists."), rt_to_str(RT_MCAP)); 2076 goto bad; 2077 } 2078 if (global_zone) 2079 zerr(gettext("WARNING: Setting a global zone memory " 2080 "cap too low could deny\nservice " 2081 "to even the root user; " 2082 "this could render the system impossible\n" 2083 "to administer. Please use caution.")); 2084 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab)); 2085 return; 2086 default: 2087 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE); 2088 long_usage(CMD_ADD, B_TRUE); 2089 usage(B_FALSE, HELP_RESOURCES); 2090 } 2091 bad: 2092 global_scope = B_TRUE; 2093 end_op = -1; 2094 } 2095 2096 static void 2097 do_complex_rctl_val(complex_property_ptr_t cp) 2098 { 2099 struct zone_rctlvaltab *rctlvaltab; 2100 complex_property_ptr_t cx; 2101 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE, 2102 seen_action = B_FALSE; 2103 rctlblk_t *rctlblk; 2104 int err; 2105 2106 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) { 2107 zone_perror(zone, Z_NOMEM, B_TRUE); 2108 exit(Z_ERR); 2109 } 2110 for (cx = cp; cx != NULL; cx = cx->cp_next) { 2111 switch (cx->cp_type) { 2112 case PT_PRIV: 2113 if (seen_priv) { 2114 zerr(gettext("%s already specified"), 2115 pt_to_str(PT_PRIV)); 2116 goto bad; 2117 } 2118 (void) strlcpy(rctlvaltab->zone_rctlval_priv, 2119 cx->cp_value, 2120 sizeof (rctlvaltab->zone_rctlval_priv)); 2121 seen_priv = B_TRUE; 2122 break; 2123 case PT_LIMIT: 2124 if (seen_limit) { 2125 zerr(gettext("%s already specified"), 2126 pt_to_str(PT_LIMIT)); 2127 goto bad; 2128 } 2129 (void) strlcpy(rctlvaltab->zone_rctlval_limit, 2130 cx->cp_value, 2131 sizeof (rctlvaltab->zone_rctlval_limit)); 2132 seen_limit = B_TRUE; 2133 break; 2134 case PT_ACTION: 2135 if (seen_action) { 2136 zerr(gettext("%s already specified"), 2137 pt_to_str(PT_ACTION)); 2138 goto bad; 2139 } 2140 (void) strlcpy(rctlvaltab->zone_rctlval_action, 2141 cx->cp_value, 2142 sizeof (rctlvaltab->zone_rctlval_action)); 2143 seen_action = B_TRUE; 2144 break; 2145 default: 2146 zone_perror(pt_to_str(PT_VALUE), 2147 Z_NO_PROPERTY_TYPE, B_TRUE); 2148 long_usage(CMD_ADD, B_TRUE); 2149 usage(B_FALSE, HELP_PROPS); 2150 zonecfg_free_rctl_value_list(rctlvaltab); 2151 return; 2152 } 2153 } 2154 if (!seen_priv) 2155 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV)); 2156 if (!seen_limit) 2157 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT)); 2158 if (!seen_action) 2159 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION)); 2160 if (!seen_priv || !seen_limit || !seen_action) 2161 goto bad; 2162 rctlvaltab->zone_rctlval_next = NULL; 2163 rctlblk = alloca(rctlblk_size()); 2164 /* 2165 * Make sure the rctl value looks roughly correct; we won't know if 2166 * it's truly OK until we verify the configuration on the target 2167 * system. 2168 */ 2169 if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK || 2170 !zonecfg_valid_rctlblk(rctlblk)) { 2171 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL), 2172 pt_to_str(PT_VALUE)); 2173 goto bad; 2174 } 2175 err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab); 2176 if (err != Z_OK) 2177 zone_perror(pt_to_str(PT_VALUE), err, B_TRUE); 2178 return; 2179 2180 bad: 2181 zonecfg_free_rctl_value_list(rctlvaltab); 2182 } 2183 2184 static void 2185 add_property(cmd_t *cmd) 2186 { 2187 char *prop_id; 2188 int err, res_type, prop_type; 2189 property_value_ptr_t pp; 2190 list_property_ptr_t l; 2191 2192 res_type = resource_scope; 2193 prop_type = cmd->cmd_prop_name[0]; 2194 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) { 2195 long_usage(CMD_ADD, B_TRUE); 2196 return; 2197 } 2198 2199 if (cmd->cmd_prop_nv_pairs != 1) { 2200 long_usage(CMD_ADD, B_TRUE); 2201 return; 2202 } 2203 2204 if (initialize(B_TRUE) != Z_OK) 2205 return; 2206 2207 switch (res_type) { 2208 case RT_FS: 2209 if (prop_type != PT_OPTIONS) { 2210 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2211 B_TRUE); 2212 long_usage(CMD_ADD, B_TRUE); 2213 usage(B_FALSE, HELP_PROPS); 2214 return; 2215 } 2216 pp = cmd->cmd_property_ptr[0]; 2217 if (pp->pv_type != PROP_VAL_SIMPLE && 2218 pp->pv_type != PROP_VAL_LIST) { 2219 zerr(gettext("A %s or %s value was expected here."), 2220 pvt_to_str(PROP_VAL_SIMPLE), 2221 pvt_to_str(PROP_VAL_LIST)); 2222 saw_error = B_TRUE; 2223 return; 2224 } 2225 if (pp->pv_type == PROP_VAL_SIMPLE) { 2226 if (pp->pv_simple == NULL) { 2227 long_usage(CMD_ADD, B_TRUE); 2228 return; 2229 } 2230 prop_id = pp->pv_simple; 2231 err = zonecfg_add_fs_option(&in_progress_fstab, 2232 prop_id); 2233 if (err != Z_OK) 2234 zone_perror(pt_to_str(prop_type), err, B_TRUE); 2235 } else { 2236 list_property_ptr_t list; 2237 2238 for (list = pp->pv_list; list != NULL; 2239 list = list->lp_next) { 2240 prop_id = list->lp_simple; 2241 if (prop_id == NULL) 2242 break; 2243 err = zonecfg_add_fs_option( 2244 &in_progress_fstab, prop_id); 2245 if (err != Z_OK) 2246 zone_perror(pt_to_str(prop_type), err, 2247 B_TRUE); 2248 } 2249 } 2250 return; 2251 case RT_RCTL: 2252 if (prop_type != PT_VALUE) { 2253 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2254 B_TRUE); 2255 long_usage(CMD_ADD, B_TRUE); 2256 usage(B_FALSE, HELP_PROPS); 2257 return; 2258 } 2259 pp = cmd->cmd_property_ptr[0]; 2260 if (pp->pv_type != PROP_VAL_COMPLEX && 2261 pp->pv_type != PROP_VAL_LIST) { 2262 zerr(gettext("A %s or %s value was expected here."), 2263 pvt_to_str(PROP_VAL_COMPLEX), 2264 pvt_to_str(PROP_VAL_LIST)); 2265 saw_error = B_TRUE; 2266 return; 2267 } 2268 if (pp->pv_type == PROP_VAL_COMPLEX) { 2269 do_complex_rctl_val(pp->pv_complex); 2270 return; 2271 } 2272 for (l = pp->pv_list; l != NULL; l = l->lp_next) 2273 do_complex_rctl_val(l->lp_complex); 2274 return; 2275 default: 2276 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE); 2277 long_usage(CMD_ADD, B_TRUE); 2278 usage(B_FALSE, HELP_RESOURCES); 2279 return; 2280 } 2281 } 2282 2283 static boolean_t 2284 gz_invalid_resource(int type) 2285 { 2286 return (global_zone && (type == RT_FS || type == RT_IPD || 2287 type == RT_NET || type == RT_DEVICE || type == RT_ATTR || 2288 type == RT_DATASET)); 2289 } 2290 2291 static boolean_t 2292 gz_invalid_rt_property(int type) 2293 { 2294 return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH || 2295 type == RT_AUTOBOOT || type == RT_LIMITPRIV || 2296 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED || 2297 type == RT_IPTYPE || type == RT_HOSTID)); 2298 } 2299 2300 static boolean_t 2301 gz_invalid_property(int type) 2302 { 2303 return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH || 2304 type == PT_AUTOBOOT || type == PT_LIMITPRIV || 2305 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED || 2306 type == PT_IPTYPE || type == PT_HOSTID)); 2307 } 2308 2309 void 2310 add_func(cmd_t *cmd) 2311 { 2312 int arg; 2313 boolean_t arg_err = B_FALSE; 2314 2315 assert(cmd != NULL); 2316 2317 optind = 0; 2318 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 2319 switch (arg) { 2320 case '?': 2321 longer_usage(CMD_ADD); 2322 arg_err = B_TRUE; 2323 break; 2324 default: 2325 short_usage(CMD_ADD); 2326 arg_err = B_TRUE; 2327 break; 2328 } 2329 } 2330 if (arg_err) 2331 return; 2332 2333 if (optind != cmd->cmd_argc) { 2334 short_usage(CMD_ADD); 2335 return; 2336 } 2337 2338 if (zone_is_read_only(CMD_ADD)) 2339 return; 2340 2341 if (initialize(B_TRUE) != Z_OK) 2342 return; 2343 if (global_scope) { 2344 if (gz_invalid_resource(cmd->cmd_res_type)) { 2345 zerr(gettext("Cannot add a %s resource to the " 2346 "global zone."), rt_to_str(cmd->cmd_res_type)); 2347 saw_error = B_TRUE; 2348 return; 2349 } 2350 2351 global_scope = B_FALSE; 2352 resource_scope = cmd->cmd_res_type; 2353 end_op = CMD_ADD; 2354 add_resource(cmd); 2355 } else 2356 add_property(cmd); 2357 } 2358 2359 /* 2360 * This routine has an unusual implementation, because it tries very 2361 * hard to succeed in the face of a variety of failure modes. 2362 * The most common and most vexing occurs when the index file and 2363 * the /etc/zones/<zonename.xml> file are not both present. In 2364 * this case, delete must eradicate as much of the zone state as is left 2365 * so that the user can later create a new zone with the same name. 2366 */ 2367 void 2368 delete_func(cmd_t *cmd) 2369 { 2370 int err, arg, answer; 2371 char line[ZONENAME_MAX + 128]; /* enough to ask a question */ 2372 boolean_t force = B_FALSE; 2373 boolean_t arg_err = B_FALSE; 2374 2375 optind = 0; 2376 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 2377 switch (arg) { 2378 case '?': 2379 longer_usage(CMD_DELETE); 2380 arg_err = B_TRUE; 2381 break; 2382 case 'F': 2383 force = B_TRUE; 2384 break; 2385 default: 2386 short_usage(CMD_DELETE); 2387 arg_err = B_TRUE; 2388 break; 2389 } 2390 } 2391 if (arg_err) 2392 return; 2393 2394 if (optind != cmd->cmd_argc) { 2395 short_usage(CMD_DELETE); 2396 return; 2397 } 2398 2399 if (zone_is_read_only(CMD_DELETE)) 2400 return; 2401 2402 if (!force) { 2403 /* 2404 * Initialize sets up the global called "handle" and warns the 2405 * user if the zone is not configured. In force mode, we don't 2406 * trust that evaluation, and hence skip it. (We don't need the 2407 * handle to be loaded anyway, since zonecfg_destroy is done by 2408 * zonename). However, we also have to take care to emulate the 2409 * messages spit out by initialize; see below. 2410 */ 2411 if (initialize(B_TRUE) != Z_OK) 2412 return; 2413 2414 (void) snprintf(line, sizeof (line), 2415 gettext("Are you sure you want to delete zone %s"), zone); 2416 if ((answer = ask_yesno(B_FALSE, line)) == -1) { 2417 zerr(gettext("Input not from terminal and -F not " 2418 "specified:\n%s command ignored, exiting."), 2419 cmd_to_str(CMD_DELETE)); 2420 exit(Z_ERR); 2421 } 2422 if (answer != 1) 2423 return; 2424 } 2425 2426 if ((err = zonecfg_destroy(zone, force)) != Z_OK) { 2427 if ((err == Z_BAD_ZONE_STATE) && !force) { 2428 zerr(gettext("Zone %s not in %s state; %s not " 2429 "allowed. Use -F to force %s."), 2430 zone, zone_state_str(ZONE_STATE_CONFIGURED), 2431 cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE)); 2432 } else { 2433 zone_perror(zone, err, B_TRUE); 2434 } 2435 } 2436 need_to_commit = B_FALSE; 2437 2438 /* 2439 * Emulate initialize's messaging; if there wasn't a valid handle to 2440 * begin with, then user had typed delete (or delete -F) multiple 2441 * times. So we emit a message. 2442 * 2443 * We only do this in the 'force' case because normally, initialize() 2444 * takes care of this for us. 2445 */ 2446 if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode) 2447 (void) printf(gettext("Use '%s' to begin " 2448 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE)); 2449 2450 /* 2451 * Time for a new handle: finish the old one off first 2452 * then get a new one properly to avoid leaks. 2453 */ 2454 if (got_handle) { 2455 zonecfg_fini_handle(handle); 2456 if ((handle = zonecfg_init_handle()) == NULL) { 2457 zone_perror(execname, Z_NOMEM, B_TRUE); 2458 exit(Z_ERR); 2459 } 2460 if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) { 2461 /* If there was no zone before, that's OK */ 2462 if (err != Z_NO_ZONE) 2463 zone_perror(zone, err, B_TRUE); 2464 got_handle = B_FALSE; 2465 } 2466 } 2467 } 2468 2469 static int 2470 fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only) 2471 { 2472 int err, i; 2473 property_value_ptr_t pp; 2474 2475 if ((err = initialize(B_TRUE)) != Z_OK) 2476 return (err); 2477 2478 bzero(fstab, sizeof (*fstab)); 2479 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2480 pp = cmd->cmd_property_ptr[i]; 2481 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2482 zerr(gettext("A simple value was expected here.")); 2483 saw_error = B_TRUE; 2484 return (Z_INSUFFICIENT_SPEC); 2485 } 2486 switch (cmd->cmd_prop_name[i]) { 2487 case PT_DIR: 2488 (void) strlcpy(fstab->zone_fs_dir, pp->pv_simple, 2489 sizeof (fstab->zone_fs_dir)); 2490 break; 2491 case PT_SPECIAL: 2492 (void) strlcpy(fstab->zone_fs_special, pp->pv_simple, 2493 sizeof (fstab->zone_fs_special)); 2494 break; 2495 case PT_RAW: 2496 (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple, 2497 sizeof (fstab->zone_fs_raw)); 2498 break; 2499 case PT_TYPE: 2500 (void) strlcpy(fstab->zone_fs_type, pp->pv_simple, 2501 sizeof (fstab->zone_fs_type)); 2502 break; 2503 default: 2504 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2505 Z_NO_PROPERTY_TYPE, B_TRUE); 2506 return (Z_INSUFFICIENT_SPEC); 2507 } 2508 } 2509 if (fill_in_only) 2510 return (Z_OK); 2511 return (zonecfg_lookup_filesystem(handle, fstab)); 2512 } 2513 2514 static int 2515 fill_in_ipdtab(cmd_t *cmd, struct zone_fstab *ipdtab, boolean_t fill_in_only) 2516 { 2517 int err, i; 2518 property_value_ptr_t pp; 2519 2520 if ((err = initialize(B_TRUE)) != Z_OK) 2521 return (err); 2522 2523 bzero(ipdtab, sizeof (*ipdtab)); 2524 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2525 pp = cmd->cmd_property_ptr[i]; 2526 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2527 zerr(gettext("A simple value was expected here.")); 2528 saw_error = B_TRUE; 2529 return (Z_INSUFFICIENT_SPEC); 2530 } 2531 switch (cmd->cmd_prop_name[i]) { 2532 case PT_DIR: 2533 (void) strlcpy(ipdtab->zone_fs_dir, pp->pv_simple, 2534 sizeof (ipdtab->zone_fs_dir)); 2535 break; 2536 default: 2537 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2538 Z_NO_PROPERTY_TYPE, B_TRUE); 2539 return (Z_INSUFFICIENT_SPEC); 2540 } 2541 } 2542 if (fill_in_only) 2543 return (Z_OK); 2544 return (zonecfg_lookup_ipd(handle, ipdtab)); 2545 } 2546 2547 static int 2548 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, 2549 boolean_t fill_in_only) 2550 { 2551 int err, i; 2552 property_value_ptr_t pp; 2553 2554 if ((err = initialize(B_TRUE)) != Z_OK) 2555 return (err); 2556 2557 bzero(nwiftab, sizeof (*nwiftab)); 2558 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2559 pp = cmd->cmd_property_ptr[i]; 2560 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2561 zerr(gettext("A simple value was expected here.")); 2562 saw_error = B_TRUE; 2563 return (Z_INSUFFICIENT_SPEC); 2564 } 2565 switch (cmd->cmd_prop_name[i]) { 2566 case PT_ADDRESS: 2567 (void) strlcpy(nwiftab->zone_nwif_address, 2568 pp->pv_simple, sizeof (nwiftab->zone_nwif_address)); 2569 break; 2570 case PT_PHYSICAL: 2571 (void) strlcpy(nwiftab->zone_nwif_physical, 2572 pp->pv_simple, 2573 sizeof (nwiftab->zone_nwif_physical)); 2574 break; 2575 case PT_DEFROUTER: 2576 (void) strlcpy(nwiftab->zone_nwif_defrouter, 2577 pp->pv_simple, 2578 sizeof (nwiftab->zone_nwif_defrouter)); 2579 break; 2580 default: 2581 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2582 Z_NO_PROPERTY_TYPE, B_TRUE); 2583 return (Z_INSUFFICIENT_SPEC); 2584 } 2585 } 2586 if (fill_in_only) 2587 return (Z_OK); 2588 err = zonecfg_lookup_nwif(handle, nwiftab); 2589 return (err); 2590 } 2591 2592 static int 2593 fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only) 2594 { 2595 int err, i; 2596 property_value_ptr_t pp; 2597 2598 if ((err = initialize(B_TRUE)) != Z_OK) 2599 return (err); 2600 2601 bzero(devtab, sizeof (*devtab)); 2602 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2603 pp = cmd->cmd_property_ptr[i]; 2604 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2605 zerr(gettext("A simple value was expected here.")); 2606 saw_error = B_TRUE; 2607 return (Z_INSUFFICIENT_SPEC); 2608 } 2609 switch (cmd->cmd_prop_name[i]) { 2610 case PT_MATCH: 2611 (void) strlcpy(devtab->zone_dev_match, pp->pv_simple, 2612 sizeof (devtab->zone_dev_match)); 2613 break; 2614 default: 2615 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2616 Z_NO_PROPERTY_TYPE, B_TRUE); 2617 return (Z_INSUFFICIENT_SPEC); 2618 } 2619 } 2620 if (fill_in_only) 2621 return (Z_OK); 2622 err = zonecfg_lookup_dev(handle, devtab); 2623 return (err); 2624 } 2625 2626 static int 2627 fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab, 2628 boolean_t fill_in_only) 2629 { 2630 int err, i; 2631 property_value_ptr_t pp; 2632 2633 if ((err = initialize(B_TRUE)) != Z_OK) 2634 return (err); 2635 2636 bzero(rctltab, sizeof (*rctltab)); 2637 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2638 pp = cmd->cmd_property_ptr[i]; 2639 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2640 zerr(gettext("A simple value was expected here.")); 2641 saw_error = B_TRUE; 2642 return (Z_INSUFFICIENT_SPEC); 2643 } 2644 switch (cmd->cmd_prop_name[i]) { 2645 case PT_NAME: 2646 (void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple, 2647 sizeof (rctltab->zone_rctl_name)); 2648 break; 2649 default: 2650 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2651 Z_NO_PROPERTY_TYPE, B_TRUE); 2652 return (Z_INSUFFICIENT_SPEC); 2653 } 2654 } 2655 if (fill_in_only) 2656 return (Z_OK); 2657 err = zonecfg_lookup_rctl(handle, rctltab); 2658 return (err); 2659 } 2660 2661 static int 2662 fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab, 2663 boolean_t fill_in_only) 2664 { 2665 int err, i; 2666 property_value_ptr_t pp; 2667 2668 if ((err = initialize(B_TRUE)) != Z_OK) 2669 return (err); 2670 2671 bzero(attrtab, sizeof (*attrtab)); 2672 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2673 pp = cmd->cmd_property_ptr[i]; 2674 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2675 zerr(gettext("A simple value was expected here.")); 2676 saw_error = B_TRUE; 2677 return (Z_INSUFFICIENT_SPEC); 2678 } 2679 switch (cmd->cmd_prop_name[i]) { 2680 case PT_NAME: 2681 (void) strlcpy(attrtab->zone_attr_name, pp->pv_simple, 2682 sizeof (attrtab->zone_attr_name)); 2683 break; 2684 case PT_TYPE: 2685 (void) strlcpy(attrtab->zone_attr_type, pp->pv_simple, 2686 sizeof (attrtab->zone_attr_type)); 2687 break; 2688 case PT_VALUE: 2689 (void) strlcpy(attrtab->zone_attr_value, pp->pv_simple, 2690 sizeof (attrtab->zone_attr_value)); 2691 break; 2692 default: 2693 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2694 Z_NO_PROPERTY_TYPE, B_TRUE); 2695 return (Z_INSUFFICIENT_SPEC); 2696 } 2697 } 2698 if (fill_in_only) 2699 return (Z_OK); 2700 err = zonecfg_lookup_attr(handle, attrtab); 2701 return (err); 2702 } 2703 2704 static int 2705 fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only) 2706 { 2707 int err, i; 2708 property_value_ptr_t pp; 2709 2710 if ((err = initialize(B_TRUE)) != Z_OK) 2711 return (err); 2712 2713 dstab->zone_dataset_name[0] = '\0'; 2714 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2715 pp = cmd->cmd_property_ptr[i]; 2716 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2717 zerr(gettext("A simple value was expected here.")); 2718 saw_error = B_TRUE; 2719 return (Z_INSUFFICIENT_SPEC); 2720 } 2721 switch (cmd->cmd_prop_name[i]) { 2722 case PT_NAME: 2723 (void) strlcpy(dstab->zone_dataset_name, pp->pv_simple, 2724 sizeof (dstab->zone_dataset_name)); 2725 break; 2726 default: 2727 zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2728 Z_NO_PROPERTY_TYPE, B_TRUE); 2729 return (Z_INSUFFICIENT_SPEC); 2730 } 2731 } 2732 if (fill_in_only) 2733 return (Z_OK); 2734 return (zonecfg_lookup_ds(handle, dstab)); 2735 } 2736 2737 static void 2738 remove_aliased_rctl(int type, char *name) 2739 { 2740 int err; 2741 uint64_t tmp; 2742 2743 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) { 2744 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type), 2745 zonecfg_strerror(err)); 2746 saw_error = B_TRUE; 2747 return; 2748 } 2749 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) { 2750 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type), 2751 zonecfg_strerror(err)); 2752 saw_error = B_TRUE; 2753 } else { 2754 need_to_commit = B_TRUE; 2755 } 2756 } 2757 2758 static boolean_t 2759 prompt_remove_resource(cmd_t *cmd, char *rsrc) 2760 { 2761 int num; 2762 int answer; 2763 int arg; 2764 boolean_t force = B_FALSE; 2765 char prompt[128]; 2766 boolean_t arg_err = B_FALSE; 2767 2768 optind = 0; 2769 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) { 2770 switch (arg) { 2771 case 'F': 2772 force = B_TRUE; 2773 break; 2774 default: 2775 arg_err = B_TRUE; 2776 break; 2777 } 2778 } 2779 if (arg_err) 2780 return (B_FALSE); 2781 2782 2783 num = zonecfg_num_resources(handle, rsrc); 2784 2785 if (num == 0) { 2786 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY, 2787 B_TRUE); 2788 return (B_FALSE); 2789 } 2790 if (num > 1 && !force) { 2791 if (!interactive_mode) { 2792 zerr(gettext("There are multiple instances of this " 2793 "resource. Either qualify the resource to\n" 2794 "remove a single instance or use the -F option to " 2795 "remove all instances.")); 2796 saw_error = B_TRUE; 2797 return (B_FALSE); 2798 } 2799 (void) snprintf(prompt, sizeof (prompt), gettext( 2800 "Are you sure you want to remove ALL '%s' resources"), 2801 rsrc); 2802 answer = ask_yesno(B_FALSE, prompt); 2803 if (answer == -1) { 2804 zerr(gettext("Resource incomplete.")); 2805 return (B_FALSE); 2806 } 2807 if (answer != 1) 2808 return (B_FALSE); 2809 } 2810 return (B_TRUE); 2811 } 2812 2813 static void 2814 remove_fs(cmd_t *cmd) 2815 { 2816 int err; 2817 2818 /* traditional, qualified fs removal */ 2819 if (cmd->cmd_prop_nv_pairs > 0) { 2820 struct zone_fstab fstab; 2821 2822 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) { 2823 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); 2824 return; 2825 } 2826 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) 2827 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); 2828 else 2829 need_to_commit = B_TRUE; 2830 zonecfg_free_fs_option_list(fstab.zone_fs_options); 2831 return; 2832 } 2833 2834 /* 2835 * unqualified fs removal. remove all fs's but prompt if more 2836 * than one. 2837 */ 2838 if (!prompt_remove_resource(cmd, "fs")) 2839 return; 2840 2841 if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK) 2842 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE); 2843 else 2844 need_to_commit = B_TRUE; 2845 } 2846 2847 static void 2848 remove_ipd(cmd_t *cmd) 2849 { 2850 int err; 2851 2852 if (state_atleast(ZONE_STATE_INSTALLED)) { 2853 zerr(gettext("Zone %s already installed; %s %s not allowed."), 2854 zone, cmd_to_str(CMD_REMOVE), rt_to_str(RT_IPD)); 2855 return; 2856 } 2857 2858 /* traditional, qualified ipd removal */ 2859 if (cmd->cmd_prop_nv_pairs > 0) { 2860 struct zone_fstab fstab; 2861 2862 if ((err = fill_in_ipdtab(cmd, &fstab, B_FALSE)) != Z_OK) { 2863 z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE); 2864 return; 2865 } 2866 if ((err = zonecfg_delete_ipd(handle, &fstab)) != Z_OK) 2867 z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE); 2868 else 2869 need_to_commit = B_TRUE; 2870 return; 2871 } 2872 2873 /* 2874 * unqualified ipd removal. remove all ipds but prompt if more 2875 * than one. 2876 */ 2877 if (!prompt_remove_resource(cmd, "inherit-pkg-dir")) 2878 return; 2879 2880 if ((err = zonecfg_del_all_resources(handle, "inherit-pkg-dir")) 2881 != Z_OK) 2882 z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE); 2883 else 2884 need_to_commit = B_TRUE; 2885 } 2886 2887 static void 2888 remove_net(cmd_t *cmd) 2889 { 2890 int err; 2891 2892 /* traditional, qualified net removal */ 2893 if (cmd->cmd_prop_nv_pairs > 0) { 2894 struct zone_nwiftab nwiftab; 2895 2896 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) { 2897 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE); 2898 return; 2899 } 2900 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) 2901 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE); 2902 else 2903 need_to_commit = B_TRUE; 2904 return; 2905 } 2906 2907 /* 2908 * unqualified net removal. remove all nets but prompt if more 2909 * than one. 2910 */ 2911 if (!prompt_remove_resource(cmd, "net")) 2912 return; 2913 2914 if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK) 2915 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE); 2916 else 2917 need_to_commit = B_TRUE; 2918 } 2919 2920 static void 2921 remove_device(cmd_t *cmd) 2922 { 2923 int err; 2924 2925 /* traditional, qualified device removal */ 2926 if (cmd->cmd_prop_nv_pairs > 0) { 2927 struct zone_devtab devtab; 2928 2929 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) { 2930 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE); 2931 return; 2932 } 2933 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) 2934 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE); 2935 else 2936 need_to_commit = B_TRUE; 2937 return; 2938 } 2939 2940 /* 2941 * unqualified device removal. remove all devices but prompt if more 2942 * than one. 2943 */ 2944 if (!prompt_remove_resource(cmd, "device")) 2945 return; 2946 2947 if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK) 2948 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE); 2949 else 2950 need_to_commit = B_TRUE; 2951 } 2952 2953 static void 2954 remove_attr(cmd_t *cmd) 2955 { 2956 int err; 2957 2958 /* traditional, qualified attr removal */ 2959 if (cmd->cmd_prop_nv_pairs > 0) { 2960 struct zone_attrtab attrtab; 2961 2962 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) { 2963 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE); 2964 return; 2965 } 2966 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) 2967 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE); 2968 else 2969 need_to_commit = B_TRUE; 2970 return; 2971 } 2972 2973 /* 2974 * unqualified attr removal. remove all attrs but prompt if more 2975 * than one. 2976 */ 2977 if (!prompt_remove_resource(cmd, "attr")) 2978 return; 2979 2980 if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK) 2981 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE); 2982 else 2983 need_to_commit = B_TRUE; 2984 } 2985 2986 static void 2987 remove_dataset(cmd_t *cmd) 2988 { 2989 int err; 2990 2991 /* traditional, qualified dataset removal */ 2992 if (cmd->cmd_prop_nv_pairs > 0) { 2993 struct zone_dstab dstab; 2994 2995 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) { 2996 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE); 2997 return; 2998 } 2999 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK) 3000 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE); 3001 else 3002 need_to_commit = B_TRUE; 3003 return; 3004 } 3005 3006 /* 3007 * unqualified dataset removal. remove all datasets but prompt if more 3008 * than one. 3009 */ 3010 if (!prompt_remove_resource(cmd, "dataset")) 3011 return; 3012 3013 if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK) 3014 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE); 3015 else 3016 need_to_commit = B_TRUE; 3017 } 3018 3019 static void 3020 remove_rctl(cmd_t *cmd) 3021 { 3022 int err; 3023 3024 /* traditional, qualified rctl removal */ 3025 if (cmd->cmd_prop_nv_pairs > 0) { 3026 struct zone_rctltab rctltab; 3027 3028 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) { 3029 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE); 3030 return; 3031 } 3032 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) 3033 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE); 3034 else 3035 need_to_commit = B_TRUE; 3036 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 3037 return; 3038 } 3039 3040 /* 3041 * unqualified rctl removal. remove all rctls but prompt if more 3042 * than one. 3043 */ 3044 if (!prompt_remove_resource(cmd, "rctl")) 3045 return; 3046 3047 if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK) 3048 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE); 3049 else 3050 need_to_commit = B_TRUE; 3051 } 3052 3053 static void 3054 remove_pset() 3055 { 3056 int err; 3057 struct zone_psettab psettab; 3058 3059 if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) { 3060 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); 3061 return; 3062 } 3063 if ((err = zonecfg_delete_pset(handle)) != Z_OK) 3064 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE); 3065 else 3066 need_to_commit = B_TRUE; 3067 } 3068 3069 static void 3070 remove_pcap() 3071 { 3072 int err; 3073 uint64_t tmp; 3074 3075 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) { 3076 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP), 3077 zonecfg_strerror(Z_NO_RESOURCE_TYPE)); 3078 saw_error = B_TRUE; 3079 return; 3080 } 3081 3082 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK) 3083 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE); 3084 else 3085 need_to_commit = B_TRUE; 3086 } 3087 3088 static void 3089 remove_mcap() 3090 { 3091 int err, res1, res2, res3; 3092 uint64_t tmp; 3093 struct zone_mcaptab mcaptab; 3094 boolean_t revert = B_FALSE; 3095 3096 res1 = zonecfg_lookup_mcap(handle, &mcaptab); 3097 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp); 3098 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp); 3099 3100 /* if none of these exist, there is no resource to remove */ 3101 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) { 3102 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP), 3103 zonecfg_strerror(Z_NO_RESOURCE_TYPE)); 3104 saw_error = B_TRUE; 3105 return; 3106 } 3107 if (res1 == Z_OK) { 3108 if ((err = zonecfg_delete_mcap(handle)) != Z_OK) { 3109 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); 3110 revert = B_TRUE; 3111 } else { 3112 need_to_commit = B_TRUE; 3113 } 3114 } 3115 if (res2 == Z_OK) { 3116 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP)) 3117 != Z_OK) { 3118 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); 3119 revert = B_TRUE; 3120 } else { 3121 need_to_commit = B_TRUE; 3122 } 3123 } 3124 if (res3 == Z_OK) { 3125 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM)) 3126 != Z_OK) { 3127 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE); 3128 revert = B_TRUE; 3129 } else { 3130 need_to_commit = B_TRUE; 3131 } 3132 } 3133 3134 if (revert) 3135 need_to_commit = B_FALSE; 3136 } 3137 3138 static void 3139 remove_resource(cmd_t *cmd) 3140 { 3141 int type; 3142 int arg; 3143 boolean_t arg_err = B_FALSE; 3144 3145 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 3146 long_usage(CMD_REMOVE, B_TRUE); 3147 return; 3148 } 3149 3150 optind = 0; 3151 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 3152 switch (arg) { 3153 case '?': 3154 longer_usage(CMD_REMOVE); 3155 arg_err = B_TRUE; 3156 break; 3157 case 'F': 3158 break; 3159 default: 3160 short_usage(CMD_REMOVE); 3161 arg_err = B_TRUE; 3162 break; 3163 } 3164 } 3165 if (arg_err) 3166 return; 3167 3168 if (initialize(B_TRUE) != Z_OK) 3169 return; 3170 3171 switch (type) { 3172 case RT_FS: 3173 remove_fs(cmd); 3174 return; 3175 case RT_IPD: 3176 remove_ipd(cmd); 3177 return; 3178 case RT_NET: 3179 remove_net(cmd); 3180 return; 3181 case RT_DEVICE: 3182 remove_device(cmd); 3183 return; 3184 case RT_RCTL: 3185 remove_rctl(cmd); 3186 return; 3187 case RT_ATTR: 3188 remove_attr(cmd); 3189 return; 3190 case RT_DATASET: 3191 remove_dataset(cmd); 3192 return; 3193 case RT_DCPU: 3194 remove_pset(); 3195 return; 3196 case RT_PCAP: 3197 remove_pcap(); 3198 return; 3199 case RT_MCAP: 3200 remove_mcap(); 3201 return; 3202 default: 3203 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE); 3204 long_usage(CMD_REMOVE, B_TRUE); 3205 usage(B_FALSE, HELP_RESOURCES); 3206 return; 3207 } 3208 } 3209 3210 static void 3211 remove_property(cmd_t *cmd) 3212 { 3213 char *prop_id; 3214 int err, res_type, prop_type; 3215 property_value_ptr_t pp; 3216 struct zone_rctlvaltab *rctlvaltab; 3217 complex_property_ptr_t cx; 3218 3219 res_type = resource_scope; 3220 prop_type = cmd->cmd_prop_name[0]; 3221 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) { 3222 long_usage(CMD_REMOVE, B_TRUE); 3223 return; 3224 } 3225 3226 if (cmd->cmd_prop_nv_pairs != 1) { 3227 long_usage(CMD_ADD, B_TRUE); 3228 return; 3229 } 3230 3231 if (initialize(B_TRUE) != Z_OK) 3232 return; 3233 3234 switch (res_type) { 3235 case RT_FS: 3236 if (prop_type != PT_OPTIONS) { 3237 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 3238 B_TRUE); 3239 long_usage(CMD_REMOVE, B_TRUE); 3240 usage(B_FALSE, HELP_PROPS); 3241 return; 3242 } 3243 pp = cmd->cmd_property_ptr[0]; 3244 if (pp->pv_type == PROP_VAL_COMPLEX) { 3245 zerr(gettext("A %s or %s value was expected here."), 3246 pvt_to_str(PROP_VAL_SIMPLE), 3247 pvt_to_str(PROP_VAL_LIST)); 3248 saw_error = B_TRUE; 3249 return; 3250 } 3251 if (pp->pv_type == PROP_VAL_SIMPLE) { 3252 if (pp->pv_simple == NULL) { 3253 long_usage(CMD_ADD, B_TRUE); 3254 return; 3255 } 3256 prop_id = pp->pv_simple; 3257 err = zonecfg_remove_fs_option(&in_progress_fstab, 3258 prop_id); 3259 if (err != Z_OK) 3260 zone_perror(pt_to_str(prop_type), err, B_TRUE); 3261 } else { 3262 list_property_ptr_t list; 3263 3264 for (list = pp->pv_list; list != NULL; 3265 list = list->lp_next) { 3266 prop_id = list->lp_simple; 3267 if (prop_id == NULL) 3268 break; 3269 err = zonecfg_remove_fs_option( 3270 &in_progress_fstab, prop_id); 3271 if (err != Z_OK) 3272 zone_perror(pt_to_str(prop_type), err, 3273 B_TRUE); 3274 } 3275 } 3276 return; 3277 case RT_RCTL: 3278 if (prop_type != PT_VALUE) { 3279 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 3280 B_TRUE); 3281 long_usage(CMD_REMOVE, B_TRUE); 3282 usage(B_FALSE, HELP_PROPS); 3283 return; 3284 } 3285 pp = cmd->cmd_property_ptr[0]; 3286 if (pp->pv_type != PROP_VAL_COMPLEX) { 3287 zerr(gettext("A %s value was expected here."), 3288 pvt_to_str(PROP_VAL_COMPLEX)); 3289 saw_error = B_TRUE; 3290 return; 3291 } 3292 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) { 3293 zone_perror(zone, Z_NOMEM, B_TRUE); 3294 exit(Z_ERR); 3295 } 3296 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) { 3297 switch (cx->cp_type) { 3298 case PT_PRIV: 3299 (void) strlcpy(rctlvaltab->zone_rctlval_priv, 3300 cx->cp_value, 3301 sizeof (rctlvaltab->zone_rctlval_priv)); 3302 break; 3303 case PT_LIMIT: 3304 (void) strlcpy(rctlvaltab->zone_rctlval_limit, 3305 cx->cp_value, 3306 sizeof (rctlvaltab->zone_rctlval_limit)); 3307 break; 3308 case PT_ACTION: 3309 (void) strlcpy(rctlvaltab->zone_rctlval_action, 3310 cx->cp_value, 3311 sizeof (rctlvaltab->zone_rctlval_action)); 3312 break; 3313 default: 3314 zone_perror(pt_to_str(prop_type), 3315 Z_NO_PROPERTY_TYPE, B_TRUE); 3316 long_usage(CMD_ADD, B_TRUE); 3317 usage(B_FALSE, HELP_PROPS); 3318 zonecfg_free_rctl_value_list(rctlvaltab); 3319 return; 3320 } 3321 } 3322 rctlvaltab->zone_rctlval_next = NULL; 3323 err = zonecfg_remove_rctl_value(&in_progress_rctltab, 3324 rctlvaltab); 3325 if (err != Z_OK) 3326 zone_perror(pt_to_str(prop_type), err, B_TRUE); 3327 zonecfg_free_rctl_value_list(rctlvaltab); 3328 return; 3329 case RT_NET: 3330 if (prop_type != PT_DEFROUTER) { 3331 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 3332 B_TRUE); 3333 long_usage(CMD_REMOVE, B_TRUE); 3334 usage(B_FALSE, HELP_PROPS); 3335 return; 3336 } else { 3337 bzero(&in_progress_nwiftab.zone_nwif_defrouter, 3338 sizeof (in_progress_nwiftab.zone_nwif_defrouter)); 3339 return; 3340 } 3341 default: 3342 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE); 3343 long_usage(CMD_REMOVE, B_TRUE); 3344 usage(B_FALSE, HELP_RESOURCES); 3345 return; 3346 } 3347 } 3348 3349 void 3350 remove_func(cmd_t *cmd) 3351 { 3352 if (zone_is_read_only(CMD_REMOVE)) 3353 return; 3354 3355 assert(cmd != NULL); 3356 3357 if (global_scope) { 3358 if (gz_invalid_resource(cmd->cmd_res_type)) { 3359 zerr(gettext("%s is not a valid resource for the " 3360 "global zone."), rt_to_str(cmd->cmd_res_type)); 3361 saw_error = B_TRUE; 3362 return; 3363 } 3364 remove_resource(cmd); 3365 } else { 3366 remove_property(cmd); 3367 } 3368 } 3369 3370 static void 3371 clear_property(cmd_t *cmd) 3372 { 3373 int res_type, prop_type; 3374 3375 res_type = resource_scope; 3376 prop_type = cmd->cmd_res_type; 3377 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) { 3378 long_usage(CMD_CLEAR, B_TRUE); 3379 return; 3380 } 3381 3382 if (initialize(B_TRUE) != Z_OK) 3383 return; 3384 3385 switch (res_type) { 3386 case RT_FS: 3387 if (prop_type == PT_RAW) { 3388 in_progress_fstab.zone_fs_raw[0] = '\0'; 3389 need_to_commit = B_TRUE; 3390 return; 3391 } 3392 break; 3393 case RT_DCPU: 3394 if (prop_type == PT_IMPORTANCE) { 3395 in_progress_psettab.zone_importance[0] = '\0'; 3396 need_to_commit = B_TRUE; 3397 return; 3398 } 3399 break; 3400 case RT_MCAP: 3401 switch (prop_type) { 3402 case PT_PHYSICAL: 3403 in_progress_mcaptab.zone_physmem_cap[0] = '\0'; 3404 need_to_commit = B_TRUE; 3405 return; 3406 case PT_SWAP: 3407 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP); 3408 return; 3409 case PT_LOCKED: 3410 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM); 3411 return; 3412 } 3413 break; 3414 default: 3415 break; 3416 } 3417 3418 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE); 3419 } 3420 3421 static void 3422 clear_global(cmd_t *cmd) 3423 { 3424 int err, type; 3425 3426 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 3427 long_usage(CMD_CLEAR, B_TRUE); 3428 return; 3429 } 3430 3431 if (initialize(B_TRUE) != Z_OK) 3432 return; 3433 3434 switch (type) { 3435 case PT_ZONENAME: 3436 /* FALLTHRU */ 3437 case PT_ZONEPATH: 3438 /* FALLTHRU */ 3439 case PT_BRAND: 3440 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE); 3441 return; 3442 case PT_AUTOBOOT: 3443 /* false is default; we'll treat as equivalent to clearing */ 3444 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK) 3445 z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE); 3446 else 3447 need_to_commit = B_TRUE; 3448 return; 3449 case PT_POOL: 3450 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK) 3451 z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE); 3452 else 3453 need_to_commit = B_TRUE; 3454 return; 3455 case PT_LIMITPRIV: 3456 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK) 3457 z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE); 3458 else 3459 need_to_commit = B_TRUE; 3460 return; 3461 case PT_BOOTARGS: 3462 if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK) 3463 z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, B_TRUE); 3464 else 3465 need_to_commit = B_TRUE; 3466 return; 3467 case PT_SCHED: 3468 if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK) 3469 z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, B_TRUE); 3470 else 3471 need_to_commit = B_TRUE; 3472 return; 3473 case PT_IPTYPE: 3474 /* shared is default; we'll treat as equivalent to clearing */ 3475 if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK) 3476 z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, B_TRUE); 3477 else 3478 need_to_commit = B_TRUE; 3479 return; 3480 case PT_MAXLWPS: 3481 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS); 3482 return; 3483 case PT_MAXSHMMEM: 3484 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM); 3485 return; 3486 case PT_MAXSHMIDS: 3487 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS); 3488 return; 3489 case PT_MAXMSGIDS: 3490 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS); 3491 return; 3492 case PT_MAXSEMIDS: 3493 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS); 3494 return; 3495 case PT_SHARES: 3496 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES); 3497 return; 3498 case PT_HOSTID: 3499 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK) 3500 z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE); 3501 else 3502 need_to_commit = B_TRUE; 3503 return; 3504 default: 3505 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE); 3506 long_usage(CMD_CLEAR, B_TRUE); 3507 usage(B_FALSE, HELP_PROPS); 3508 return; 3509 } 3510 } 3511 3512 void 3513 clear_func(cmd_t *cmd) 3514 { 3515 if (zone_is_read_only(CMD_CLEAR)) 3516 return; 3517 3518 assert(cmd != NULL); 3519 3520 if (global_scope) { 3521 if (gz_invalid_property(cmd->cmd_res_type)) { 3522 zerr(gettext("%s is not a valid property for the " 3523 "global zone."), pt_to_str(cmd->cmd_res_type)); 3524 saw_error = B_TRUE; 3525 return; 3526 } 3527 3528 clear_global(cmd); 3529 } else { 3530 clear_property(cmd); 3531 } 3532 } 3533 3534 void 3535 select_func(cmd_t *cmd) 3536 { 3537 int type, err, res; 3538 uint64_t limit; 3539 uint64_t tmp; 3540 3541 if (zone_is_read_only(CMD_SELECT)) 3542 return; 3543 3544 assert(cmd != NULL); 3545 3546 if (global_scope) { 3547 global_scope = B_FALSE; 3548 resource_scope = cmd->cmd_res_type; 3549 end_op = CMD_SELECT; 3550 } else { 3551 scope_usage(CMD_SELECT); 3552 return; 3553 } 3554 3555 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 3556 long_usage(CMD_SELECT, B_TRUE); 3557 return; 3558 } 3559 3560 if (initialize(B_TRUE) != Z_OK) 3561 return; 3562 3563 switch (type) { 3564 case RT_FS: 3565 if ((err = fill_in_fstab(cmd, &old_fstab, B_FALSE)) != Z_OK) { 3566 z_cmd_rt_perror(CMD_SELECT, RT_FS, err, B_TRUE); 3567 global_scope = B_TRUE; 3568 } 3569 bcopy(&old_fstab, &in_progress_fstab, 3570 sizeof (struct zone_fstab)); 3571 return; 3572 case RT_IPD: 3573 if (state_atleast(ZONE_STATE_INCOMPLETE)) { 3574 zerr(gettext("Zone %s not in %s state; %s %s not " 3575 "allowed."), zone, 3576 zone_state_str(ZONE_STATE_CONFIGURED), 3577 cmd_to_str(CMD_SELECT), rt_to_str(RT_IPD)); 3578 global_scope = B_TRUE; 3579 end_op = -1; 3580 return; 3581 } 3582 if ((err = fill_in_ipdtab(cmd, &old_ipdtab, B_FALSE)) != Z_OK) { 3583 z_cmd_rt_perror(CMD_SELECT, RT_IPD, err, B_TRUE); 3584 global_scope = B_TRUE; 3585 } 3586 bcopy(&old_ipdtab, &in_progress_ipdtab, 3587 sizeof (struct zone_fstab)); 3588 return; 3589 case RT_NET: 3590 if ((err = fill_in_nwiftab(cmd, &old_nwiftab, B_FALSE)) 3591 != Z_OK) { 3592 z_cmd_rt_perror(CMD_SELECT, RT_NET, err, B_TRUE); 3593 global_scope = B_TRUE; 3594 } 3595 bcopy(&old_nwiftab, &in_progress_nwiftab, 3596 sizeof (struct zone_nwiftab)); 3597 return; 3598 case RT_DEVICE: 3599 if ((err = fill_in_devtab(cmd, &old_devtab, B_FALSE)) != Z_OK) { 3600 z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, B_TRUE); 3601 global_scope = B_TRUE; 3602 } 3603 bcopy(&old_devtab, &in_progress_devtab, 3604 sizeof (struct zone_devtab)); 3605 return; 3606 case RT_RCTL: 3607 if ((err = fill_in_rctltab(cmd, &old_rctltab, B_FALSE)) 3608 != Z_OK) { 3609 z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, B_TRUE); 3610 global_scope = B_TRUE; 3611 } 3612 bcopy(&old_rctltab, &in_progress_rctltab, 3613 sizeof (struct zone_rctltab)); 3614 return; 3615 case RT_ATTR: 3616 if ((err = fill_in_attrtab(cmd, &old_attrtab, B_FALSE)) 3617 != Z_OK) { 3618 z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, B_TRUE); 3619 global_scope = B_TRUE; 3620 } 3621 bcopy(&old_attrtab, &in_progress_attrtab, 3622 sizeof (struct zone_attrtab)); 3623 return; 3624 case RT_DATASET: 3625 if ((err = fill_in_dstab(cmd, &old_dstab, B_FALSE)) != Z_OK) { 3626 z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, B_TRUE); 3627 global_scope = B_TRUE; 3628 } 3629 bcopy(&old_dstab, &in_progress_dstab, 3630 sizeof (struct zone_dstab)); 3631 return; 3632 case RT_DCPU: 3633 if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) { 3634 z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE); 3635 global_scope = B_TRUE; 3636 } 3637 bcopy(&old_psettab, &in_progress_psettab, 3638 sizeof (struct zone_psettab)); 3639 return; 3640 case RT_PCAP: 3641 if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) 3642 != Z_OK) { 3643 z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE); 3644 global_scope = B_TRUE; 3645 } 3646 return; 3647 case RT_MCAP: 3648 /* if none of these exist, there is no resource to select */ 3649 if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK && 3650 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit) 3651 != Z_OK && 3652 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit) 3653 != Z_OK) { 3654 z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE, 3655 B_TRUE); 3656 global_scope = B_TRUE; 3657 } 3658 if (res == Z_OK) 3659 bcopy(&old_mcaptab, &in_progress_mcaptab, 3660 sizeof (struct zone_mcaptab)); 3661 else 3662 bzero(&in_progress_mcaptab, 3663 sizeof (in_progress_mcaptab)); 3664 return; 3665 default: 3666 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE); 3667 long_usage(CMD_SELECT, B_TRUE); 3668 usage(B_FALSE, HELP_RESOURCES); 3669 return; 3670 } 3671 } 3672 3673 /* 3674 * Network "addresses" can be one of the following forms: 3675 * <IPv4 address> 3676 * <IPv4 address>/<prefix length> 3677 * <IPv6 address>/<prefix length> 3678 * <host name> 3679 * <host name>/<prefix length> 3680 * In other words, the "/" followed by a prefix length is allowed but not 3681 * required for IPv4 addresses and host names, and required for IPv6 addresses. 3682 * If a prefix length is given, it must be in the allowable range: 0 to 32 for 3683 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses. 3684 * Host names must start with an alpha-numeric character, and all subsequent 3685 * characters must be either alpha-numeric or "-". 3686 */ 3687 3688 static int 3689 validate_net_address_syntax(char *address) 3690 { 3691 char *slashp, part1[MAXHOSTNAMELEN]; 3692 struct in6_addr in6; 3693 struct in_addr in4; 3694 int prefixlen, i; 3695 3696 /* 3697 * Copy the part before any '/' into part1 or copy the whole 3698 * thing if there is no '/'. 3699 */ 3700 if ((slashp = strchr(address, '/')) != NULL) { 3701 *slashp = '\0'; 3702 (void) strlcpy(part1, address, sizeof (part1)); 3703 *slashp = '/'; 3704 prefixlen = atoi(++slashp); 3705 } else { 3706 (void) strlcpy(part1, address, sizeof (part1)); 3707 } 3708 3709 if (inet_pton(AF_INET6, part1, &in6) == 1) { 3710 if (slashp == NULL) { 3711 zerr(gettext("%s: IPv6 addresses " 3712 "require /prefix-length suffix."), address); 3713 return (Z_ERR); 3714 } 3715 if (prefixlen < 0 || prefixlen > 128) { 3716 zerr(gettext("%s: IPv6 address " 3717 "prefix lengths must be 0 - 128."), address); 3718 return (Z_ERR); 3719 } 3720 return (Z_OK); 3721 } 3722 3723 /* At this point, any /prefix must be for IPv4. */ 3724 if (slashp != NULL) { 3725 if (prefixlen < 0 || prefixlen > 32) { 3726 zerr(gettext("%s: IPv4 address " 3727 "prefix lengths must be 0 - 32."), address); 3728 return (Z_ERR); 3729 } 3730 } 3731 if (inet_pton(AF_INET, part1, &in4) == 1) 3732 return (Z_OK); 3733 3734 /* address may also be a host name */ 3735 if (!isalnum(part1[0])) { 3736 zerr(gettext("%s: bogus host name or network address syntax"), 3737 part1); 3738 saw_error = B_TRUE; 3739 usage(B_FALSE, HELP_NETADDR); 3740 return (Z_ERR); 3741 } 3742 for (i = 1; part1[i]; i++) 3743 if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') { 3744 zerr(gettext("%s: bogus host name or " 3745 "network address syntax"), part1); 3746 saw_error = B_TRUE; 3747 usage(B_FALSE, HELP_NETADDR); 3748 return (Z_ERR); 3749 } 3750 return (Z_OK); 3751 } 3752 3753 static int 3754 validate_net_physical_syntax(const char *ifname) 3755 { 3756 ifspec_t ifnameprop; 3757 zone_iptype_t iptype; 3758 3759 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) { 3760 zerr(gettext("zone configuration has an invalid or nonexistent " 3761 "ip-type property")); 3762 return (Z_ERR); 3763 } 3764 switch (iptype) { 3765 case ZS_SHARED: 3766 if (ifparse_ifspec(ifname, &ifnameprop) == B_FALSE) { 3767 zerr(gettext("%s: invalid physical interface name"), 3768 ifname); 3769 return (Z_ERR); 3770 } 3771 if (ifnameprop.ifsp_lunvalid) { 3772 zerr(gettext("%s: LUNs not allowed in physical " 3773 "interface names"), ifname); 3774 return (Z_ERR); 3775 } 3776 break; 3777 case ZS_EXCLUSIVE: 3778 if (dladm_valid_linkname(ifname) == B_FALSE) { 3779 if (strchr(ifname, ':') != NULL) 3780 zerr(gettext("%s: physical interface name " 3781 "required; logical interface name not " 3782 "allowed"), ifname); 3783 else 3784 zerr(gettext("%s: invalid physical interface " 3785 "name"), ifname); 3786 return (Z_ERR); 3787 } 3788 break; 3789 } 3790 return (Z_OK); 3791 } 3792 3793 static boolean_t 3794 valid_fs_type(const char *type) 3795 { 3796 /* 3797 * Is this a valid path component? 3798 */ 3799 if (strlen(type) + 1 > MAXNAMELEN) 3800 return (B_FALSE); 3801 /* 3802 * Make sure a bad value for "type" doesn't make 3803 * /usr/lib/fs/<type>/mount turn into something else. 3804 */ 3805 if (strchr(type, '/') != NULL || type[0] == '\0' || 3806 strcmp(type, ".") == 0 || strcmp(type, "..") == 0) 3807 return (B_FALSE); 3808 /* 3809 * More detailed verification happens later by zoneadm(1m). 3810 */ 3811 return (B_TRUE); 3812 } 3813 3814 static boolean_t 3815 allow_exclusive() 3816 { 3817 brand_handle_t bh; 3818 char brand[MAXNAMELEN]; 3819 boolean_t ret; 3820 3821 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) { 3822 zerr("%s: %s\n", zone, gettext("could not get zone brand")); 3823 return (B_FALSE); 3824 } 3825 if ((bh = brand_open(brand)) == NULL) { 3826 zerr("%s: %s\n", zone, gettext("unknown brand.")); 3827 return (B_FALSE); 3828 } 3829 ret = brand_allow_exclusive_ip(bh); 3830 brand_close(bh); 3831 if (!ret) 3832 zerr(gettext("%s cannot be '%s' when %s is '%s'."), 3833 pt_to_str(PT_IPTYPE), "exclusive", 3834 pt_to_str(PT_BRAND), brand); 3835 return (ret); 3836 } 3837 3838 static void 3839 set_aliased_rctl(char *alias, int prop_type, char *s) 3840 { 3841 uint64_t limit; 3842 int err; 3843 char tmp[128]; 3844 3845 if (global_zone && strcmp(alias, ALIAS_SHARES) != 0) 3846 zerr(gettext("WARNING: Setting a global zone resource " 3847 "control too low could deny\nservice " 3848 "to even the root user; " 3849 "this could render the system impossible\n" 3850 "to administer. Please use caution.")); 3851 3852 /* convert memory based properties */ 3853 if (prop_type == PT_MAXSHMMEM) { 3854 if (!zonecfg_valid_memlimit(s, &limit)) { 3855 zerr(gettext("A non-negative number with a required " 3856 "scale suffix (K, M, G or T) was expected\nhere.")); 3857 saw_error = B_TRUE; 3858 return; 3859 } 3860 3861 (void) snprintf(tmp, sizeof (tmp), "%llu", limit);