Print this page
    
dccp: properties
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
          +++ new/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  #include <arpa/inet.h>
  25   25  #include <errno.h>
  26   26  #include <getopt.h>
  27   27  #include <inet/ip.h>
  28   28  #include <inet/iptun.h>
  29   29  #include <inet/tunables.h>
  30   30  #include <libdladm.h>
  31   31  #include <libdliptun.h>
  32   32  #include <libdllink.h>
  33   33  #include <libinetutil.h>
  34   34  #include <libipadm.h>
  35   35  #include <locale.h>
  36   36  #include <netdb.h>
  37   37  #include <netinet/in.h>
  38   38  #include <ofmt.h>
  39   39  #include <stdarg.h>
  40   40  #include <stddef.h>
  41   41  #include <stdio.h>
  42   42  #include <stdlib.h>
  43   43  #include <string.h>
  44   44  #include <strings.h>
  45   45  #include <sys/stat.h>
  46   46  #include <sys/types.h>
  47   47  #include <zone.h>
  48   48  
  49   49  #define STR_UNKNOWN_VAL "?"
  50   50  #define LIFC_DEFAULT    (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
  51   51                          LIFC_UNDER_IPMP)
  52   52  
  53   53  typedef void cmdfunc_t(int, char **, const char *);
  54   54  static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
  55   55  static cmdfunc_t do_show_if;
  56   56  static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
  57   57  static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
  58   58  static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
  59   59  static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
  60   60  static cmdfunc_t do_enable_addr, do_disable_addr;
  61   61  static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
  62   62  
  63   63  typedef struct  cmd {
  64   64          char            *c_name;
  65   65          cmdfunc_t       *c_fn;
  66   66          const char      *c_usage;
  67   67  } cmd_t;
  68   68  
  69   69  static cmd_t    cmds[] = {
  70   70          /* interface management related sub-commands */
  71   71          { "create-if",  do_create_if,   "\tcreate-if\t[-t] <interface>" },
  72   72          { "disable-if", do_disable_if,  "\tdisable-if\t-t <interface>"  },
  73   73          { "enable-if",  do_enable_if,   "\tenable-if\t-t <interface>"   },
  74   74          { "delete-if",  do_delete_if,   "\tdelete-if\t<interface>"      },
  75   75          { "show-if",    do_show_if,
  76   76              "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"        },
  77   77          { "set-ifprop", do_set_ifprop,
  78   78              "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
  79   79              "<interface>"                                               },
  80   80          { "reset-ifprop", do_reset_ifprop,
  81   81              "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>"  },
  82   82          { "show-ifprop", do_show_ifprop,
  83   83              "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
  84   84              "\t\t\t[-m <protocol>] [interface]\n"                       },
  85   85  
  86   86          /* address management related sub-commands */
  87   87          { "create-addr", do_create_addr,
  88   88              "\tcreate-addr\t[-t] {-T static <static_args> |"
  89   89              " -T dhcp <dhcp_args> |\n"
  90   90              "\t\t\t-T addrconf <addrconf_args>} <addrobj>\n"
  91   91              "\t\t\tstatic_args = <[-d] -a {local|remote}=addr[/prefixlen]>\n"
  92   92              "\t\t\tdhcp_args = <[-w <seconds> | forever]>\n"
  93   93              "\t\t\taddrconf_args = <[-i interface-id]\n"
  94   94              "\t\t\t\t\t[-p {stateful|stateless}={yes|no}]>"             },
  95   95          { "down-addr",  do_down_addr,   "\tdown-addr\t[-t] <addrobj>"   },
  96   96          { "up-addr",    do_up_addr,     "\tup-addr\t\t[-t] <addrobj>"   },
  97   97          { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
  98   98          { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>"  },
  99   99          { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
 100  100          { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
 101  101          { "show-addr",  do_show_addr,
 102  102              "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n"          },
 103  103          { "set-addrprop", do_set_addrprop,
 104  104              "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>"    },
 105  105          { "reset-addrprop", do_reset_addrprop,
 106  106              "\treset-addrprop\t[-t] -p <prop> <addrobj>"                },
 107  107          { "show-addrprop", do_show_addrprop,
 108  108              "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
 109  109              "<addrobj>\n"                                               },
 110  110  
 111  111          /* protocol properties related sub-commands */
 112  112          { "set-prop",   do_set_prop,
 113  113              "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>"  },
 114  114          { "reset-prop", do_reset_prop,
 115  115              "\treset-prop\t[-t] -p <prop> <protocol>"                   },
 116  116          { "show-prop",  do_show_prop,
 117  117              "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
 118  118              " [protocol]"                                               }
 119  119  };
 120  120  
 121  121  static const struct option if_longopts[] = {
 122  122          {"temporary",   no_argument,            0, 't'  },
 123  123          { 0, 0, 0, 0 }
 124  124  };
 125  125  
 126  126  static const struct option show_prop_longopts[] = {
 127  127          {"parsable",    no_argument,            0, 'c'  },
 128  128          {"prop",        required_argument,      0, 'p'  },
 129  129          {"output",      required_argument,      0, 'o'  },
 130  130          { 0, 0, 0, 0 }
 131  131  };
 132  132  
 133  133  static const struct option show_ifprop_longopts[] = {
 134  134          {"module",      required_argument,      0, 'm'  },
 135  135          {"parsable",    no_argument,            0, 'c'  },
 136  136          {"prop",        required_argument,      0, 'p'  },
 137  137          {"output",      required_argument,      0, 'o'  },
 138  138          { 0, 0, 0, 0 }
 139  139  };
 140  140  
 141  141  static const struct option set_prop_longopts[] = {
 142  142          {"prop",        required_argument,      0, 'p'  },
 143  143          {"temporary",   no_argument,            0, 't'  },
 144  144          { 0, 0, 0, 0 }
 145  145  };
 146  146  
 147  147  static const struct option set_ifprop_longopts[] = {
 148  148          {"module",      required_argument,      0, 'm'  },
 149  149          {"prop",        required_argument,      0, 'p'  },
 150  150          {"temporary",   no_argument,            0, 't'  },
 151  151          { 0, 0, 0, 0 }
 152  152  };
 153  153  
 154  154  static const struct option addr_misc_longopts[] = {
 155  155          {"inform",      no_argument,            0, 'i'  },
 156  156          {"release",     no_argument,            0, 'r'  },
 157  157          {"temporary",   no_argument,            0, 't'  },
 158  158          { 0, 0, 0, 0 }
 159  159  };
 160  160  
 161  161  static const struct option addr_longopts[] = {
 162  162          {"address",     required_argument,      0, 'a'  },
 163  163          {"down",        no_argument,            0, 'd'  },
 164  164          {"interface-id", required_argument,     0, 'i'  },
 165  165          {"prop",        required_argument,      0, 'p'  },
 166  166          {"temporary",   no_argument,            0, 't'  },
 167  167          {"type",        required_argument,      0, 'T'  },
 168  168          {"wait",        required_argument,      0, 'w'  },
 169  169          { 0, 0, 0, 0 }
 170  170  };
 171  171  
 172  172  static const struct option show_addr_longopts[] = {
 173  173          {"parsable",    no_argument,            0, 'p'  },
 174  174          {"output",      required_argument,      0, 'o'  },
 175  175          { 0, 0, 0, 0 }
 176  176  };
 177  177  
 178  178  static const struct option show_if_longopts[] = {
 179  179          {"parsable",    no_argument,            0, 'p'  },
 180  180          {"output",      required_argument,      0, 'o'  },
 181  181          { 0, 0, 0, 0 }
 182  182  };
 183  183  
 184  184  /* callback functions to print show-* subcommands output */
 185  185  static ofmt_cb_t print_prop_cb;
 186  186  static ofmt_cb_t print_sa_cb;
 187  187  static ofmt_cb_t print_si_cb;
 188  188  
 189  189  /* structures for 'ipadm show-*' subcommands */
 190  190  typedef enum {
 191  191          IPADM_PROPFIELD_IFNAME,
 192  192          IPADM_PROPFIELD_PROTO,
 193  193          IPADM_PROPFIELD_ADDROBJ,
 194  194          IPADM_PROPFIELD_PROPERTY,
 195  195          IPADM_PROPFIELD_PERM,
 196  196          IPADM_PROPFIELD_CURRENT,
 197  197          IPADM_PROPFIELD_PERSISTENT,
 198  198          IPADM_PROPFIELD_DEFAULT,
 199  199          IPADM_PROPFIELD_POSSIBLE
 200  200  } ipadm_propfield_index_t;
 201  201  
 202  202  static ofmt_field_t intfprop_fields[] = {
 203  203  /* name,        field width,    index,                  callback */
 204  204  { "IFNAME",     12,     IPADM_PROPFIELD_IFNAME,         print_prop_cb},
 205  205  { "PROPERTY",   16,     IPADM_PROPFIELD_PROPERTY,       print_prop_cb},
 206  206  { "PROTO",      6,      IPADM_PROPFIELD_PROTO,          print_prop_cb},
 207  207  { "PERM",       5,      IPADM_PROPFIELD_PERM,           print_prop_cb},
 208  208  { "CURRENT",    11,     IPADM_PROPFIELD_CURRENT,        print_prop_cb},
 209  209  { "PERSISTENT", 11,     IPADM_PROPFIELD_PERSISTENT,     print_prop_cb},
 210  210  { "DEFAULT",    11,     IPADM_PROPFIELD_DEFAULT,        print_prop_cb},
 211  211  { "POSSIBLE",   16,     IPADM_PROPFIELD_POSSIBLE,       print_prop_cb},
 212  212  { NULL,         0,      0,                              NULL}
 213  213  };
 214  214  
 215  215  
 216  216  static ofmt_field_t modprop_fields[] = {
 217  217  /* name,        field width,    index,                  callback */
 218  218  { "PROTO",      6,      IPADM_PROPFIELD_PROTO,          print_prop_cb},
 219  219  { "PROPERTY",   22,     IPADM_PROPFIELD_PROPERTY,       print_prop_cb},
 220  220  { "PERM",       5,      IPADM_PROPFIELD_PERM,           print_prop_cb},
 221  221  { "CURRENT",    13,     IPADM_PROPFIELD_CURRENT,        print_prop_cb},
 222  222  { "PERSISTENT", 13,     IPADM_PROPFIELD_PERSISTENT,     print_prop_cb},
 223  223  { "DEFAULT",    13,     IPADM_PROPFIELD_DEFAULT,        print_prop_cb},
 224  224  { "POSSIBLE",   15,     IPADM_PROPFIELD_POSSIBLE,       print_prop_cb},
 225  225  { NULL,         0,      0,                              NULL}
 226  226  };
 227  227  
 228  228  static ofmt_field_t addrprop_fields[] = {
 229  229  /* name,        field width,    index,                  callback */
 230  230  { "ADDROBJ",    18,     IPADM_PROPFIELD_ADDROBJ,        print_prop_cb},
 231  231  { "PROPERTY",   11,     IPADM_PROPFIELD_PROPERTY,       print_prop_cb},
 232  232  { "PERM",       5,      IPADM_PROPFIELD_PERM,           print_prop_cb},
 233  233  { "CURRENT",    16,     IPADM_PROPFIELD_CURRENT,        print_prop_cb},
 234  234  { "PERSISTENT", 16,     IPADM_PROPFIELD_PERSISTENT,     print_prop_cb},
 235  235  { "DEFAULT",    16,     IPADM_PROPFIELD_DEFAULT,        print_prop_cb},
 236  236  { "POSSIBLE",   15,     IPADM_PROPFIELD_POSSIBLE,       print_prop_cb},
 237  237  { NULL,         0,      0,                              NULL}
 238  238  };
 239  239  
 240  240  typedef struct show_prop_state {
 241  241          char            sps_ifname[LIFNAMSIZ];
 242  242          char            sps_aobjname[IPADM_AOBJSIZ];
 243  243          const char      *sps_pname;
 244  244          uint_t          sps_proto;
 245  245          char            *sps_propval;
 246  246          nvlist_t        *sps_proplist;
 247  247          boolean_t       sps_parsable;
 248  248          boolean_t       sps_addrprop;
 249  249          boolean_t       sps_ifprop;
 250  250          boolean_t       sps_modprop;
 251  251          ipadm_status_t  sps_status;
 252  252          ipadm_status_t  sps_retstatus;
 253  253          ofmt_handle_t   sps_ofmt;
 254  254  } show_prop_state_t;
 255  255  
 256  256  typedef struct show_addr_state {
 257  257          boolean_t       sa_parsable;
 258  258          boolean_t       sa_persist;
 259  259          ofmt_handle_t   sa_ofmt;
 260  260  } show_addr_state_t;
 261  261  
 262  262  typedef struct show_if_state {
 263  263          boolean_t       si_parsable;
 264  264          ofmt_handle_t   si_ofmt;
 265  265  } show_if_state_t;
 266  266  
 267  267  typedef struct show_addr_args_s {
 268  268          show_addr_state_t       *sa_state;
 269  269          ipadm_addr_info_t       *sa_info;
 270  270  } show_addr_args_t;
 271  271  
 272  272  typedef struct show_if_args_s {
 273  273          show_if_state_t *si_state;
 274  274          ipadm_if_info_t *si_info;
 275  275  } show_if_args_t;
 276  276  
 277  277  typedef enum {
 278  278          SA_ADDROBJ,
 279  279          SA_TYPE,
 280  280          SA_STATE,
 281  281          SA_CURRENT,
 282  282          SA_PERSISTENT,
 283  283          SA_ADDR
 284  284  } sa_field_index_t;
 285  285  
 286  286  typedef enum {
 287  287          SI_IFNAME,
 288  288          SI_STATE,
 289  289          SI_CURRENT,
 290  290          SI_PERSISTENT
 291  291  } si_field_index_t;
 292  292  
 293  293  static ofmt_field_t show_addr_fields[] = {
 294  294  /* name,        field width,    id,             callback */
 295  295  { "ADDROBJ",    18,             SA_ADDROBJ,     print_sa_cb},
 296  296  { "TYPE",       9,              SA_TYPE,        print_sa_cb},
 297  297  { "STATE",      13,             SA_STATE,       print_sa_cb},
 298  298  { "CURRENT",    8,              SA_CURRENT,     print_sa_cb},
 299  299  { "PERSISTENT", 11,             SA_PERSISTENT,  print_sa_cb},
 300  300  { "ADDR",       46,             SA_ADDR,        print_sa_cb},
 301  301  { NULL,         0,              0,              NULL}
 302  302  };
 303  303  
 304  304  static ofmt_field_t show_if_fields[] = {
 305  305  /* name,        field width,    id,             callback */
 306  306  { "IFNAME",     11,             SI_IFNAME,      print_si_cb},
 307  307  { "STATE",      9,              SI_STATE,       print_si_cb},
 308  308  { "CURRENT",    13,             SI_CURRENT,     print_si_cb},
 309  309  { "PERSISTENT", 11,             SI_PERSISTENT,  print_si_cb},
 310  310  { NULL,         0,              0,              NULL}
 311  311  };
 312  312  
 313  313  #define IPADM_ALL_BITS  ((uint_t)-1)
 314  314  typedef struct intf_mask {
 315  315          char            *name;
 316  316          uint64_t        bits;
 317  317          uint64_t        mask;
 318  318  } fmask_t;
 319  319  
 320  320  /*
 321  321   * Handle to libipadm. Opened in main() before the sub-command specific
 322  322   * function is called and is closed before the program exits.
 323  323   */
 324  324  ipadm_handle_t  iph = NULL;
 325  325  
 326  326  /*
 327  327   * Opaque ipadm address object. Used by all the address management subcommands.
 328  328   */
 329  329  ipadm_addrobj_t ipaddr = NULL;
 330  330  
 331  331  static char *progname;
 332  332  
 333  333  static void     die(const char *, ...);
 334  334  static void     die_opterr(int, int, const char *);
 335  335  static void     warn_ipadmerr(ipadm_status_t, const char *, ...);
 336  336  static void     ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
 337  337  static void     ipadm_check_propstr(const char *, boolean_t, const char *);
 338  338  static void     process_misc_addrargs(int, char **, const char *, int *,
 339  339                      uint32_t *);
 340  340  
 341  341  static void
 342  342  usage(void)
 343  343  {
 344  344          int     i;
 345  345          cmd_t   *cmdp;
 346  346  
 347  347          (void) fprintf(stderr,
 348  348              gettext("usage:  ipadm <subcommand> <args> ...\n"));
 349  349          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 350  350                  cmdp = &cmds[i];
 351  351                  if (cmdp->c_usage != NULL)
 352  352                          (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
 353  353          }
 354  354  
 355  355          ipadm_destroy_addrobj(ipaddr);
 356  356          ipadm_close(iph);
 357  357          exit(1);
 358  358  }
 359  359  
 360  360  int
 361  361  main(int argc, char *argv[])
 362  362  {
 363  363          int     i;
 364  364          cmd_t   *cmdp;
 365  365          ipadm_status_t status;
 366  366  
 367  367          (void) setlocale(LC_ALL, "");
 368  368          (void) textdomain(TEXT_DOMAIN);
 369  369  
 370  370          if ((progname = strrchr(argv[0], '/')) == NULL)
 371  371                  progname = argv[0];
 372  372          else
 373  373                  progname++;
 374  374  
 375  375          if (argc < 2)
 376  376                  usage();
 377  377  
 378  378          status = ipadm_open(&iph, 0);
 379  379          if (status != IPADM_SUCCESS) {
 380  380                  die("Could not open handle to library - %s",
 381  381                      ipadm_status2str(status));
 382  382          }
 383  383  
 384  384          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 385  385                  cmdp = &cmds[i];
 386  386                  if (strcmp(argv[1], cmdp->c_name) == 0) {
 387  387                          cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
 388  388                          ipadm_destroy_addrobj(ipaddr);
 389  389                          ipadm_close(iph);
 390  390                          exit(0);
 391  391                  }
 392  392          }
 393  393  
 394  394          (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
 395  395              progname, argv[1]);
 396  396          usage();
 397  397  
 398  398          return (0);
 399  399  }
 400  400  
 401  401  /*
 402  402   * Create an IP interface for which no saved configuration exists in the
 403  403   * persistent store.
 404  404   */
 405  405  static void
 406  406  do_create_if(int argc, char *argv[], const char *use)
 407  407  {
 408  408          ipadm_status_t  status;
 409  409          int             option;
 410  410          uint32_t        flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
 411  411  
 412  412          opterr = 0;
 413  413          while ((option = getopt_long(argc, argv, ":t", if_longopts,
 414  414              NULL)) != -1) {
 415  415                  switch (option) {
 416  416                  case 't':
 417  417                          /*
 418  418                           * "ifconfig" mode - plumb interface, but do not
 419  419                           * restore settings that may exist in db.
 420  420                           */
 421  421                          flags &= ~IPADM_OPT_PERSIST;
 422  422                          break;
 423  423                  default:
 424  424                          die_opterr(optopt, option, use);
 425  425                  }
 426  426          }
 427  427          if (optind != (argc - 1))
 428  428                  die("Usage: %s", use);
 429  429          status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
 430  430          if (status != IPADM_SUCCESS) {
 431  431                  die("Could not create %s : %s",
 432  432                      argv[optind], ipadm_status2str(status));
 433  433          }
 434  434  }
 435  435  
 436  436  /*
 437  437   * Enable an IP interface based on the persistent configuration for
 438  438   * that interface.
 439  439   */
 440  440  static void
 441  441  do_enable_if(int argc, char *argv[], const char *use)
 442  442  {
 443  443          ipadm_status_t  status;
 444  444          int             index;
 445  445          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 446  446  
 447  447          process_misc_addrargs(argc, argv, use, &index, &flags);
 448  448          if (flags & IPADM_OPT_PERSIST)
 449  449                  die("persistent operation not supported for enable-if");
 450  450          status = ipadm_enable_if(iph, argv[index], flags);
 451  451          if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
 452  452                  warn_ipadmerr(status, "");
 453  453          } else if (status != IPADM_SUCCESS) {
 454  454                  die("Could not enable %s : %s",
 455  455                      argv[optind], ipadm_status2str(status));
 456  456          }
 457  457  }
 458  458  
 459  459  /*
 460  460   * Remove an IP interface from both active and persistent configuration.
 461  461   */
 462  462  static void
 463  463  do_delete_if(int argc, char *argv[], const char *use)
 464  464  {
 465  465          ipadm_status_t  status;
 466  466          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 467  467  
 468  468          if (argc != 2)
 469  469                  die("Usage: %s", use);
 470  470  
 471  471          status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
 472  472          if (status != IPADM_SUCCESS) {
 473  473                  die("Could not delete %s: %s",
 474  474                      argv[optind], ipadm_status2str(status));
 475  475          }
 476  476  }
 477  477  
 478  478  /*
 479  479   * Disable an IP interface by removing it from active configuration.
 480  480   */
 481  481  static void
 482  482  do_disable_if(int argc, char *argv[], const char *use)
 483  483  {
 484  484          ipadm_status_t  status;
 485  485          int             index;
 486  486          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 487  487  
 488  488          process_misc_addrargs(argc, argv, use, &index, &flags);
 489  489          if (flags & IPADM_OPT_PERSIST)
 490  490                  die("persistent operation not supported for disable-if");
 491  491          status = ipadm_disable_if(iph, argv[index], flags);
 492  492          if (status != IPADM_SUCCESS) {
 493  493                  die("Could not disable %s: %s",
 494  494                      argv[optind], ipadm_status2str(status));
 495  495          }
 496  496  }
 497  497  
 498  498  /*
 499  499   * called in from print_prop_cb() and does the job of printing each
 500  500   * individual column in the 'ipadm show-*prop' output.
 501  501   */
 502  502  static void
 503  503  print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
 504  504  {
 505  505          const char              *prop_name = statep->sps_pname;
 506  506          char                    *ifname = statep->sps_ifname;
 507  507          char                    *propval = statep->sps_propval;
 508  508          uint_t                  proto = statep->sps_proto;
 509  509          size_t                  propsize = MAXPROPVALLEN;
 510  510          char                    *object;
 511  511          ipadm_status_t          status;
 512  512  
 513  513          if (statep->sps_ifprop) {
 514  514                  status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
 515  515                      &propsize, proto, flags);
 516  516                  object = ifname;
 517  517          } else if (statep->sps_modprop) {
 518  518                  status = ipadm_get_prop(iph, prop_name, propval, &propsize,
 519  519                      proto, flags);
 520  520                  object = ipadm_proto2str(proto);
 521  521          } else {
 522  522                  status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
 523  523                      statep->sps_aobjname, flags);
 524  524                  object = statep->sps_aobjname;
 525  525          }
 526  526  
 527  527          if (status != IPADM_SUCCESS) {
 528  528                  if (status == IPADM_PROP_UNKNOWN ||
 529  529                      status == IPADM_INVALID_ARG) {
 530  530                          warn_ipadmerr(status, "cannot get property '%s' for "
 531  531                              "'%s'", prop_name, object);
 532  532                  } else if (status == IPADM_NOTSUP) {
 533  533                          warn_ipadmerr(status, "'%s'", object);
 534  534                  } else if (status == IPADM_NOTFOUND) {
 535  535                          if (flags & IPADM_OPT_PERSIST) {
 536  536                                  propval[0] = '\0';
 537  537                                  goto cont;
 538  538                          } else {
 539  539                                  warn_ipadmerr(status, "no such object '%s'",
 540  540                                      object);
 541  541                          }
 542  542                  } else if (status == IPADM_ENXIO) {
 543  543                          /* the interface is probably disabled */
 544  544                          propval[0] = '\0';
 545  545                          goto cont;
 546  546                  }
 547  547                  statep->sps_status = status;
 548  548                  statep->sps_retstatus = status;
 549  549                  return;
 550  550          }
 551  551  cont:
 552  552          statep->sps_status = IPADM_SUCCESS;
 553  553          (void) snprintf(buf, bufsize, "%s", propval);
 554  554  }
 555  555  
 556  556  /*
 557  557   * callback function which displays output for set-prop, set-ifprop and
 558  558   * set-addrprop subcommands.
 559  559   */
 560  560  static boolean_t
 561  561  print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
 562  562  {
 563  563          show_prop_state_t       *statep = ofarg->ofmt_cbarg;
 564  564          const char              *propname = statep->sps_pname;
 565  565          uint_t                  proto = statep->sps_proto;
 566  566          boolean_t               cont = _B_TRUE;
 567  567  
 568  568          /*
 569  569           * Fail retrieving remaining fields, if you fail
 570  570           * to retrieve a field.
 571  571           */
 572  572          if (statep->sps_status != IPADM_SUCCESS)
 573  573                  return (_B_FALSE);
 574  574  
 575  575          switch (ofarg->ofmt_id) {
 576  576          case IPADM_PROPFIELD_IFNAME:
 577  577                  (void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
 578  578                  break;
 579  579          case IPADM_PROPFIELD_PROTO:
 580  580                  (void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
 581  581                  break;
 582  582          case IPADM_PROPFIELD_ADDROBJ:
 583  583                  (void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
 584  584                  break;
 585  585          case IPADM_PROPFIELD_PROPERTY:
 586  586                  (void) snprintf(buf, bufsize, "%s", propname);
 587  587                  break;
 588  588          case IPADM_PROPFIELD_PERM:
 589  589                  print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
 590  590                  break;
 591  591          case IPADM_PROPFIELD_CURRENT:
 592  592                  print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
 593  593                  break;
 594  594          case IPADM_PROPFIELD_PERSISTENT:
 595  595                  print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
 596  596                  break;
 597  597          case IPADM_PROPFIELD_DEFAULT:
 598  598                  print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
 599  599                  break;
 600  600          case IPADM_PROPFIELD_POSSIBLE:
 601  601                  print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
 602  602                  break;
 603  603          }
 604  604          if (statep->sps_status != IPADM_SUCCESS)
 605  605                  cont = _B_FALSE;
 606  606          return (cont);
 607  607  }
 608  608  
 609  609  /*
 610  610   * Callback function called by the property walker (ipadm_walk_prop() or
 611  611   * ipadm_walk_proptbl()), for every matched property. This function in turn
 612  612   * calls ofmt_print() to print property information.
 613  613   */
 614  614  boolean_t
 615  615  show_property(void *arg, const char *pname, uint_t proto)
 616  616  {
 617  617          show_prop_state_t       *statep = arg;
 618  618  
 619  619          statep->sps_pname = pname;
 620  620          statep->sps_proto = proto;
 621  621          statep->sps_status = IPADM_SUCCESS;
 622  622          ofmt_print(statep->sps_ofmt, arg);
 623  623  
 624  624          /*
 625  625           * if an object is not found or operation is not supported then
  
    | 
      ↓ open down ↓ | 
    625 lines elided | 
    
      ↑ open up ↑ | 
  
 626  626           * stop the walker.
 627  627           */
 628  628          if (statep->sps_status == IPADM_NOTFOUND ||
 629  629              statep->sps_status == IPADM_NOTSUP)
 630  630                  return (_B_FALSE);
 631  631          return (_B_TRUE);
 632  632  }
 633  633  
 634  634  /*
 635  635   * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
 636      - * for all the properties for the specified object, relavant information, will
      636 + * for all the properties for the specified object, relevant information, will
 637  637   * be displayed. Otherwise, for the selected property set, display relevant
 638  638   * information
 639  639   */
 640  640  static void
 641  641  show_properties(void *arg, int prop_class)
 642  642  {
 643  643          show_prop_state_t       *statep = arg;
 644  644          nvlist_t                *nvl = statep->sps_proplist;
 645  645          uint_t                  proto = statep->sps_proto;
 646  646          nvpair_t                *curr_nvp;
 647  647          char                    *buf, *name;
 648  648          ipadm_status_t          status;
 649  649  
 650  650          /* allocate sufficient buffer to hold a property value */
 651  651          if ((buf = malloc(MAXPROPVALLEN)) == NULL)
 652  652                  die("insufficient memory");
 653  653          statep->sps_propval = buf;
 654  654  
 655  655          /* if no properties were specified, display all the properties */
 656  656          if (nvl == NULL) {
 657  657                  (void) ipadm_walk_proptbl(proto, prop_class, show_property,
 658  658                      statep);
 659  659          } else {
 660  660                  for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
 661  661                      curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
 662  662                          name = nvpair_name(curr_nvp);
 663  663                          status = ipadm_walk_prop(name, proto, prop_class,
 664  664                              show_property, statep);
 665  665                          if (status == IPADM_PROP_UNKNOWN)
 666  666                                  (void) show_property(statep, name, proto);
 667  667                  }
 668  668          }
 669  669  
 670  670          free(buf);
 671  671  }
 672  672  
 673  673  /*
 674  674   * Display information for all or specific interface properties, either for a
 675  675   * given interface or for all the interfaces in the system.
 676  676   */
 677  677  static void
 678  678  do_show_ifprop(int argc, char **argv, const char *use)
 679  679  {
 680  680          int             option;
 681  681          nvlist_t        *proplist = NULL;
 682  682          char            *fields_str = NULL;
 683  683          char            *ifname;
 684  684          ofmt_handle_t   ofmt;
 685  685          ofmt_status_t   oferr;
 686  686          uint_t          ofmtflags = 0;
 687  687          uint_t          proto;
 688  688          boolean_t       m_arg = _B_FALSE;
 689  689          char            *protostr;
 690  690          ipadm_if_info_t *ifinfo, *ifp;
 691  691          ipadm_status_t  status;
 692  692          show_prop_state_t state;
 693  693  
 694  694          opterr = 0;
 695  695          bzero(&state, sizeof (state));
 696  696          state.sps_propval = NULL;
 697  697          state.sps_parsable = _B_FALSE;
 698  698          state.sps_ifprop = _B_TRUE;
 699  699          state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
 700  700          while ((option = getopt_long(argc, argv, ":p:m:co:",
 701  701              show_ifprop_longopts, NULL)) != -1) {
 702  702                  switch (option) {
 703  703                  case 'p':
 704  704                          if (ipadm_str2nvlist(optarg, &proplist,
 705  705                              IPADM_NORVAL) != 0)
 706  706                                  die("invalid interface properties specified");
 707  707                          break;
 708  708                  case 'c':
 709  709                          state.sps_parsable = _B_TRUE;
 710  710                          break;
 711  711                  case 'o':
 712  712                          fields_str = optarg;
 713  713                          break;
 714  714                  case 'm':
 715  715                          if (m_arg)
 716  716                                  die("cannot specify more than one -m");
 717  717                          m_arg = _B_TRUE;
 718  718                          protostr = optarg;
 719  719                          break;
 720  720                  default:
 721  721                          die_opterr(optopt, option, use);
 722  722                          break;
 723  723                  }
 724  724          }
 725  725  
 726  726          if (optind == argc - 1)
 727  727                  ifname = argv[optind];
 728  728          else if (optind != argc)
 729  729                  die("Usage: %s", use);
 730  730          else
 731  731                  ifname = NULL;
 732  732  
 733  733          if (!m_arg)
 734  734                  protostr = "ip";
 735  735          if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
 736  736                  die("invalid protocol '%s' specified", protostr);
 737  737  
 738  738          state.sps_proto = proto;
 739  739          state.sps_proplist = proplist;
 740  740  
 741  741          if (state.sps_parsable)
 742  742                  ofmtflags |= OFMT_PARSABLE;
 743  743          oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
 744  744          ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
 745  745          state.sps_ofmt = ofmt;
 746  746  
 747  747          /* retrieve interface(s) and print the properties */
 748  748          status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
 749  749          if (ifname != NULL && status == IPADM_ENXIO)
 750  750                  die("no such object '%s': %s", ifname,
 751  751                      ipadm_status2str(status));
 752  752          if (status != IPADM_SUCCESS)
 753  753                  die("Error retrieving interface(s): %s",
 754  754                      ipadm_status2str(status));
 755  755          for (ifp = ifinfo; ifp; ifp = ifp->ifi_next) {
 756  756                  (void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
 757  757                  state.sps_proto = proto;
 758  758                  show_properties(&state, IPADMPROP_CLASS_IF);
 759  759          }
 760  760          if (ifinfo)
 761  761                  ipadm_free_if_info(ifinfo);
 762  762  
 763  763          nvlist_free(proplist);
 764  764          ofmt_close(ofmt);
 765  765  
 766  766          if (state.sps_retstatus != IPADM_SUCCESS) {
 767  767                  ipadm_close(iph);
 768  768                  exit(EXIT_FAILURE);
 769  769          }
 770  770  }
 771  771  
 772  772  /*
 773  773   * set/reset the interface property for a given interface.
 774  774   */
 775  775  static void
 776  776  set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
 777  777  {
 778  778          int                     option;
 779  779          ipadm_status_t          status = IPADM_SUCCESS;
 780  780          boolean_t               p_arg = _B_FALSE;
 781  781          boolean_t               m_arg = _B_FALSE;
 782  782          char                    *ifname, *nv, *protostr;
 783  783          char                    *prop_name, *prop_val;
 784  784          uint_t                  flags = IPADM_OPT_PERSIST;
 785  785          uint_t                  proto;
 786  786  
 787  787          opterr = 0;
 788  788          while ((option = getopt_long(argc, argv, ":m:p:t",
 789  789              set_ifprop_longopts, NULL)) != -1) {
 790  790                  switch (option) {
 791  791                  case 'p':
 792  792                          if (p_arg)
 793  793                                  die("-p must be specified once only");
 794  794                          p_arg = _B_TRUE;
 795  795  
 796  796                          ipadm_check_propstr(optarg, reset, use);
 797  797                          nv = optarg;
 798  798                          break;
 799  799                  case 'm':
 800  800                          if (m_arg)
 801  801                                  die("-m must be specified once only");
 802  802                          m_arg = _B_TRUE;
 803  803                          protostr = optarg;
 804  804                          break;
 805  805                  case 't':
 806  806                          flags &= ~IPADM_OPT_PERSIST;
 807  807                          break;
 808  808                  default:
 809  809                          die_opterr(optopt, option, use);
 810  810                  }
 811  811          }
 812  812  
 813  813          if (!m_arg || !p_arg || optind != argc - 1)
 814  814                  die("Usage: %s", use);
 815  815  
 816  816          ifname = argv[optind];
 817  817  
 818  818          prop_name = nv;
 819  819          prop_val = strchr(nv, '=');
 820  820          if (prop_val != NULL)
 821  821                  *prop_val++ = '\0';
 822  822  
 823  823          if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
 824  824                  die("invalid protocol '%s' specified", protostr);
 825  825  
 826  826          if (reset)
 827  827                  flags |= IPADM_OPT_DEFAULT;
 828  828          else
 829  829                  flags |= IPADM_OPT_ACTIVE;
 830  830          status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
 831  831              flags);
 832  832  
 833  833  done:
 834  834          if (status != IPADM_SUCCESS) {
 835  835                  if (reset)
 836  836                          die("reset-ifprop: %s: %s",
 837  837                              prop_name, ipadm_status2str(status));
 838  838                  else
 839  839                          die("set-ifprop: %s: %s",
 840  840                              prop_name, ipadm_status2str(status));
 841  841          }
 842  842  }
 843  843  
 844  844  static void
 845  845  do_set_ifprop(int argc, char **argv, const char *use)
 846  846  {
 847  847          set_ifprop(argc, argv, _B_FALSE, use);
  
    | 
      ↓ open down ↓ | 
    201 lines elided | 
    
      ↑ open up ↑ | 
  
 848  848  }
 849  849  
 850  850  static void
 851  851  do_reset_ifprop(int argc, char **argv, const char *use)
 852  852  {
 853  853          set_ifprop(argc, argv, _B_TRUE, use);
 854  854  }
 855  855  
 856  856  /*
 857  857   * Display information for all or specific protocol properties, either for a
 858      - * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
      858 + * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP/DCCP)
 859  859   */
 860  860  static void
 861  861  do_show_prop(int argc, char **argv, const char *use)
 862  862  {
 863  863          char                    option;
 864  864          nvlist_t                *proplist = NULL;
 865  865          char                    *fields_str = NULL;
 866  866          char                    *protostr;
 867  867          show_prop_state_t       state;
 868  868          ofmt_handle_t           ofmt;
 869  869          ofmt_status_t           oferr;
 870  870          uint_t                  ofmtflags = 0;
 871  871          uint_t                  proto;
 872  872          boolean_t               p_arg = _B_FALSE;
 873  873  
 874  874          opterr = 0;
 875  875          bzero(&state, sizeof (state));
 876  876          state.sps_propval = NULL;
 877  877          state.sps_parsable = _B_FALSE;
 878  878          state.sps_modprop = _B_TRUE;
 879  879          state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
 880  880          while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
 881  881              NULL)) != -1) {
 882  882                  switch (option) {
 883  883                  case 'p':
 884  884                          if (p_arg)
 885  885                                  die("-p must be specified once only");
 886  886                          p_arg = _B_TRUE;
 887  887                          if (ipadm_str2nvlist(optarg, &proplist,
 888  888                              IPADM_NORVAL) != 0)
 889  889                                  die("invalid protocol properties specified");
 890  890                          break;
 891  891                  case 'c':
 892  892                          state.sps_parsable = _B_TRUE;
 893  893                          break;
 894  894                  case 'o':
 895  895                          fields_str = optarg;
 896  896                          break;
 897  897                  default:
 898  898                          die_opterr(optopt, option, use);
 899  899                          break;
 900  900                  }
 901  901          }
 902  902          if (optind == argc - 1) {
 903  903                  protostr =  argv[optind];
 904  904                  if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
 905  905                          die("invalid protocol '%s' specified", protostr);
 906  906                  state.sps_proto = proto;
 907  907          } else if (optind != argc) {
 908  908                  die("Usage: %s", use);
 909  909          } else {
 910  910                  if (p_arg)
 911  911                          die("protocol must be specified when "
 912  912                              "property name is used");
 913  913                  state.sps_proto = MOD_PROTO_NONE;
 914  914          }
 915  915  
 916  916          state.sps_proplist = proplist;
 917  917  
 918  918          if (state.sps_parsable)
 919  919                  ofmtflags |= OFMT_PARSABLE;
 920  920          else
 921  921                  ofmtflags |= OFMT_WRAP;
 922  922          oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
 923  923          ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
 924  924          state.sps_ofmt = ofmt;
 925  925  
 926  926          /* handles all the errors */
 927  927          show_properties(&state, IPADMPROP_CLASS_MODULE);
 928  928  
 929  929          nvlist_free(proplist);
 930  930          ofmt_close(ofmt);
 931  931  
 932  932          if (state.sps_retstatus != IPADM_SUCCESS) {
 933  933                  ipadm_close(iph);
 934  934                  exit(EXIT_FAILURE);
 935  935          }
 936  936  }
 937  937  
 938  938  /*
 939  939   * Checks to see if there are any modifiers, + or -. If there are modifiers
 940  940   * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
 941  941   */
 942  942  static void
 943  943  parse_modifiers(const char *pstr, uint_t *flags, const char *use)
 944  944  {
 945  945          char *p;
 946  946  
 947  947          if ((p = strchr(pstr, '=')) == NULL)
 948  948                  return;
 949  949  
 950  950          if (p == pstr)
 951  951                  die("Invalid prop=val specified\n%s", use);
 952  952  
 953  953          --p;
 954  954          if (*p == '+')
 955  955                  *flags |= IPADM_OPT_APPEND;
 956  956          else if (*p == '-')
 957  957                  *flags |= IPADM_OPT_REMOVE;
 958  958  }
 959  959  
 960  960  /*
 961  961   * set/reset the protocol property for a given protocol.
 962  962   */
 963  963  static void
 964  964  set_prop(int argc, char **argv, boolean_t reset, const char *use)
 965  965  {
 966  966          int                     option;
 967  967          ipadm_status_t          status = IPADM_SUCCESS;
 968  968          char                    *protostr, *nv, *prop_name, *prop_val;
 969  969          boolean_t               p_arg = _B_FALSE;
 970  970          uint_t                  proto;
 971  971          uint_t                  flags = IPADM_OPT_PERSIST;
 972  972  
 973  973          opterr = 0;
 974  974          while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
 975  975              NULL)) != -1) {
 976  976                  switch (option) {
 977  977                  case 'p':
 978  978                          if (p_arg)
 979  979                                  die("-p must be specified once only");
 980  980                          p_arg = _B_TRUE;
 981  981  
 982  982                          ipadm_check_propstr(optarg, reset, use);
 983  983                          nv = optarg;
 984  984                          break;
 985  985                  case 't':
 986  986                          flags &= ~IPADM_OPT_PERSIST;
 987  987                          break;
 988  988                  default:
 989  989                          die_opterr(optopt, option, use);
 990  990                  }
 991  991          }
 992  992  
 993  993          if (!p_arg || optind != argc - 1)
 994  994                  die("Usage: %s", use);
 995  995  
 996  996          parse_modifiers(nv, &flags, use);
 997  997          prop_name = nv;
 998  998          prop_val = strchr(nv, '=');
 999  999          if (prop_val != NULL) {
1000 1000                  if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
1001 1001                          *(prop_val - 1) = '\0';
1002 1002                  *prop_val++ = '\0';
1003 1003          }
1004 1004          protostr = argv[optind];
1005 1005          if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
1006 1006                  die("invalid protocol '%s' specified", protostr);
1007 1007  
1008 1008          if (reset)
1009 1009                  flags |= IPADM_OPT_DEFAULT;
1010 1010          else
1011 1011                  flags |= IPADM_OPT_ACTIVE;
1012 1012          status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
1013 1013  done:
1014 1014          if (status != IPADM_SUCCESS) {
1015 1015                  if (reset)
1016 1016                          die("reset-prop: %s: %s",
1017 1017                              prop_name, ipadm_status2str(status));
1018 1018                  else
1019 1019                          die("set-prop: %s: %s",
1020 1020                              prop_name, ipadm_status2str(status));
1021 1021          }
1022 1022  }
1023 1023  
1024 1024  static void
1025 1025  do_set_prop(int argc, char **argv, const char *use)
1026 1026  {
1027 1027          set_prop(argc, argv, _B_FALSE, use);
1028 1028  }
1029 1029  
1030 1030  static void
1031 1031  do_reset_prop(int argc, char **argv, const char *use)
1032 1032  {
1033 1033          set_prop(argc, argv,  _B_TRUE, use);
1034 1034  }
1035 1035  
1036 1036  /* PRINTFLIKE1 */
1037 1037  static void
1038 1038  warn(const char *format, ...)
1039 1039  {
1040 1040          va_list alist;
1041 1041  
1042 1042          format = gettext(format);
1043 1043          (void) fprintf(stderr, gettext("%s: warning: "), progname);
1044 1044  
1045 1045          va_start(alist, format);
1046 1046          (void) vfprintf(stderr, format, alist);
1047 1047          va_end(alist);
1048 1048  
1049 1049          (void) fprintf(stderr, "\n");
1050 1050  }
1051 1051  
1052 1052  /* PRINTFLIKE1 */
1053 1053  static void
1054 1054  die(const char *format, ...)
1055 1055  {
1056 1056          va_list alist;
1057 1057  
1058 1058          format = gettext(format);
1059 1059          (void) fprintf(stderr, "%s: ", progname);
1060 1060  
1061 1061          va_start(alist, format);
1062 1062          (void) vfprintf(stderr, format, alist);
1063 1063          va_end(alist);
1064 1064  
1065 1065          (void) putchar('\n');
1066 1066  
1067 1067          ipadm_destroy_addrobj(ipaddr);
1068 1068          ipadm_close(iph);
1069 1069          exit(EXIT_FAILURE);
1070 1070  }
1071 1071  
1072 1072  static void
1073 1073  die_opterr(int opt, int opterr, const char *usage)
1074 1074  {
1075 1075          switch (opterr) {
1076 1076          case ':':
1077 1077                  die("option '-%c' requires a value\nusage: %s", opt,
1078 1078                      gettext(usage));
1079 1079                  break;
1080 1080          case '?':
1081 1081          default:
1082 1082                  die("unrecognized option '-%c'\nusage: %s", opt,
1083 1083                      gettext(usage));
1084 1084                  break;
1085 1085          }
1086 1086  }
1087 1087  
1088 1088  /* PRINTFLIKE2 */
1089 1089  static void
1090 1090  warn_ipadmerr(ipadm_status_t err, const char *format, ...)
1091 1091  {
1092 1092          va_list alist;
1093 1093  
1094 1094          format = gettext(format);
1095 1095          (void) fprintf(stderr, gettext("%s: warning: "), progname);
1096 1096  
1097 1097          va_start(alist, format);
1098 1098          (void) vfprintf(stderr, format, alist);
1099 1099          va_end(alist);
1100 1100  
1101 1101          (void) fprintf(stderr, "%s\n", ipadm_status2str(err));
1102 1102  }
1103 1103  
1104 1104  static void
1105 1105  process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
1106 1106  {
1107 1107          int             option;
1108 1108          char            *val;
1109 1109          char            *laddr = NULL;
1110 1110          char            *raddr = NULL;
1111 1111          char            *save_input_arg = addrarg;
1112 1112          boolean_t       found_mismatch = _B_FALSE;
1113 1113          ipadm_status_t  status;
1114 1114          enum            { A_LOCAL, A_REMOTE };
1115 1115          static char     *addr_optstr[] = {
1116 1116                  "local",
1117 1117                  "remote",
1118 1118                  NULL,
1119 1119          };
1120 1120  
1121 1121          while (*addrarg != '\0') {
1122 1122                  option = getsubopt(&addrarg, addr_optstr, &val);
1123 1123                  switch (option) {
1124 1124                  case A_LOCAL:
1125 1125                          if (laddr != NULL)
1126 1126                                  die("Multiple local addresses provided");
1127 1127                          laddr = val;
1128 1128                          break;
1129 1129                  case A_REMOTE:
1130 1130                          if (raddr != NULL)
1131 1131                                  die("Multiple remote addresses provided");
1132 1132                          raddr = val;
1133 1133                          break;
1134 1134                  default:
1135 1135                          if (found_mismatch)
1136 1136                                  die("Invalid address provided\nusage: %s", use);
1137 1137                          found_mismatch = _B_TRUE;
1138 1138                          break;
1139 1139                  }
1140 1140          }
1141 1141          if (raddr != NULL && laddr == NULL)
1142 1142                  die("Missing local address\nusage: %s", use);
1143 1143  
1144 1144          /* If only one address is provided, it is assumed a local address. */
1145 1145          if (laddr == NULL) {
1146 1146                  if (found_mismatch)
1147 1147                          laddr = save_input_arg;
1148 1148                  else
1149 1149                          die("Missing local address\nusage: %s", use);
1150 1150          }
1151 1151  
1152 1152          /* Initialize the addrobj for static addresses. */
1153 1153          status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
1154 1154          if (status != IPADM_SUCCESS) {
1155 1155                  die("Error in creating address object: %s",
1156 1156                      ipadm_status2str(status));
1157 1157          }
1158 1158  
1159 1159          /* Set the local and remote addresses */
1160 1160          status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
1161 1161          if (status != IPADM_SUCCESS) {
1162 1162                  die("Error in setting local address: %s",
1163 1163                      ipadm_status2str(status));
1164 1164          }
1165 1165          if (raddr != NULL) {
1166 1166                  status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
1167 1167                  if (status != IPADM_SUCCESS) {
1168 1168                          die("Error in setting remote address: %s",
1169 1169                              ipadm_status2str(status));
1170 1170                  }
1171 1171          }
1172 1172  }
1173 1173  
1174 1174  static void
1175 1175  process_addrconf_addrargs(const char *use, char *addrarg)
1176 1176  {
1177 1177          int             option;
1178 1178          char            *val;
1179 1179          enum            { P_STATELESS, P_STATEFUL };
1180 1180          static char     *addr_optstr[] = {
1181 1181                  "stateless",
1182 1182                  "stateful",
1183 1183                  NULL,
1184 1184          };
1185 1185          boolean_t       stateless;
1186 1186          boolean_t       stateless_arg = _B_FALSE;
1187 1187          boolean_t       stateful;
1188 1188          boolean_t       stateful_arg = _B_FALSE;
1189 1189          ipadm_status_t  status;
1190 1190  
1191 1191          while (*addrarg != '\0') {
1192 1192                  option = getsubopt(&addrarg, addr_optstr, &val);
1193 1193                  switch (option) {
1194 1194                  case P_STATELESS:
1195 1195                          if (stateless_arg)
1196 1196                                  die("Duplicate option");
1197 1197                          if (strcmp(val, "yes") == 0)
1198 1198                                  stateless = _B_TRUE;
1199 1199                          else if (strcmp(val, "no") == 0)
1200 1200                                  stateless = _B_FALSE;
1201 1201                          else
1202 1202                                  die("Invalid argument");
1203 1203                          stateless_arg = _B_TRUE;
1204 1204                          break;
1205 1205                  case P_STATEFUL:
1206 1206                          if (stateful_arg)
1207 1207                                  die("Duplicate option");
1208 1208                          if (strcmp(val, "yes") == 0)
1209 1209                                  stateful = _B_TRUE;
1210 1210                          else if (strcmp(val, "no") == 0)
1211 1211                                  stateful = _B_FALSE;
1212 1212                          else
1213 1213                                  die("Invalid argument");
1214 1214                          stateful_arg = _B_TRUE;
1215 1215                          break;
1216 1216                  default:
1217 1217                          die_opterr(optopt, option, use);
1218 1218                  }
1219 1219          }
1220 1220  
1221 1221          if (!stateless_arg && !stateful_arg)
1222 1222                  die("Invalid arguments for option -p");
1223 1223  
1224 1224          /* Set the addrobj fields for addrconf */
1225 1225          if (stateless_arg) {
1226 1226                  status = ipadm_set_stateless(ipaddr, stateless);
1227 1227                  if (status != IPADM_SUCCESS) {
1228 1228                          die("Error in setting stateless option: %s",
1229 1229                              ipadm_status2str(status));
1230 1230                  }
1231 1231          }
1232 1232          if (stateful_arg) {
1233 1233                  status = ipadm_set_stateful(ipaddr, stateful);
1234 1234                  if (status != IPADM_SUCCESS) {
1235 1235                          die("Error in setting stateful option: %s",
1236 1236                              ipadm_status2str(status));
1237 1237                  }
1238 1238          }
1239 1239  }
1240 1240  
1241 1241  /*
1242 1242   * Creates static, dhcp or addrconf addresses and associates the created
1243 1243   * addresses with the specified address object name.
1244 1244   */
1245 1245  static void
1246 1246  do_create_addr(int argc, char *argv[], const char *use)
1247 1247  {
1248 1248          ipadm_status_t  status;
1249 1249          int             option;
1250 1250          uint32_t        flags =
1251 1251              IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
1252 1252          char            *cp;
1253 1253          char            *atype = NULL;
1254 1254          char            *static_arg = NULL;
1255 1255          char            *addrconf_arg = NULL;
1256 1256          char            *interface_id = NULL;
1257 1257          char            *wait = NULL;
1258 1258          boolean_t       s_opt = _B_FALSE;       /* static addr options */
1259 1259          boolean_t       auto_opt = _B_FALSE;    /* Addrconf options */
1260 1260          boolean_t       dhcp_opt = _B_FALSE;    /* dhcp options */
1261 1261  
1262 1262          opterr = 0;
1263 1263          while ((option = getopt_long(argc, argv, ":T:a:di:p:w:t",
1264 1264              addr_longopts, NULL)) != -1) {
1265 1265                  switch (option) {
1266 1266                  case 'T':
1267 1267                          atype = optarg;
1268 1268                          break;
1269 1269                  case 'a':
1270 1270                          static_arg = optarg;
1271 1271                          s_opt = _B_TRUE;
1272 1272                          break;
1273 1273                  case 'd':
1274 1274                          flags &= ~IPADM_OPT_UP;
1275 1275                          s_opt = _B_TRUE;
1276 1276                          break;
1277 1277                  case 'i':
1278 1278                          interface_id = optarg;
1279 1279                          auto_opt = _B_TRUE;
1280 1280                          break;
1281 1281                  case 'p':
1282 1282                          addrconf_arg = optarg;
1283 1283                          auto_opt = _B_TRUE;
1284 1284                          break;
1285 1285                  case 'w':
1286 1286                          wait = optarg;
1287 1287                          dhcp_opt = _B_TRUE;
1288 1288                          break;
1289 1289                  case 't':
1290 1290                          flags &= ~IPADM_OPT_PERSIST;
1291 1291                          break;
1292 1292                  default:
1293 1293                          die_opterr(optopt, option, use);
1294 1294                  }
1295 1295          }
1296 1296          if (atype == NULL || optind != (argc - 1)) {
1297 1297                  die("Invalid arguments\nusage: %s", use);
1298 1298          } else if ((cp = strchr(argv[optind], '/')) == NULL ||
1299 1299              strlen(++cp) == 0) {
1300 1300                  die("invalid address object name: %s\nusage: %s",
1301 1301                      argv[optind], use);
1302 1302          }
1303 1303  
1304 1304          /*
1305 1305           * Allocate and initialize the addrobj based on the address type.
1306 1306           */
1307 1307          if (strcmp(atype, "static") == 0) {
1308 1308                  if (static_arg == NULL || auto_opt || dhcp_opt) {
1309 1309                          die("Invalid arguments for type %s\nusage: %s",
1310 1310                              atype, use);
1311 1311                  }
1312 1312                  process_static_addrargs(use, static_arg, argv[optind]);
1313 1313          } else if (strcmp(atype, "dhcp") == 0) {
1314 1314                  if (auto_opt || s_opt) {
1315 1315                          die("Invalid arguments for type %s\nusage: %s",
1316 1316                              atype, use);
1317 1317                  }
1318 1318  
1319 1319                  /* Initialize the addrobj for dhcp addresses. */
1320 1320                  status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
1321 1321                      &ipaddr);
1322 1322                  if (status != IPADM_SUCCESS) {
1323 1323                          die("Error in creating address object: %s",
1324 1324                              ipadm_status2str(status));
1325 1325                  }
1326 1326                  if (wait != NULL) {
1327 1327                          int32_t ipadm_wait;
1328 1328  
1329 1329                          if (strcmp(wait, "forever") == 0) {
1330 1330                                  ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
1331 1331                          } else {
1332 1332                                  char *end;
1333 1333                                  long timeout = strtol(wait, &end, 10);
1334 1334  
1335 1335                                  if (*end != '\0' || timeout < 0)
1336 1336                                          die("Invalid argument");
1337 1337                                  ipadm_wait = (int32_t)timeout;
1338 1338                          }
1339 1339                          status = ipadm_set_wait_time(ipaddr, ipadm_wait);
1340 1340                          if (status != IPADM_SUCCESS) {
1341 1341                                  die("Error in setting wait time: %s",
1342 1342                                      ipadm_status2str(status));
1343 1343                          }
1344 1344                  }
1345 1345          } else if (strcmp(atype, "addrconf") == 0) {
1346 1346                  if (dhcp_opt || s_opt) {
1347 1347                          die("Invalid arguments for type %s\nusage: %s",
1348 1348                              atype, use);
1349 1349                  }
1350 1350  
1351 1351                  /* Initialize the addrobj for dhcp addresses. */
1352 1352                  status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
1353 1353                      argv[optind], &ipaddr);
1354 1354                  if (status != IPADM_SUCCESS) {
1355 1355                          die("Error in creating address object: %s",
1356 1356                              ipadm_status2str(status));
1357 1357                  }
1358 1358                  if (interface_id != NULL) {
1359 1359                          status = ipadm_set_interface_id(ipaddr, interface_id);
1360 1360                          if (status != IPADM_SUCCESS) {
1361 1361                                  die("Error in setting interface ID: %s",
1362 1362                                      ipadm_status2str(status));
1363 1363                          }
1364 1364                  }
1365 1365                  if (addrconf_arg)
1366 1366                          process_addrconf_addrargs(use, addrconf_arg);
1367 1367          } else {
1368 1368                  die("Invalid address type %s", atype);
1369 1369          }
1370 1370  
1371 1371          status = ipadm_create_addr(iph, ipaddr, flags);
1372 1372          if (status == IPADM_DHCP_IPC_TIMEOUT)
1373 1373                  warn_ipadmerr(status, "");
1374 1374          else if (status != IPADM_SUCCESS)
1375 1375                  die("Could not create address: %s", ipadm_status2str(status));
1376 1376  }
1377 1377  
1378 1378  /*
1379 1379   * Used by some address management functions to parse the command line
1380 1380   * arguments and create `ipaddr' address object.
1381 1381   */
1382 1382  static void
1383 1383  process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
1384 1384      uint32_t *flags)
1385 1385  {
1386 1386          int             option;
1387 1387  
1388 1388          opterr = 0;
1389 1389          while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
1390 1390              NULL)) != -1) {
1391 1391                  switch (option) {
1392 1392                  case 't':
1393 1393                          *flags &= ~IPADM_OPT_PERSIST;
1394 1394                          break;
1395 1395                  default:
1396 1396                          die_opterr(optopt, option, use);
1397 1397                  }
1398 1398          }
1399 1399          if (optind != (argc - 1))
1400 1400                  die("Usage: %s", use);
1401 1401  
1402 1402          *index = optind;
1403 1403  }
1404 1404  
1405 1405  /*
1406 1406   * Remove an addrobj from both active and persistent configuration.
1407 1407   */
1408 1408  static void
1409 1409  do_delete_addr(int argc, char *argv[], const char *use)
1410 1410  {
1411 1411          ipadm_status_t  status;
1412 1412          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1413 1413          int             option;
1414 1414  
1415 1415          opterr = 0;
1416 1416          while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
1417 1417              NULL)) != -1) {
1418 1418                  switch (option) {
1419 1419                  case 'r':
1420 1420                          flags |= IPADM_OPT_RELEASE;
1421 1421                          break;
1422 1422                  default:
1423 1423                          die_opterr(optopt, option, use);
1424 1424                  }
1425 1425          }
1426 1426          if (optind != (argc - 1))
1427 1427                  die("Usage: %s", use);
1428 1428  
1429 1429          status = ipadm_delete_addr(iph, argv[optind], flags);
1430 1430          if (status != IPADM_SUCCESS) {
1431 1431                  die("could not delete address: %s",
1432 1432                      ipadm_status2str(status));
1433 1433          }
1434 1434  }
1435 1435  
1436 1436  /*
1437 1437   * Enable an IP address based on the persistent configuration for that
1438 1438   * IP address
1439 1439   */
1440 1440  static void
1441 1441  do_enable_addr(int argc, char *argv[], const char *use)
1442 1442  {
1443 1443          ipadm_status_t  status;
1444 1444          int             index;
1445 1445          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1446 1446  
1447 1447          process_misc_addrargs(argc, argv, use, &index, &flags);
1448 1448          if (flags & IPADM_OPT_PERSIST)
1449 1449                  die("persistent operation not supported for enable-addr");
1450 1450  
1451 1451          status = ipadm_enable_addr(iph, argv[index], flags);
1452 1452          if (status != IPADM_SUCCESS)
1453 1453                  die("could not enable address: %s", ipadm_status2str(status));
1454 1454  }
1455 1455  
1456 1456  /*
1457 1457   * Mark the address identified by addrobj 'up'
1458 1458   */
1459 1459  static void
1460 1460  do_up_addr(int argc, char *argv[], const char *use)
1461 1461  {
1462 1462          ipadm_status_t  status;
1463 1463          int             index;
1464 1464          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1465 1465  
1466 1466          process_misc_addrargs(argc, argv, use, &index, &flags);
1467 1467          status = ipadm_up_addr(iph, argv[index], flags);
1468 1468          if (status != IPADM_SUCCESS) {
1469 1469                  die("Could not mark the address up: %s",
1470 1470                      ipadm_status2str(status));
1471 1471          }
1472 1472  }
1473 1473  
1474 1474  /*
1475 1475   * Disable the specified addrobj by removing it from active cofiguration
1476 1476   */
1477 1477  static void
1478 1478  do_disable_addr(int argc, char *argv[], const char *use)
1479 1479  {
1480 1480          ipadm_status_t  status;
1481 1481          int             index;
1482 1482          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1483 1483  
1484 1484          process_misc_addrargs(argc, argv, use, &index, &flags);
1485 1485          if (flags & IPADM_OPT_PERSIST)
1486 1486                  die("persistent operation not supported for disable-addr");
1487 1487  
1488 1488          status = ipadm_disable_addr(iph, argv[index], flags);
1489 1489          if (status != IPADM_SUCCESS) {
1490 1490                  die("could not disable address: %s",
1491 1491                      ipadm_status2str(status));
1492 1492          }
1493 1493  }
1494 1494  
1495 1495  /*
1496 1496   * Mark the address identified by addrobj 'down'
1497 1497   */
1498 1498  static void
1499 1499  do_down_addr(int argc, char *argv[], const char *use)
1500 1500  {
1501 1501          ipadm_status_t  status;
1502 1502          int             index;
1503 1503          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1504 1504  
1505 1505          process_misc_addrargs(argc, argv, use, &index, &flags);
1506 1506          status = ipadm_down_addr(iph, argv[index], flags);
1507 1507          if (status != IPADM_SUCCESS)
1508 1508                  die("Could not mark the address down: %s",
1509 1509                      ipadm_status2str(status));
1510 1510  }
1511 1511  
1512 1512  /*
1513 1513   * Restart DAD for static address. Extend lease duration for DHCP addresses
1514 1514   */
1515 1515  static void
1516 1516  do_refresh_addr(int argc, char *argv[], const char *use)
1517 1517  {
1518 1518          ipadm_status_t  status;
1519 1519          int             option;
1520 1520          uint32_t        flags = 0;
1521 1521  
1522 1522          opterr = 0;
1523 1523          while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
1524 1524              NULL)) != -1) {
1525 1525                  switch (option) {
1526 1526                  case 'i':
1527 1527                          flags |= IPADM_OPT_INFORM;
1528 1528                          break;
1529 1529                  default:
1530 1530                          die_opterr(optopt, option, use);
1531 1531                  }
1532 1532          }
1533 1533          if (optind != (argc - 1))
1534 1534                  die("Usage: %s", use);
1535 1535  
1536 1536          status = ipadm_refresh_addr(iph, argv[optind], flags);
1537 1537          if (status == IPADM_DHCP_IPC_TIMEOUT)
1538 1538                  warn_ipadmerr(status, "");
1539 1539          else if (status != IPADM_SUCCESS)
1540 1540                  die("could not refresh address %s", ipadm_status2str(status));
1541 1541  }
1542 1542  
1543 1543  static void
1544 1544  sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
1545 1545  {
1546 1546          socklen_t socklen;
1547 1547          struct sockaddr *sp = (struct sockaddr *)ssp;
1548 1548  
1549 1549          switch (ssp->ss_family) {
1550 1550          case AF_INET:
1551 1551                  socklen = sizeof (struct sockaddr_in);
1552 1552                  break;
1553 1553          case AF_INET6:
1554 1554                  socklen = sizeof (struct sockaddr_in6);
1555 1555                  break;
1556 1556          default:
1557 1557                  (void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
1558 1558                  return;
1559 1559          }
1560 1560  
1561 1561          (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
1562 1562              (NI_NOFQDN | NI_NUMERICHOST));
1563 1563  }
1564 1564  
1565 1565  static void
1566 1566  flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
1567 1567      char *buf, uint_t bufsize)
1568 1568  {
1569 1569          int             i;
1570 1570          boolean_t       first = _B_TRUE;
1571 1571  
1572 1572          if (is_bits) {
1573 1573                  for (i = 0;  tbl[i].name; i++) {
1574 1574                          if ((flags & tbl[i].mask) == tbl[i].bits)
1575 1575                                  (void) strlcat(buf, tbl[i].name, bufsize);
1576 1576                          else
1577 1577                                  (void) strlcat(buf, "-", bufsize);
1578 1578                  }
1579 1579          } else {
1580 1580                  for (i = 0; tbl[i].name; i++) {
1581 1581                          if ((flags & tbl[i].mask) == tbl[i].bits) {
1582 1582                                  if (!first)
1583 1583                                          (void) strlcat(buf, ",", bufsize);
1584 1584                                  (void) strlcat(buf, tbl[i].name, bufsize);
1585 1585                                  first = _B_FALSE;
1586 1586                          }
1587 1587                  }
1588 1588          }
1589 1589  }
1590 1590  
1591 1591  /*
1592 1592   * return true if the address for lifname comes to us from the global zone
1593 1593   * with 'allowed-ips' constraints.
1594 1594   */
1595 1595  static boolean_t
1596 1596  is_from_gz(const char *lifname)
1597 1597  {
1598 1598          ipadm_if_info_t         *if_info;
1599 1599          char                    phyname[LIFNAMSIZ], *cp;
1600 1600          boolean_t               ret = _B_FALSE;
1601 1601          ipadm_status_t          status;
1602 1602          zoneid_t                zoneid;
1603 1603          ushort_t                zflags;
1604 1604  
1605 1605          if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1606 1606                  return (_B_FALSE); /* from-gz only  makes sense in a NGZ */
1607 1607  
1608 1608          if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1609 1609                  return (_B_FALSE);
1610 1610  
1611 1611          if (!(zflags & ZF_NET_EXCL))
1612 1612                  return (_B_TRUE);  /* everything is from the GZ for shared-ip */
1613 1613  
1614 1614          (void) strncpy(phyname, lifname, sizeof (phyname));
1615 1615          if ((cp = strchr(phyname, ':')) != NULL)
1616 1616                  *cp = '\0';
1617 1617          status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1618 1618          if (status != IPADM_SUCCESS)
1619 1619                  return (ret);
1620 1620  
1621 1621          if (if_info->ifi_cflags & IFIF_L3PROTECT)
1622 1622                  ret = _B_TRUE;
1623 1623          if (if_info)
1624 1624                  ipadm_free_if_info(if_info);
1625 1625          return (ret);
1626 1626  }
1627 1627  
1628 1628  static boolean_t
1629 1629  print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1630 1630  {
1631 1631          show_addr_args_t        *arg = ofarg->ofmt_cbarg;
1632 1632          ipadm_addr_info_t       *ainfo = arg->sa_info;
1633 1633          char                    interface[LIFNAMSIZ];
1634 1634          char                    addrbuf[MAXPROPVALLEN];
1635 1635          char                    dstbuf[MAXPROPVALLEN];
1636 1636          char                    prefixlenstr[MAXPROPVALLEN];
1637 1637          int                     prefixlen;
1638 1638          struct sockaddr_in      *sin;
1639 1639          struct sockaddr_in6     *sin6;
1640 1640          sa_family_t             af;
1641 1641          char                    *phyname = NULL;
1642 1642          struct ifaddrs          *ifa = &ainfo->ia_ifa;
1643 1643          fmask_t cflags_mask[] = {
1644 1644                  { "U",  IA_UP,                  IA_UP           },
1645 1645                  { "u",  IA_UNNUMBERED,          IA_UNNUMBERED   },
1646 1646                  { "p",  IA_PRIVATE,             IA_PRIVATE      },
1647 1647                  { "t",  IA_TEMPORARY,           IA_TEMPORARY    },
1648 1648                  { "d",  IA_DEPRECATED,          IA_DEPRECATED   },
1649 1649                  { NULL,         0,                      0       }
1650 1650          };
1651 1651          fmask_t pflags_mask[] = {
1652 1652                  { "U",  IA_UP,                  IA_UP           },
1653 1653                  { "p",  IA_PRIVATE,             IA_PRIVATE      },
1654 1654                  { "d",  IA_DEPRECATED,          IA_DEPRECATED   },
1655 1655                  { NULL,         0,                      0       }
1656 1656          };
1657 1657          fmask_t type[] = {
1658 1658                  { "static",     IPADM_ADDR_STATIC,      IPADM_ALL_BITS},
1659 1659                  { "addrconf",   IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
1660 1660                  { "dhcp",       IPADM_ADDR_DHCP,        IPADM_ALL_BITS},
1661 1661                  { NULL,         0,                      0       }
1662 1662          };
1663 1663          fmask_t addr_state[] = {
1664 1664                  { "disabled",   IFA_DISABLED,   IPADM_ALL_BITS},
1665 1665                  { "duplicate",  IFA_DUPLICATE,  IPADM_ALL_BITS},
1666 1666                  { "down",       IFA_DOWN,       IPADM_ALL_BITS},
1667 1667                  { "tentative",  IFA_TENTATIVE,  IPADM_ALL_BITS},
1668 1668                  { "ok",         IFA_OK,         IPADM_ALL_BITS},
1669 1669                  { "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
1670 1670                  { NULL,         0,              0       }
1671 1671          };
1672 1672  
1673 1673          buf[0] = '\0';
1674 1674          switch (ofarg->ofmt_id) {
1675 1675          case SA_ADDROBJ:
1676 1676                  if (ainfo->ia_aobjname[0] == '\0') {
1677 1677                          (void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
1678 1678                          phyname = strrchr(interface, ':');
1679 1679                          if (phyname)
1680 1680                                  *phyname = '\0';
1681 1681                          (void) snprintf(buf, bufsize, "%s/%s", interface,
1682 1682                              STR_UNKNOWN_VAL);
1683 1683                  } else {
1684 1684                          (void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
1685 1685                  }
1686 1686                  break;
1687 1687          case SA_STATE:
1688 1688                  flags2str(ainfo->ia_state, addr_state, _B_FALSE,
1689 1689                      buf, bufsize);
1690 1690                  break;
1691 1691          case SA_TYPE:
1692 1692                  if (is_from_gz(ifa->ifa_name))
1693 1693                          (void) snprintf(buf, bufsize, "from-gz");
1694 1694                  else
1695 1695                          flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1696 1696                              bufsize);
1697 1697                  break;
1698 1698          case SA_CURRENT:
1699 1699                  flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
1700 1700                  break;
1701 1701          case SA_PERSISTENT:
1702 1702                  flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
1703 1703                  break;
1704 1704          case SA_ADDR:
1705 1705                  af = ifa->ifa_addr->sa_family;
1706 1706                  /*
1707 1707                   * If the address is 0.0.0.0 or :: and the origin is DHCP,
1708 1708                   * print STR_UNKNOWN_VAL.
1709 1709                   */
1710 1710                  if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
1711 1711                          sin = (struct sockaddr_in *)ifa->ifa_addr;
1712 1712                          sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1713 1713                          if ((af == AF_INET &&
1714 1714                              sin->sin_addr.s_addr == INADDR_ANY) ||
1715 1715                              (af == AF_INET6 &&
1716 1716                              IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
1717 1717                                  (void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
1718 1718                                  break;
1719 1719                          }
1720 1720                  }
1721 1721                  if (ifa->ifa_netmask == NULL)
1722 1722                          prefixlen = 0;
1723 1723                  else
1724 1724                          prefixlen = mask2plen(ifa->ifa_netmask);
1725 1725                  bzero(prefixlenstr, sizeof (prefixlenstr));
1726 1726                  if (prefixlen > 0) {
1727 1727                          (void) snprintf(prefixlenstr, sizeof (prefixlenstr),
1728 1728                              "/%d", prefixlen);
1729 1729                  }
1730 1730                  bzero(addrbuf, sizeof (addrbuf));
1731 1731                  bzero(dstbuf, sizeof (dstbuf));
1732 1732                  if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
1733 1733                          /*
1734 1734                           * Print the hostname fields if the address is not
1735 1735                           * in active configuration.
1736 1736                           */
1737 1737                          if (ainfo->ia_state == IFA_DISABLED) {
1738 1738                                  (void) snprintf(buf, bufsize, "%s",
1739 1739                                      ainfo->ia_sname);
1740 1740                                  if (ainfo->ia_dname[0] != '\0') {
1741 1741                                          (void) snprintf(dstbuf, sizeof (dstbuf),
1742 1742                                              "->%s", ainfo->ia_dname);
1743 1743                                          (void) strlcat(buf, dstbuf, bufsize);
1744 1744                                  } else {
1745 1745                                          (void) strlcat(buf, prefixlenstr,
1746 1746                                              bufsize);
1747 1747                                  }
1748 1748                                  break;
1749 1749                          }
1750 1750                  }
1751 1751                  /*
1752 1752                   * For the non-persistent case, we need to show the
1753 1753                   * currently configured addresses for source and
1754 1754                   * destination.
1755 1755                   */
1756 1756                  sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
1757 1757                      addrbuf, sizeof (addrbuf));
1758 1758                  if (ifa->ifa_flags & IFF_POINTOPOINT) {
1759 1759                          sockaddr2str(
1760 1760                              (struct sockaddr_storage *)ifa->ifa_dstaddr,
1761 1761                              dstbuf, sizeof (dstbuf));
1762 1762                          (void) snprintf(buf, bufsize, "%s->%s", addrbuf,
1763 1763                              dstbuf);
1764 1764                  } else {
1765 1765                          (void) snprintf(buf, bufsize, "%s%s", addrbuf,
1766 1766                              prefixlenstr);
1767 1767                  }
1768 1768                  break;
1769 1769          default:
1770 1770                  die("invalid input");
1771 1771                  break;
1772 1772          }
1773 1773  
1774 1774          return (_B_TRUE);
1775 1775  }
1776 1776  
1777 1777  /*
1778 1778   * Display address information, either for the given address or
1779 1779   * for all the addresses managed by ipadm.
1780 1780   */
1781 1781  static void
1782 1782  do_show_addr(int argc, char *argv[], const char *use)
1783 1783  {
1784 1784          ipadm_status_t          status;
1785 1785          show_addr_state_t       state;
1786 1786          char                    *def_fields_str = "addrobj,type,state,addr";
1787 1787          char                    *fields_str = NULL;
1788 1788          ipadm_addr_info_t       *ainfo;
1789 1789          ipadm_addr_info_t       *ptr;
1790 1790          show_addr_args_t        sargs;
1791 1791          int                     option;
1792 1792          ofmt_handle_t           ofmt;
1793 1793          ofmt_status_t           oferr;
1794 1794          uint_t                  ofmtflags = 0;
1795 1795          char                    *aname;
1796 1796          char                    *ifname = NULL;
1797 1797          char                    *cp;
1798 1798          boolean_t               found = _B_FALSE;
1799 1799  
1800 1800          opterr = 0;
1801 1801          state.sa_parsable = _B_FALSE;
1802 1802          state.sa_persist = _B_FALSE;
1803 1803          while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
1804 1804              NULL)) != -1) {
1805 1805                  switch (option) {
1806 1806                  case 'p':
1807 1807                          state.sa_parsable = _B_TRUE;
1808 1808                          break;
1809 1809                  case 'o':
1810 1810                          fields_str = optarg;
1811 1811                          break;
1812 1812                  default:
1813 1813                          die_opterr(optopt, option, use);
1814 1814                          break;
1815 1815                  }
1816 1816          }
1817 1817          if (state.sa_parsable && fields_str == NULL)
1818 1818                  die("-p requires -o");
1819 1819  
1820 1820          if (optind == argc - 1) {
1821 1821                  aname = argv[optind];
1822 1822                  if ((cp = strchr(aname, '/')) == NULL)
1823 1823                          die("Invalid address object name provided");
1824 1824                  if (*(cp + 1) == '\0') {
1825 1825                          ifname = aname;
1826 1826                          *cp = '\0';
1827 1827                          aname = NULL;
1828 1828                  }
1829 1829          } else if (optind == argc) {
1830 1830                  aname = NULL;
1831 1831          } else {
1832 1832                  die("Usage: %s", use);
1833 1833          }
1834 1834  
1835 1835          if (state.sa_parsable)
1836 1836                  ofmtflags |= OFMT_PARSABLE;
1837 1837          if (fields_str == NULL)
1838 1838                  fields_str = def_fields_str;
1839 1839          oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
1840 1840  
1841 1841          ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
1842 1842          state.sa_ofmt = ofmt;
1843 1843  
1844 1844          status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
1845 1845          /*
1846 1846           * Return without printing any error, if no addresses were found,
1847 1847           * for the case where all addresses are requested.
1848 1848           */
1849 1849          if (status != IPADM_SUCCESS)
1850 1850                  die("Could not get address: %s", ipadm_status2str(status));
1851 1851          if (ainfo == NULL) {
1852 1852                  ofmt_close(ofmt);
1853 1853                  return;
1854 1854          }
1855 1855  
1856 1856          bzero(&sargs, sizeof (sargs));
1857 1857          sargs.sa_state = &state;
1858 1858          for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
1859 1859                  sargs.sa_info = ptr;
1860 1860                  if (aname != NULL) {
1861 1861                          if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
1862 1862                                  continue;
1863 1863                          found = _B_TRUE;
1864 1864                  }
1865 1865                  ofmt_print(state.sa_ofmt, &sargs);
1866 1866          }
1867 1867          if (ainfo)
1868 1868                  ipadm_free_addr_info(ainfo);
1869 1869          if (aname != NULL && !found)
1870 1870                  die("Address object not found");
1871 1871  }
1872 1872  
1873 1873  static boolean_t
1874 1874  print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1875 1875  {
1876 1876          show_if_args_t          *arg = ofarg->ofmt_cbarg;
1877 1877          ipadm_if_info_t         *ifinfo = arg->si_info;
1878 1878          char                    *ifname = ifinfo->ifi_name;
1879 1879          fmask_t intf_state[] = {
1880 1880                  { "ok",         IFIS_OK,        IPADM_ALL_BITS},
1881 1881                  { "down",       IFIS_DOWN,      IPADM_ALL_BITS},
1882 1882                  { "disabled",   IFIS_DISABLED,  IPADM_ALL_BITS},
1883 1883                  { "failed",     IFIS_FAILED,    IPADM_ALL_BITS},
1884 1884                  { "offline",    IFIS_OFFLINE,   IPADM_ALL_BITS},
1885 1885                  { NULL,         0,              0       }
1886 1886          };
1887 1887          fmask_t intf_pflags[] = {
1888 1888                  { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
1889 1889                  { "4",  IFIF_IPV4,              IFIF_IPV4       },
1890 1890                  { "6",  IFIF_IPV6,              IFIF_IPV6       },
1891 1891                  { NULL, 0,                      0               }
1892 1892          };
1893 1893          fmask_t intf_cflags[] = {
1894 1894                  { "b",  IFIF_BROADCAST,         IFIF_BROADCAST  },
1895 1895                  { "m",  IFIF_MULTICAST,         IFIF_MULTICAST  },
1896 1896                  { "p",  IFIF_POINTOPOINT,       IFIF_POINTOPOINT},
1897 1897                  { "v",  IFIF_VIRTUAL,           IFIF_VIRTUAL    },
1898 1898                  { "I",  IFIF_IPMP,              IFIF_IPMP       },
1899 1899                  { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
1900 1900                  { "i",  IFIF_INACTIVE,          IFIF_INACTIVE   },
1901 1901                  { "V",  IFIF_VRRP,              IFIF_VRRP       },
1902 1902                  { "a",  IFIF_NOACCEPT,          IFIF_NOACCEPT   },
1903 1903                  { "Z",  IFIF_L3PROTECT,         IFIF_L3PROTECT  },
1904 1904                  { "4",  IFIF_IPV4,              IFIF_IPV4       },
1905 1905                  { "6",  IFIF_IPV6,              IFIF_IPV6       },
1906 1906                  { NULL, 0,                      0               }
1907 1907          };
1908 1908  
1909 1909          buf[0] = '\0';
1910 1910          switch (ofarg->ofmt_id) {
1911 1911          case SI_IFNAME:
1912 1912                  (void) snprintf(buf, bufsize, "%s", ifname);
1913 1913                  break;
1914 1914          case SI_STATE:
1915 1915                  flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1916 1916                      buf, bufsize);
1917 1917                  break;
1918 1918          case SI_CURRENT:
1919 1919                  flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1920 1920                      buf, bufsize);
1921 1921                  break;
1922 1922          case SI_PERSISTENT:
1923 1923                  flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
1924 1924                      buf, bufsize);
1925 1925                  break;
1926 1926          default:
1927 1927                  die("invalid input");
1928 1928                  break;
1929 1929          }
1930 1930  
1931 1931          return (_B_TRUE);
1932 1932  }
1933 1933  
1934 1934  /*
1935 1935   * Display interface information, either for the given interface or
1936 1936   * for all the interfaces in the system.
1937 1937   */
1938 1938  static void
1939 1939  do_show_if(int argc, char *argv[], const char *use)
1940 1940  {
1941 1941          ipadm_status_t          status;
1942 1942          show_if_state_t         state;
1943 1943          char                    *fields_str = NULL;
1944 1944          ipadm_if_info_t         *if_info, *ptr;
1945 1945          show_if_args_t          sargs;
1946 1946          int                     option;
1947 1947          ofmt_handle_t           ofmt;
1948 1948          ofmt_status_t           oferr;
1949 1949          uint_t                  ofmtflags = 0;
1950 1950          char                    *ifname = NULL;
1951 1951  
1952 1952          opterr = 0;
1953 1953          state.si_parsable = _B_FALSE;
1954 1954  
1955 1955          while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
1956 1956              NULL)) != -1) {
1957 1957                  switch (option) {
1958 1958                  case 'p':
1959 1959                          state.si_parsable = _B_TRUE;
1960 1960                          break;
1961 1961                  case 'o':
1962 1962                          fields_str = optarg;
1963 1963                          break;
1964 1964                  default:
1965 1965                          die_opterr(optopt, option, use);
1966 1966                          break;
1967 1967                  }
1968 1968          }
1969 1969          if (optind == argc - 1)
1970 1970                  ifname = argv[optind];
1971 1971          else if (optind != argc)
1972 1972                  die("Usage: %s", use);
1973 1973          if (state.si_parsable)
1974 1974                  ofmtflags |= OFMT_PARSABLE;
1975 1975          oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
1976 1976          ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
1977 1977          state.si_ofmt = ofmt;
1978 1978          bzero(&sargs, sizeof (sargs));
1979 1979          sargs.si_state = &state;
1980 1980          status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
1981 1981          /*
1982 1982           * Return without printing any error, if no addresses were found.
1983 1983           */
1984 1984          if (status != IPADM_SUCCESS) {
1985 1985                  die("Could not get interface(s): %s",
1986 1986                      ipadm_status2str(status));
1987 1987          }
1988 1988  
1989 1989          for (ptr = if_info; ptr; ptr = ptr->ifi_next) {
1990 1990                  sargs.si_info = ptr;
1991 1991                  ofmt_print(state.si_ofmt, &sargs);
1992 1992          }
1993 1993          if (if_info)
1994 1994                  ipadm_free_if_info(if_info);
1995 1995  }
1996 1996  
1997 1997  /*
1998 1998   * set/reset the address property for a given address
1999 1999   */
2000 2000  static void
2001 2001  set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
2002 2002  {
2003 2003          int                     option;
2004 2004          ipadm_status_t          status = IPADM_SUCCESS;
2005 2005          boolean_t               p_arg = _B_FALSE;
2006 2006          char                    *nv, *aobjname;
2007 2007          char                    *prop_name, *prop_val;
2008 2008          uint_t                  flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
2009 2009  
2010 2010          opterr = 0;
2011 2011          while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
2012 2012              NULL)) != -1) {
2013 2013                  switch (option) {
2014 2014                  case 'p':
2015 2015                          if (p_arg)
2016 2016                                  die("-p must be specified once only");
2017 2017                          p_arg = _B_TRUE;
2018 2018  
2019 2019                          ipadm_check_propstr(optarg, reset, use);
2020 2020                          nv = optarg;
2021 2021                          break;
2022 2022                  case 't':
2023 2023                          flags &= ~IPADM_OPT_PERSIST;
2024 2024                          break;
2025 2025                  default:
2026 2026                          die_opterr(optopt, option, use);
2027 2027                  }
2028 2028          }
2029 2029  
2030 2030          if (!p_arg || optind != (argc - 1))
2031 2031                  die("Usage: %s", use);
2032 2032  
2033 2033          prop_name = nv;
2034 2034          prop_val = strchr(nv, '=');
2035 2035          if (prop_val != NULL)
2036 2036                  *prop_val++ = '\0';
2037 2037          aobjname = argv[optind];
2038 2038          if (reset)
2039 2039                  flags |= IPADM_OPT_DEFAULT;
2040 2040          status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
2041 2041          if (status != IPADM_SUCCESS) {
2042 2042                  if (reset)
2043 2043                          die("reset-addrprop: %s: %s", prop_name,
2044 2044                              ipadm_status2str(status));
2045 2045                  else
2046 2046                          die("set-addrprop: %s: %s", prop_name,
2047 2047                              ipadm_status2str(status));
2048 2048          }
2049 2049  }
2050 2050  
2051 2051  /*
2052 2052   * Sets a property on an address object.
2053 2053   */
2054 2054  static void
2055 2055  do_set_addrprop(int argc, char **argv, const char *use)
2056 2056  {
2057 2057          set_addrprop(argc, argv, _B_FALSE, use);
2058 2058  }
2059 2059  
2060 2060  /*
2061 2061   * Resets a property to its default value on an address object.
2062 2062   */
2063 2063  static void
2064 2064  do_reset_addrprop(int argc, char **argv, const char *use)
2065 2065  {
2066 2066          set_addrprop(argc, argv,  _B_TRUE, use);
2067 2067  }
2068 2068  
2069 2069  /*
2070 2070   * Display information for all or specific address properties, either for a
2071 2071   * given address or for all the addresses in the system.
2072 2072   */
2073 2073  static void
2074 2074  do_show_addrprop(int argc, char *argv[], const char *use)
2075 2075  {
2076 2076          int                     option;
2077 2077          nvlist_t                *proplist = NULL;
2078 2078          char                    *fields_str = NULL;
2079 2079          show_prop_state_t       state;
2080 2080          ofmt_handle_t           ofmt;
2081 2081          ofmt_status_t           oferr;
2082 2082          uint_t                  ofmtflags = 0;
2083 2083          char                    *aobjname;
2084 2084          char                    *ifname = NULL;
2085 2085          char                    *cp;
2086 2086  
2087 2087          opterr = 0;
2088 2088          bzero(&state, sizeof (state));
2089 2089          state.sps_propval = NULL;
2090 2090          state.sps_parsable = _B_FALSE;
2091 2091          state.sps_addrprop = _B_TRUE;
2092 2092          state.sps_proto = MOD_PROTO_NONE;
2093 2093          state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
2094 2094          while ((option = getopt_long(argc, argv, ":p:i:cPo:",
2095 2095              show_prop_longopts, NULL)) != -1) {
2096 2096                  switch (option) {
2097 2097                  case 'p':
2098 2098                          if (ipadm_str2nvlist(optarg, &proplist,
2099 2099                              IPADM_NORVAL) != 0)
2100 2100                                  die("invalid interface properties specified");
2101 2101                          break;
2102 2102                  case 'c':
2103 2103                          state.sps_parsable = _B_TRUE;
2104 2104                          break;
2105 2105                  case 'o':
2106 2106                          fields_str = optarg;
2107 2107                          break;
2108 2108                  default:
2109 2109                          die_opterr(optopt, option, use);
2110 2110                          break;
2111 2111                  }
2112 2112          }
2113 2113          if (optind == argc - 1) {
2114 2114                  aobjname = argv[optind];
2115 2115                  cp = strchr(aobjname, '/');
2116 2116                  if (cp == NULL)
2117 2117                          die("Invalid address object name provided");
2118 2118                  if (*(cp + 1) == '\0') {
2119 2119                          ifname = aobjname;
2120 2120                          *cp = '\0';
2121 2121                          aobjname = NULL;
2122 2122                  }
2123 2123          } else if (optind == argc) {
2124 2124                  aobjname = NULL;
2125 2125          } else {
2126 2126                  die("Usage: %s", use);
2127 2127          }
2128 2128          state.sps_proplist = proplist;
2129 2129          if (state.sps_parsable)
2130 2130                  ofmtflags |= OFMT_PARSABLE;
2131 2131          oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
2132 2132          ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
2133 2133          state.sps_ofmt = ofmt;
2134 2134  
2135 2135          if (aobjname != NULL) {
2136 2136                  (void) strlcpy(state.sps_aobjname, aobjname,
2137 2137                      sizeof (state.sps_aobjname));
2138 2138                  show_properties(&state, IPADMPROP_CLASS_ADDR);
2139 2139          } else {
2140 2140                  ipadm_addr_info_t       *ainfop = NULL;
2141 2141                  ipadm_addr_info_t       *ptr;
2142 2142                  ipadm_status_t          status;
2143 2143  
2144 2144                  status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
2145 2145                  /*
2146 2146                   * Return without printing any error, if no addresses were
2147 2147                   * found.
2148 2148                   */
2149 2149                  if (status == IPADM_NOTFOUND)
2150 2150                          return;
2151 2151                  if (status != IPADM_SUCCESS) {
2152 2152                          die("Error retrieving address: %s",
2153 2153                              ipadm_status2str(status));
2154 2154                  }
2155 2155                  for (ptr = ainfop; ptr; ptr = IA_NEXT(ptr)) {
2156 2156                          aobjname = ptr->ia_aobjname;
2157 2157                          if (aobjname[0] == '\0' ||
2158 2158                              ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
2159 2159                                  continue;
2160 2160                          }
2161 2161                          (void) strlcpy(state.sps_aobjname, aobjname,
2162 2162                              sizeof (state.sps_aobjname));
2163 2163                          show_properties(&state, IPADMPROP_CLASS_ADDR);
2164 2164                  }
2165 2165                  ipadm_free_addr_info(ainfop);
2166 2166          }
2167 2167          nvlist_free(proplist);
2168 2168          ofmt_close(ofmt);
2169 2169          if (state.sps_retstatus != IPADM_SUCCESS) {
2170 2170                  ipadm_close(iph);
2171 2171                  exit(EXIT_FAILURE);
2172 2172          }
2173 2173  }
2174 2174  
2175 2175  static void
2176 2176  ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
2177 2177      ofmt_handle_t ofmt)
2178 2178  {
2179 2179          char buf[OFMT_BUFSIZE];
2180 2180  
2181 2181          if (oferr == OFMT_SUCCESS)
2182 2182                  return;
2183 2183          (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
2184 2184          /*
2185 2185           * All errors are considered fatal in parsable mode.
2186 2186           * NOMEM errors are always fatal, regardless of mode.
2187 2187           * For other errors, we print diagnostics in human-readable
2188 2188           * mode and processs what we can.
2189 2189           */
2190 2190          if (parsable || oferr == OFMT_ENOFIELDS) {
2191 2191                  ofmt_close(ofmt);
2192 2192                  die(buf);
2193 2193          } else {
2194 2194                  warn(buf);
2195 2195          }
2196 2196  }
2197 2197  
2198 2198  /*
2199 2199   * check if the `pstr' adheres to following syntax
2200 2200   *      - prop=<value[,...]>    (for set)
2201 2201   *      - prop                  (for reset)
2202 2202   */
2203 2203  static void
2204 2204  ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
2205 2205  {
2206 2206          char    *nv;
2207 2207  
2208 2208          nv = strchr(pstr, '=');
2209 2209          if (reset) {
2210 2210                  if (nv != NULL)
2211 2211                          die("incorrect syntax used for -p.\n%s", use);
2212 2212          } else {
2213 2213                  if (nv == NULL || *++nv == '\0')
2214 2214                          die("please specify the value to be set.\n%s", use);
2215 2215                  nv = strchr(nv, '=');
2216 2216                  /* cannot have multiple 'prop=val' for single -p */
2217 2217                  if (nv != NULL)
2218 2218                          die("cannot specify more than one prop=val at "
2219 2219                              "a time.\n%s", use);
2220 2220          }
2221 2221  }
  
    | 
      ↓ open down ↓ | 
    1353 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX