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