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