Print this page
    
OS-792 dladm show-linkprop -z zonename doesn't restrict output to that zone, unless you also specify the vnic name
OS-406
OS-249
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/dladm/dladm.c
          +++ new/usr/src/cmd/dladm/dladm.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   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright (c) 2012 Joyent, Inc. All rights reserved.
  23   24   */
  24   25  
  25   26  #include <stdio.h>
  26   27  #include <ctype.h>
  27   28  #include <dlfcn.h>
  28   29  #include <locale.h>
  29   30  #include <signal.h>
  30   31  #include <stdarg.h>
  31   32  #include <stdlib.h>
  32   33  #include <fcntl.h>
  33   34  #include <string.h>
  34   35  #include <stropts.h>
  35   36  #include <sys/stat.h>
  36   37  #include <errno.h>
  37   38  #include <kstat.h>
  38   39  #include <strings.h>
  39   40  #include <getopt.h>
  40   41  #include <unistd.h>
  41   42  #include <priv.h>
  42   43  #include <limits.h>
  43   44  #include <termios.h>
  44   45  #include <pwd.h>
  45   46  #include <auth_attr.h>
  46   47  #include <auth_list.h>
  47   48  #include <libintl.h>
  48   49  #include <libdevinfo.h>
  49   50  #include <libdlpi.h>
  50   51  #include <libdladm.h>
  51   52  #include <libdllink.h>
  52   53  #include <libdlstat.h>
  53   54  #include <libdlaggr.h>
  54   55  #include <libdlwlan.h>
  55   56  #include <libdlvlan.h>
  56   57  #include <libdlvnic.h>
  57   58  #include <libdlib.h>
  58   59  #include <libdlether.h>
  59   60  #include <libdliptun.h>
  60   61  #include <libdlsim.h>
  61   62  #include <libdlbridge.h>
  62   63  #include <libinetutil.h>
  63   64  #include <libvrrpadm.h>
  64   65  #include <bsm/adt.h>
  65   66  #include <bsm/adt_event.h>
  66   67  #include <libdlvnic.h>
  67   68  #include <sys/types.h>
  68   69  #include <sys/socket.h>
  69   70  #include <sys/ib/ib_types.h>
  70   71  #include <sys/processor.h>
  71   72  #include <netinet/in.h>
  72   73  #include <arpa/inet.h>
  73   74  #include <net/if_types.h>
  74   75  #include <stddef.h>
  75   76  #include <stp_in.h>
  76   77  #include <ofmt.h>
  77   78  
  78   79  #define MAXPORT                 256
  79   80  #define MAXVNIC                 256
  80   81  #define BUFLEN(lim, ptr)        (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
  81   82  #define MAXLINELEN              1024
  82   83  #define SMF_UPGRADE_FILE                "/var/svc/profile/upgrade"
  83   84  #define SMF_UPGRADEDATALINK_FILE        "/var/svc/profile/upgrade_datalink"
  84   85  #define SMF_DLADM_UPGRADE_MSG           " # added by dladm(1M)"
  85   86  #define DLADM_DEFAULT_COL       80
  86   87  
  87   88  /*
  88   89   * used by the wifi show-* commands to set up ofmt_field_t structures.
  89   90   */
  90   91  #define WIFI_CMD_SCAN           0x00000001
  91   92  #define WIFI_CMD_SHOW           0x00000002
  92   93  #define WIFI_CMD_ALL            (WIFI_CMD_SCAN | WIFI_CMD_SHOW)
  93   94  
  94   95  /* No larger than pktsum_t */
  95   96  typedef struct brsum_s {
  96   97          uint64_t        drops;
  97   98          uint64_t        forward_dir;
  98   99          uint64_t        forward_mb;
  99  100          uint64_t        forward_unk;
 100  101          uint64_t        recv;
 101  102          uint64_t        sent;
 102  103  } brsum_t;
 103  104  
 104  105  /* No larger than pktsum_t */
 105  106  typedef struct brlsum_s {
 106  107          uint32_t        cfgbpdu;
 107  108          uint32_t        tcnbpdu;
 108  109          uint32_t        rstpbpdu;
 109  110          uint32_t        txbpdu;
 110  111          uint64_t        drops;
 111  112          uint64_t        recv;
 112  113          uint64_t        xmit;
 113  114  } brlsum_t;
 114  115  
 115  116  typedef struct show_state {
 116  117          boolean_t       ls_firstonly;
 117  118          boolean_t       ls_donefirst;
 118  119          pktsum_t        ls_prevstats;
 119  120          uint32_t        ls_flags;
 120  121          dladm_status_t  ls_status;
 121  122          ofmt_handle_t   ls_ofmt;
 122  123          boolean_t       ls_parsable;
 123  124          boolean_t       ls_mac;
 124  125          boolean_t       ls_hwgrp;
 125  126  } show_state_t;
 126  127  
 127  128  typedef struct show_grp_state {
 128  129          pktsum_t        gs_prevstats[MAXPORT];
 129  130          uint32_t        gs_flags;
 130  131          dladm_status_t  gs_status;
 131  132          boolean_t       gs_parsable;
 132  133          boolean_t       gs_lacp;
 133  134          boolean_t       gs_extended;
 134  135          boolean_t       gs_stats;
 135  136          boolean_t       gs_firstonly;
 136  137          boolean_t       gs_donefirst;
 137  138          ofmt_handle_t   gs_ofmt;
 138  139  } show_grp_state_t;
 139  140  
 140  141  typedef struct show_vnic_state {
 141  142          datalink_id_t   vs_vnic_id;
 142  143          datalink_id_t   vs_link_id;
 143  144          char            vs_vnic[MAXLINKNAMELEN];
 144  145          char            vs_link[MAXLINKNAMELEN];
 145  146          boolean_t       vs_parsable;
 146  147          boolean_t       vs_found;
  
    | 
      ↓ open down ↓ | 
    114 lines elided | 
    
      ↑ open up ↑ | 
  
 147  148          boolean_t       vs_firstonly;
 148  149          boolean_t       vs_donefirst;
 149  150          boolean_t       vs_stats;
 150  151          boolean_t       vs_printstats;
 151  152          pktsum_t        vs_totalstats;
 152  153          pktsum_t        vs_prevstats[MAXVNIC];
 153  154          boolean_t       vs_etherstub;
 154  155          dladm_status_t  vs_status;
 155  156          uint32_t        vs_flags;
 156  157          ofmt_handle_t   vs_ofmt;
      158 +        char            *vs_zonename;
 157  159  } show_vnic_state_t;
 158  160  
 159  161  typedef struct show_part_state {
 160  162          datalink_id_t   ps_over_id;
 161  163          char            ps_part[MAXLINKNAMELEN];
 162  164          boolean_t       ps_parsable;
 163  165          boolean_t       ps_found;
 164  166          dladm_status_t  ps_status;
 165  167          uint32_t        ps_flags;
 166  168          ofmt_handle_t   ps_ofmt;
 167  169  } show_part_state_t;
 168  170  
 169  171  typedef struct show_ib_state {
 170  172          datalink_id_t   is_link_id;
 171  173          char            is_link[MAXLINKNAMELEN];
 172  174          boolean_t       is_parsable;
 173  175          dladm_status_t  is_status;
 174  176          uint32_t        is_flags;
 175  177          ofmt_handle_t   is_ofmt;
 176  178  } show_ib_state_t;
 177  179  
 178  180  typedef struct show_usage_state_s {
 179  181          boolean_t       us_plot;
 180  182          boolean_t       us_parsable;
 181  183          boolean_t       us_printheader;
 182  184          boolean_t       us_first;
 183  185          boolean_t       us_showall;
 184  186          ofmt_handle_t   us_ofmt;
 185  187  } show_usage_state_t;
 186  188  
 187  189  /*
 188  190   * callback functions for printing output and error diagnostics.
 189  191   */
 190  192  static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb;
 191  193  static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb;
 192  194  static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb;
 193  195  static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb;
 194  196  static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb;
 195  197  static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
 196  198  
 197  199  typedef void cmdfunc_t(int, char **, const char *);
 198  200  
 199  201  static cmdfunc_t do_show_link, do_show_wifi, do_show_phys;
 200  202  static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr;
 201  203  static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr;
 202  204  static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi;
 203  205  static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop;
 204  206  static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj;
 205  207  static cmdfunc_t do_init_linkprop, do_init_secobj;
 206  208  static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan;
 207  209  static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys;
 208  210  static cmdfunc_t do_show_linkmap;
 209  211  static cmdfunc_t do_show_ether;
 210  212  static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic;
 211  213  static cmdfunc_t do_up_vnic;
 212  214  static cmdfunc_t do_create_part, do_delete_part, do_show_part, do_show_ib;
 213  215  static cmdfunc_t do_up_part;
 214  216  static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub;
 215  217  static cmdfunc_t do_create_simnet, do_modify_simnet;
 216  218  static cmdfunc_t do_delete_simnet, do_show_simnet, do_up_simnet;
 217  219  static cmdfunc_t do_show_usage;
 218  220  static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge;
 219  221  static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge;
 220  222  static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun;
 221  223  static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun;
 222  224  
 223  225  static void     do_up_vnic_common(int, char **, const char *, boolean_t);
 224  226  
 225  227  static int show_part(dladm_handle_t, datalink_id_t, void *);
 226  228  
 227  229  static void     altroot_cmd(char *, int, char **);
 228  230  static int      show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *);
 229  231  
 230  232  static void     link_stats(datalink_id_t, uint_t, char *, show_state_t *);
 231  233  static void     aggr_stats(datalink_id_t, show_grp_state_t *, uint_t);
 232  234  static void     vnic_stats(show_vnic_state_t *, uint32_t);
 233  235  
 234  236  static int      get_one_kstat(const char *, const char *, uint8_t,
 235  237                      void *, boolean_t);
 236  238  static void     get_mac_stats(const char *, pktsum_t *);
 237  239  static void     get_link_stats(const char *, pktsum_t *);
 238  240  static uint64_t get_ifspeed(const char *, boolean_t);
 239  241  static const char       *get_linkstate(const char *, boolean_t, char *);
 240  242  static const char       *get_linkduplex(const char *, boolean_t, char *);
 241  243  
 242  244  static iptun_type_t     iptun_gettypebyname(char *);
 243  245  static const char       *iptun_gettypebyvalue(iptun_type_t);
 244  246  static dladm_status_t   print_iptun(dladm_handle_t, datalink_id_t,
 245  247                              show_state_t *);
 246  248  static int      print_iptun_walker(dladm_handle_t, datalink_id_t, void *);
 247  249  
 248  250  static int      show_etherprop(dladm_handle_t, datalink_id_t, void *);
 249  251  static void     show_ether_xprop(void *, dladm_ether_info_t *);
 250  252  static boolean_t        link_is_ether(const char *, datalink_id_t *);
 251  253  
 252  254  static boolean_t str2int(const char *, int *);
 253  255  static void     die(const char *, ...);
 254  256  static void     die_optdup(int);
 255  257  static void     die_opterr(int, int, const char *);
 256  258  static void     die_dlerr(dladm_status_t, const char *, ...);
 257  259  static void     warn(const char *, ...);
  
    | 
      ↓ open down ↓ | 
    91 lines elided | 
    
      ↑ open up ↑ | 
  
 258  260  static void     warn_dlerr(dladm_status_t, const char *, ...);
 259  261  
 260  262  typedef struct  cmd {
 261  263          char            *c_name;
 262  264          cmdfunc_t       *c_fn;
 263  265          const char      *c_usage;
 264  266  } cmd_t;
 265  267  
 266  268  static cmd_t    cmds[] = {
 267  269          { "rename-link",        do_rename_link,
 268      -            "    rename-link      <oldlink> <newlink>"                  },
      270 +            "    rename-link      [-z zonename] <oldlink> <newlink>"    },
 269  271          { "show-link",          do_show_link,
 270  272              "    show-link        [-pP] [-o <field>,..] [-s [-i <interval>]] "
 271  273              "[<link>]\n"                                                },
 272  274          { "create-aggr",        do_create_aggr,
 273  275              "    create-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
 274  276              "[-u <address>]\n"
 275  277              "\t\t     -l <link> [-l <link>...] <link>"                  },
 276  278          { "delete-aggr",        do_delete_aggr,
 277  279              "    delete-aggr      [-t] <link>"                          },
 278  280          { "add-aggr",           do_add_aggr,
 279  281              "    add-aggr         [-t] -l <link> [-l <link>...] <link>" },
 280  282          { "remove-aggr",        do_remove_aggr,
 281  283              "    remove-aggr      [-t] -l <link> [-l <link>...] <link>" },
 282  284          { "modify-aggr",        do_modify_aggr,
 283  285              "    modify-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
 284  286              "[-u <address>]\n"
 285  287              "\t\t     <link>"                                           },
 286  288          { "show-aggr",          do_show_aggr,
 287  289              "    show-aggr        [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
 288  290              "[<link>]\n"                                                },
 289  291          { "up-aggr",            do_up_aggr,     NULL                    },
 290  292          { "scan-wifi",          do_scan_wifi,
 291  293              "    scan-wifi        [-p] [-o <field>,...] [<link>]"       },
 292  294          { "connect-wifi",       do_connect_wifi,
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
 293  295              "    connect-wifi     [-e <essid>] [-i <bssid>] [-k <key>,...] "
 294  296              "[-s wep|wpa]\n"
 295  297              "\t\t     [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
 296  298              "[-T <time>]\n"
 297  299              "\t\t     [<link>]"                                         },
 298  300          { "disconnect-wifi",    do_disconnect_wifi,
 299  301              "    disconnect-wifi  [-a] [<link>]"                        },
 300  302          { "show-wifi",          do_show_wifi,
 301  303              "    show-wifi        [-p] [-o <field>,...] [<link>]\n"     },
 302  304          { "set-linkprop",       do_set_linkprop,
 303      -            "    set-linkprop     [-t] -p <prop>=<value>[,...] <name>"  },
      305 +            "    set-linkprop     [-t] [-z zonename] -p <prop>=<value>[,...] "
      306 +            "<name>"                                                    },
 304  307          { "reset-linkprop",     do_reset_linkprop,
 305      -            "    reset-linkprop   [-t] [-p <prop>,...] <name>"          },
      308 +            "    reset-linkprop   [-t] [-z zonename] [-p <prop>,...] <name>"},
 306  309          { "show-linkprop",      do_show_linkprop,
 307      -            "    show-linkprop    [-cP] [-o <field>,...] [-p <prop>,...] "
 308      -            "<name>\n"                                                  },
      310 +            "    show-linkprop    [-cP] [-o <field>,...] [-z zonename] "
      311 +            "[-p <prop>,...] <name>\n"                                  },
 309  312          { "show-ether",         do_show_ether,
 310  313              "    show-ether       [-px][-o <field>,...] <link>\n"       },
 311  314          { "create-secobj",      do_create_secobj,
 312  315              "    create-secobj    [-t] [-f <file>] -c <class> <secobj>" },
 313  316          { "delete-secobj",      do_delete_secobj,
 314  317              "    delete-secobj    [-t] <secobj>[,...]"                  },
 315  318          { "show-secobj",        do_show_secobj,
 316  319              "    show-secobj      [-pP] [-o <field>,...] [<secobj>,...]\n" },
 317  320          { "init-linkprop",      do_init_linkprop,       NULL            },
 318  321          { "init-secobj",        do_init_secobj,         NULL            },
 319  322          { "create-vlan",        do_create_vlan,
 320  323              "    create-vlan      [-ft] -l <link> -v <vid> [link]"      },
 321  324          { "delete-vlan",        do_delete_vlan,
 322  325              "    delete-vlan      [-t] <link>"                          },
 323  326          { "show-vlan",          do_show_vlan,
 324  327              "    show-vlan        [-pP] [-o <field>,..] [<link>]\n"     },
 325  328          { "up-vlan",            do_up_vlan,             NULL            },
 326  329          { "create-iptun",       do_create_iptun,
 327  330              "    create-iptun     [-t] -T <type> "
 328  331              "[-a {local|remote}=<addr>,...] <link>]" },
 329  332          { "delete-iptun",       do_delete_iptun,
 330  333              "    delete-iptun     [-t] <link>"                          },
 331  334          { "modify-iptun",       do_modify_iptun,
 332  335              "    modify-iptun     [-t] -a {local|remote}=<addr>,... <link>" },
 333  336          { "show-iptun",         do_show_iptun,
 334  337              "    show-iptun       [-pP] [-o <field>,..] [<link>]\n"     },
 335  338          { "up-iptun",           do_up_iptun,            NULL            },
 336  339          { "down-iptun",         do_down_iptun,          NULL            },
 337  340          { "delete-phys",        do_delete_phys,
 338  341              "    delete-phys      <link>"                               },
 339  342          { "show-phys",          do_show_phys,
  
    | 
      ↓ open down ↓ | 
    21 lines elided | 
    
      ↑ open up ↑ | 
  
 340  343              "    show-phys        [-m | -H | -P] [[-p] [-o <field>[,...]] "
 341  344              "[<link>]\n"                                                },
 342  345          { "init-phys",          do_init_phys,           NULL            },
 343  346          { "show-linkmap",       do_show_linkmap,        NULL            },
 344  347          { "create-vnic",        do_create_vnic,
 345  348              "    create-vnic      [-t] -l <link> [-m <value> | auto |\n"
 346  349              "\t\t     {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
 347  350              "\t\t     {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
 348  351              "\t\t     [-p <prop>=<value>[,...]] <vnic-link>"    },
 349  352          { "delete-vnic",        do_delete_vnic,
 350      -            "    delete-vnic      [-t] <vnic-link>"                     },
      353 +            "    delete-vnic      [-t] [-z zonename] <vnic-link>"       },
 351  354          { "show-vnic",          do_show_vnic,
 352      -            "    show-vnic        [-pP] [-l <link>] [-s [-i <interval>]] "
 353      -            "[<link>]\n"                                                },
      355 +            "    show-vnic        [-pP] [-l <link>] [-z zonename] "
      356 +            "[-s [-i <interval>]] [<link>]\n"                                           },
 354  357          { "up-vnic",            do_up_vnic,             NULL            },
 355  358          { "create-part",        do_create_part,
 356  359              "    create-part      [-t] [-f] -l <link> [-P <pkey>]\n"
 357  360              "\t\t     [-R <root-dir>] <part-link>"                      },
 358  361          { "delete-part",        do_delete_part,
 359  362              "    delete-part      [-t] [-R <root-dir>] <part-link>"},
 360  363          { "show-part",          do_show_part,
 361  364              "    show-part        [-pP] [-o <field>,...][-l <linkover>]\n"
 362  365              "\t\t     [<part-link>]"            },
 363  366          { "show-ib",            do_show_ib,
 364  367              "    show-ib          [-p] [-o <field>,...] [<link>]\n"     },
 365  368          { "up-part",            do_up_part,             NULL            },
 366  369          { "create-etherstub",   do_create_etherstub,
 367  370              "    create-etherstub [-t] <link>"                          },
 368  371          { "delete-etherstub",   do_delete_etherstub,
 369  372              "    delete-etherstub [-t] <link>"                          },
 370  373          { "show-etherstub",     do_show_etherstub,
 371  374              "    show-etherstub   [-t] [<link>]\n"                      },
 372  375          { "create-simnet",      do_create_simnet,       NULL            },
 373  376          { "modify-simnet",      do_modify_simnet,       NULL            },
 374  377          { "delete-simnet",      do_delete_simnet,       NULL            },
 375  378          { "show-simnet",        do_show_simnet,         NULL            },
 376  379          { "up-simnet",          do_up_simnet,           NULL            },
 377  380          { "create-bridge",      do_create_bridge,
 378  381              "    create-bridge    [-R <root-dir>] [-P <protect>] "
 379  382              "[-p <priority>]\n"
 380  383              "\t\t     [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n"
 381  384              "\t\t     [-f <force-protocol>] [-l <link>]... <bridge>"    },
 382  385          { "modify-bridge",      do_modify_bridge,
 383  386              "    modify-bridge    [-R <root-dir>] [-P <protect>] "
 384  387              "[-p <priority>]\n"
 385  388              "\t\t     [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n"
 386  389              "\t\t     [-f <force-protocol>] <bridge>"                   },
 387  390          { "delete-bridge",      do_delete_bridge,
 388  391              "    delete-bridge    [-R <root-dir>] <bridge>"             },
 389  392          { "add-bridge",         do_add_bridge,
 390  393              "    add-bridge       [-R <root-dir>] -l <link> [-l <link>]... "
 391  394              "<bridge>"                                                  },
 392  395          { "remove-bridge",      do_remove_bridge,
 393  396              "    remove-bridge    [-R <root-dir>] -l <link> [-l <link>]... "
 394  397              "<bridge>"                                                  },
 395  398          { "show-bridge",        do_show_bridge,
 396  399              "    show-bridge      [-p] [-o <field>,...] [-s [-i <interval>]] "
 397  400              "[<bridge>]\n"
 398  401              "    show-bridge      -l [-p] [-o <field>,...] [-s [-i <interval>]]"
 399  402              " <bridge>\n"
 400  403              "    show-bridge      -f [-p] [-o <field>,...] [-s [-i <interval>]]"
 401  404              " <bridge>\n"
 402  405              "    show-bridge      -t [-p] [-o <field>,...] [-s [-i <interval>]]"
 403  406              " <bridge>\n"                                               },
 404  407          { "show-usage",         do_show_usage,
 405  408              "    show-usage       [-a] [-d | -F <format>] "
 406  409              "[-s <DD/MM/YYYY,HH:MM:SS>]\n"
 407  410              "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" }
 408  411  };
 409  412  
 410  413  static const struct option lopts[] = {
 411  414          {"vlan-id",     required_argument,      0, 'v'},
 412  415          {"output",      required_argument,      0, 'o'},
 413  416          {"dev",         required_argument,      0, 'd'},
 414  417          {"policy",      required_argument,      0, 'P'},
 415  418          {"lacp-mode",   required_argument,      0, 'L'},
 416  419          {"lacp-timer",  required_argument,      0, 'T'},
 417  420          {"unicast",     required_argument,      0, 'u'},
 418  421          {"temporary",   no_argument,            0, 't'},
 419  422          {"root-dir",    required_argument,      0, 'R'},
 420  423          {"link",        required_argument,      0, 'l'},
 421  424          {"forcible",    no_argument,            0, 'f'},
 422  425          {"bw-limit",    required_argument,      0, 'b'},
 423  426          {"mac-address", required_argument,      0, 'm'},
 424  427          {"slot",        required_argument,      0, 'n'},
 425  428          { 0, 0, 0, 0 }
 426  429  };
 427  430  
 428  431  static const struct option show_lopts[] = {
 429  432          {"statistics",  no_argument,            0, 's'},
 430  433          {"continuous",  no_argument,            0, 'S'},
 431  434          {"interval",    required_argument,      0, 'i'},
 432  435          {"parsable",    no_argument,            0, 'p'},
 433  436          {"parseable",   no_argument,            0, 'p'},
 434  437          {"extended",    no_argument,            0, 'x'},
 435  438          {"output",      required_argument,      0, 'o'},
 436  439          {"persistent",  no_argument,            0, 'P'},
 437  440          {"lacp",        no_argument,            0, 'L'},
 438  441          { 0, 0, 0, 0 }
 439  442  };
 440  443  
 441  444  static const struct option iptun_lopts[] = {
 442  445          {"output",      required_argument,      0, 'o'},
 443  446          {"tunnel-type", required_argument,      0, 'T'},
 444  447          {"address",     required_argument,      0, 'a'},
 445  448          {"root-dir",    required_argument,      0, 'R'},
 446  449          {"parsable",    no_argument,            0, 'p'},
 447  450          {"parseable",   no_argument,            0, 'p'},
 448  451          {"persistent",  no_argument,            0, 'P'},
 449  452          { 0, 0, 0, 0 }
 450  453  };
 451  454  
 452  455  static char * const iptun_addropts[] = {
 453  456  #define IPTUN_LOCAL     0
 454  457          "local",
 455  458  #define IPTUN_REMOTE    1
 456  459          "remote",
 457  460          NULL};
 458  461  
 459  462  static const struct {
 460  463          const char      *type_name;
 461  464          iptun_type_t    type_value;
 462  465  } iptun_types[] = {
 463  466          {"ipv4",        IPTUN_TYPE_IPV4},
 464  467          {"ipv6",        IPTUN_TYPE_IPV6},
 465  468          {"6to4",        IPTUN_TYPE_6TO4},
 466  469          {NULL,          0}
 467  470  };
 468  471  
 469  472  static const struct option prop_longopts[] = {
 470  473          {"temporary",   no_argument,            0, 't'  },
 471  474          {"output",      required_argument,      0, 'o'  },
 472  475          {"root-dir",    required_argument,      0, 'R'  },
 473  476          {"prop",        required_argument,      0, 'p'  },
 474  477          {"parsable",    no_argument,            0, 'c'  },
 475  478          {"parseable",   no_argument,            0, 'c'  },
 476  479          {"persistent",  no_argument,            0, 'P'  },
 477  480          { 0, 0, 0, 0 }
 478  481  };
 479  482  
 480  483  static const struct option wifi_longopts[] = {
 481  484          {"parsable",    no_argument,            0, 'p'  },
 482  485          {"parseable",   no_argument,            0, 'p'  },
 483  486          {"output",      required_argument,      0, 'o'  },
 484  487          {"essid",       required_argument,      0, 'e'  },
 485  488          {"bsstype",     required_argument,      0, 'b'  },
 486  489          {"mode",        required_argument,      0, 'm'  },
 487  490          {"key",         required_argument,      0, 'k'  },
 488  491          {"sec",         required_argument,      0, 's'  },
 489  492          {"auth",        required_argument,      0, 'a'  },
 490  493          {"create-ibss", required_argument,      0, 'c'  },
 491  494          {"timeout",     required_argument,      0, 'T'  },
 492  495          {"all-links",   no_argument,            0, 'a'  },
 493  496          {"temporary",   no_argument,            0, 't'  },
 494  497          {"root-dir",    required_argument,      0, 'R'  },
 495  498          {"persistent",  no_argument,            0, 'P'  },
 496  499          {"file",        required_argument,      0, 'f'  },
 497  500          { 0, 0, 0, 0 }
 498  501  };
 499  502  
 500  503  static const struct option showeth_lopts[] = {
 501  504          {"parsable",    no_argument,            0, 'p'  },
 502  505          {"parseable",   no_argument,            0, 'p'  },
 503  506          {"extended",    no_argument,            0, 'x'  },
 504  507          {"output",      required_argument,      0, 'o'  },
 505  508          { 0, 0, 0, 0 }
 506  509  };
 507  510  
 508  511  static const struct option vnic_lopts[] = {
 509  512          {"temporary",   no_argument,            0, 't'  },
 510  513          {"root-dir",    required_argument,      0, 'R'  },
 511  514          {"dev",         required_argument,      0, 'd'  },
 512  515          {"mac-address", required_argument,      0, 'm'  },
 513  516          {"cpus",        required_argument,      0, 'c'  },
 514  517          {"bw-limit",    required_argument,      0, 'b'  },
 515  518          {"slot",        required_argument,      0, 'n'  },
 516  519          {"mac-prefix",  required_argument,      0, 'r'  },
 517  520          {"vrid",        required_argument,      0, 'V'  },
 518  521          {"address-family",      required_argument,      0, 'A'  },
 519  522          { 0, 0, 0, 0 }
 520  523  };
 521  524  
 522  525  static const struct option part_lopts[] = {
 523  526          {"temporary",   no_argument,            0, 't'  },
 524  527          {"pkey",        required_argument,      0, 'P'  },
 525  528          {"link",        required_argument,      0, 'l'  },
 526  529          {"force",       no_argument,            0, 'f'  },
 527  530          {"root-dir",    required_argument,      0, 'R'  },
 528  531          {"prop",        required_argument,      0, 'p'  },
 529  532          { 0, 0, 0, 0 }
 530  533  };
 531  534  
 532  535  static const struct option show_part_lopts[] = {
 533  536          {"parsable",    no_argument,            0, 'p'  },
 534  537          {"parseable",   no_argument,            0, 'p'  },
 535  538          {"link",        required_argument,      0, 'l'  },
 536  539          {"persistent",  no_argument,            0, 'P'  },
 537  540          {"output",      required_argument,      0, 'o'  },
 538  541          { 0, 0, 0, 0 }
 539  542  };
 540  543  
 541  544  static const struct option etherstub_lopts[] = {
 542  545          {"temporary",   no_argument,            0, 't'  },
 543  546          {"root-dir",    required_argument,      0, 'R'  },
 544  547          { 0, 0, 0, 0 }
 545  548  };
 546  549  
 547  550  static const struct option usage_opts[] = {
 548  551          {"file",        required_argument,      0, 'f'  },
 549  552          {"format",      required_argument,      0, 'F'  },
 550  553          {"start",       required_argument,      0, 's'  },
 551  554          {"stop",        required_argument,      0, 'e'  },
 552  555          { 0, 0, 0, 0 }
 553  556  };
 554  557  
 555  558  static const struct option simnet_lopts[] = {
 556  559          {"temporary",   no_argument,            0, 't'  },
 557  560          {"root-dir",    required_argument,      0, 'R'  },
 558  561          {"media",       required_argument,      0, 'm'  },
 559  562          {"peer",        required_argument,      0, 'p'  },
 560  563          { 0, 0, 0, 0 }
 561  564  };
 562  565  
 563  566  static const struct option bridge_lopts[] = {
 564  567          { "protect",            required_argument,      0, 'P' },
 565  568          { "root-dir",           required_argument,      0, 'R'  },
 566  569          { "forward-delay",      required_argument,      0, 'd'  },
 567  570          { "force-protocol",     required_argument,      0, 'f'  },
 568  571          { "hello-time",         required_argument,      0, 'h'  },
 569  572          { "link",               required_argument,      0, 'l'  },
 570  573          { "max-age",            required_argument,      0, 'm'  },
 571  574          { "priority",           required_argument,      0, 'p'  },
 572  575          { NULL, NULL, 0, 0 }
 573  576  };
 574  577  
 575  578  static const struct option bridge_show_lopts[] = {
 576  579          { "forwarding", no_argument,            0, 'f' },
 577  580          { "interval",   required_argument,      0, 'i' },
 578  581          { "link",       no_argument,            0, 'l' },
 579  582          { "output",     required_argument,      0, 'o' },
 580  583          { "parsable",   no_argument,            0, 'p' },
 581  584          { "parseable",  no_argument,            0, 'p' },
 582  585          { "statistics", no_argument,            0, 's' },
 583  586          { "trill",      no_argument,            0, 't' },
 584  587          { 0, 0, 0, 0 }
 585  588  };
 586  589  
 587  590  /*
 588  591   * structures for 'dladm show-ether'
 589  592   */
 590  593  static const char *ptype[] = {LEI_ATTR_NAMES};
 591  594  
 592  595  typedef struct ether_fields_buf_s
 593  596  {
 594  597          char    eth_link[15];
 595  598          char    eth_ptype[8];
 596  599          char    eth_state[8];
 597  600          char    eth_autoneg[5];
 598  601          char    eth_spdx[31];
 599  602          char    eth_pause[6];
 600  603          char    eth_rem_fault[16];
 601  604  } ether_fields_buf_t;
 602  605  
 603  606  static const ofmt_field_t ether_fields[] = {
 604  607  /* name,        field width,    offset      callback */
 605  608  { "LINK",       16,
 606  609          offsetof(ether_fields_buf_t, eth_link), print_default_cb},
 607  610  { "PTYPE",      9,
 608  611          offsetof(ether_fields_buf_t, eth_ptype), print_default_cb},
 609  612  { "STATE",      9,
 610  613          offsetof(ether_fields_buf_t, eth_state),
 611  614          print_default_cb},
 612  615  { "AUTO",       6,
 613  616          offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb},
 614  617  { "SPEED-DUPLEX", 32,
 615  618          offsetof(ether_fields_buf_t, eth_spdx), print_default_cb},
 616  619  { "PAUSE",      7,
 617  620          offsetof(ether_fields_buf_t, eth_pause), print_default_cb},
 618  621  { "REM_FAULT",  17,
 619  622          offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb},
 620  623  {NULL,          0,
 621  624          0,      NULL}}
 622  625  ;
 623  626  
 624  627  typedef struct print_ether_state {
 625  628          const char      *es_link;
 626  629          boolean_t       es_parsable;
 627  630          boolean_t       es_header;
 628  631          boolean_t       es_extended;
 629  632          ofmt_handle_t   es_ofmt;
 630  633  } print_ether_state_t;
 631  634  
 632  635  /*
 633  636   * structures for 'dladm show-link -s' (print statistics)
 634  637   */
 635  638  typedef enum {
 636  639          LINK_S_LINK,
 637  640          LINK_S_IPKTS,
 638  641          LINK_S_RBYTES,
 639  642          LINK_S_IERRORS,
 640  643          LINK_S_OPKTS,
 641  644          LINK_S_OBYTES,
 642  645          LINK_S_OERRORS
 643  646  } link_s_field_index_t;
 644  647  
 645  648  static const ofmt_field_t link_s_fields[] = {
 646  649  /* name,        field width,    index,          callback        */
 647  650  { "LINK",       15,             LINK_S_LINK,    print_link_stats_cb},
 648  651  { "IPACKETS",   10,             LINK_S_IPKTS,   print_link_stats_cb},
 649  652  { "RBYTES",     8,              LINK_S_RBYTES,  print_link_stats_cb},
 650  653  { "IERRORS",    10,             LINK_S_IERRORS, print_link_stats_cb},
 651  654  { "OPACKETS",   12,             LINK_S_OPKTS,   print_link_stats_cb},
 652  655  { "OBYTES",     12,             LINK_S_OBYTES,  print_link_stats_cb},
 653  656  { "OERRORS",    8,              LINK_S_OERRORS, print_link_stats_cb}}
 654  657  ;
 655  658  
 656  659  typedef struct link_args_s {
 657  660          char            *link_s_link;
 658  661          pktsum_t        *link_s_psum;
 659  662  } link_args_t;
 660  663  
 661  664  /*
 662  665   * buffer used by print functions for show-{link,phys,vlan} commands.
 663  666   */
 664  667  typedef struct link_fields_buf_s {
 665  668          char link_name[MAXLINKNAMELEN];
 666  669          char link_class[DLADM_STRSIZE];
 667  670          char link_mtu[11];
 668  671          char link_state[DLADM_STRSIZE];
 669  672          char link_bridge[MAXLINKNAMELEN];
 670  673          char link_over[MAXLINKNAMELEN];
 671  674          char link_phys_state[DLADM_STRSIZE];
 672  675          char link_phys_media[DLADM_STRSIZE];
 673  676          char link_phys_speed[DLADM_STRSIZE];
 674  677          char link_phys_duplex[DLPI_LINKNAME_MAX];
 675  678          char link_phys_device[DLPI_LINKNAME_MAX];
 676  679          char link_flags[6];
 677  680          char link_vlan_vid[6];
 678  681  } link_fields_buf_t;
 679  682  
 680  683  /*
 681  684   * structures for 'dladm show-link'
 682  685   */
 683  686  static const ofmt_field_t link_fields[] = {
 684  687  /* name,        field width,    index,  callback */
 685  688  { "LINK",       12,
 686  689          offsetof(link_fields_buf_t, link_name), print_default_cb},
 687  690  { "CLASS",      10,
 688  691          offsetof(link_fields_buf_t, link_class), print_default_cb},
 689  692  { "MTU",        7,
 690  693          offsetof(link_fields_buf_t, link_mtu), print_default_cb},
 691  694  { "STATE",      9,
 692  695          offsetof(link_fields_buf_t, link_state), print_default_cb},
 693  696  { "BRIDGE",     11,
 694  697      offsetof(link_fields_buf_t, link_bridge), print_default_cb},
 695  698  { "OVER",       DLPI_LINKNAME_MAX,
 696  699          offsetof(link_fields_buf_t, link_over), print_default_cb},
 697  700  { NULL,         0, 0, NULL}}
 698  701  ;
 699  702  
 700  703  /*
 701  704   * structures for 'dladm show-aggr'
 702  705   */
 703  706  typedef struct laggr_fields_buf_s {
 704  707          char laggr_name[DLPI_LINKNAME_MAX];
 705  708          char laggr_policy[9];
 706  709          char laggr_addrpolicy[ETHERADDRL * 3 + 3];
 707  710          char laggr_lacpactivity[14];
 708  711          char laggr_lacptimer[DLADM_STRSIZE];
 709  712          char laggr_flags[7];
 710  713  } laggr_fields_buf_t;
 711  714  
 712  715  typedef struct laggr_args_s {
 713  716          int                     laggr_lport; /* -1 indicates the aggr itself */
 714  717          const char              *laggr_link;
 715  718          dladm_aggr_grp_attr_t   *laggr_ginfop;
 716  719          dladm_status_t          *laggr_status;
 717  720          pktsum_t                *laggr_pktsumtot; /* -s only */
 718  721          pktsum_t                *laggr_diffstats; /* -s only */
 719  722          boolean_t               laggr_parsable;
 720  723  } laggr_args_t;
 721  724  
 722  725  static const ofmt_field_t laggr_fields[] = {
 723  726  /* name,        field width,    offset, callback */
 724  727  { "LINK",       16,
 725  728          offsetof(laggr_fields_buf_t, laggr_name), print_default_cb},
 726  729  { "POLICY",     9,
 727  730          offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb},
 728  731  { "ADDRPOLICY", ETHERADDRL * 3 + 3,
 729  732          offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb},
 730  733  { "LACPACTIVITY", 14,
 731  734          offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb},
 732  735  { "LACPTIMER",  12,
 733  736          offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb},
 734  737  { "FLAGS",      8,
 735  738          offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb},
 736  739  { NULL,         0, 0, NULL}}
 737  740  ;
 738  741  
 739  742  /*
 740  743   * structures for 'dladm show-aggr -x'.
 741  744   */
 742  745  typedef enum {
 743  746          AGGR_X_LINK,
 744  747          AGGR_X_PORT,
 745  748          AGGR_X_SPEED,
 746  749          AGGR_X_DUPLEX,
 747  750          AGGR_X_STATE,
 748  751          AGGR_X_ADDRESS,
 749  752          AGGR_X_PORTSTATE
 750  753  } aggr_x_field_index_t;
 751  754  
 752  755  static const ofmt_field_t aggr_x_fields[] = {
 753  756  /* name,        field width,    index           callback */
 754  757  { "LINK",       12,     AGGR_X_LINK,            print_xaggr_cb},
 755  758  { "PORT",       15,     AGGR_X_PORT,            print_xaggr_cb},
 756  759  { "SPEED",      5,      AGGR_X_SPEED,           print_xaggr_cb},
 757  760  { "DUPLEX",     10,     AGGR_X_DUPLEX,          print_xaggr_cb},
 758  761  { "STATE",      10,     AGGR_X_STATE,           print_xaggr_cb},
 759  762  { "ADDRESS",    19,     AGGR_X_ADDRESS,         print_xaggr_cb},
 760  763  { "PORTSTATE",  16,     AGGR_X_PORTSTATE,       print_xaggr_cb},
 761  764  { NULL,         0,      0,                      NULL}}
 762  765  ;
 763  766  
 764  767  /*
 765  768   * structures for 'dladm show-aggr -s'.
 766  769   */
 767  770  typedef enum {
 768  771          AGGR_S_LINK,
 769  772          AGGR_S_PORT,
 770  773          AGGR_S_IPKTS,
 771  774          AGGR_S_RBYTES,
 772  775          AGGR_S_OPKTS,
 773  776          AGGR_S_OBYTES,
 774  777          AGGR_S_IPKTDIST,
 775  778          AGGR_S_OPKTDIST
 776  779  } aggr_s_field_index_t;
 777  780  
 778  781  static const ofmt_field_t aggr_s_fields[] = {
 779  782  { "LINK",               12,     AGGR_S_LINK, print_aggr_stats_cb},
 780  783  { "PORT",               10,     AGGR_S_PORT, print_aggr_stats_cb},
 781  784  { "IPACKETS",           8,      AGGR_S_IPKTS, print_aggr_stats_cb},
 782  785  { "RBYTES",             8,      AGGR_S_RBYTES, print_aggr_stats_cb},
 783  786  { "OPACKETS",           8,      AGGR_S_OPKTS, print_aggr_stats_cb},
 784  787  { "OBYTES",             8,      AGGR_S_OBYTES, print_aggr_stats_cb},
 785  788  { "IPKTDIST",           9,      AGGR_S_IPKTDIST, print_aggr_stats_cb},
 786  789  { "OPKTDIST",           15,     AGGR_S_OPKTDIST, print_aggr_stats_cb},
 787  790  { NULL,                 0,      0,              NULL}}
 788  791  ;
 789  792  
 790  793  /*
 791  794   * structures for 'dladm show-aggr -L'.
 792  795   */
 793  796  typedef enum {
 794  797          AGGR_L_LINK,
 795  798          AGGR_L_PORT,
 796  799          AGGR_L_AGGREGATABLE,
 797  800          AGGR_L_SYNC,
 798  801          AGGR_L_COLL,
 799  802          AGGR_L_DIST,
 800  803          AGGR_L_DEFAULTED,
 801  804          AGGR_L_EXPIRED
 802  805  } aggr_l_field_index_t;
 803  806  
 804  807  static const ofmt_field_t aggr_l_fields[] = {
 805  808  /* name,                field width,    index */
 806  809  { "LINK",               12,     AGGR_L_LINK,            print_lacp_cb},
 807  810  { "PORT",               13,     AGGR_L_PORT,            print_lacp_cb},
 808  811  { "AGGREGATABLE",       13,     AGGR_L_AGGREGATABLE,    print_lacp_cb},
 809  812  { "SYNC",               5,      AGGR_L_SYNC,            print_lacp_cb},
 810  813  { "COLL",               5,      AGGR_L_COLL,            print_lacp_cb},
 811  814  { "DIST",               5,      AGGR_L_DIST,            print_lacp_cb},
 812  815  { "DEFAULTED",          10,     AGGR_L_DEFAULTED,       print_lacp_cb},
 813  816  { "EXPIRED",            15,     AGGR_L_EXPIRED,         print_lacp_cb},
 814  817  { NULL,                 0,      0,                      NULL}}
 815  818  ;
 816  819  
 817  820  /*
 818  821   * structures for 'dladm show-phys'
 819  822   */
 820  823  
 821  824  static const ofmt_field_t phys_fields[] = {
 822  825  /* name,        field width,    offset */
 823  826  { "LINK",       13,
 824  827          offsetof(link_fields_buf_t, link_name), print_default_cb},
 825  828  { "MEDIA",      21,
 826  829          offsetof(link_fields_buf_t, link_phys_media), print_default_cb},
 827  830  { "STATE",      11,
 828  831          offsetof(link_fields_buf_t, link_phys_state), print_default_cb},
 829  832  { "SPEED",      7,
 830  833          offsetof(link_fields_buf_t, link_phys_speed), print_default_cb},
 831  834  { "DUPLEX",     10,
 832  835          offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb},
 833  836  { "DEVICE",     13,
 834  837          offsetof(link_fields_buf_t, link_phys_device), print_default_cb},
 835  838  { "FLAGS",      7,
 836  839          offsetof(link_fields_buf_t, link_flags), print_default_cb},
 837  840  { NULL,         0, NULL, 0}}
 838  841  ;
 839  842  
 840  843  /*
 841  844   * structures for 'dladm show-phys -m'
 842  845   */
 843  846  
 844  847  typedef enum {
 845  848          PHYS_M_LINK,
 846  849          PHYS_M_SLOT,
 847  850          PHYS_M_ADDRESS,
 848  851          PHYS_M_INUSE,
 849  852          PHYS_M_CLIENT
 850  853  } phys_m_field_index_t;
 851  854  
 852  855  static const ofmt_field_t phys_m_fields[] = {
 853  856  /* name,        field width,    offset */
 854  857  { "LINK",       13,     PHYS_M_LINK,    print_phys_one_mac_cb},
 855  858  { "SLOT",       9,      PHYS_M_SLOT,    print_phys_one_mac_cb},
 856  859  { "ADDRESS",    19,     PHYS_M_ADDRESS, print_phys_one_mac_cb},
 857  860  { "INUSE",      5,      PHYS_M_INUSE,   print_phys_one_mac_cb},
 858  861  { "CLIENT",     13,     PHYS_M_CLIENT,  print_phys_one_mac_cb},
 859  862  { NULL,         0,      0,              NULL}}
 860  863  ;
 861  864  
 862  865  /*
 863  866   * structures for 'dladm show-phys -H'
 864  867   */
 865  868  
 866  869  typedef enum {
 867  870          PHYS_H_LINK,
 868  871          PHYS_H_RINGTYPE,
 869  872          PHYS_H_RINGS,
 870  873          PHYS_H_CLIENTS
 871  874  } phys_h_field_index_t;
 872  875  
 873  876  #define RINGSTRLEN      21
 874  877  
 875  878  static const ofmt_field_t phys_h_fields[] = {
 876  879  { "LINK",       13,     PHYS_H_LINK,    print_phys_one_hwgrp_cb},
 877  880  { "RINGTYPE",   9,      PHYS_H_RINGTYPE,        print_phys_one_hwgrp_cb},
 878  881  { "RINGS",      RINGSTRLEN,     PHYS_H_RINGS,   print_phys_one_hwgrp_cb},
 879  882  { "CLIENTS",    24,     PHYS_H_CLIENTS, print_phys_one_hwgrp_cb},
 880  883  { NULL,         0,      0,              NULL}}
 881  884  ;
 882  885  
 883  886  /*
 884  887   * structures for 'dladm show-vlan'
 885  888   */
 886  889  static const ofmt_field_t vlan_fields[] = {
 887  890  { "LINK",       16,
 888  891          offsetof(link_fields_buf_t, link_name), print_default_cb},
 889  892  { "VID",        9,
 890  893          offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb},
 891  894  { "OVER",       13,
 892  895          offsetof(link_fields_buf_t, link_over), print_default_cb},
 893  896  { "FLAGS",      7,
 894  897          offsetof(link_fields_buf_t, link_flags), print_default_cb},
 895  898  { NULL,         0, 0, NULL}}
 896  899  ;
 897  900  
 898  901  /*
 899  902   * structures common to 'dladm scan-wifi' and 'dladm show-wifi'
 900  903   * callback will be determined in parse_wifi_fields.
 901  904   */
 902  905  static ofmt_field_t wifi_common_fields[] = {
 903  906  { "LINK",       11, 0,                          NULL},
 904  907  { "ESSID",      20, DLADM_WLAN_ATTR_ESSID,      NULL},
 905  908  { "BSSID",      18, DLADM_WLAN_ATTR_BSSID,      NULL},
 906  909  { "IBSSID",     18, DLADM_WLAN_ATTR_BSSID,      NULL},
 907  910  { "MODE",       7,  DLADM_WLAN_ATTR_MODE,       NULL},
 908  911  { "SPEED",      7,  DLADM_WLAN_ATTR_SPEED,      NULL},
 909  912  { "BSSTYPE",    9,  DLADM_WLAN_ATTR_BSSTYPE,    NULL},
 910  913  { "SEC",        7,  DLADM_WLAN_ATTR_SECMODE,    NULL},
 911  914  { "STRENGTH",   11, DLADM_WLAN_ATTR_STRENGTH,   NULL},
 912  915  { NULL,         0,  0,                          NULL}};
 913  916  
 914  917  /*
 915  918   * the 'show-wifi' command supports all the fields in wifi_common_fields
 916  919   * plus the AUTH and STATUS fields.
 917  920   */
 918  921  static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = {
 919  922  { "AUTH",       9,  DLADM_WLAN_ATTR_AUTH,       NULL},
 920  923  { "STATUS",     18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb},
 921  924  /* copy wifi_common_fields here */
 922  925  };
 923  926  
 924  927  static char *all_scan_wifi_fields =
 925  928          "link,essid,bssid,sec,strength,mode,speed,bsstype";
 926  929  static char *all_show_wifi_fields =
 927  930          "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype";
 928  931  static char *def_scan_wifi_fields =
 929  932          "link,essid,bssid,sec,strength,mode,speed";
 930  933  static char *def_show_wifi_fields =
 931  934          "link,status,essid,sec,strength,mode,speed";
 932  935  
 933  936  /*
 934  937   * structures for 'dladm show-linkprop'
 935  938   */
 936  939  typedef enum {
 937  940          LINKPROP_LINK,
 938  941          LINKPROP_PROPERTY,
 939  942          LINKPROP_PERM,
 940  943          LINKPROP_VALUE,
 941  944          LINKPROP_DEFAULT,
 942  945          LINKPROP_POSSIBLE
 943  946  } linkprop_field_index_t;
 944  947  
 945  948  static const ofmt_field_t linkprop_fields[] = {
 946  949  /* name,        field width,  index */
 947  950  { "LINK",       13,     LINKPROP_LINK,          print_linkprop_cb},
 948  951  { "PROPERTY",   16,     LINKPROP_PROPERTY,      print_linkprop_cb},
 949  952  { "PERM",       5,      LINKPROP_PERM,          print_linkprop_cb},
 950  953  { "VALUE",      15,     LINKPROP_VALUE,         print_linkprop_cb},
 951  954  { "DEFAULT",    15,     LINKPROP_DEFAULT,       print_linkprop_cb},
  
    | 
      ↓ open down ↓ | 
    588 lines elided | 
    
      ↑ open up ↑ | 
  
 952  955  { "POSSIBLE",   20,     LINKPROP_POSSIBLE,      print_linkprop_cb},
 953  956  { NULL,         0,      0,                      NULL}}
 954  957  ;
 955  958  
 956  959  #define MAX_PROP_LINE           512
 957  960  
 958  961  typedef struct show_linkprop_state {
 959  962          char                    ls_link[MAXLINKNAMELEN];
 960  963          char                    *ls_line;
 961  964          char                    **ls_propvals;
      965 +        char                    *ls_zonename;
 962  966          dladm_arg_list_t        *ls_proplist;
 963  967          boolean_t               ls_parsable;
 964  968          boolean_t               ls_persist;
 965  969          boolean_t               ls_header;
 966  970          dladm_status_t          ls_status;
 967  971          dladm_status_t          ls_retstatus;
 968  972          ofmt_handle_t           ls_ofmt;
 969  973  } show_linkprop_state_t;
 970  974  
 971  975  typedef struct set_linkprop_state {
 972  976          const char              *ls_name;
 973  977          boolean_t               ls_reset;
 974  978          boolean_t               ls_temp;
 975  979          dladm_status_t          ls_status;
 976  980  } set_linkprop_state_t;
 977  981  
 978  982  typedef struct linkprop_args_s {
 979  983          show_linkprop_state_t   *ls_state;
 980  984          char                    *ls_propname;
 981  985          datalink_id_t           ls_linkid;
 982  986  } linkprop_args_t;
 983  987  
 984  988  /*
 985  989   * structures for 'dladm show-secobj'
 986  990   */
 987  991  typedef struct secobj_fields_buf_s {
 988  992          char                    ss_obj_name[DLADM_SECOBJ_VAL_MAX];
 989  993          char                    ss_class[20];
 990  994          char                    ss_val[30];
 991  995  } secobj_fields_buf_t;
 992  996  
 993  997  static const ofmt_field_t secobj_fields[] = {
 994  998  { "OBJECT",     21,
 995  999          offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
 996 1000  { "CLASS",      21,
 997 1001          offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
 998 1002  { "VALUE",      31,
 999 1003          offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
1000 1004  { NULL,         0, 0, NULL}}
1001 1005  ;
1002 1006  
1003 1007  /*
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
1004 1008   * structures for 'dladm show-vnic'
1005 1009   */
1006 1010  typedef struct vnic_fields_buf_s
1007 1011  {
1008 1012          char vnic_link[DLPI_LINKNAME_MAX];
1009 1013          char vnic_over[DLPI_LINKNAME_MAX];
1010 1014          char vnic_speed[6];
1011 1015          char vnic_macaddr[18];
1012 1016          char vnic_macaddrtype[19];
1013 1017          char vnic_vid[6];
     1018 +        char vnic_zone[ZONENAME_MAX];
1014 1019  } vnic_fields_buf_t;
1015 1020  
1016 1021  static const ofmt_field_t vnic_fields[] = {
1017 1022  { "LINK",               13,
1018 1023          offsetof(vnic_fields_buf_t, vnic_link), print_default_cb},
1019      -{ "OVER",               13,
     1024 +{ "OVER",               11,
1020 1025          offsetof(vnic_fields_buf_t, vnic_over), print_default_cb},
1021      -{ "SPEED",              7,
     1026 +{ "SPEED",              6,
1022 1027          offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
1023 1028  { "MACADDRESS",         18,
1024 1029          offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
1025      -{ "MACADDRTYPE",        20,
     1030 +{ "MACADDRTYPE",        12,
1026 1031          offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
1027      -{ "VID",                7,
     1032 +{ "VID",                5,
1028 1033          offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
     1034 +{ "ZONE",               20,
     1035 +        offsetof(vnic_fields_buf_t, vnic_zone), print_default_cb},
1029 1036  { NULL,                 0, 0, NULL}}
1030 1037  ;
1031 1038  
1032 1039  /*
1033 1040   * structures for 'dladm show-ib'
1034 1041   */
1035 1042  typedef struct ib_fields_buf_s
1036 1043  {
1037 1044          char ib_link[DLPI_LINKNAME_MAX];
1038 1045          char ib_hcaguid[17];
1039 1046          char ib_portguid[17];
1040 1047          char ib_portnum[4];
1041 1048          char ib_state[6];
1042 1049          char ib_pkeys[MAXPKEYSTRSZ];
1043 1050  } ib_fields_buf_t;
1044 1051  
1045 1052  static const ofmt_field_t ib_fields[] = {
1046 1053  { "LINK",               13,
1047 1054          offsetof(ib_fields_buf_t, ib_link),     print_default_cb},
1048 1055  { "HCAGUID",            IBGUIDSTRLEN,
1049 1056          offsetof(ib_fields_buf_t, ib_hcaguid),  print_default_cb},
1050 1057  { "PORTGUID",           IBGUIDSTRLEN,
1051 1058          offsetof(ib_fields_buf_t, ib_portguid), print_default_cb},
1052 1059  { "PORT",               IBPORTSTRLEN,
1053 1060          offsetof(ib_fields_buf_t, ib_portnum), print_default_cb},
1054 1061  { "STATE",              7,
1055 1062          offsetof(ib_fields_buf_t, ib_state), print_default_cb},
1056 1063  { "PKEYS",      18,
1057 1064          offsetof(ib_fields_buf_t, ib_pkeys), print_default_cb},
1058 1065  { NULL,                 0, 0, NULL}};
1059 1066  
1060 1067  /*
1061 1068   * structures for 'dladm show-part'
1062 1069   */
1063 1070  typedef struct part_fields_buf_s
1064 1071  {
1065 1072          char part_link[DLPI_LINKNAME_MAX];
1066 1073          char part_pkey[5];
1067 1074          char part_over[DLPI_LINKNAME_MAX];
1068 1075          char part_state[8];
1069 1076          char part_flags[5];
1070 1077  } part_fields_buf_t;
1071 1078  
1072 1079  static const ofmt_field_t part_fields[] = {
1073 1080  { "LINK",               13,
1074 1081          offsetof(part_fields_buf_t, part_link), print_default_cb},
1075 1082  { "PKEY",               MAXPKEYLEN,
1076 1083          offsetof(part_fields_buf_t, part_pkey), print_default_cb},
1077 1084  { "OVER",               13,
1078 1085          offsetof(part_fields_buf_t, part_over), print_default_cb},
1079 1086  { "STATE",              9,
1080 1087          offsetof(part_fields_buf_t, part_state), print_default_cb},
1081 1088  { "FLAGS",      5,
1082 1089          offsetof(part_fields_buf_t, part_flags), print_default_cb},
1083 1090  { NULL,                 0, 0, NULL}};
1084 1091  
1085 1092  /*
1086 1093   * structures for 'dladm show-simnet'
1087 1094   */
1088 1095  typedef struct simnet_fields_buf_s
1089 1096  {
1090 1097          char simnet_name[DLPI_LINKNAME_MAX];
1091 1098          char simnet_media[DLADM_STRSIZE];
1092 1099          char simnet_macaddr[18];
1093 1100          char simnet_otherlink[DLPI_LINKNAME_MAX];
1094 1101  } simnet_fields_buf_t;
1095 1102  
1096 1103  static const ofmt_field_t simnet_fields[] = {
1097 1104  { "LINK",               12,
1098 1105          offsetof(simnet_fields_buf_t, simnet_name), print_default_cb},
1099 1106  { "MEDIA",              20,
1100 1107          offsetof(simnet_fields_buf_t, simnet_media), print_default_cb},
1101 1108  { "MACADDRESS",         18,
1102 1109          offsetof(simnet_fields_buf_t, simnet_macaddr), print_default_cb},
1103 1110  { "OTHERLINK",          12,
1104 1111          offsetof(simnet_fields_buf_t, simnet_otherlink), print_default_cb},
1105 1112  { NULL,                 0, 0, NULL}}
1106 1113  ;
1107 1114  
1108 1115  /*
1109 1116   * structures for 'dladm show-usage'
1110 1117   */
1111 1118  
1112 1119  typedef struct  usage_fields_buf_s {
1113 1120          char    usage_link[12];
1114 1121          char    usage_duration[10];
1115 1122          char    usage_ipackets[9];
1116 1123          char    usage_rbytes[10];
1117 1124          char    usage_opackets[9];
1118 1125          char    usage_obytes[10];
1119 1126          char    usage_bandwidth[14];
1120 1127  } usage_fields_buf_t;
1121 1128  
1122 1129  static const ofmt_field_t usage_fields[] = {
1123 1130  { "LINK",       13,
1124 1131          offsetof(usage_fields_buf_t, usage_link), print_default_cb},
1125 1132  { "DURATION",   11,
1126 1133          offsetof(usage_fields_buf_t, usage_duration), print_default_cb},
1127 1134  { "IPACKETS",   10,
1128 1135          offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb},
1129 1136  { "RBYTES",     11,
1130 1137          offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb},
1131 1138  { "OPACKETS",   10,
1132 1139          offsetof(usage_fields_buf_t, usage_opackets), print_default_cb},
1133 1140  { "OBYTES",     11,
1134 1141          offsetof(usage_fields_buf_t, usage_obytes), print_default_cb},
1135 1142  { "BANDWIDTH",  15,
1136 1143          offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
1137 1144  { NULL,         0, 0, NULL}}
1138 1145  ;
1139 1146  
1140 1147  
1141 1148  /*
1142 1149   * structures for 'dladm show-usage link'
1143 1150   */
1144 1151  
1145 1152  typedef struct  usage_l_fields_buf_s {
1146 1153          char    usage_l_link[12];
1147 1154          char    usage_l_stime[13];
1148 1155          char    usage_l_etime[13];
1149 1156          char    usage_l_rbytes[8];
1150 1157          char    usage_l_obytes[8];
1151 1158          char    usage_l_bandwidth[14];
1152 1159  } usage_l_fields_buf_t;
1153 1160  
1154 1161  static const ofmt_field_t usage_l_fields[] = {
1155 1162  /* name,        field width,    offset */
1156 1163  { "LINK",       13,
1157 1164          offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb},
1158 1165  { "START",      14,
1159 1166          offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb},
1160 1167  { "END",        14,
1161 1168          offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb},
1162 1169  { "RBYTES",     9,
1163 1170          offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb},
1164 1171  { "OBYTES",     9,
1165 1172          offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb},
1166 1173  { "BANDWIDTH",  15,
1167 1174          offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb},
1168 1175  { NULL,         0, 0, NULL}}
1169 1176  ;
1170 1177  
1171 1178  /* IPTUN_*FLAG_INDEX values are indices into iptun_flags below. */
1172 1179  enum { IPTUN_SFLAG_INDEX, IPTUN_IFLAG_INDEX, IPTUN_NUM_FLAGS };
1173 1180  
1174 1181  /*
1175 1182   * structures for 'dladm show-iptun'
1176 1183   */
1177 1184  typedef struct iptun_fields_buf_s {
1178 1185          char    iptun_name[MAXLINKNAMELEN];
1179 1186          char    iptun_type[5];
1180 1187          char    iptun_laddr[NI_MAXHOST];
1181 1188          char    iptun_raddr[NI_MAXHOST];
1182 1189          char    iptun_flags[IPTUN_NUM_FLAGS + 1];
1183 1190  } iptun_fields_buf_t;
1184 1191  
1185 1192  static const ofmt_field_t iptun_fields[] = {
1186 1193  { "LINK",       16,
1187 1194          offsetof(iptun_fields_buf_t, iptun_name), print_default_cb },
1188 1195  { "TYPE",       6,
1189 1196          offsetof(iptun_fields_buf_t, iptun_type), print_default_cb },
1190 1197  { "FLAGS",      7,
1191 1198          offsetof(iptun_fields_buf_t, iptun_flags), print_default_cb },
1192 1199  { "LOCAL",      20,
1193 1200          offsetof(iptun_fields_buf_t, iptun_laddr), print_default_cb },
1194 1201  { "REMOTE",     20,
1195 1202          offsetof(iptun_fields_buf_t, iptun_raddr), print_default_cb },
1196 1203  { NULL, 0, 0, NULL}
1197 1204  };
1198 1205  
1199 1206  /*
1200 1207   * structures for 'dladm show-bridge'.  These are based on sections 14.8.1.1.3
1201 1208   * and 14.8.1.2.2 of IEEE 802.1D-2004.
1202 1209   */
1203 1210  typedef struct bridge_fields_buf_s {
1204 1211          char bridge_name[MAXLINKNAMELEN]; /* 14.4.1.2.3(b) */
1205 1212          char bridge_protect[7];         /* stp or trill */
1206 1213          char bridge_address[24];        /* 17.18.3, 7.12.5, 14.4.1.2.3(a) */
1207 1214          char bridge_priority[7];        /* 17.18.3 9.2.5 - only upper 4 bits */
1208 1215          char bridge_bmaxage[7];         /* 17.18.4 configured */
1209 1216          char bridge_bhellotime[7];      /* 17.18.4 configured */
1210 1217          char bridge_bfwddelay[7];       /* 17.18.4 configured */
1211 1218          char bridge_forceproto[3];      /* 17.13.4 configured */
1212 1219          char bridge_tctime[12];         /* 14.8.1.1.3(b) */
1213 1220          char bridge_tccount[12];        /* 17.17.8 */
1214 1221          char bridge_tchange[12];        /* 17.17.8 */
1215 1222          char bridge_desroot[24];        /* 17.18.6 priority "/" MAC */
1216 1223          char bridge_rootcost[12];       /* 17.18.6 */
1217 1224          char bridge_rootport[12];       /* 17.18.6 */
1218 1225          char bridge_maxage[7];          /* 17.18.7 for root */
1219 1226          char bridge_hellotime[7];       /* 17.13.6 for root */
1220 1227          char bridge_fwddelay[7];        /* 17.13.5 for root */
1221 1228          char bridge_holdtime[12];       /* 17.13.12 for root */
1222 1229  } bridge_fields_buf_t;
1223 1230  
1224 1231  static ofmt_field_t bridge_fields[] = {
1225 1232  /* name,        field width,    offset, callback        */
1226 1233  { "BRIDGE",     12,
1227 1234      offsetof(bridge_fields_buf_t, bridge_name), print_default_cb },
1228 1235  { "PROTECT",    8,
1229 1236      offsetof(bridge_fields_buf_t, bridge_protect), print_default_cb },
1230 1237  { "ADDRESS",    19,
1231 1238      offsetof(bridge_fields_buf_t, bridge_address), print_default_cb },
1232 1239  { "PRIORITY",   9,
1233 1240      offsetof(bridge_fields_buf_t, bridge_priority), print_default_cb },
1234 1241  { "BMAXAGE",    8,
1235 1242      offsetof(bridge_fields_buf_t, bridge_bmaxage), print_default_cb },
1236 1243  { "BHELLOTIME", 11,
1237 1244      offsetof(bridge_fields_buf_t, bridge_bhellotime), print_default_cb },
1238 1245  { "BFWDDELAY",  10,
1239 1246      offsetof(bridge_fields_buf_t, bridge_bfwddelay), print_default_cb },
1240 1247  { "FORCEPROTO", 11,
1241 1248      offsetof(bridge_fields_buf_t, bridge_forceproto), print_default_cb },
1242 1249  { "TCTIME",     10,
1243 1250      offsetof(bridge_fields_buf_t, bridge_tctime), print_default_cb },
1244 1251  { "TCCOUNT",    10,
1245 1252      offsetof(bridge_fields_buf_t, bridge_tccount), print_default_cb },
1246 1253  { "TCHANGE",    10,
1247 1254      offsetof(bridge_fields_buf_t, bridge_tchange), print_default_cb },
1248 1255  { "DESROOT",    23,
1249 1256      offsetof(bridge_fields_buf_t, bridge_desroot), print_default_cb },
1250 1257  { "ROOTCOST",   11,
1251 1258      offsetof(bridge_fields_buf_t, bridge_rootcost), print_default_cb },
1252 1259  { "ROOTPORT",   11,
1253 1260      offsetof(bridge_fields_buf_t, bridge_rootport), print_default_cb },
1254 1261  { "MAXAGE",     8,
1255 1262      offsetof(bridge_fields_buf_t, bridge_maxage), print_default_cb },
1256 1263  { "HELLOTIME",  10,
1257 1264      offsetof(bridge_fields_buf_t, bridge_hellotime), print_default_cb },
1258 1265  { "FWDDELAY",   9,
1259 1266      offsetof(bridge_fields_buf_t, bridge_fwddelay), print_default_cb },
1260 1267  { "HOLDTIME",   9,
1261 1268      offsetof(bridge_fields_buf_t, bridge_holdtime), print_default_cb },
1262 1269  { NULL,         0, 0, NULL}};
1263 1270  
1264 1271  /*
1265 1272   * structures for 'dladm show-bridge -l'.  These are based on 14.4.1.2.3 and
1266 1273   * 14.8.2.1.3 of IEEE 802.1D-2004.
1267 1274   */
1268 1275  typedef struct bridge_link_fields_buf_s {
1269 1276          char bridgel_link[MAXLINKNAMELEN];
1270 1277          char bridgel_index[7];                  /* 14.4.1.2.3(d1) */
1271 1278          char bridgel_state[11];                 /* 14.8.2.1.3(b) */
1272 1279          char bridgel_uptime[7];                 /* 14.8.2.1.3(a) */
1273 1280          char bridgel_opercost[7]                /* 14.8.2.1.3(d) */;
1274 1281          char bridgel_operp2p[4];                /* 14.8.2.1.3(p) */
1275 1282          char bridgel_operedge[4];               /* 14.8.2.1.3(k) */
1276 1283          char bridgel_desroot[23];               /* 14.8.2.1.3(e) */
1277 1284          char bridgel_descost[12];               /* 14.8.2.1.3(f) */
1278 1285          char bridgel_desbridge[23];             /* 14.8.2.1.3(g) */
1279 1286          char bridgel_desport[7];                /* 14.8.2.1.3(h) */
1280 1287          char bridgel_tcack[4];                  /* 14.8.2.1.3(i) */
1281 1288  } bridge_link_fields_buf_t;
1282 1289  
1283 1290  static ofmt_field_t bridge_link_fields[] = {
1284 1291  /* name,        field width,    offset, callback        */
1285 1292  { "LINK",               12,
1286 1293      offsetof(bridge_link_fields_buf_t, bridgel_link), print_default_cb },
1287 1294  { "INDEX",      8,
1288 1295      offsetof(bridge_link_fields_buf_t, bridgel_index), print_default_cb },
1289 1296  { "STATE",      12,
1290 1297      offsetof(bridge_link_fields_buf_t, bridgel_state), print_default_cb },
1291 1298  { "UPTIME",     8,
1292 1299      offsetof(bridge_link_fields_buf_t, bridgel_uptime), print_default_cb },
1293 1300  { "OPERCOST",   9,
1294 1301      offsetof(bridge_link_fields_buf_t, bridgel_opercost), print_default_cb },
1295 1302  { "OPERP2P",    8,
1296 1303      offsetof(bridge_link_fields_buf_t, bridgel_operp2p), print_default_cb },
1297 1304  { "OPEREDGE",   9,
1298 1305      offsetof(bridge_link_fields_buf_t, bridgel_operedge), print_default_cb },
1299 1306  { "DESROOT",    22,
1300 1307      offsetof(bridge_link_fields_buf_t, bridgel_desroot), print_default_cb },
1301 1308  { "DESCOST",    11,
1302 1309      offsetof(bridge_link_fields_buf_t, bridgel_descost), print_default_cb },
1303 1310  { "DESBRIDGE",  22,
1304 1311      offsetof(bridge_link_fields_buf_t, bridgel_desbridge), print_default_cb },
1305 1312  { "DESPORT",    8,
1306 1313      offsetof(bridge_link_fields_buf_t, bridgel_desport), print_default_cb },
1307 1314  { "TCACK",      6,
1308 1315      offsetof(bridge_link_fields_buf_t, bridgel_tcack), print_default_cb },
1309 1316  { NULL,         0, 0, NULL}};
1310 1317  
1311 1318  /*
1312 1319   * structures for 'dladm show-bridge -s'.  These are not based on IEEE
1313 1320   * 802.1D-2004.
1314 1321   */
1315 1322  #define ULONG_DIG       (((sizeof (ulong_t) * NBBY) * 3 / 10) + 1)
1316 1323  #define UINT64_DIG      (((sizeof (uint64_t) * NBBY) * 3 / 10) + 1)
1317 1324  typedef struct bridge_statfields_buf_s {
1318 1325          char bridges_name[MAXLINKNAMELEN];
1319 1326          char bridges_drops[UINT64_DIG];
1320 1327          char bridges_forwards[UINT64_DIG];
1321 1328          char bridges_mbcast[UINT64_DIG];
1322 1329          char bridges_unknown[UINT64_DIG];
1323 1330          char bridges_recv[UINT64_DIG];
1324 1331          char bridges_sent[UINT64_DIG];
1325 1332  } bridge_statfields_buf_t;
1326 1333  
1327 1334  static ofmt_field_t bridge_statfields[] = {
1328 1335  /* name,        field width,    offset, callback        */
1329 1336  { "BRIDGE",     12,
1330 1337      offsetof(bridge_statfields_buf_t, bridges_name), print_default_cb },
1331 1338  { "DROPS",      12,
1332 1339      offsetof(bridge_statfields_buf_t, bridges_drops), print_default_cb },
1333 1340  { "FORWARDS",   12,
1334 1341      offsetof(bridge_statfields_buf_t, bridges_forwards), print_default_cb },
1335 1342  { "MBCAST",     12,
1336 1343      offsetof(bridge_statfields_buf_t, bridges_mbcast), print_default_cb },
1337 1344  { "UNKNOWN",    12,
1338 1345      offsetof(bridge_statfields_buf_t, bridges_unknown), print_default_cb },
1339 1346  { "RECV",       12,
1340 1347      offsetof(bridge_statfields_buf_t, bridges_recv), print_default_cb },
1341 1348  { "SENT",       12,
1342 1349      offsetof(bridge_statfields_buf_t, bridges_sent), print_default_cb },
1343 1350  { NULL,         0, 0, NULL}};
1344 1351  
1345 1352  /*
1346 1353   * structures for 'dladm show-bridge -s -l'.  These are based in part on
1347 1354   * section 14.6.1.1.3 of IEEE 802.1D-2004.
1348 1355   */
1349 1356  typedef struct bridge_link_statfields_buf_s {
1350 1357          char bridgels_link[MAXLINKNAMELEN];
1351 1358          char bridgels_cfgbpdu[ULONG_DIG];
1352 1359          char bridgels_tcnbpdu[ULONG_DIG];
1353 1360          char bridgels_rstpbpdu[ULONG_DIG];
1354 1361          char bridgels_txbpdu[ULONG_DIG];
1355 1362          char bridgels_drops[UINT64_DIG];        /* 14.6.1.1.3(d) */
1356 1363          char bridgels_recv[UINT64_DIG];         /* 14.6.1.1.3(a) */
1357 1364          char bridgels_xmit[UINT64_DIG];         /* 14.6.1.1.3(c) */
1358 1365  } bridge_link_statfields_buf_t;
1359 1366  
1360 1367  static ofmt_field_t bridge_link_statfields[] = {
1361 1368  /* name,        field width,    offset, callback        */
1362 1369  { "LINK",       12,
1363 1370      offsetof(bridge_link_statfields_buf_t, bridgels_link), print_default_cb },
1364 1371  { "CFGBPDU",    9,
1365 1372      offsetof(bridge_link_statfields_buf_t, bridgels_cfgbpdu),
1366 1373      print_default_cb },
1367 1374  { "TCNBPDU",    9,
1368 1375      offsetof(bridge_link_statfields_buf_t, bridgels_tcnbpdu),
1369 1376      print_default_cb },
1370 1377  { "RSTPBPDU",   9,
1371 1378      offsetof(bridge_link_statfields_buf_t, bridgels_rstpbpdu),
1372 1379      print_default_cb },
1373 1380  { "TXBPDU",     9,
1374 1381      offsetof(bridge_link_statfields_buf_t, bridgels_txbpdu), print_default_cb },
1375 1382  { "DROPS",      9,
1376 1383      offsetof(bridge_link_statfields_buf_t, bridgels_drops), print_default_cb },
1377 1384  { "RECV",       9,
1378 1385      offsetof(bridge_link_statfields_buf_t, bridgels_recv), print_default_cb },
1379 1386  { "XMIT",       9,
1380 1387      offsetof(bridge_link_statfields_buf_t, bridgels_xmit), print_default_cb },
1381 1388  { NULL,         0, 0, NULL}};
1382 1389  
1383 1390  /*
1384 1391   * structures for 'dladm show-bridge -f'.  These are based in part on
1385 1392   * section  14.7.6.3.3 of IEEE 802.1D-2004.
1386 1393   */
1387 1394  typedef struct bridge_fwd_fields_buf_s {
1388 1395          char bridgef_dest[18];                  /* 14.7.6.3.3(a) */
1389 1396          char bridgef_age[8];
1390 1397          char bridgef_flags[6];
1391 1398          char bridgef_output[MAXLINKNAMELEN];    /* 14.7.6.3.3(c) */
1392 1399  } bridge_fwd_fields_buf_t;
1393 1400  
1394 1401  static ofmt_field_t bridge_fwd_fields[] = {
1395 1402  /* name,        field width,    offset, callback        */
1396 1403  { "DEST",       17,
1397 1404      offsetof(bridge_fwd_fields_buf_t, bridgef_dest), print_default_cb },
1398 1405  { "AGE",        7,
1399 1406      offsetof(bridge_fwd_fields_buf_t, bridgef_age), print_default_cb },
1400 1407  { "FLAGS",      6,
1401 1408      offsetof(bridge_fwd_fields_buf_t, bridgef_flags), print_default_cb },
1402 1409  { "OUTPUT",     12,
1403 1410      offsetof(bridge_fwd_fields_buf_t, bridgef_output), print_default_cb },
1404 1411  { NULL,         0, 0, NULL}};
1405 1412  
1406 1413  /*
1407 1414   * structures for 'dladm show-bridge -t'.
1408 1415   */
1409 1416  typedef struct bridge_trill_fields_buf_s {
1410 1417          char bridget_nick[6];
1411 1418          char bridget_flags[6];
1412 1419          char bridget_link[MAXLINKNAMELEN];
1413 1420          char bridget_nexthop[18];
1414 1421  } bridge_trill_fields_buf_t;
1415 1422  
1416 1423  static ofmt_field_t bridge_trill_fields[] = {
1417 1424  /* name,        field width,    offset, callback        */
1418 1425  { "NICK",       5,
1419 1426      offsetof(bridge_trill_fields_buf_t, bridget_nick), print_default_cb },
1420 1427  { "FLAGS",      6,
1421 1428      offsetof(bridge_trill_fields_buf_t, bridget_flags), print_default_cb },
1422 1429  { "LINK",       12,
1423 1430      offsetof(bridge_trill_fields_buf_t, bridget_link), print_default_cb },
1424 1431  { "NEXTHOP",    17,
1425 1432      offsetof(bridge_trill_fields_buf_t, bridget_nexthop), print_default_cb },
1426 1433  { NULL,         0, 0, NULL}};
1427 1434  
1428 1435  static char *progname;
1429 1436  static sig_atomic_t signalled;
1430 1437  
1431 1438  /*
1432 1439   * Handle to libdladm.  Opened in main() before the sub-command
1433 1440   * specific function is called.
1434 1441   */
1435 1442  static dladm_handle_t handle = NULL;
1436 1443  
1437 1444  #define DLADM_ETHERSTUB_NAME    "etherstub"
1438 1445  #define DLADM_IS_ETHERSTUB(id)  (id == DATALINK_INVALID_LINKID)
1439 1446  
1440 1447  static void
1441 1448  usage(void)
1442 1449  {
1443 1450          int     i;
1444 1451          cmd_t   *cmdp;
1445 1452          (void) fprintf(stderr, gettext("usage:  dladm <subcommand> <args> ..."
1446 1453              "\n"));
1447 1454          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
1448 1455                  cmdp = &cmds[i];
1449 1456                  if (cmdp->c_usage != NULL)
1450 1457                          (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
1451 1458          }
1452 1459  
1453 1460          /* close dladm handle if it was opened */
1454 1461          if (handle != NULL)
1455 1462                  dladm_close(handle);
1456 1463  
1457 1464          exit(EXIT_FAILURE);
1458 1465  }
1459 1466  
1460 1467  int
1461 1468  main(int argc, char *argv[])
1462 1469  {
1463 1470          int     i;
1464 1471          cmd_t   *cmdp;
1465 1472          dladm_status_t status;
1466 1473  
1467 1474          (void) setlocale(LC_ALL, "");
1468 1475  #if !defined(TEXT_DOMAIN)
1469 1476  #define TEXT_DOMAIN "SYS_TEST"
1470 1477  #endif
1471 1478          (void) textdomain(TEXT_DOMAIN);
1472 1479  
1473 1480          progname = argv[0];
1474 1481  
1475 1482          if (argc < 2)
1476 1483                  usage();
1477 1484  
1478 1485          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
1479 1486                  cmdp = &cmds[i];
1480 1487                  if (strcmp(argv[1], cmdp->c_name) == 0) {
1481 1488                          /* Open the libdladm handle */
1482 1489                          if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
1483 1490                                  die_dlerr(status,
1484 1491                                      "could not open /dev/dld");
1485 1492                          }
1486 1493  
1487 1494                          cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
1488 1495  
1489 1496                          dladm_close(handle);
1490 1497                          return (EXIT_SUCCESS);
1491 1498                  }
1492 1499          }
1493 1500  
1494 1501          (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
1495 1502              progname, argv[1]);
1496 1503          usage();
1497 1504          return (EXIT_FAILURE);
1498 1505  }
1499 1506  
1500 1507  /*ARGSUSED*/
1501 1508  static int
1502 1509  show_usage_date(dladm_usage_t *usage, void *arg)
1503 1510  {
1504 1511          show_usage_state_t      *state = (show_usage_state_t *)arg;
1505 1512          time_t                  stime;
1506 1513          char                    timebuf[20];
1507 1514          dladm_status_t          status;
1508 1515          uint32_t                flags;
1509 1516  
1510 1517          /*
1511 1518           * Only show usage information for existing links unless '-a'
1512 1519           * is specified.
1513 1520           */
1514 1521          if (!state->us_showall) {
1515 1522                  if ((status = dladm_name2info(handle, usage->du_name,
1516 1523                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1517 1524                          return (status);
1518 1525                  }
1519 1526                  if ((flags & DLADM_OPT_ACTIVE) == 0)
1520 1527                          return (DLADM_STATUS_LINKINVAL);
1521 1528          }
1522 1529  
1523 1530          stime = usage->du_stime;
1524 1531          (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
1525 1532              localtime(&stime));
1526 1533          (void) printf("%s\n", timebuf);
1527 1534  
1528 1535          return (DLADM_STATUS_OK);
1529 1536  }
1530 1537  
1531 1538  static int
1532 1539  show_usage_time(dladm_usage_t *usage, void *arg)
1533 1540  {
1534 1541          show_usage_state_t      *state = (show_usage_state_t *)arg;
1535 1542          char                    buf[DLADM_STRSIZE];
1536 1543          usage_l_fields_buf_t    ubuf;
1537 1544          time_t                  time;
1538 1545          double                  bw;
1539 1546          dladm_status_t          status;
1540 1547          uint32_t                flags;
1541 1548  
1542 1549          /*
1543 1550           * Only show usage information for existing links unless '-a'
1544 1551           * is specified.
1545 1552           */
1546 1553          if (!state->us_showall) {
1547 1554                  if ((status = dladm_name2info(handle, usage->du_name,
1548 1555                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1549 1556                          return (status);
1550 1557                  }
1551 1558                  if ((flags & DLADM_OPT_ACTIVE) == 0)
1552 1559                          return (DLADM_STATUS_LINKINVAL);
1553 1560          }
1554 1561  
1555 1562          if (state->us_plot) {
1556 1563                  if (!state->us_printheader) {
1557 1564                          if (state->us_first) {
1558 1565                                  (void) printf("# Time");
1559 1566                                  state->us_first = B_FALSE;
1560 1567                          }
1561 1568                          (void) printf(" %s", usage->du_name);
1562 1569                          if (usage->du_last) {
1563 1570                                  (void) printf("\n");
1564 1571                                  state->us_first = B_TRUE;
1565 1572                                  state->us_printheader = B_TRUE;
1566 1573                          }
1567 1574                  } else {
1568 1575                          if (state->us_first) {
1569 1576                                  time = usage->du_etime;
1570 1577                                  (void) strftime(buf, sizeof (buf), "%T",
1571 1578                                      localtime(&time));
1572 1579                                  state->us_first = B_FALSE;
1573 1580                                  (void) printf("%s", buf);
1574 1581                          }
1575 1582                          bw = (double)usage->du_bandwidth/1000;
1576 1583                          (void) printf(" %.2f", bw);
1577 1584                          if (usage->du_last) {
1578 1585                                  (void) printf("\n");
1579 1586                                  state->us_first = B_TRUE;
1580 1587                          }
1581 1588                  }
1582 1589                  return (DLADM_STATUS_OK);
1583 1590          }
1584 1591  
1585 1592          bzero(&ubuf, sizeof (ubuf));
1586 1593  
1587 1594          (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s",
1588 1595              usage->du_name);
1589 1596          time = usage->du_stime;
1590 1597          (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1591 1598          (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s",
1592 1599              buf);
1593 1600          time = usage->du_etime;
1594 1601          (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1595 1602          (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s",
1596 1603              buf);
1597 1604          (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes),
1598 1605              "%llu", usage->du_rbytes);
1599 1606          (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes),
1600 1607              "%llu", usage->du_obytes);
1601 1608          (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth),
1602 1609              "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1603 1610  
1604 1611          ofmt_print(state->us_ofmt, &ubuf);
1605 1612          return (DLADM_STATUS_OK);
1606 1613  }
1607 1614  
1608 1615  static int
1609 1616  show_usage_res(dladm_usage_t *usage, void *arg)
1610 1617  {
1611 1618          show_usage_state_t      *state = (show_usage_state_t *)arg;
1612 1619          char                    buf[DLADM_STRSIZE];
1613 1620          usage_fields_buf_t      ubuf;
1614 1621          dladm_status_t          status;
1615 1622          uint32_t                flags;
1616 1623  
1617 1624          /*
1618 1625           * Only show usage information for existing links unless '-a'
1619 1626           * is specified.
1620 1627           */
1621 1628          if (!state->us_showall) {
1622 1629                  if ((status = dladm_name2info(handle, usage->du_name,
1623 1630                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1624 1631                          return (status);
1625 1632                  }
1626 1633                  if ((flags & DLADM_OPT_ACTIVE) == 0)
1627 1634                          return (DLADM_STATUS_LINKINVAL);
1628 1635          }
1629 1636  
1630 1637          bzero(&ubuf, sizeof (ubuf));
1631 1638  
1632 1639          (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s",
1633 1640              usage->du_name);
1634 1641          (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration),
1635 1642              "%llu", usage->du_duration);
1636 1643          (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets),
1637 1644              "%llu", usage->du_ipackets);
1638 1645          (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes),
1639 1646              "%llu", usage->du_rbytes);
1640 1647          (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets),
1641 1648              "%llu", usage->du_opackets);
1642 1649          (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes),
1643 1650              "%llu", usage->du_obytes);
1644 1651          (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth),
1645 1652              "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1646 1653  
1647 1654          ofmt_print(state->us_ofmt, &ubuf);
1648 1655  
1649 1656          return (DLADM_STATUS_OK);
1650 1657  }
1651 1658  
1652 1659  static boolean_t
1653 1660  valid_formatspec(char *formatspec_str)
1654 1661  {
1655 1662          if (strcmp(formatspec_str, "gnuplot") == 0)
1656 1663                  return (B_TRUE);
1657 1664          return (B_FALSE);
1658 1665  
1659 1666  }
1660 1667  
1661 1668  /*ARGSUSED*/
1662 1669  static void
1663 1670  do_show_usage(int argc, char *argv[], const char *use)
1664 1671  {
1665 1672          char                    *file = NULL;
1666 1673          int                     opt;
1667 1674          dladm_status_t          status;
1668 1675          boolean_t               d_arg = B_FALSE;
1669 1676          char                    *stime = NULL;
1670 1677          char                    *etime = NULL;
1671 1678          char                    *resource = NULL;
1672 1679          show_usage_state_t      state;
1673 1680          boolean_t               o_arg = B_FALSE;
1674 1681          boolean_t               F_arg = B_FALSE;
1675 1682          char                    *fields_str = NULL;
1676 1683          char                    *formatspec_str = NULL;
1677 1684          char                    *all_l_fields =
1678 1685              "link,start,end,rbytes,obytes,bandwidth";
1679 1686          ofmt_handle_t           ofmt;
1680 1687          ofmt_status_t           oferr;
1681 1688          uint_t                  ofmtflags = 0;
1682 1689  
1683 1690          bzero(&state, sizeof (show_usage_state_t));
1684 1691          state.us_parsable = B_FALSE;
1685 1692          state.us_printheader = B_FALSE;
1686 1693          state.us_plot = B_FALSE;
1687 1694          state.us_first = B_TRUE;
1688 1695  
1689 1696          while ((opt = getopt_long(argc, argv, "das:e:o:f:F:",
1690 1697              usage_opts, NULL)) != -1) {
1691 1698                  switch (opt) {
1692 1699                  case 'd':
1693 1700                          d_arg = B_TRUE;
1694 1701                          break;
1695 1702                  case 'a':
1696 1703                          state.us_showall = B_TRUE;
1697 1704                          break;
1698 1705                  case 'f':
1699 1706                          file = optarg;
1700 1707                          break;
1701 1708                  case 's':
1702 1709                          stime = optarg;
1703 1710                          break;
1704 1711                  case 'e':
1705 1712                          etime = optarg;
1706 1713                          break;
1707 1714                  case 'o':
1708 1715                          o_arg = B_TRUE;
1709 1716                          fields_str = optarg;
1710 1717                          break;
1711 1718                  case 'F':
1712 1719                          state.us_plot = F_arg = B_TRUE;
1713 1720                          formatspec_str = optarg;
1714 1721                          break;
1715 1722                  default:
1716 1723                          die_opterr(optopt, opt, use);
1717 1724                          break;
1718 1725                  }
1719 1726          }
1720 1727  
1721 1728          if (file == NULL)
1722 1729                  die("show-usage requires a file");
1723 1730  
1724 1731          if (optind == (argc-1)) {
1725 1732                  uint32_t        flags;
1726 1733  
1727 1734                  resource = argv[optind];
1728 1735                  if (!state.us_showall &&
1729 1736                      (((status = dladm_name2info(handle, resource, NULL, &flags,
1730 1737                      NULL, NULL)) != DLADM_STATUS_OK) ||
1731 1738                      ((flags & DLADM_OPT_ACTIVE) == 0))) {
1732 1739                          die("invalid link: '%s'", resource);
1733 1740                  }
1734 1741          }
1735 1742  
1736 1743          if (F_arg && d_arg)
1737 1744                  die("incompatible -d and -F options");
1738 1745  
1739 1746          if (F_arg && valid_formatspec(formatspec_str) == B_FALSE)
1740 1747                  die("Format specifier %s not supported", formatspec_str);
1741 1748  
1742 1749          if (state.us_parsable)
1743 1750                  ofmtflags |= OFMT_PARSABLE;
1744 1751  
1745 1752          if (resource == NULL && stime == NULL && etime == NULL) {
1746 1753                  oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0,
1747 1754                      &ofmt);
1748 1755          } else {
1749 1756                  if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
1750 1757                          fields_str = all_l_fields;
1751 1758                  oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0,
1752 1759                      &ofmt);
1753 1760  
1754 1761          }
1755 1762          dladm_ofmt_check(oferr, state.us_parsable, ofmt);
1756 1763          state.us_ofmt = ofmt;
1757 1764  
1758 1765          if (d_arg) {
1759 1766                  /* Print log dates */
1760 1767                  status = dladm_usage_dates(show_usage_date,
1761 1768                      DLADM_LOGTYPE_LINK, file, resource, &state);
1762 1769          } else if (resource == NULL && stime == NULL && etime == NULL &&
1763 1770              !F_arg) {
1764 1771                  /* Print summary */
1765 1772                  status = dladm_usage_summary(show_usage_res,
1766 1773                      DLADM_LOGTYPE_LINK, file, &state);
1767 1774          } else if (resource != NULL) {
1768 1775                  /* Print log entries for named resource */
1769 1776                  status = dladm_walk_usage_res(show_usage_time,
1770 1777                      DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
1771 1778          } else {
1772 1779                  /* Print time and information for each link */
1773 1780                  status = dladm_walk_usage_time(show_usage_time,
1774 1781                      DLADM_LOGTYPE_LINK, file, stime, etime, &state);
1775 1782          }
1776 1783  
1777 1784          if (status != DLADM_STATUS_OK)
1778 1785                  die_dlerr(status, "show-usage");
1779 1786          ofmt_close(ofmt);
1780 1787  }
1781 1788  
1782 1789  static void
1783 1790  do_create_aggr(int argc, char *argv[], const char *use)
1784 1791  {
1785 1792          int                     option;
1786 1793          int                     key = 0;
1787 1794          uint32_t                policy = AGGR_POLICY_L4;
1788 1795          aggr_lacp_mode_t        lacp_mode = AGGR_LACP_OFF;
1789 1796          aggr_lacp_timer_t       lacp_timer = AGGR_LACP_TIMER_SHORT;
1790 1797          dladm_aggr_port_attr_db_t       port[MAXPORT];
1791 1798          uint_t                  n, ndev, nlink;
1792 1799          uint8_t                 mac_addr[ETHERADDRL];
1793 1800          boolean_t               mac_addr_fixed = B_FALSE;
1794 1801          boolean_t               P_arg = B_FALSE;
1795 1802          boolean_t               l_arg = B_FALSE;
1796 1803          boolean_t               u_arg = B_FALSE;
1797 1804          boolean_t               T_arg = B_FALSE;
1798 1805          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1799 1806          char                    *altroot = NULL;
1800 1807          char                    name[MAXLINKNAMELEN];
1801 1808          char                    *devs[MAXPORT];
1802 1809          char                    *links[MAXPORT];
1803 1810          dladm_status_t          status;
1804 1811          dladm_status_t          pstatus;
1805 1812          char                    propstr[DLADM_STRSIZE];
1806 1813          dladm_arg_list_t        *proplist = NULL;
1807 1814          int                     i;
1808 1815          datalink_id_t           linkid;
1809 1816  
1810 1817          ndev = nlink = opterr = 0;
1811 1818          bzero(propstr, DLADM_STRSIZE);
1812 1819  
1813 1820          while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:",
1814 1821              lopts, NULL)) != -1) {
1815 1822                  switch (option) {
1816 1823                  case 'd':
1817 1824                          if (ndev + nlink >= MAXPORT)
1818 1825                                  die("too many ports specified");
1819 1826  
1820 1827                          devs[ndev++] = optarg;
1821 1828                          break;
1822 1829                  case 'P':
1823 1830                          if (P_arg)
1824 1831                                  die_optdup(option);
1825 1832  
1826 1833                          P_arg = B_TRUE;
1827 1834                          if (!dladm_aggr_str2policy(optarg, &policy))
1828 1835                                  die("invalid policy '%s'", optarg);
1829 1836                          break;
1830 1837                  case 'u':
1831 1838                          if (u_arg)
1832 1839                                  die_optdup(option);
1833 1840  
1834 1841                          u_arg = B_TRUE;
1835 1842                          if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
1836 1843                              mac_addr))
1837 1844                                  die("invalid MAC address '%s'", optarg);
1838 1845                          break;
1839 1846                  case 'l':
1840 1847                          if (isdigit(optarg[strlen(optarg) - 1])) {
1841 1848  
1842 1849                                  /*
1843 1850                                   * Ended with digit, possibly a link name.
1844 1851                                   */
1845 1852                                  if (ndev + nlink >= MAXPORT)
1846 1853                                          die("too many ports specified");
1847 1854  
1848 1855                                  links[nlink++] = optarg;
1849 1856                                  break;
1850 1857                          }
1851 1858                          /* FALLTHROUGH */
1852 1859                  case 'L':
1853 1860                          if (l_arg)
1854 1861                                  die_optdup(option);
1855 1862  
1856 1863                          l_arg = B_TRUE;
1857 1864                          if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
1858 1865                                  die("invalid LACP mode '%s'", optarg);
1859 1866                          break;
1860 1867                  case 'T':
1861 1868                          if (T_arg)
1862 1869                                  die_optdup(option);
1863 1870  
1864 1871                          T_arg = B_TRUE;
1865 1872                          if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
1866 1873                                  die("invalid LACP timer value '%s'", optarg);
1867 1874                          break;
1868 1875                  case 't':
1869 1876                          flags &= ~DLADM_OPT_PERSIST;
1870 1877                          break;
1871 1878                  case 'f':
1872 1879                          flags |= DLADM_OPT_FORCE;
1873 1880                          break;
1874 1881                  case 'R':
1875 1882                          altroot = optarg;
1876 1883                          break;
1877 1884                  case 'p':
1878 1885                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
1879 1886                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
1880 1887                              DLADM_STRSIZE)
1881 1888                                  die("property list too long '%s'", propstr);
1882 1889                          break;
1883 1890  
1884 1891                  default:
1885 1892                          die_opterr(optopt, option, use);
1886 1893                          break;
1887 1894                  }
1888 1895          }
1889 1896  
1890 1897          if (ndev + nlink == 0)
1891 1898                  usage();
1892 1899  
1893 1900          /* get key value or the aggregation name (required last argument) */
1894 1901          if (optind != (argc-1))
1895 1902                  usage();
1896 1903  
1897 1904          if (!str2int(argv[optind], &key)) {
1898 1905                  if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >=
1899 1906                      MAXLINKNAMELEN) {
1900 1907                          die("link name too long '%s'", argv[optind]);
1901 1908                  }
1902 1909  
1903 1910                  if (!dladm_valid_linkname(name))
1904 1911                          die("invalid link name '%s'", argv[optind]);
1905 1912          } else {
1906 1913                  (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key);
1907 1914          }
1908 1915  
1909 1916          if (altroot != NULL)
1910 1917                  altroot_cmd(altroot, argc, argv);
1911 1918  
1912 1919          for (n = 0; n < ndev; n++) {
1913 1920                  if ((status = dladm_dev2linkid(handle, devs[n],
1914 1921                      &port[n].lp_linkid)) != DLADM_STATUS_OK) {
1915 1922                          die_dlerr(status, "invalid dev name '%s'", devs[n]);
1916 1923                  }
1917 1924          }
1918 1925  
1919 1926          for (n = 0; n < nlink; n++) {
1920 1927                  if ((status = dladm_name2info(handle, links[n],
1921 1928                      &port[ndev + n].lp_linkid, NULL, NULL, NULL)) !=
1922 1929                      DLADM_STATUS_OK) {
1923 1930                          die_dlerr(status, "invalid link name '%s'", links[n]);
1924 1931                  }
1925 1932          }
1926 1933  
1927 1934          status = dladm_aggr_create(handle, name, key, ndev + nlink, port,
1928 1935              policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode,
1929 1936              lacp_timer, flags);
1930 1937          if (status != DLADM_STATUS_OK)
1931 1938                  goto done;
1932 1939  
1933 1940          if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
1934 1941              != DLADM_STATUS_OK)
1935 1942                  die("invalid aggregation property");
1936 1943  
1937 1944          if (proplist == NULL)
1938 1945                  return;
1939 1946  
1940 1947          status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL);
1941 1948          if (status != DLADM_STATUS_OK)
1942 1949                  goto done;
1943 1950  
1944 1951          for (i = 0; i < proplist->al_count; i++) {
1945 1952                  dladm_arg_info_t        *aip = &proplist->al_info[i];
1946 1953  
1947 1954                  pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name,
1948 1955                      aip->ai_val, aip->ai_count, flags);
1949 1956  
1950 1957                  if (pstatus != DLADM_STATUS_OK) {
1951 1958                          die_dlerr(pstatus,
1952 1959                              "aggr creation succeeded but "
1953 1960                              "could not set property '%s'", aip->ai_name);
1954 1961                  }
1955 1962          }
1956 1963  done:
1957 1964          dladm_free_props(proplist);
1958 1965          if (status != DLADM_STATUS_OK) {
1959 1966                  if (status == DLADM_STATUS_NONOTIF) {
1960 1967                          die("not all links have link up/down detection; must "
1961 1968                              "use -f (see dladm(1M))");
1962 1969                  } else {
1963 1970                          die_dlerr(status, "create operation failed");
1964 1971                  }
1965 1972          }
1966 1973  }
1967 1974  
1968 1975  /*
1969 1976   * arg is either the key or the aggr name. Validate it and convert it to
1970 1977   * the linkid if altroot is NULL.
1971 1978   */
1972 1979  static dladm_status_t
1973 1980  i_dladm_aggr_get_linkid(const char *altroot, const char *arg,
1974 1981      datalink_id_t *linkidp, uint32_t flags)
1975 1982  {
1976 1983          int             key = 0;
1977 1984          char            *aggr = NULL;
1978 1985          dladm_status_t  status;
1979 1986  
1980 1987          if (!str2int(arg, &key))
1981 1988                  aggr = (char *)arg;
1982 1989  
1983 1990          if (aggr == NULL && key == 0)
1984 1991                  return (DLADM_STATUS_LINKINVAL);
1985 1992  
1986 1993          if (altroot != NULL)
1987 1994                  return (DLADM_STATUS_OK);
1988 1995  
1989 1996          if (aggr != NULL) {
1990 1997                  status = dladm_name2info(handle, aggr, linkidp, NULL, NULL,
1991 1998                      NULL);
1992 1999          } else {
1993 2000                  status = dladm_key2linkid(handle, key, linkidp, flags);
1994 2001          }
1995 2002  
1996 2003          return (status);
1997 2004  }
1998 2005  
1999 2006  static void
2000 2007  do_delete_aggr(int argc, char *argv[], const char *use)
2001 2008  {
2002 2009          int                     option;
2003 2010          char                    *altroot = NULL;
2004 2011          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2005 2012          dladm_status_t          status;
2006 2013          datalink_id_t           linkid;
2007 2014  
2008 2015          opterr = 0;
2009 2016          while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
2010 2017                  switch (option) {
2011 2018                  case 't':
2012 2019                          flags &= ~DLADM_OPT_PERSIST;
2013 2020                          break;
2014 2021                  case 'R':
2015 2022                          altroot = optarg;
2016 2023                          break;
2017 2024                  default:
2018 2025                          die_opterr(optopt, option, use);
2019 2026                          break;
2020 2027                  }
2021 2028          }
2022 2029  
2023 2030          /* get key value or the aggregation name (required last argument) */
2024 2031          if (optind != (argc-1))
2025 2032                  usage();
2026 2033  
2027 2034          status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2028 2035          if (status != DLADM_STATUS_OK)
2029 2036                  goto done;
2030 2037  
2031 2038          if (altroot != NULL)
2032 2039                  altroot_cmd(altroot, argc, argv);
2033 2040  
2034 2041          status = dladm_aggr_delete(handle, linkid, flags);
2035 2042  done:
2036 2043          if (status != DLADM_STATUS_OK)
2037 2044                  die_dlerr(status, "delete operation failed");
2038 2045  }
2039 2046  
2040 2047  static void
2041 2048  do_add_aggr(int argc, char *argv[], const char *use)
2042 2049  {
2043 2050          int                     option;
2044 2051          uint_t                  n, ndev, nlink;
2045 2052          char                    *altroot = NULL;
2046 2053          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2047 2054          datalink_id_t           linkid;
2048 2055          dladm_status_t          status;
2049 2056          dladm_aggr_port_attr_db_t       port[MAXPORT];
2050 2057          char                    *devs[MAXPORT];
2051 2058          char                    *links[MAXPORT];
2052 2059  
2053 2060          ndev = nlink = opterr = 0;
2054 2061          while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts,
2055 2062              NULL)) != -1) {
2056 2063                  switch (option) {
2057 2064                  case 'd':
2058 2065                          if (ndev + nlink >= MAXPORT)
2059 2066                                  die("too many ports specified");
2060 2067  
2061 2068                          devs[ndev++] = optarg;
2062 2069                          break;
2063 2070                  case 'l':
2064 2071                          if (ndev + nlink >= MAXPORT)
2065 2072                                  die("too many ports specified");
2066 2073  
2067 2074                          links[nlink++] = optarg;
2068 2075                          break;
2069 2076                  case 't':
2070 2077                          flags &= ~DLADM_OPT_PERSIST;
2071 2078                          break;
2072 2079                  case 'f':
2073 2080                          flags |= DLADM_OPT_FORCE;
2074 2081                          break;
2075 2082                  case 'R':
2076 2083                          altroot = optarg;
2077 2084                          break;
2078 2085                  default:
2079 2086                          die_opterr(optopt, option, use);
2080 2087                          break;
2081 2088                  }
2082 2089          }
2083 2090  
2084 2091          if (ndev + nlink == 0)
2085 2092                  usage();
2086 2093  
2087 2094          /* get key value or the aggregation name (required last argument) */
2088 2095          if (optind != (argc-1))
2089 2096                  usage();
2090 2097  
2091 2098          if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid,
2092 2099              flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) !=
2093 2100              DLADM_STATUS_OK) {
2094 2101                  goto done;
2095 2102          }
2096 2103  
2097 2104          if (altroot != NULL)
2098 2105                  altroot_cmd(altroot, argc, argv);
2099 2106  
2100 2107          for (n = 0; n < ndev; n++) {
2101 2108                  if ((status = dladm_dev2linkid(handle, devs[n],
2102 2109                      &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
2103 2110                          die_dlerr(status, "invalid <dev> '%s'", devs[n]);
2104 2111                  }
2105 2112          }
2106 2113  
2107 2114          for (n = 0; n < nlink; n++) {
2108 2115                  if ((status = dladm_name2info(handle, links[n],
2109 2116                      &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
2110 2117                      DLADM_STATUS_OK) {
2111 2118                          die_dlerr(status, "invalid <link> '%s'", links[n]);
2112 2119                  }
2113 2120          }
2114 2121  
2115 2122          status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags);
2116 2123  done:
2117 2124          if (status != DLADM_STATUS_OK) {
2118 2125                  /*
2119 2126                   * checking DLADM_STATUS_NOTSUP is a temporary workaround
2120 2127                   * and should be removed once 6399681 is fixed.
2121 2128                   */
2122 2129                  if (status == DLADM_STATUS_NOTSUP) {
2123 2130                          die("add operation failed: link capabilities don't "
2124 2131                              "match");
2125 2132                  } else if (status == DLADM_STATUS_NONOTIF) {
2126 2133                          die("not all links have link up/down detection; must "
2127 2134                              "use -f (see dladm(1M))");
2128 2135                  } else {
2129 2136                          die_dlerr(status, "add operation failed");
2130 2137                  }
2131 2138          }
2132 2139  }
2133 2140  
2134 2141  static void
2135 2142  do_remove_aggr(int argc, char *argv[], const char *use)
2136 2143  {
2137 2144          int                             option;
2138 2145          dladm_aggr_port_attr_db_t       port[MAXPORT];
2139 2146          uint_t                          n, ndev, nlink;
2140 2147          char                            *devs[MAXPORT];
2141 2148          char                            *links[MAXPORT];
2142 2149          char                            *altroot = NULL;
2143 2150          uint32_t                        flags;
2144 2151          datalink_id_t                   linkid;
2145 2152          dladm_status_t                  status;
2146 2153  
2147 2154          flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2148 2155          ndev = nlink = opterr = 0;
2149 2156          while ((option = getopt_long(argc, argv, ":d:l:R:t",
2150 2157              lopts, NULL)) != -1) {
2151 2158                  switch (option) {
2152 2159                  case 'd':
2153 2160                          if (ndev + nlink >= MAXPORT)
2154 2161                                  die("too many ports specified");
2155 2162  
2156 2163                          devs[ndev++] = optarg;
2157 2164                          break;
2158 2165                  case 'l':
2159 2166                          if (ndev + nlink >= MAXPORT)
2160 2167                                  die("too many ports specified");
2161 2168  
2162 2169                          links[nlink++] = optarg;
2163 2170                          break;
2164 2171                  case 't':
2165 2172                          flags &= ~DLADM_OPT_PERSIST;
2166 2173                          break;
2167 2174                  case 'R':
2168 2175                          altroot = optarg;
2169 2176                          break;
2170 2177                  default:
2171 2178                          die_opterr(optopt, option, use);
2172 2179                          break;
2173 2180                  }
2174 2181          }
2175 2182  
2176 2183          if (ndev + nlink == 0)
2177 2184                  usage();
2178 2185  
2179 2186          /* get key value or the aggregation name (required last argument) */
2180 2187          if (optind != (argc-1))
2181 2188                  usage();
2182 2189  
2183 2190          status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2184 2191          if (status != DLADM_STATUS_OK)
2185 2192                  goto done;
2186 2193  
2187 2194          if (altroot != NULL)
2188 2195                  altroot_cmd(altroot, argc, argv);
2189 2196  
2190 2197          for (n = 0; n < ndev; n++) {
2191 2198                  if ((status = dladm_dev2linkid(handle, devs[n],
2192 2199                      &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
2193 2200                          die_dlerr(status, "invalid <dev> '%s'", devs[n]);
2194 2201                  }
2195 2202          }
2196 2203  
2197 2204          for (n = 0; n < nlink; n++) {
2198 2205                  if ((status = dladm_name2info(handle, links[n],
2199 2206                      &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
2200 2207                      DLADM_STATUS_OK) {
2201 2208                          die_dlerr(status, "invalid <link> '%s'", links[n]);
2202 2209                  }
2203 2210          }
2204 2211  
2205 2212          status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags);
2206 2213  done:
2207 2214          if (status != DLADM_STATUS_OK)
2208 2215                  die_dlerr(status, "remove operation failed");
2209 2216  }
2210 2217  
2211 2218  static void
2212 2219  do_modify_aggr(int argc, char *argv[], const char *use)
2213 2220  {
2214 2221          int                     option;
2215 2222          uint32_t                policy = AGGR_POLICY_L4;
2216 2223          aggr_lacp_mode_t        lacp_mode = AGGR_LACP_OFF;
2217 2224          aggr_lacp_timer_t       lacp_timer = AGGR_LACP_TIMER_SHORT;
2218 2225          uint8_t                 mac_addr[ETHERADDRL];
2219 2226          boolean_t               mac_addr_fixed = B_FALSE;
2220 2227          uint8_t                 modify_mask = 0;
2221 2228          char                    *altroot = NULL;
2222 2229          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2223 2230          datalink_id_t           linkid;
2224 2231          dladm_status_t          status;
2225 2232  
2226 2233          opterr = 0;
2227 2234          while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts,
2228 2235              NULL)) != -1) {
2229 2236                  switch (option) {
2230 2237                  case 'P':
2231 2238                          if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
2232 2239                                  die_optdup(option);
2233 2240  
2234 2241                          modify_mask |= DLADM_AGGR_MODIFY_POLICY;
2235 2242  
2236 2243                          if (!dladm_aggr_str2policy(optarg, &policy))
2237 2244                                  die("invalid policy '%s'", optarg);
2238 2245                          break;
2239 2246                  case 'u':
2240 2247                          if (modify_mask & DLADM_AGGR_MODIFY_MAC)
2241 2248                                  die_optdup(option);
2242 2249  
2243 2250                          modify_mask |= DLADM_AGGR_MODIFY_MAC;
2244 2251  
2245 2252                          if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
2246 2253                              mac_addr))
2247 2254                                  die("invalid MAC address '%s'", optarg);
2248 2255                          break;
2249 2256                  case 'l':
2250 2257                  case 'L':
2251 2258                          if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
2252 2259                                  die_optdup(option);
2253 2260  
2254 2261                          modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE;
2255 2262  
2256 2263                          if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
2257 2264                                  die("invalid LACP mode '%s'", optarg);
2258 2265                          break;
2259 2266                  case 'T':
2260 2267                          if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
2261 2268                                  die_optdup(option);
2262 2269  
2263 2270                          modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER;
2264 2271  
2265 2272                          if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
2266 2273                                  die("invalid LACP timer value '%s'", optarg);
2267 2274                          break;
2268 2275                  case 't':
2269 2276                          flags &= ~DLADM_OPT_PERSIST;
2270 2277                          break;
2271 2278                  case 'R':
2272 2279                          altroot = optarg;
2273 2280                          break;
2274 2281                  default:
2275 2282                          die_opterr(optopt, option, use);
2276 2283                          break;
2277 2284                  }
2278 2285          }
2279 2286  
2280 2287          if (modify_mask == 0)
2281 2288                  die("at least one of the -PulT options must be specified");
2282 2289  
2283 2290          /* get key value or the aggregation name (required last argument) */
2284 2291          if (optind != (argc-1))
2285 2292                  usage();
2286 2293  
2287 2294          status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2288 2295          if (status != DLADM_STATUS_OK)
2289 2296                  goto done;
2290 2297  
2291 2298          if (altroot != NULL)
2292 2299                  altroot_cmd(altroot, argc, argv);
2293 2300  
2294 2301          status = dladm_aggr_modify(handle, linkid, modify_mask, policy,
2295 2302              mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer,
2296 2303              flags);
2297 2304  
2298 2305  done:
2299 2306          if (status != DLADM_STATUS_OK)
2300 2307                  die_dlerr(status, "modify operation failed");
2301 2308  }
2302 2309  
2303 2310  /*ARGSUSED*/
2304 2311  static void
2305 2312  do_up_aggr(int argc, char *argv[], const char *use)
2306 2313  {
2307 2314          datalink_id_t   linkid = DATALINK_ALL_LINKID;
2308 2315          dladm_status_t  status;
2309 2316  
2310 2317          /*
2311 2318           * get the key or the name of the aggregation (optional last argument)
2312 2319           */
2313 2320          if (argc == 2) {
2314 2321                  if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid,
2315 2322                      DLADM_OPT_PERSIST)) != DLADM_STATUS_OK)
2316 2323                          goto done;
2317 2324          } else if (argc > 2) {
2318 2325                  usage();
2319 2326          }
2320 2327  
2321 2328          status = dladm_aggr_up(handle, linkid);
2322 2329  done:
2323 2330          if (status != DLADM_STATUS_OK) {
2324 2331                  if (argc == 2) {
2325 2332                          die_dlerr(status,
2326 2333                              "could not bring up aggregation '%s'", argv[1]);
2327 2334                  } else {
2328 2335                          die_dlerr(status, "could not bring aggregations up");
2329 2336                  }
2330 2337          }
2331 2338  }
2332 2339  
2333 2340  static void
2334 2341  do_create_vlan(int argc, char *argv[], const char *use)
2335 2342  {
2336 2343          char                    *link = NULL;
2337 2344          char                    drv[DLPI_LINKNAME_MAX];
2338 2345          uint_t                  ppa;
2339 2346          datalink_id_t           linkid;
2340 2347          datalink_id_t           dev_linkid;
2341 2348          int                     vid = 0;
2342 2349          int                     option;
2343 2350          uint32_t                flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2344 2351          char                    *altroot = NULL;
2345 2352          char                    vlan[MAXLINKNAMELEN];
2346 2353          char                    propstr[DLADM_STRSIZE];
2347 2354          dladm_arg_list_t        *proplist = NULL;
2348 2355          dladm_status_t          status;
2349 2356  
2350 2357          opterr = 0;
2351 2358          bzero(propstr, DLADM_STRSIZE);
2352 2359  
2353 2360          while ((option = getopt_long(argc, argv, ":tfR:l:v:p:",
2354 2361              lopts, NULL)) != -1) {
2355 2362                  switch (option) {
2356 2363                  case 'v':
2357 2364                          if (vid != 0)
2358 2365                                  die_optdup(option);
2359 2366  
2360 2367                          if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
2361 2368                                  die("invalid VLAN identifier '%s'", optarg);
2362 2369  
2363 2370                          break;
2364 2371                  case 'l':
2365 2372                          if (link != NULL)
2366 2373                                  die_optdup(option);
2367 2374  
2368 2375                          link = optarg;
2369 2376                          break;
2370 2377                  case 't':
2371 2378                          flags &= ~DLADM_OPT_PERSIST;
2372 2379                          break;
2373 2380                  case 'R':
2374 2381                          altroot = optarg;
2375 2382                          break;
2376 2383                  case 'p':
2377 2384                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
2378 2385                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
2379 2386                              DLADM_STRSIZE)
2380 2387                                  die("property list too long '%s'", propstr);
2381 2388                          break;
2382 2389                  case 'f':
2383 2390                          flags |= DLADM_OPT_FORCE;
2384 2391                          break;
2385 2392                  default:
2386 2393                          die_opterr(optopt, option, use);
2387 2394                          break;
2388 2395                  }
2389 2396          }
2390 2397  
2391 2398          /* get vlan name if there is any */
2392 2399          if ((vid == 0) || (link == NULL) || (argc - optind > 1))
2393 2400                  usage();
2394 2401  
2395 2402          if (optind == (argc - 1)) {
2396 2403                  if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >=
2397 2404                      MAXLINKNAMELEN) {
2398 2405                          die("vlan name too long '%s'", argv[optind]);
2399 2406                  }
2400 2407          } else {
2401 2408                  if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) ||
2402 2409                      (ppa >= 1000) ||
2403 2410                      (dlpi_makelink(vlan, drv, vid * 1000 + ppa) !=
2404 2411                      DLPI_SUCCESS)) {
2405 2412                          die("invalid link name '%s'", link);
2406 2413                  }
2407 2414          }
2408 2415  
2409 2416          if (altroot != NULL)
2410 2417                  altroot_cmd(altroot, argc, argv);
2411 2418  
2412 2419          if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) !=
2413 2420              DLADM_STATUS_OK) {
2414 2421                  die("invalid link name '%s'", link);
2415 2422          }
2416 2423  
2417 2424          if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
2418 2425              != DLADM_STATUS_OK)
2419 2426                  die("invalid vlan property");
2420 2427  
2421 2428          status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist,
2422 2429              flags, &linkid);
2423 2430          switch (status) {
2424 2431          case DLADM_STATUS_OK:
2425 2432                  break;
2426 2433  
2427 2434          case DLADM_STATUS_NOTSUP:
2428 2435                  die("VLAN over '%s' may require lowered MTU; must use -f (see "
2429 2436                      "dladm(1M))", link);
2430 2437                  break;
2431 2438  
2432 2439          case DLADM_STATUS_LINKBUSY:
2433 2440                  die("VLAN over '%s' may not use default_tag ID "
2434 2441                      "(see dladm(1M))", link);
2435 2442                  break;
2436 2443  
2437 2444          default:
2438 2445                  die_dlerr(status, "create operation failed");
2439 2446          }
2440 2447  }
2441 2448  
2442 2449  static void
2443 2450  do_delete_vlan(int argc, char *argv[], const char *use)
2444 2451  {
2445 2452          int             option;
2446 2453          uint32_t        flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2447 2454          char            *altroot = NULL;
2448 2455          datalink_id_t   linkid;
2449 2456          dladm_status_t  status;
2450 2457  
2451 2458          opterr = 0;
2452 2459          while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
2453 2460                  switch (option) {
2454 2461                  case 't':
2455 2462                          flags &= ~DLADM_OPT_PERSIST;
2456 2463                          break;
2457 2464                  case 'R':
2458 2465                          altroot = optarg;
2459 2466                          break;
2460 2467                  default:
2461 2468                          die_opterr(optopt, option, use);
2462 2469                          break;
2463 2470                  }
2464 2471          }
2465 2472  
2466 2473          /* get VLAN link name (required last argument) */
2467 2474          if (optind != (argc - 1))
2468 2475                  usage();
2469 2476  
2470 2477          if (altroot != NULL)
2471 2478                  altroot_cmd(altroot, argc, argv);
2472 2479  
2473 2480          status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
2474 2481              NULL);
2475 2482          if (status != DLADM_STATUS_OK)
2476 2483                  goto done;
2477 2484  
2478 2485          status = dladm_vlan_delete(handle, linkid, flags);
2479 2486  done:
2480 2487          if (status != DLADM_STATUS_OK)
2481 2488                  die_dlerr(status, "delete operation failed");
2482 2489  }
2483 2490  
2484 2491  /*ARGSUSED*/
2485 2492  static void
2486 2493  do_up_vlan(int argc, char *argv[], const char *use)
2487 2494  {
  
    | 
      ↓ open down ↓ | 
    1449 lines elided | 
    
      ↑ open up ↑ | 
  
2488 2495          do_up_vnic_common(argc, argv, use, B_TRUE);
2489 2496  }
2490 2497  
2491 2498  static void
2492 2499  do_rename_link(int argc, char *argv[], const char *use)
2493 2500  {
2494 2501          int             option;
2495 2502          char            *link1, *link2;
2496 2503          char            *altroot = NULL;
2497 2504          dladm_status_t  status;
     2505 +        char            *zonename = NULL;
2498 2506  
2499 2507          opterr = 0;
2500      -        while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
     2508 +        while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) {
2501 2509                  switch (option) {
2502 2510                  case 'R':
2503 2511                          altroot = optarg;
2504 2512                          break;
     2513 +                case 'z':
     2514 +                        zonename = optarg;
     2515 +                        break;
2505 2516                  default:
2506 2517                          die_opterr(optopt, option, use);
2507 2518                          break;
2508 2519                  }
2509 2520          }
2510 2521  
2511 2522          /* get link1 and link2 name (required the last 2 arguments) */
2512 2523          if (optind != (argc - 2))
2513 2524                  usage();
2514 2525  
2515 2526          if (altroot != NULL)
2516 2527                  altroot_cmd(altroot, argc, argv);
2517 2528  
2518 2529          link1 = argv[optind++];
2519 2530          link2 = argv[optind];
2520      -        if ((status = dladm_rename_link(handle, link1, link2)) !=
     2531 +        if ((status = dladm_rename_link(handle, zonename, link1, link2)) !=
2521 2532              DLADM_STATUS_OK)
2522 2533                  die_dlerr(status, "rename operation failed");
2523 2534  }
2524 2535  
2525 2536  /*ARGSUSED*/
2526 2537  static void
2527 2538  do_delete_phys(int argc, char *argv[], const char *use)
2528 2539  {
2529 2540          datalink_id_t   linkid = DATALINK_ALL_LINKID;
2530 2541          dladm_status_t  status;
2531 2542  
2532 2543          /* get link name (required the last argument) */
2533 2544          if (argc > 2)
2534 2545                  usage();
2535 2546  
2536 2547          if (argc == 2) {
2537 2548                  if ((status = dladm_name2info(handle, argv[1], &linkid, NULL,
2538 2549                      NULL, NULL)) != DLADM_STATUS_OK)
2539 2550                          die_dlerr(status, "cannot delete '%s'", argv[1]);
2540 2551          }
2541 2552  
2542 2553          if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) {
2543 2554                  if (argc == 2)
2544 2555                          die_dlerr(status, "cannot delete '%s'", argv[1]);
2545 2556                  else
2546 2557                          die_dlerr(status, "delete operation failed");
2547 2558          }
2548 2559  }
2549 2560  
2550 2561  /*ARGSUSED*/
2551 2562  static int
2552 2563  i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2553 2564  {
2554 2565          char                    name[MAXLINKNAMELEN];
2555 2566          char                    mediabuf[DLADM_STRSIZE];
2556 2567          char                    classbuf[DLADM_STRSIZE];
2557 2568          datalink_class_t        class;
2558 2569          uint32_t                media;
2559 2570          uint32_t                flags;
2560 2571  
2561 2572          if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name,
2562 2573              MAXLINKNAMELEN) == DLADM_STATUS_OK) {
2563 2574                  (void) dladm_class2str(class, classbuf);
2564 2575                  (void) dladm_media2str(media, mediabuf);
2565 2576                  (void) printf("%-12s%8d  %-12s%-20s %6d\n", name,
2566 2577                      linkid, classbuf, mediabuf, flags);
2567 2578          }
2568 2579          return (DLADM_WALK_CONTINUE);
2569 2580  }
2570 2581  
2571 2582  /*ARGSUSED*/
2572 2583  static void
2573 2584  do_show_linkmap(int argc, char *argv[], const char *use)
2574 2585  {
2575 2586          if (argc != 1)
2576 2587                  die("invalid arguments");
2577 2588  
2578 2589          (void) printf("%-12s%8s  %-12s%-20s %6s\n", "NAME", "LINKID",
2579 2590              "CLASS", "MEDIA", "FLAGS");
2580 2591  
2581 2592          (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL,
2582 2593              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
2583 2594              DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2584 2595  }
2585 2596  
2586 2597  /*
2587 2598   * Delete inactive physical links.
2588 2599   */
2589 2600  /*ARGSUSED*/
2590 2601  static int
2591 2602  purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2592 2603  {
2593 2604          datalink_class_t        class;
2594 2605          uint32_t                flags;
2595 2606  
2596 2607          if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0)
2597 2608              != DLADM_STATUS_OK) {
2598 2609                  return (DLADM_WALK_CONTINUE);
2599 2610          }
2600 2611  
2601 2612          if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE))
2602 2613                  (void) dladm_phys_delete(dh, linkid);
2603 2614  
2604 2615          return (DLADM_WALK_CONTINUE);
2605 2616  }
2606 2617  
2607 2618  /*ARGSUSED*/
2608 2619  static void
2609 2620  do_init_phys(int argc, char *argv[], const char *use)
2610 2621  {
2611 2622          di_node_t       devtree;
2612 2623  
2613 2624          if (argc > 1)
2614 2625                  usage();
2615 2626  
2616 2627          /*
2617 2628           * Force all the devices to attach, therefore all the network physical
2618 2629           * devices can be known to the dlmgmtd daemon.
2619 2630           */
2620 2631          if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL)
2621 2632                  di_fini(devtree);
2622 2633  
2623 2634          (void) dladm_walk_datalink_id(purge_phys, handle, NULL,
2624 2635              DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
2625 2636  }
2626 2637  
2627 2638  /*
2628 2639   * Print the active topology information.
2629 2640   */
2630 2641  void
2631 2642  print_link_topology(show_state_t *state, datalink_id_t linkid,
2632 2643      datalink_class_t class, link_fields_buf_t *lbuf)
2633 2644  {
2634 2645          uint32_t        flags = state->ls_flags;
2635 2646          dladm_status_t  status;
2636 2647          char            tmpbuf[MAXLINKNAMELEN];
2637 2648  
2638 2649          lbuf->link_over[0] = '\0';
2639 2650          lbuf->link_bridge[0] = '\0';
2640 2651  
2641 2652          switch (class) {
2642 2653          case DATALINK_CLASS_AGGR:
2643 2654          case DATALINK_CLASS_PHYS:
2644 2655          case DATALINK_CLASS_ETHERSTUB:
2645 2656                  status = dladm_bridge_getlink(handle, linkid, lbuf->link_bridge,
2646 2657                      sizeof (lbuf->link_bridge));
2647 2658                  if (status != DLADM_STATUS_OK &&
2648 2659                      status != DLADM_STATUS_NOTFOUND)
2649 2660                          (void) strcpy(lbuf->link_bridge, "?");
2650 2661                  break;
2651 2662          }
2652 2663  
2653 2664          switch (class) {
2654 2665          case DATALINK_CLASS_VLAN: {
2655 2666                  dladm_vlan_attr_t       vinfo;
2656 2667  
2657 2668                  if (dladm_vlan_info(handle, linkid, &vinfo, flags) !=
2658 2669                      DLADM_STATUS_OK) {
2659 2670                          (void) strcpy(lbuf->link_over, "?");
2660 2671                          break;
2661 2672                  }
2662 2673                  if (dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, NULL,
2663 2674                      NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2664 2675                      DLADM_STATUS_OK)
2665 2676                          (void) strcpy(lbuf->link_over, "?");
2666 2677                  break;
2667 2678          }
2668 2679          case DATALINK_CLASS_AGGR: {
2669 2680                  dladm_aggr_grp_attr_t   ginfo;
2670 2681                  int                     i;
2671 2682  
2672 2683                  if (dladm_aggr_info(handle, linkid, &ginfo, flags) !=
2673 2684                      DLADM_STATUS_OK || ginfo.lg_nports == 0) {
2674 2685                          (void) strcpy(lbuf->link_over, "?");
2675 2686                          break;
2676 2687                  }
2677 2688                  for (i = 0; i < ginfo.lg_nports; i++) {
2678 2689                          if (dladm_datalink_id2info(handle,
2679 2690                              ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL,
2680 2691                              tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) {
2681 2692                                  (void) strcpy(lbuf->link_over, "?");
2682 2693                                  break;
2683 2694                          }
2684 2695                          (void) strlcat(lbuf->link_over, tmpbuf,
2685 2696                              sizeof (lbuf->link_over));
2686 2697                          if (i != (ginfo.lg_nports - 1)) {
2687 2698                                  (void) strlcat(lbuf->link_over, " ",
2688 2699                                      sizeof (lbuf->link_over));
2689 2700                          }
2690 2701                  }
2691 2702                  free(ginfo.lg_ports);
2692 2703                  break;
2693 2704          }
2694 2705          case DATALINK_CLASS_VNIC: {
2695 2706                  dladm_vnic_attr_t       vinfo;
2696 2707  
2697 2708                  if (dladm_vnic_info(handle, linkid, &vinfo, flags) !=
2698 2709                      DLADM_STATUS_OK) {
2699 2710                          (void) strcpy(lbuf->link_over, "?");
2700 2711                          break;
2701 2712                  }
2702 2713                  if (dladm_datalink_id2info(handle, vinfo.va_link_id, NULL, NULL,
2703 2714                      NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2704 2715                      DLADM_STATUS_OK)
2705 2716                          (void) strcpy(lbuf->link_over, "?");
2706 2717                  break;
2707 2718          }
2708 2719  
2709 2720          case DATALINK_CLASS_PART: {
2710 2721                  dladm_part_attr_t       pinfo;
2711 2722  
2712 2723                  if (dladm_part_info(handle, linkid, &pinfo, flags) !=
2713 2724                      DLADM_STATUS_OK) {
2714 2725                          (void) strcpy(lbuf->link_over, "?");
2715 2726                          break;
2716 2727                  }
2717 2728                  if (dladm_datalink_id2info(handle, pinfo.dia_physlinkid, NULL,
2718 2729                      NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2719 2730                      DLADM_STATUS_OK)
2720 2731                          (void) strcpy(lbuf->link_over, "?");
2721 2732                  break;
2722 2733          }
2723 2734  
2724 2735          case DATALINK_CLASS_BRIDGE: {
2725 2736                  datalink_id_t *dlp;
2726 2737                  uint_t i, nports;
2727 2738  
2728 2739                  if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
2729 2740                      NULL, tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) {
2730 2741                          (void) strcpy(lbuf->link_over, "?");
2731 2742                          break;
2732 2743                  }
2733 2744                  if (tmpbuf[0] != '\0')
2734 2745                          tmpbuf[strlen(tmpbuf) - 1] = '\0';
2735 2746                  dlp = dladm_bridge_get_portlist(tmpbuf, &nports);
2736 2747                  if (dlp == NULL) {
2737 2748                          (void) strcpy(lbuf->link_over, "?");
2738 2749                          break;
2739 2750                  }
2740 2751                  for (i = 0; i < nports; i++) {
2741 2752                          if (dladm_datalink_id2info(handle, dlp[i], NULL,
2742 2753                              NULL, NULL, tmpbuf, sizeof (tmpbuf)) !=
2743 2754                              DLADM_STATUS_OK) {
2744 2755                                  (void) strcpy(lbuf->link_over, "?");
2745 2756                                  break;
2746 2757                          }
2747 2758                          (void) strlcat(lbuf->link_over, tmpbuf,
2748 2759                              sizeof (lbuf->link_over));
2749 2760                          if (i != nports - 1) {
2750 2761                                  (void) strlcat(lbuf->link_over, " ",
2751 2762                                      sizeof (lbuf->link_over));
2752 2763                          }
2753 2764                  }
2754 2765                  dladm_bridge_free_portlist(dlp);
2755 2766                  break;
2756 2767          }
2757 2768  
2758 2769          case DATALINK_CLASS_SIMNET: {
2759 2770                  dladm_simnet_attr_t     slinfo;
2760 2771  
2761 2772                  if (dladm_simnet_info(handle, linkid, &slinfo, flags) !=
2762 2773                      DLADM_STATUS_OK) {
2763 2774                          (void) strcpy(lbuf->link_over, "?");
2764 2775                          break;
2765 2776                  }
2766 2777                  if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID) {
2767 2778                          if (dladm_datalink_id2info(handle,
2768 2779                              slinfo.sna_peer_link_id, NULL, NULL, NULL,
2769 2780                              lbuf->link_over, sizeof (lbuf->link_over)) !=
2770 2781                              DLADM_STATUS_OK)
2771 2782                                  (void) strcpy(lbuf->link_over, "?");
2772 2783                  }
2773 2784                  break;
2774 2785          }
2775 2786          }
2776 2787  }
2777 2788  
2778 2789  static dladm_status_t
2779 2790  print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf)
2780 2791  {
2781 2792          char                    link[MAXLINKNAMELEN];
2782 2793          datalink_class_t        class;
2783 2794          uint_t                  mtu;
2784 2795          uint32_t                flags;
2785 2796          dladm_status_t          status;
2786 2797  
2787 2798          if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
2788 2799              NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
2789 2800                  goto done;
2790 2801          }
2791 2802  
2792 2803          if (!(state->ls_flags & flags)) {
2793 2804                  status = DLADM_STATUS_NOTFOUND;
2794 2805                  goto done;
2795 2806          }
2796 2807  
2797 2808          if (state->ls_flags == DLADM_OPT_ACTIVE) {
2798 2809                  dladm_attr_t    dlattr;
2799 2810  
2800 2811                  if (class == DATALINK_CLASS_PHYS) {
2801 2812                          dladm_phys_attr_t       dpa;
2802 2813                          dlpi_handle_t           dh;
2803 2814                          dlpi_info_t             dlinfo;
2804 2815  
2805 2816                          if ((status = dladm_phys_info(handle, linkid, &dpa,
2806 2817                              DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
2807 2818                                  goto done;
2808 2819                          }
2809 2820  
2810 2821                          if (!dpa.dp_novanity)
2811 2822                                  goto link_mtu;
2812 2823  
2813 2824                          /*
2814 2825                           * This is a physical link that does not have
2815 2826                           * vanity naming support.
2816 2827                           */
2817 2828                          if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) !=
2818 2829                              DLPI_SUCCESS) {
2819 2830                                  status = DLADM_STATUS_NOTFOUND;
2820 2831                                  goto done;
2821 2832                          }
2822 2833  
2823 2834                          if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
2824 2835                                  dlpi_close(dh);
2825 2836                                  status = DLADM_STATUS_BADARG;
2826 2837                                  goto done;
2827 2838                          }
2828 2839  
2829 2840                          dlpi_close(dh);
2830 2841                          mtu = dlinfo.di_max_sdu;
2831 2842                  } else {
2832 2843  link_mtu:
2833 2844                          status = dladm_info(handle, linkid, &dlattr);
2834 2845                          if (status != DLADM_STATUS_OK)
2835 2846                                  goto done;
2836 2847                          mtu = dlattr.da_max_sdu;
2837 2848                  }
2838 2849          }
2839 2850  
2840 2851          (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name),
2841 2852              "%s", link);
2842 2853          (void) dladm_class2str(class, lbuf->link_class);
2843 2854          if (state->ls_flags == DLADM_OPT_ACTIVE) {
2844 2855                  (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu),
2845 2856                      "%u", mtu);
2846 2857                  (void) get_linkstate(link, B_TRUE, lbuf->link_state);
2847 2858          }
2848 2859  
2849 2860          print_link_topology(state, linkid, class, lbuf);
2850 2861  done:
2851 2862          return (status);
2852 2863  }
2853 2864  
2854 2865  /* ARGSUSED */
2855 2866  static int
2856 2867  show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2857 2868  {
2858 2869          show_state_t            *state = (show_state_t *)arg;
2859 2870          dladm_status_t          status;
2860 2871          link_fields_buf_t       lbuf;
2861 2872  
2862 2873          /*
2863 2874           * first get all the link attributes into lbuf;
2864 2875           */
2865 2876          bzero(&lbuf, sizeof (link_fields_buf_t));
2866 2877          if ((status = print_link(state, linkid, &lbuf)) == DLADM_STATUS_OK)
2867 2878                  ofmt_print(state->ls_ofmt, &lbuf);
2868 2879          state->ls_status = status;
2869 2880          return (DLADM_WALK_CONTINUE);
2870 2881  }
2871 2882  
2872 2883  static boolean_t
2873 2884  print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2874 2885  {
2875 2886          link_args_t *largs = ofarg->ofmt_cbarg;
2876 2887          pktsum_t *diff_stats = largs->link_s_psum;
2877 2888  
2878 2889          switch (ofarg->ofmt_id) {
2879 2890          case LINK_S_LINK:
2880 2891                  (void) snprintf(buf, bufsize, "%s", largs->link_s_link);
2881 2892                  break;
2882 2893          case LINK_S_IPKTS:
2883 2894                  (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets);
2884 2895                  break;
2885 2896          case LINK_S_RBYTES:
2886 2897                  (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes);
2887 2898                  break;
2888 2899          case LINK_S_IERRORS:
2889 2900                  (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors);
2890 2901                  break;
2891 2902          case LINK_S_OPKTS:
2892 2903                  (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets);
2893 2904                  break;
2894 2905          case LINK_S_OBYTES:
2895 2906                  (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes);
2896 2907                  break;
2897 2908          case LINK_S_OERRORS:
2898 2909                  (void) snprintf(buf, bufsize, "%u", diff_stats->oerrors);
2899 2910                  break;
2900 2911          default:
2901 2912                  die("invalid input");
2902 2913                  break;
2903 2914          }
2904 2915          return (B_TRUE);
2905 2916  }
2906 2917  
2907 2918  static int
2908 2919  show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2909 2920  {
2910 2921          char                    link[DLPI_LINKNAME_MAX];
2911 2922          datalink_class_t        class;
2912 2923          show_state_t            *state = arg;
2913 2924          pktsum_t                stats, diff_stats;
2914 2925          dladm_phys_attr_t       dpa;
2915 2926          link_args_t             largs;
2916 2927  
2917 2928          if (state->ls_firstonly) {
2918 2929                  if (state->ls_donefirst)
2919 2930                          return (DLADM_WALK_CONTINUE);
2920 2931                  state->ls_donefirst = B_TRUE;
2921 2932          } else {
2922 2933                  bzero(&state->ls_prevstats, sizeof (state->ls_prevstats));
2923 2934          }
2924 2935  
2925 2936          if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link,
2926 2937              DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2927 2938                  return (DLADM_WALK_CONTINUE);
2928 2939          }
2929 2940  
2930 2941          if (class == DATALINK_CLASS_PHYS) {
2931 2942                  if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
2932 2943                      DLADM_STATUS_OK) {
2933 2944                          return (DLADM_WALK_CONTINUE);
2934 2945                  }
2935 2946                  if (dpa.dp_novanity)
2936 2947                          get_mac_stats(dpa.dp_dev, &stats);
2937 2948                  else
2938 2949                          get_link_stats(link, &stats);
2939 2950          } else {
2940 2951                  get_link_stats(link, &stats);
2941 2952          }
2942 2953          dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats);
2943 2954  
2944 2955          largs.link_s_link = link;
2945 2956          largs.link_s_psum = &diff_stats;
2946 2957          ofmt_print(state->ls_ofmt, &largs);
2947 2958  
2948 2959          state->ls_prevstats = stats;
2949 2960          return (DLADM_WALK_CONTINUE);
2950 2961  }
2951 2962  
2952 2963  
2953 2964  static dladm_status_t
2954 2965  print_aggr_info(show_grp_state_t *state, const char *link,
2955 2966      dladm_aggr_grp_attr_t *ginfop)
2956 2967  {
2957 2968          char                    addr_str[ETHERADDRL * 3];
2958 2969          laggr_fields_buf_t      lbuf;
2959 2970  
2960 2971          (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name),
2961 2972              "%s", link);
2962 2973  
2963 2974          (void) dladm_aggr_policy2str(ginfop->lg_policy,
2964 2975              lbuf.laggr_policy);
2965 2976  
2966 2977          if (ginfop->lg_mac_fixed) {
2967 2978                  (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
2968 2979                  (void) snprintf(lbuf.laggr_addrpolicy,
2969 2980                      sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str);
2970 2981          } else {
2971 2982                  (void) snprintf(lbuf.laggr_addrpolicy,
2972 2983                      sizeof (lbuf.laggr_addrpolicy), "auto");
2973 2984          }
2974 2985  
2975 2986          (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode,
2976 2987              lbuf.laggr_lacpactivity);
2977 2988          (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer,
2978 2989              lbuf.laggr_lacptimer);
2979 2990          (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----",
2980 2991              ginfop->lg_force ? 'f' : '-');
2981 2992  
2982 2993          ofmt_print(state->gs_ofmt, &lbuf);
2983 2994  
2984 2995          return (DLADM_STATUS_OK);
2985 2996  }
2986 2997  
2987 2998  static boolean_t
2988 2999  print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2989 3000  {
2990 3001          const laggr_args_t      *l = ofarg->ofmt_cbarg;
2991 3002          boolean_t               is_port = (l->laggr_lport >= 0);
2992 3003          char                    tmpbuf[DLADM_STRSIZE];
2993 3004          const char              *objname;
2994 3005          dladm_aggr_port_attr_t  *portp;
2995 3006          dladm_phys_attr_t       dpa;
2996 3007  
2997 3008          if (is_port) {
2998 3009                  portp = &(l->laggr_ginfop->lg_ports[l->laggr_lport]);
2999 3010                  if (dladm_phys_info(handle, portp->lp_linkid, &dpa,
3000 3011                      DLADM_OPT_ACTIVE) != DLADM_STATUS_OK)
3001 3012                          objname = "?";
3002 3013                  else
3003 3014                          objname = dpa.dp_dev;
3004 3015          } else {
3005 3016                  objname = l->laggr_link;
3006 3017          }
3007 3018  
3008 3019          switch (ofarg->ofmt_id) {
3009 3020          case AGGR_X_LINK:
3010 3021                  (void) snprintf(buf, bufsize, "%s",
3011 3022                      (is_port && !l->laggr_parsable ? " " : l->laggr_link));
3012 3023                  break;
3013 3024          case AGGR_X_PORT:
3014 3025                  if (is_port) {
3015 3026                          if (dladm_datalink_id2info(handle, portp->lp_linkid,
3016 3027                              NULL, NULL, NULL, buf, bufsize) != DLADM_STATUS_OK)
3017 3028                                  (void) sprintf(buf, "?");
3018 3029                  }
3019 3030                  break;
3020 3031  
3021 3032          case AGGR_X_SPEED:
3022 3033                  (void) snprintf(buf, bufsize, "%uMb",
3023 3034                      (uint_t)((get_ifspeed(objname, !is_port)) / 1000000ull));
3024 3035                  break;
3025 3036  
3026 3037          case AGGR_X_DUPLEX:
3027 3038                  (void) get_linkduplex(objname, !is_port, tmpbuf);
3028 3039                  (void) strlcpy(buf, tmpbuf, bufsize);
3029 3040                  break;
3030 3041  
3031 3042          case AGGR_X_STATE:
3032 3043                  (void) get_linkstate(objname, !is_port, tmpbuf);
3033 3044                  (void) strlcpy(buf, tmpbuf, bufsize);
3034 3045                  break;
3035 3046          case AGGR_X_ADDRESS:
3036 3047                  (void) dladm_aggr_macaddr2str(
3037 3048                      (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac),
3038 3049                      tmpbuf);
3039 3050                  (void) strlcpy(buf, tmpbuf, bufsize);
3040 3051                  break;
3041 3052          case AGGR_X_PORTSTATE:
3042 3053                  if (is_port) {
3043 3054                          (void) dladm_aggr_portstate2str(portp->lp_state,
3044 3055                              tmpbuf);
3045 3056                          (void) strlcpy(buf, tmpbuf, bufsize);
3046 3057                  }
3047 3058                  break;
3048 3059          }
3049 3060  err:
3050 3061          *(l->laggr_status) = DLADM_STATUS_OK;
3051 3062          return (B_TRUE);
3052 3063  }
3053 3064  
3054 3065  static dladm_status_t
3055 3066  print_aggr_extended(show_grp_state_t *state, const char *link,
3056 3067      dladm_aggr_grp_attr_t *ginfop)
3057 3068  {
3058 3069          int                     i;
3059 3070          dladm_status_t          status;
3060 3071          laggr_args_t            largs;
3061 3072  
3062 3073          largs.laggr_lport = -1;
3063 3074          largs.laggr_link = link;
3064 3075          largs.laggr_ginfop = ginfop;
3065 3076          largs.laggr_status = &status;
3066 3077          largs.laggr_parsable = state->gs_parsable;
3067 3078  
3068 3079          ofmt_print(state->gs_ofmt, &largs);
3069 3080  
3070 3081          if (status != DLADM_STATUS_OK)
3071 3082                  goto done;
3072 3083  
3073 3084          for (i = 0; i < ginfop->lg_nports; i++) {
3074 3085                  largs.laggr_lport = i;
3075 3086                  ofmt_print(state->gs_ofmt, &largs);
3076 3087                  if (status != DLADM_STATUS_OK)
3077 3088                          goto done;
3078 3089          }
3079 3090  
3080 3091          status = DLADM_STATUS_OK;
3081 3092  done:
3082 3093          return (status);
3083 3094  }
3084 3095  
3085 3096  static boolean_t
3086 3097  print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3087 3098  {
3088 3099          const laggr_args_t      *l = ofarg->ofmt_cbarg;
3089 3100          int                     portnum;
3090 3101          boolean_t               is_port = (l->laggr_lport >= 0);
3091 3102          dladm_aggr_port_attr_t  *portp;
3092 3103          aggr_lacp_state_t       *lstate;
3093 3104  
3094 3105          if (!is_port)
3095 3106                  return (B_FALSE); /* cannot happen! */
3096 3107  
3097 3108          portnum = l->laggr_lport;
3098 3109          portp = &(l->laggr_ginfop->lg_ports[portnum]);
3099 3110          lstate = &(portp->lp_lacp_state);
3100 3111  
3101 3112          switch (ofarg->ofmt_id) {
3102 3113          case AGGR_L_LINK:
3103 3114                  (void) snprintf(buf, bufsize, "%s",
3104 3115                      (portnum > 0 ? "" : l->laggr_link));
3105 3116                  break;
3106 3117  
3107 3118          case AGGR_L_PORT:
3108 3119                  if (dladm_datalink_id2info(handle, portp->lp_linkid, NULL, NULL,
3109 3120                      NULL, buf, bufsize) != DLADM_STATUS_OK)
3110 3121                          (void) sprintf(buf, "?");
3111 3122                  break;
3112 3123  
3113 3124          case AGGR_L_AGGREGATABLE:
3114 3125                  (void) snprintf(buf, bufsize, "%s",
3115 3126                      (lstate->bit.aggregation ? "yes" : "no"));
3116 3127                  break;
3117 3128  
3118 3129          case AGGR_L_SYNC:
3119 3130                  (void) snprintf(buf, bufsize, "%s",
3120 3131                      (lstate->bit.sync ? "yes" : "no"));
3121 3132                  break;
3122 3133  
3123 3134          case AGGR_L_COLL:
3124 3135                  (void) snprintf(buf, bufsize, "%s",
3125 3136                      (lstate->bit.collecting ? "yes" : "no"));
3126 3137                  break;
3127 3138  
3128 3139          case AGGR_L_DIST:
3129 3140                  (void) snprintf(buf, bufsize, "%s",
3130 3141                      (lstate->bit.distributing ? "yes" : "no"));
3131 3142                  break;
3132 3143  
3133 3144          case AGGR_L_DEFAULTED:
3134 3145                  (void) snprintf(buf, bufsize, "%s",
3135 3146                      (lstate->bit.defaulted ? "yes" : "no"));
3136 3147                  break;
3137 3148  
3138 3149          case AGGR_L_EXPIRED:
3139 3150                  (void) snprintf(buf, bufsize, "%s",
3140 3151                      (lstate->bit.expired ? "yes" : "no"));
3141 3152                  break;
3142 3153          }
3143 3154  
3144 3155          *(l->laggr_status) = DLADM_STATUS_OK;
3145 3156          return (B_TRUE);
3146 3157  }
3147 3158  
3148 3159  static dladm_status_t
3149 3160  print_aggr_lacp(show_grp_state_t *state, const char *link,
3150 3161      dladm_aggr_grp_attr_t *ginfop)
3151 3162  {
3152 3163          int             i;
3153 3164          dladm_status_t  status;
3154 3165          laggr_args_t    largs;
3155 3166  
3156 3167          largs.laggr_link = link;
3157 3168          largs.laggr_ginfop = ginfop;
3158 3169          largs.laggr_status = &status;
3159 3170  
3160 3171          for (i = 0; i < ginfop->lg_nports; i++) {
3161 3172                  largs.laggr_lport = i;
3162 3173                  ofmt_print(state->gs_ofmt, &largs);
3163 3174                  if (status != DLADM_STATUS_OK)
3164 3175                          goto done;
3165 3176          }
3166 3177  
3167 3178          status = DLADM_STATUS_OK;
3168 3179  done:
3169 3180          return (status);
3170 3181  }
3171 3182  
3172 3183  static boolean_t
3173 3184  print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3174 3185  {
3175 3186          const laggr_args_t      *l = ofarg->ofmt_cbarg;
3176 3187          int                     portnum;
3177 3188          boolean_t               is_port = (l->laggr_lport >= 0);
3178 3189          dladm_aggr_port_attr_t  *portp;
3179 3190          dladm_status_t          *stat, status;
3180 3191          pktsum_t                *diff_stats;
3181 3192  
3182 3193          stat = l->laggr_status;
3183 3194          *stat = DLADM_STATUS_OK;
3184 3195  
3185 3196          if (is_port) {
3186 3197                  portnum = l->laggr_lport;
3187 3198                  portp = &(l->laggr_ginfop->lg_ports[portnum]);
3188 3199  
3189 3200                  if ((status = dladm_datalink_id2info(handle,
3190 3201                      portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
3191 3202                      DLADM_STATUS_OK) {
3192 3203                          goto err;
3193 3204                  }
3194 3205                  diff_stats = l->laggr_diffstats;
3195 3206          }
3196 3207  
3197 3208          switch (ofarg->ofmt_id) {
3198 3209          case AGGR_S_LINK:
3199 3210                  (void) snprintf(buf, bufsize, "%s",
3200 3211                      (is_port ? "" : l->laggr_link));
3201 3212                  break;
3202 3213          case AGGR_S_PORT:
3203 3214                  /*
3204 3215                   * if (is_port), buf has port name. Otherwise we print
3205 3216                   * STR_UNDEF_VAL
3206 3217                   */
3207 3218                  break;
3208 3219  
3209 3220          case AGGR_S_IPKTS:
3210 3221                  if (is_port) {
3211 3222                          (void) snprintf(buf, bufsize, "%llu",
3212 3223                              diff_stats->ipackets);
3213 3224                  } else {
3214 3225                          (void) snprintf(buf, bufsize, "%llu",
3215 3226                              l->laggr_pktsumtot->ipackets);
3216 3227                  }
3217 3228                  break;
3218 3229  
3219 3230          case AGGR_S_RBYTES:
3220 3231                  if (is_port) {
3221 3232                          (void) snprintf(buf, bufsize, "%llu",
3222 3233                              diff_stats->rbytes);
3223 3234                  } else {
3224 3235                          (void) snprintf(buf, bufsize, "%llu",
3225 3236                              l->laggr_pktsumtot->rbytes);
3226 3237                  }
3227 3238                  break;
3228 3239  
3229 3240          case AGGR_S_OPKTS:
3230 3241                  if (is_port) {
3231 3242                          (void) snprintf(buf, bufsize, "%llu",
3232 3243                              diff_stats->opackets);
3233 3244                  } else {
3234 3245                          (void) snprintf(buf, bufsize, "%llu",
3235 3246                              l->laggr_pktsumtot->opackets);
3236 3247                  }
3237 3248                  break;
3238 3249          case AGGR_S_OBYTES:
3239 3250                  if (is_port) {
3240 3251                          (void) snprintf(buf, bufsize, "%llu",
3241 3252                              diff_stats->obytes);
3242 3253                  } else {
3243 3254                          (void) snprintf(buf, bufsize, "%llu",
3244 3255                              l->laggr_pktsumtot->obytes);
3245 3256                  }
3246 3257                  break;
3247 3258  
3248 3259          case AGGR_S_IPKTDIST:
3249 3260                  if (is_port) {
3250 3261                          (void) snprintf(buf, bufsize, "%-6.1f",
3251 3262                              (double)diff_stats->ipackets/
3252 3263                              (double)l->laggr_pktsumtot->ipackets * 100);
3253 3264                  }
3254 3265                  break;
3255 3266          case AGGR_S_OPKTDIST:
3256 3267                  if (is_port) {
3257 3268                          (void) snprintf(buf, bufsize, "%-6.1f",
3258 3269                              (double)diff_stats->opackets/
3259 3270                              (double)l->laggr_pktsumtot->opackets * 100);
3260 3271                  }
3261 3272                  break;
3262 3273          }
3263 3274          return (B_TRUE);
3264 3275  
3265 3276  err:
3266 3277          *stat = status;
3267 3278          return (B_TRUE);
3268 3279  }
3269 3280  
3270 3281  static dladm_status_t
3271 3282  print_aggr_stats(show_grp_state_t *state, const char *link,
3272 3283      dladm_aggr_grp_attr_t *ginfop)
3273 3284  {
3274 3285          dladm_phys_attr_t       dpa;
3275 3286          dladm_aggr_port_attr_t  *portp;
3276 3287          pktsum_t                pktsumtot, *port_stat;
3277 3288          dladm_status_t          status;
3278 3289          int                     i;
3279 3290          laggr_args_t            largs;
3280 3291  
3281 3292          /* sum the ports statistics */
3282 3293          bzero(&pktsumtot, sizeof (pktsumtot));
3283 3294  
3284 3295          /* Allocate memory to keep stats of each port */
3285 3296          port_stat = malloc(ginfop->lg_nports * sizeof (pktsum_t));
3286 3297          if (port_stat == NULL) {
3287 3298                  /* Bail out; no memory */
3288 3299                  return (DLADM_STATUS_NOMEM);
3289 3300          }
3290 3301  
3291 3302  
3292 3303          for (i = 0; i < ginfop->lg_nports; i++) {
3293 3304  
3294 3305                  portp = &(ginfop->lg_ports[i]);
3295 3306                  if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa,
3296 3307                      DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
3297 3308                          goto done;
3298 3309                  }
3299 3310  
3300 3311                  get_mac_stats(dpa.dp_dev, &port_stat[i]);
3301 3312  
3302 3313                  /*
3303 3314                   * Let's re-use gs_prevstats[] to store the difference of the
3304 3315                   * counters since last use. We will store the new stats from
3305 3316                   * port_stat[] once we have the stats displayed.
3306 3317                   */
3307 3318  
3308 3319                  dladm_stats_diff(&state->gs_prevstats[i], &port_stat[i],
3309 3320                      &state->gs_prevstats[i]);
3310 3321                  dladm_stats_total(&pktsumtot, &pktsumtot,
3311 3322                      &state->gs_prevstats[i]);
3312 3323          }
3313 3324  
3314 3325          largs.laggr_lport = -1;
3315 3326          largs.laggr_link = link;
3316 3327          largs.laggr_ginfop = ginfop;
3317 3328          largs.laggr_status = &status;
3318 3329          largs.laggr_pktsumtot = &pktsumtot;
3319 3330  
3320 3331          ofmt_print(state->gs_ofmt, &largs);
3321 3332  
3322 3333          if (status != DLADM_STATUS_OK)
3323 3334                  goto done;
3324 3335  
3325 3336          for (i = 0; i < ginfop->lg_nports; i++) {
3326 3337                  largs.laggr_lport = i;
3327 3338                  largs.laggr_diffstats = &state->gs_prevstats[i];
3328 3339                  ofmt_print(state->gs_ofmt, &largs);
3329 3340                  if (status != DLADM_STATUS_OK)
3330 3341                          goto done;
3331 3342          }
3332 3343  
3333 3344          status = DLADM_STATUS_OK;
3334 3345          for (i = 0; i < ginfop->lg_nports; i++)
3335 3346                  state->gs_prevstats[i] = port_stat[i];
3336 3347  
3337 3348  done:
3338 3349          free(port_stat);
3339 3350          return (status);
3340 3351  }
3341 3352  
3342 3353  static dladm_status_t
3343 3354  print_aggr(show_grp_state_t *state, datalink_id_t linkid)
3344 3355  {
3345 3356          char                    link[MAXLINKNAMELEN];
3346 3357          dladm_aggr_grp_attr_t   ginfo;
3347 3358          uint32_t                flags;
3348 3359          dladm_status_t          status;
3349 3360  
3350 3361          bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t));
3351 3362          if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
3352 3363              NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
3353 3364                  return (status);
3354 3365          }
3355 3366  
3356 3367          if (!(state->gs_flags & flags))
3357 3368                  return (DLADM_STATUS_NOTFOUND);
3358 3369  
3359 3370          status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags);
3360 3371          if (status != DLADM_STATUS_OK)
3361 3372                  return (status);
3362 3373  
3363 3374          if (state->gs_lacp)
3364 3375                  status = print_aggr_lacp(state, link, &ginfo);
3365 3376          else if (state->gs_extended)
3366 3377                  status = print_aggr_extended(state, link, &ginfo);
3367 3378          else if (state->gs_stats)
3368 3379                  status = print_aggr_stats(state, link, &ginfo);
3369 3380          else
3370 3381                  status = print_aggr_info(state, link, &ginfo);
3371 3382  
3372 3383  done:
3373 3384          free(ginfo.lg_ports);
3374 3385          return (status);
3375 3386  }
3376 3387  
3377 3388  /* ARGSUSED */
3378 3389  static int
3379 3390  show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg)
3380 3391  {
3381 3392          show_grp_state_t        *state = arg;
3382 3393  
3383 3394          state->gs_status = print_aggr(state, linkid);
3384 3395          return (DLADM_WALK_CONTINUE);
3385 3396  }
3386 3397  
3387 3398  static void
3388 3399  do_show_link(int argc, char *argv[], const char *use)
3389 3400  {
3390 3401          int             option;
3391 3402          boolean_t       s_arg = B_FALSE;
3392 3403          boolean_t       S_arg = B_FALSE;
3393 3404          boolean_t       i_arg = B_FALSE;
3394 3405          uint32_t        flags = DLADM_OPT_ACTIVE;
3395 3406          boolean_t       p_arg = B_FALSE;
3396 3407          datalink_id_t   linkid = DATALINK_ALL_LINKID;
3397 3408          char            linkname[MAXLINKNAMELEN];
3398 3409          uint32_t        interval = 0;
3399 3410          show_state_t    state;
  
    | 
      ↓ open down ↓ | 
    869 lines elided | 
    
      ↑ open up ↑ | 
  
3400 3411          dladm_status_t  status;
3401 3412          boolean_t       o_arg = B_FALSE;
3402 3413          char            *fields_str = NULL;
3403 3414          char            *all_active_fields = "link,class,mtu,state,bridge,over";
3404 3415          char            *all_inactive_fields = "link,class,bridge,over";
3405 3416          char            *allstat_fields =
3406 3417              "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
3407 3418          ofmt_handle_t   ofmt;
3408 3419          ofmt_status_t   oferr;
3409 3420          uint_t          ofmtflags = 0;
     3421 +        char            *zonename = NULL;
3410 3422  
3411 3423          bzero(&state, sizeof (state));
3412 3424  
3413 3425          opterr = 0;
3414      -        while ((option = getopt_long(argc, argv, ":pPsSi:o:",
     3426 +        while ((option = getopt_long(argc, argv, ":pPsSi:o:z:",
3415 3427              show_lopts, NULL)) != -1) {
3416 3428                  switch (option) {
3417 3429                  case 'p':
3418 3430                          if (p_arg)
3419 3431                                  die_optdup(option);
3420 3432  
3421 3433                          p_arg = B_TRUE;
3422 3434                          break;
3423 3435                  case 's':
3424 3436                          if (s_arg)
3425 3437                                  die_optdup(option);
3426 3438  
3427 3439                          s_arg = B_TRUE;
3428 3440                          break;
3429 3441                  case 'P':
3430 3442                          if (flags != DLADM_OPT_ACTIVE)
3431 3443                                  die_optdup(option);
3432 3444  
3433 3445                          flags = DLADM_OPT_PERSIST;
3434 3446                          break;
3435 3447                  case 'S':
3436 3448                          if (S_arg)
3437 3449                                  die_optdup(option);
3438 3450  
3439 3451                          S_arg = B_TRUE;
3440 3452                          break;
3441 3453                  case 'o':
3442 3454                          o_arg = B_TRUE;
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
3443 3455                          fields_str = optarg;
3444 3456                          break;
3445 3457                  case 'i':
3446 3458                          if (i_arg)
3447 3459                                  die_optdup(option);
3448 3460  
3449 3461                          i_arg = B_TRUE;
3450 3462                          if (!dladm_str2interval(optarg, &interval))
3451 3463                                  die("invalid interval value '%s'", optarg);
3452 3464                          break;
     3465 +                case 'z':
     3466 +                        zonename = optarg;
     3467 +                        break;
3453 3468                  default:
3454 3469                          die_opterr(optopt, option, use);
3455 3470                          break;
3456 3471                  }
3457 3472          }
3458 3473  
3459 3474          if (i_arg && !(s_arg || S_arg))
3460 3475                  die("the option -i can be used only with -s or -S");
3461 3476  
3462 3477          if (s_arg && S_arg)
3463 3478                  die("the -s option cannot be used with -S");
3464 3479  
3465 3480          if (s_arg && flags != DLADM_OPT_ACTIVE)
3466 3481                  die("the option -P cannot be used with -s");
3467 3482  
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
3468 3483          if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
3469 3484                  die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P');
3470 3485  
3471 3486          /* get link name (optional last argument) */
3472 3487          if (optind == (argc-1)) {
3473 3488                  uint32_t        f;
3474 3489  
3475 3490                  if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >=
3476 3491                      MAXLINKNAMELEN)
3477 3492                          die("link name too long");
3478      -                if ((status = dladm_name2info(handle, linkname, &linkid, &f,
3479      -                    NULL, NULL)) != DLADM_STATUS_OK) {
     3493 +                if ((status = dladm_zname2info(handle, zonename, linkname,
     3494 +                    &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) {
3480 3495                          die_dlerr(status, "link %s is not valid", linkname);
3481 3496                  }
3482 3497  
3483 3498                  if (!(f & flags)) {
3484 3499                          die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
3485 3500                              argv[optind], flags == DLADM_OPT_PERSIST ?
3486 3501                              "a temporary link" : "temporarily removed");
3487 3502                  }
3488 3503          } else if (optind != argc) {
3489 3504                  usage();
3490 3505          }
3491 3506  
3492 3507          if (p_arg && !o_arg)
3493 3508                  die("-p requires -o");
3494 3509  
3495 3510          if (S_arg) {
3496 3511                  dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT);
3497 3512                  return;
3498 3513          }
3499 3514  
3500 3515          if (p_arg && strcasecmp(fields_str, "all") == 0)
3501 3516                  die("\"-o all\" is invalid with -p");
3502 3517  
3503 3518          if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3504 3519                  if (s_arg)
3505 3520                          fields_str = allstat_fields;
3506 3521                  else if (flags & DLADM_OPT_ACTIVE)
3507 3522                          fields_str = all_active_fields;
3508 3523                  else
3509 3524                          fields_str = all_inactive_fields;
3510 3525          }
3511 3526  
3512 3527          state.ls_parsable = p_arg;
3513 3528          state.ls_flags = flags;
3514 3529          state.ls_donefirst = B_FALSE;
3515 3530  
3516 3531          if (s_arg) {
3517 3532                  link_stats(linkid, interval, fields_str, &state);
3518 3533                  return;
3519 3534          }
3520 3535          if (state.ls_parsable)
3521 3536                  ofmtflags |= OFMT_PARSABLE;
3522 3537          oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt);
3523 3538          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
3524 3539          state.ls_ofmt = ofmt;
3525 3540  
3526 3541          if (linkid == DATALINK_ALL_LINKID) {
3527 3542                  (void) dladm_walk_datalink_id(show_link, handle, &state,
3528 3543                      DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
3529 3544          } else {
3530 3545                  (void) show_link(handle, linkid, &state);
3531 3546                  if (state.ls_status != DLADM_STATUS_OK) {
3532 3547                          die_dlerr(state.ls_status, "failed to show link %s",
3533 3548                              argv[optind]);
3534 3549                  }
3535 3550          }
3536 3551          ofmt_close(ofmt);
3537 3552  }
3538 3553  
3539 3554  static void
3540 3555  do_show_aggr(int argc, char *argv[], const char *use)
3541 3556  {
3542 3557          boolean_t               L_arg = B_FALSE;
3543 3558          boolean_t               s_arg = B_FALSE;
3544 3559          boolean_t               i_arg = B_FALSE;
3545 3560          boolean_t               p_arg = B_FALSE;
3546 3561          boolean_t               x_arg = B_FALSE;
3547 3562          show_grp_state_t        state;
3548 3563          uint32_t                flags = DLADM_OPT_ACTIVE;
3549 3564          datalink_id_t           linkid = DATALINK_ALL_LINKID;
3550 3565          int                     option;
3551 3566          uint32_t                interval = 0;
3552 3567          int                     key;
3553 3568          dladm_status_t          status;
3554 3569          boolean_t               o_arg = B_FALSE;
3555 3570          char                    *fields_str = NULL;
3556 3571          char                    *all_fields =
3557 3572              "link,policy,addrpolicy,lacpactivity,lacptimer,flags";
3558 3573          char                    *all_lacp_fields =
3559 3574              "link,port,aggregatable,sync,coll,dist,defaulted,expired";
3560 3575          char                    *all_stats_fields =
3561 3576              "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist";
3562 3577          char                    *all_extended_fields =
3563 3578              "link,port,speed,duplex,state,address,portstate";
3564 3579          const ofmt_field_t      *pf;
3565 3580          ofmt_handle_t           ofmt;
3566 3581          ofmt_status_t           oferr;
3567 3582          uint_t                  ofmtflags = 0;
3568 3583  
3569 3584          opterr = 0;
3570 3585          while ((option = getopt_long(argc, argv, ":LpPxsi:o:",
3571 3586              show_lopts, NULL)) != -1) {
3572 3587                  switch (option) {
3573 3588                  case 'L':
3574 3589                          if (L_arg)
3575 3590                                  die_optdup(option);
3576 3591  
3577 3592                          L_arg = B_TRUE;
3578 3593                          break;
3579 3594                  case 'p':
3580 3595                          if (p_arg)
3581 3596                                  die_optdup(option);
3582 3597  
3583 3598                          p_arg = B_TRUE;
3584 3599                          break;
3585 3600                  case 'x':
3586 3601                          if (x_arg)
3587 3602                                  die_optdup(option);
3588 3603  
3589 3604                          x_arg = B_TRUE;
3590 3605                          break;
3591 3606                  case 'P':
3592 3607                          if (flags != DLADM_OPT_ACTIVE)
3593 3608                                  die_optdup(option);
3594 3609  
3595 3610                          flags = DLADM_OPT_PERSIST;
3596 3611                          break;
3597 3612                  case 's':
3598 3613                          if (s_arg)
3599 3614                                  die_optdup(option);
3600 3615  
3601 3616                          s_arg = B_TRUE;
3602 3617                          break;
3603 3618                  case 'o':
3604 3619                          o_arg = B_TRUE;
3605 3620                          fields_str = optarg;
3606 3621                          break;
3607 3622                  case 'i':
3608 3623                          if (i_arg)
3609 3624                                  die_optdup(option);
3610 3625  
3611 3626                          i_arg = B_TRUE;
3612 3627                          if (!dladm_str2interval(optarg, &interval))
3613 3628                                  die("invalid interval value '%s'", optarg);
3614 3629                          break;
3615 3630                  default:
3616 3631                          die_opterr(optopt, option, use);
3617 3632                          break;
3618 3633                  }
3619 3634          }
3620 3635  
3621 3636          if (p_arg && !o_arg)
3622 3637                  die("-p requires -o");
3623 3638  
3624 3639          if (p_arg && strcasecmp(fields_str, "all") == 0)
3625 3640                  die("\"-o all\" is invalid with -p");
3626 3641  
3627 3642          if (i_arg && !s_arg)
3628 3643                  die("the option -i can be used only with -s");
3629 3644  
3630 3645          if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) {
3631 3646                  die("the option -%c cannot be used with -s",
3632 3647                      L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P')));
3633 3648          }
3634 3649  
3635 3650          if (L_arg && flags != DLADM_OPT_ACTIVE)
3636 3651                  die("the option -P cannot be used with -L");
3637 3652  
3638 3653          if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE))
3639 3654                  die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P');
3640 3655  
3641 3656          /* get aggregation key or aggrname (optional last argument) */
3642 3657          if (optind == (argc-1)) {
3643 3658                  if (!str2int(argv[optind], &key)) {
3644 3659                          status = dladm_name2info(handle, argv[optind],
3645 3660                              &linkid, NULL, NULL, NULL);
3646 3661                  } else {
3647 3662                          status = dladm_key2linkid(handle, (uint16_t)key,
3648 3663                              &linkid, DLADM_OPT_ACTIVE);
3649 3664                  }
3650 3665  
3651 3666                  if (status != DLADM_STATUS_OK)
3652 3667                          die("non-existent aggregation '%s'", argv[optind]);
3653 3668  
3654 3669          } else if (optind != argc) {
3655 3670                  usage();
3656 3671          }
3657 3672  
3658 3673          bzero(&state, sizeof (state));
3659 3674          state.gs_lacp = L_arg;
3660 3675          state.gs_stats = s_arg;
3661 3676          state.gs_flags = flags;
3662 3677          state.gs_parsable = p_arg;
3663 3678          state.gs_extended = x_arg;
3664 3679  
3665 3680          if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3666 3681                  if (state.gs_lacp)
3667 3682                          fields_str = all_lacp_fields;
3668 3683                  else if (state.gs_stats)
3669 3684                          fields_str = all_stats_fields;
3670 3685                  else if (state.gs_extended)
3671 3686                          fields_str = all_extended_fields;
3672 3687                  else
3673 3688                          fields_str = all_fields;
3674 3689          }
3675 3690  
3676 3691          if (state.gs_lacp) {
3677 3692                  pf = aggr_l_fields;
3678 3693          } else if (state.gs_stats) {
3679 3694                  pf = aggr_s_fields;
3680 3695          } else if (state.gs_extended) {
3681 3696                  pf = aggr_x_fields;
3682 3697          } else {
3683 3698                  pf = laggr_fields;
3684 3699          }
3685 3700  
3686 3701          if (state.gs_parsable)
3687 3702                  ofmtflags |= OFMT_PARSABLE;
3688 3703          oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
3689 3704          dladm_ofmt_check(oferr, state.gs_parsable, ofmt);
3690 3705          state.gs_ofmt = ofmt;
3691 3706  
3692 3707          if (s_arg) {
3693 3708                  aggr_stats(linkid, &state, interval);
3694 3709                  ofmt_close(ofmt);
3695 3710                  return;
3696 3711          }
3697 3712  
3698 3713          if (linkid == DATALINK_ALL_LINKID) {
3699 3714                  (void) dladm_walk_datalink_id(show_aggr, handle, &state,
3700 3715                      DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags);
3701 3716          } else {
3702 3717                  (void) show_aggr(handle, linkid, &state);
3703 3718                  if (state.gs_status != DLADM_STATUS_OK) {
3704 3719                          die_dlerr(state.gs_status, "failed to show aggr %s",
3705 3720                              argv[optind]);
3706 3721                  }
3707 3722          }
3708 3723          ofmt_close(ofmt);
3709 3724  }
3710 3725  
3711 3726  static dladm_status_t
3712 3727  print_phys_default(show_state_t *state, datalink_id_t linkid,
3713 3728      const char *link, uint32_t flags, uint32_t media)
3714 3729  {
3715 3730          dladm_phys_attr_t dpa;
3716 3731          dladm_status_t status;
3717 3732          link_fields_buf_t pattr;
3718 3733  
3719 3734          status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags);
3720 3735          if (status != DLADM_STATUS_OK)
3721 3736                  goto done;
3722 3737  
3723 3738          (void) snprintf(pattr.link_phys_device,
3724 3739              sizeof (pattr.link_phys_device), "%s", dpa.dp_dev);
3725 3740          (void) dladm_media2str(media, pattr.link_phys_media);
3726 3741          if (state->ls_flags == DLADM_OPT_ACTIVE) {
3727 3742                  boolean_t       islink;
3728 3743  
3729 3744                  if (!dpa.dp_novanity) {
3730 3745                          (void) strlcpy(pattr.link_name, link,
3731 3746                              sizeof (pattr.link_name));
3732 3747                          islink = B_TRUE;
3733 3748                  } else {
3734 3749                          /*
3735 3750                           * This is a physical link that does not have
3736 3751                           * vanity naming support.
3737 3752                           */
3738 3753                          (void) strlcpy(pattr.link_name, dpa.dp_dev,
3739 3754                              sizeof (pattr.link_name));
3740 3755                          islink = B_FALSE;
3741 3756                  }
3742 3757  
3743 3758                  (void) get_linkstate(pattr.link_name, islink,
3744 3759                      pattr.link_phys_state);
3745 3760                  (void) snprintf(pattr.link_phys_speed,
3746 3761                      sizeof (pattr.link_phys_speed), "%u",
3747 3762                      (uint_t)((get_ifspeed(pattr.link_name,
3748 3763                      islink)) / 1000000ull));
3749 3764                  (void) get_linkduplex(pattr.link_name, islink,
3750 3765                      pattr.link_phys_duplex);
3751 3766          } else {
3752 3767                  (void) snprintf(pattr.link_name, sizeof (pattr.link_name),
3753 3768                      "%s", link);
3754 3769                  (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags),
3755 3770                      "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r');
3756 3771          }
3757 3772  
3758 3773          ofmt_print(state->ls_ofmt, &pattr);
3759 3774  
3760 3775  done:
3761 3776          return (status);
3762 3777  }
3763 3778  
3764 3779  typedef struct {
3765 3780          show_state_t    *ms_state;
3766 3781          char            *ms_link;
3767 3782          dladm_macaddr_attr_t *ms_mac_attr;
3768 3783  } print_phys_mac_state_t;
3769 3784  
3770 3785  /*
3771 3786   *  callback for ofmt_print()
3772 3787   */
3773 3788  static boolean_t
3774 3789  print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3775 3790  {
3776 3791          print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg;
3777 3792          dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr;
3778 3793          boolean_t is_primary = (attr->ma_slot == 0);
3779 3794          boolean_t is_parsable = mac_state->ms_state->ls_parsable;
3780 3795  
3781 3796          switch (ofarg->ofmt_id) {
3782 3797          case PHYS_M_LINK:
3783 3798                  (void) snprintf(buf, bufsize, "%s",
3784 3799                      (is_primary || is_parsable) ? mac_state->ms_link : " ");
3785 3800                  break;
3786 3801          case PHYS_M_SLOT:
3787 3802                  if (is_primary)
3788 3803                          (void) snprintf(buf, bufsize, gettext("primary"));
3789 3804                  else
3790 3805                          (void) snprintf(buf, bufsize, "%d", attr->ma_slot);
3791 3806                  break;
3792 3807          case PHYS_M_ADDRESS:
3793 3808                  (void) dladm_aggr_macaddr2str(attr->ma_addr, buf);
3794 3809                  break;
3795 3810          case PHYS_M_INUSE:
3796 3811                  (void) snprintf(buf, bufsize, "%s",
3797 3812                      attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") :
3798 3813                      gettext("no"));
3799 3814                  break;
3800 3815          case PHYS_M_CLIENT:
3801 3816                  /*
3802 3817                   * CR 6678526: resolve link id to actual link name if
3803 3818                   * it is valid.
3804 3819                   */
3805 3820                  (void) snprintf(buf, bufsize, "%s", attr->ma_client_name);
3806 3821                  break;
3807 3822          }
3808 3823  
3809 3824          return (B_TRUE);
3810 3825  }
3811 3826  
3812 3827  typedef struct {
3813 3828          show_state_t    *hs_state;
3814 3829          char            *hs_link;
3815 3830          dladm_hwgrp_attr_t *hs_grp_attr;
3816 3831  } print_phys_hwgrp_state_t;
3817 3832  
3818 3833  static boolean_t
3819 3834  print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3820 3835  {
3821 3836          int             i;
3822 3837          boolean_t       first = B_TRUE;
3823 3838          int             start = -1;
3824 3839          int             end = -1;
3825 3840          char            ringstr[RINGSTRLEN];
3826 3841          char            ringsubstr[RINGSTRLEN];
3827 3842  
3828 3843          print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg;
3829 3844          dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr;
3830 3845  
3831 3846          switch (ofarg->ofmt_id) {
3832 3847          case PHYS_H_LINK:
3833 3848                  (void) snprintf(buf, bufsize, "%s", attr->hg_link_name);
3834 3849                  break;
3835 3850          case PHYS_H_RINGTYPE:
3836 3851                  (void) snprintf(buf, bufsize, "%s",
3837 3852                      attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX");
3838 3853                  break;
3839 3854          case PHYS_H_RINGS:
3840 3855                  ringstr[0] = '\0';
3841 3856                  for (i = 0; i < attr->hg_n_rings; i++) {
3842 3857                          uint_t  index = attr->hg_rings[i];
3843 3858  
3844 3859                          if (start == -1) {
3845 3860                                  start = index;
3846 3861                                  end = index;
3847 3862                          } else if (index == end + 1) {
3848 3863                                  end = index;
3849 3864                          } else {
3850 3865                                  if (start == end) {
3851 3866                                          if (first) {
3852 3867                                                  (void) snprintf(
3853 3868                                                      ringsubstr,
3854 3869                                                      RINGSTRLEN, "%d",
3855 3870                                                      start);
3856 3871                                                  first = B_FALSE;
3857 3872                                          } else {
3858 3873                                                  (void) snprintf(
3859 3874                                                      ringsubstr,
3860 3875                                                      RINGSTRLEN, ",%d",
3861 3876                                                      start);
3862 3877                                          }
3863 3878                                  } else {
3864 3879                                          if (first) {
3865 3880                                                  (void) snprintf(
3866 3881                                                      ringsubstr,
3867 3882                                                      RINGSTRLEN,
3868 3883                                                      "%d-%d",
3869 3884                                                      start, end);
3870 3885                                                  first = B_FALSE;
3871 3886                                          } else {
3872 3887                                                  (void) snprintf(
3873 3888                                                      ringsubstr,
3874 3889                                                      RINGSTRLEN,
3875 3890                                                      ",%d-%d",
3876 3891                                                      start, end);
3877 3892                                          }
3878 3893                                  }
3879 3894                                  (void) strlcat(ringstr, ringsubstr,
3880 3895                                      RINGSTRLEN);
3881 3896                                  start = index;
3882 3897                                  end = index;
3883 3898                          }
3884 3899                  }
3885 3900                  /* The last one */
3886 3901                  if (start != -1) {
3887 3902                          if (first) {
3888 3903                                  if (start == end) {
3889 3904                                          (void) snprintf(buf, bufsize, "%d",
3890 3905                                              start);
3891 3906                                  } else {
3892 3907                                          (void) snprintf(buf, bufsize, "%d-%d",
3893 3908                                              start, end);
3894 3909                                  }
3895 3910                          } else {
3896 3911                                  if (start == end) {
3897 3912                                          (void) snprintf(ringsubstr, RINGSTRLEN,
3898 3913                                              ",%d", start);
3899 3914                                  } else {
3900 3915                                          (void) snprintf(ringsubstr, RINGSTRLEN,
3901 3916                                              ",%d-%d", start, end);
3902 3917                                  }
3903 3918                                  (void) strlcat(ringstr, ringsubstr, RINGSTRLEN);
3904 3919                                  (void) snprintf(buf, bufsize, "%s", ringstr);
3905 3920                          }
3906 3921                  }
3907 3922                  break;
3908 3923          case PHYS_H_CLIENTS:
3909 3924                  if (attr->hg_client_names[0] == '\0') {
3910 3925                          (void) snprintf(buf, bufsize, "--");
3911 3926                  } else {
3912 3927                          (void) snprintf(buf, bufsize, "%s ",
3913 3928                              attr->hg_client_names);
3914 3929                  }
3915 3930                  break;
3916 3931          }
3917 3932  
3918 3933          return (B_TRUE);
3919 3934  }
3920 3935  
3921 3936  /*
3922 3937   * callback for dladm_walk_macaddr, invoked for each MAC address slot
3923 3938   */
3924 3939  static boolean_t
3925 3940  print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr)
3926 3941  {
3927 3942          print_phys_mac_state_t *mac_state = arg;
3928 3943          show_state_t *state = mac_state->ms_state;
3929 3944  
3930 3945          mac_state->ms_mac_attr = attr;
3931 3946          ofmt_print(state->ls_ofmt, mac_state);
3932 3947  
3933 3948          return (B_TRUE);
3934 3949  }
3935 3950  
3936 3951  /*
3937 3952   * invoked by show-phys -m for each physical data-link
3938 3953   */
3939 3954  static dladm_status_t
3940 3955  print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link)
3941 3956  {
3942 3957          print_phys_mac_state_t mac_state;
3943 3958  
3944 3959          mac_state.ms_state = state;
3945 3960          mac_state.ms_link = link;
3946 3961  
3947 3962          return (dladm_walk_macaddr(handle, linkid, &mac_state,
3948 3963              print_phys_mac_callback));
3949 3964  }
3950 3965  
3951 3966  /*
3952 3967   * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp
3953 3968   */
3954 3969  static boolean_t
3955 3970  print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr)
3956 3971  {
3957 3972          print_phys_hwgrp_state_t *hwgrp_state = arg;
3958 3973          show_state_t *state = hwgrp_state->hs_state;
3959 3974  
3960 3975          hwgrp_state->hs_grp_attr = attr;
3961 3976          ofmt_print(state->ls_ofmt, hwgrp_state);
3962 3977  
3963 3978          return (B_TRUE);
3964 3979  }
3965 3980  
3966 3981  /* invoked by show-phys -H for each physical data-link */
3967 3982  static dladm_status_t
3968 3983  print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link)
3969 3984  {
3970 3985          print_phys_hwgrp_state_t hwgrp_state;
3971 3986  
3972 3987          hwgrp_state.hs_state = state;
3973 3988          hwgrp_state.hs_link = link;
3974 3989          return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state,
3975 3990              print_phys_hwgrp_callback));
3976 3991  }
3977 3992  
3978 3993  /*
3979 3994   * Parse the "local=<laddr>,remote=<raddr>" sub-options for the -a option of
3980 3995   * *-iptun subcommands.
3981 3996   */
3982 3997  static void
3983 3998  iptun_process_addrarg(char *addrarg, iptun_params_t *params)
3984 3999  {
3985 4000          char *addrval;
3986 4001  
3987 4002          while (*addrarg != '\0') {
3988 4003                  switch (getsubopt(&addrarg, iptun_addropts, &addrval)) {
3989 4004                  case IPTUN_LOCAL:
3990 4005                          params->iptun_param_flags |= IPTUN_PARAM_LADDR;
3991 4006                          if (strlcpy(params->iptun_param_laddr, addrval,
3992 4007                              sizeof (params->iptun_param_laddr)) >=
3993 4008                              sizeof (params->iptun_param_laddr))
3994 4009                                  die("tunnel source address is too long");
3995 4010                          break;
3996 4011                  case IPTUN_REMOTE:
3997 4012                          params->iptun_param_flags |= IPTUN_PARAM_RADDR;
3998 4013                          if (strlcpy(params->iptun_param_raddr, addrval,
3999 4014                              sizeof (params->iptun_param_raddr)) >=
4000 4015                              sizeof (params->iptun_param_raddr))
4001 4016                                  die("tunnel destination address is too long");
4002 4017                          break;
4003 4018                  default:
4004 4019                          die("invalid address type: %s", addrval);
4005 4020                          break;
4006 4021                  }
4007 4022          }
4008 4023  }
4009 4024  
4010 4025  /*
4011 4026   * Convenience routine to process iptun-create/modify/delete subcommand
4012 4027   * arguments.
4013 4028   */
4014 4029  static void
4015 4030  iptun_process_args(int argc, char *argv[], const char *opts,
4016 4031      iptun_params_t *params, uint32_t *flags, char *name, const char *use)
4017 4032  {
4018 4033          int     option;
4019 4034          char    *altroot = NULL;
4020 4035  
4021 4036          if (params != NULL)
4022 4037                  bzero(params, sizeof (*params));
4023 4038          *flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4024 4039  
4025 4040          opterr = 0;
4026 4041          while ((option = getopt_long(argc, argv, opts, iptun_lopts, NULL)) !=
4027 4042              -1) {
4028 4043                  switch (option) {
4029 4044                  case 'a':
4030 4045                          iptun_process_addrarg(optarg, params);
4031 4046                          break;
4032 4047                  case 'R':
4033 4048                          altroot = optarg;
4034 4049                          break;
4035 4050                  case 't':
4036 4051                          *flags &= ~DLADM_OPT_PERSIST;
4037 4052                          break;
4038 4053                  case 'T':
4039 4054                          params->iptun_param_type = iptun_gettypebyname(optarg);
4040 4055                          if (params->iptun_param_type == IPTUN_TYPE_UNKNOWN)
4041 4056                                  die("unknown tunnel type: %s", optarg);
4042 4057                          params->iptun_param_flags |= IPTUN_PARAM_TYPE;
4043 4058                          break;
4044 4059                  default:
4045 4060                          die_opterr(optopt, option, use);
4046 4061                          break;
4047 4062                  }
4048 4063          }
4049 4064  
4050 4065          /* Get the required tunnel name argument. */
4051 4066          if (argc - optind != 1)
4052 4067                  usage();
4053 4068  
4054 4069          if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4055 4070                  die("tunnel name is too long");
4056 4071  
4057 4072          if (altroot != NULL)
4058 4073                  altroot_cmd(altroot, argc, argv);
4059 4074  }
4060 4075  
4061 4076  static void
4062 4077  do_create_iptun(int argc, char *argv[], const char *use)
4063 4078  {
4064 4079          iptun_params_t  params;
4065 4080          dladm_status_t  status;
4066 4081          uint32_t        flags;
4067 4082          char            name[MAXLINKNAMELEN];
4068 4083  
4069 4084          iptun_process_args(argc, argv, ":a:R:tT:", ¶ms, &flags, name,
4070 4085              use);
4071 4086  
4072 4087          status = dladm_iptun_create(handle, name, ¶ms, flags);
4073 4088          if (status != DLADM_STATUS_OK)
4074 4089                  die_dlerr(status, "could not create tunnel");
4075 4090  }
4076 4091  
4077 4092  static void
4078 4093  do_delete_iptun(int argc, char *argv[], const char *use)
4079 4094  {
4080 4095          uint32_t        flags;
4081 4096          datalink_id_t   linkid;
4082 4097          dladm_status_t  status;
4083 4098          char            name[MAXLINKNAMELEN];
4084 4099  
4085 4100          iptun_process_args(argc, argv, ":R:t", NULL, &flags, name, use);
4086 4101  
4087 4102          status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL);
4088 4103          if (status != DLADM_STATUS_OK)
4089 4104                  die_dlerr(status, "could not delete tunnel");
4090 4105          status = dladm_iptun_delete(handle, linkid, flags);
4091 4106          if (status != DLADM_STATUS_OK)
4092 4107                  die_dlerr(status, "could not delete tunnel");
4093 4108  }
4094 4109  
4095 4110  static void
4096 4111  do_modify_iptun(int argc, char *argv[], const char *use)
4097 4112  {
4098 4113          iptun_params_t  params;
4099 4114          uint32_t        flags;
4100 4115          dladm_status_t  status;
4101 4116          char            name[MAXLINKNAMELEN];
4102 4117  
4103 4118          iptun_process_args(argc, argv, ":a:R:t", ¶ms, &flags, name, use);
4104 4119  
4105 4120          if ((status = dladm_name2info(handle, name, ¶ms.iptun_param_linkid,
4106 4121              NULL, NULL, NULL)) != DLADM_STATUS_OK)
4107 4122                  die_dlerr(status, "could not modify tunnel");
4108 4123          status = dladm_iptun_modify(handle, ¶ms, flags);
4109 4124          if (status != DLADM_STATUS_OK)
4110 4125                  die_dlerr(status, "could not modify tunnel");
4111 4126  }
4112 4127  
4113 4128  static void
4114 4129  do_show_iptun(int argc, char *argv[], const char *use)
4115 4130  {
4116 4131          char            option;
4117 4132          datalink_id_t   linkid;
4118 4133          uint32_t        flags = DLADM_OPT_ACTIVE;
4119 4134          char            *name = NULL;
4120 4135          dladm_status_t  status;
4121 4136          const char      *fields_str = NULL;
4122 4137          show_state_t    state;
4123 4138          ofmt_handle_t   ofmt;
4124 4139          ofmt_status_t   oferr;
4125 4140          uint_t          ofmtflags = 0;
4126 4141  
4127 4142          bzero(&state, sizeof (state));
4128 4143          opterr = 0;
4129 4144          while ((option = getopt_long(argc, argv, ":pPo:",
4130 4145              iptun_lopts, NULL)) != -1) {
4131 4146                  switch (option) {
4132 4147                  case 'o':
4133 4148                          fields_str = optarg;
4134 4149                          break;
4135 4150                  case 'p':
4136 4151                          state.ls_parsable = B_TRUE;
4137 4152                          ofmtflags = OFMT_PARSABLE;
4138 4153                          break;
4139 4154                  case 'P':
4140 4155                          flags = DLADM_OPT_PERSIST;
4141 4156                          break;
4142 4157                  default:
4143 4158                          die_opterr(optopt, option, use);
4144 4159                          break;
4145 4160                  }
4146 4161          }
4147 4162  
4148 4163          /*
4149 4164           * Get the optional tunnel name argument.  If there is one, it must
4150 4165           * be the last thing remaining on the command-line.
4151 4166           */
4152 4167          if (argc - optind > 1)
4153 4168                  die(gettext(use));
4154 4169          if (argc - optind == 1)
4155 4170                  name = argv[optind];
4156 4171  
4157 4172          oferr = ofmt_open(fields_str, iptun_fields, ofmtflags,
4158 4173              DLADM_DEFAULT_COL, &ofmt);
4159 4174          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4160 4175  
4161 4176          state.ls_ofmt = ofmt;
4162 4177          state.ls_flags = flags;
4163 4178  
4164 4179          if (name == NULL) {
4165 4180                  (void) dladm_walk_datalink_id(print_iptun_walker, handle,
4166 4181                      &state, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE,
4167 4182                      flags);
4168 4183                  status = state.ls_status;
4169 4184          } else {
4170 4185                  if ((status = dladm_name2info(handle, name, &linkid, NULL, NULL,
4171 4186                      NULL)) == DLADM_STATUS_OK)
4172 4187                          status = print_iptun(handle, linkid, &state);
4173 4188          }
4174 4189  
4175 4190          if (status != DLADM_STATUS_OK)
4176 4191                  die_dlerr(status, "unable to obtain tunnel status");
4177 4192  }
4178 4193  
4179 4194  /* ARGSUSED */
4180 4195  static void
4181 4196  do_up_iptun(int argc, char *argv[], const char *use)
4182 4197  {
4183 4198          datalink_id_t   linkid = DATALINK_ALL_LINKID;
4184 4199          dladm_status_t  status = DLADM_STATUS_OK;
4185 4200  
4186 4201          /*
4187 4202           * Get the optional tunnel name argument.  If there is one, it must
4188 4203           * be the last thing remaining on the command-line.
4189 4204           */
4190 4205          if (argc - optind > 1)
4191 4206                  usage();
4192 4207          if (argc - optind == 1) {
4193 4208                  status = dladm_name2info(handle, argv[optind], &linkid, NULL,
4194 4209                      NULL, NULL);
4195 4210          }
4196 4211          if (status == DLADM_STATUS_OK)
4197 4212                  status = dladm_iptun_up(handle, linkid);
4198 4213          if (status != DLADM_STATUS_OK)
4199 4214                  die_dlerr(status, "unable to configure IP tunnel links");
4200 4215  }
4201 4216  
4202 4217  /* ARGSUSED */
4203 4218  static void
4204 4219  do_down_iptun(int argc, char *argv[], const char *use)
4205 4220  {
4206 4221          datalink_id_t   linkid = DATALINK_ALL_LINKID;
4207 4222          dladm_status_t  status = DLADM_STATUS_OK;
4208 4223  
4209 4224          /*
4210 4225           * Get the optional tunnel name argument.  If there is one, it must
4211 4226           * be the last thing remaining on the command-line.
4212 4227           */
4213 4228          if (argc - optind > 1)
4214 4229                  usage();
4215 4230          if (argc - optind == 1) {
4216 4231                  status = dladm_name2info(handle, argv[optind], &linkid, NULL,
4217 4232                      NULL, NULL);
4218 4233          }
4219 4234          if (status == DLADM_STATUS_OK)
4220 4235                  status = dladm_iptun_down(handle, linkid);
4221 4236          if (status != DLADM_STATUS_OK)
4222 4237                  die_dlerr(status, "unable to bring down IP tunnel links");
4223 4238  }
4224 4239  
4225 4240  static iptun_type_t
4226 4241  iptun_gettypebyname(char *typestr)
4227 4242  {
4228 4243          int i;
4229 4244  
4230 4245          for (i = 0; iptun_types[i].type_name != NULL; i++) {
4231 4246                  if (strncmp(iptun_types[i].type_name, typestr,
4232 4247                      strlen(iptun_types[i].type_name)) == 0) {
4233 4248                          return (iptun_types[i].type_value);
4234 4249                  }
4235 4250          }
4236 4251          return (IPTUN_TYPE_UNKNOWN);
4237 4252  }
4238 4253  
4239 4254  static const char *
4240 4255  iptun_gettypebyvalue(iptun_type_t type)
4241 4256  {
4242 4257          int i;
4243 4258  
4244 4259          for (i = 0; iptun_types[i].type_name != NULL; i++) {
4245 4260                  if (iptun_types[i].type_value == type)
4246 4261                          return (iptun_types[i].type_name);
4247 4262          }
4248 4263          return (NULL);
4249 4264  }
4250 4265  
4251 4266  static dladm_status_t
4252 4267  print_iptun(dladm_handle_t dh, datalink_id_t linkid, show_state_t *state)
4253 4268  {
4254 4269          dladm_status_t          status;
4255 4270          iptun_params_t          params;
4256 4271          iptun_fields_buf_t      lbuf;
4257 4272          const char              *laddr;
4258 4273          const char              *raddr;
4259 4274  
4260 4275          params.iptun_param_linkid = linkid;
4261 4276          status = dladm_iptun_getparams(dh, ¶ms, state->ls_flags);
4262 4277          if (status != DLADM_STATUS_OK)
4263 4278                  return (status);
4264 4279  
4265 4280          /* LINK */
4266 4281          status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL,
4267 4282              lbuf.iptun_name, sizeof (lbuf.iptun_name));
4268 4283          if (status != DLADM_STATUS_OK)
4269 4284                  return (status);
4270 4285  
4271 4286          /* TYPE */
4272 4287          (void) strlcpy(lbuf.iptun_type,
4273 4288              iptun_gettypebyvalue(params.iptun_param_type),
4274 4289              sizeof (lbuf.iptun_type));
4275 4290  
4276 4291          /* FLAGS */
4277 4292          (void) memset(lbuf.iptun_flags, '-', IPTUN_NUM_FLAGS);
4278 4293          lbuf.iptun_flags[IPTUN_NUM_FLAGS] = '\0';
4279 4294          if (params.iptun_param_flags & IPTUN_PARAM_IPSECPOL)
4280 4295                  lbuf.iptun_flags[IPTUN_SFLAG_INDEX] = 's';
4281 4296          if (params.iptun_param_flags & IPTUN_PARAM_IMPLICIT)
4282 4297                  lbuf.iptun_flags[IPTUN_IFLAG_INDEX] = 'i';
4283 4298  
4284 4299          /* LOCAL */
4285 4300          if (params.iptun_param_flags & IPTUN_PARAM_LADDR)
4286 4301                  laddr = params.iptun_param_laddr;
4287 4302          else
4288 4303                  laddr = (state->ls_parsable) ? "" : "--";
4289 4304          (void) strlcpy(lbuf.iptun_laddr, laddr, sizeof (lbuf.iptun_laddr));
4290 4305  
4291 4306          /* REMOTE */
4292 4307          if (params.iptun_param_flags & IPTUN_PARAM_RADDR)
4293 4308                  raddr = params.iptun_param_raddr;
4294 4309          else
4295 4310                  raddr = (state->ls_parsable) ? "" : "--";
4296 4311          (void) strlcpy(lbuf.iptun_raddr, raddr, sizeof (lbuf.iptun_raddr));
4297 4312  
4298 4313          ofmt_print(state->ls_ofmt, &lbuf);
4299 4314  
4300 4315          return (DLADM_STATUS_OK);
4301 4316  }
4302 4317  
4303 4318  static int
4304 4319  print_iptun_walker(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4305 4320  {
4306 4321          ((show_state_t *)arg)->ls_status = print_iptun(dh, linkid, arg);
4307 4322          return (DLADM_WALK_CONTINUE);
4308 4323  }
4309 4324  
4310 4325  static dladm_status_t
4311 4326  print_phys(show_state_t *state, datalink_id_t linkid)
4312 4327  {
4313 4328          char                    link[MAXLINKNAMELEN];
4314 4329          uint32_t                flags;
4315 4330          dladm_status_t          status;
4316 4331          datalink_class_t        class;
4317 4332          uint32_t                media;
4318 4333  
4319 4334          if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
4320 4335              &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
4321 4336                  goto done;
4322 4337          }
4323 4338  
4324 4339          if (class != DATALINK_CLASS_PHYS) {
4325 4340                  status = DLADM_STATUS_BADARG;
4326 4341                  goto done;
4327 4342          }
4328 4343  
4329 4344          if (!(state->ls_flags & flags)) {
4330 4345                  status = DLADM_STATUS_NOTFOUND;
4331 4346                  goto done;
4332 4347          }
4333 4348  
4334 4349          if (state->ls_mac)
4335 4350                  status = print_phys_mac(state, linkid, link);
4336 4351          else if (state->ls_hwgrp)
4337 4352                  status = print_phys_hwgrp(state, linkid, link);
4338 4353          else
4339 4354                  status = print_phys_default(state, linkid, link, flags, media);
4340 4355  
4341 4356  done:
4342 4357          return (status);
4343 4358  }
4344 4359  
4345 4360  /* ARGSUSED */
4346 4361  static int
4347 4362  show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4348 4363  {
4349 4364          show_state_t    *state = arg;
4350 4365  
4351 4366          state->ls_status = print_phys(state, linkid);
4352 4367          return (DLADM_WALK_CONTINUE);
4353 4368  }
4354 4369  
4355 4370  /*
4356 4371   * Print the active topology information.
4357 4372   */
4358 4373  static dladm_status_t
4359 4374  print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l)
4360 4375  {
4361 4376          dladm_vlan_attr_t       vinfo;
4362 4377          uint32_t                flags;
4363 4378          dladm_status_t          status;
4364 4379  
4365 4380          if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
4366 4381              l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) {
4367 4382                  goto done;
4368 4383          }
4369 4384  
4370 4385          if (!(state->ls_flags & flags)) {
4371 4386                  status = DLADM_STATUS_NOTFOUND;
4372 4387                  goto done;
4373 4388          }
4374 4389  
4375 4390          if ((status = dladm_vlan_info(handle, linkid, &vinfo,
4376 4391              state->ls_flags)) != DLADM_STATUS_OK ||
4377 4392              (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL,
4378 4393              NULL, NULL, l->link_over, sizeof (l->link_over))) !=
4379 4394              DLADM_STATUS_OK) {
4380 4395                  goto done;
4381 4396          }
4382 4397  
4383 4398          (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d",
4384 4399              vinfo.dv_vid);
4385 4400          (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----",
4386 4401              vinfo.dv_force ? 'f' : '-');
4387 4402  
4388 4403  done:
4389 4404          return (status);
4390 4405  }
4391 4406  
4392 4407  /* ARGSUSED */
4393 4408  static int
4394 4409  show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4395 4410  {
4396 4411          show_state_t            *state = arg;
4397 4412          dladm_status_t          status;
4398 4413          link_fields_buf_t       lbuf;
4399 4414  
4400 4415          bzero(&lbuf, sizeof (link_fields_buf_t));
4401 4416          status = print_vlan(state, linkid, &lbuf);
4402 4417          if (status != DLADM_STATUS_OK)
4403 4418                  goto done;
4404 4419  
4405 4420          ofmt_print(state->ls_ofmt, &lbuf);
4406 4421  
4407 4422  done:
4408 4423          state->ls_status = status;
4409 4424          return (DLADM_WALK_CONTINUE);
4410 4425  }
4411 4426  
4412 4427  static void
4413 4428  do_show_phys(int argc, char *argv[], const char *use)
4414 4429  {
4415 4430          int             option;
4416 4431          uint32_t        flags = DLADM_OPT_ACTIVE;
4417 4432          boolean_t       p_arg = B_FALSE;
4418 4433          boolean_t       o_arg = B_FALSE;
4419 4434          boolean_t       m_arg = B_FALSE;
4420 4435          boolean_t       H_arg = B_FALSE;
4421 4436          datalink_id_t   linkid = DATALINK_ALL_LINKID;
4422 4437          show_state_t    state;
4423 4438          dladm_status_t  status;
4424 4439          char            *fields_str = NULL;
4425 4440          char            *all_active_fields =
4426 4441              "link,media,state,speed,duplex,device";
4427 4442          char            *all_inactive_fields = "link,device,media,flags";
4428 4443          char            *all_mac_fields = "link,slot,address,inuse,client";
4429 4444          char            *all_hwgrp_fields = "link,ringtype,rings,clients";
4430 4445          const ofmt_field_t *pf;
4431 4446          ofmt_handle_t   ofmt;
4432 4447          ofmt_status_t   oferr;
4433 4448          uint_t          ofmtflags = 0;
4434 4449  
4435 4450          bzero(&state, sizeof (state));
4436 4451          opterr = 0;
4437 4452          while ((option = getopt_long(argc, argv, ":pPo:mH",
4438 4453              show_lopts, NULL)) != -1) {
4439 4454                  switch (option) {
4440 4455                  case 'p':
4441 4456                          if (p_arg)
4442 4457                                  die_optdup(option);
4443 4458  
4444 4459                          p_arg = B_TRUE;
4445 4460                          break;
4446 4461                  case 'P':
4447 4462                          if (flags != DLADM_OPT_ACTIVE)
4448 4463                                  die_optdup(option);
4449 4464  
4450 4465                          flags = DLADM_OPT_PERSIST;
4451 4466                          break;
4452 4467                  case 'o':
4453 4468                          o_arg = B_TRUE;
4454 4469                          fields_str = optarg;
4455 4470                          break;
4456 4471                  case 'm':
4457 4472                          m_arg = B_TRUE;
4458 4473                          break;
4459 4474                  case 'H':
4460 4475                          H_arg = B_TRUE;
4461 4476                          break;
4462 4477                  default:
4463 4478                          die_opterr(optopt, option, use);
4464 4479                          break;
4465 4480                  }
4466 4481          }
4467 4482  
4468 4483          if (p_arg && !o_arg)
4469 4484                  die("-p requires -o");
4470 4485  
4471 4486          if (m_arg && H_arg)
4472 4487                  die("-m cannot combine with -H");
4473 4488  
4474 4489          if (p_arg && strcasecmp(fields_str, "all") == 0)
4475 4490                  die("\"-o all\" is invalid with -p");
4476 4491  
4477 4492          /* get link name (optional last argument) */
4478 4493          if (optind == (argc-1)) {
4479 4494                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
4480 4495                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
4481 4496                          die_dlerr(status, "link %s is not valid", argv[optind]);
4482 4497                  }
4483 4498          } else if (optind != argc) {
4484 4499                  usage();
4485 4500          }
4486 4501  
4487 4502          state.ls_parsable = p_arg;
4488 4503          state.ls_flags = flags;
4489 4504          state.ls_donefirst = B_FALSE;
4490 4505          state.ls_mac = m_arg;
4491 4506          state.ls_hwgrp = H_arg;
4492 4507  
4493 4508          if (m_arg && !(flags & DLADM_OPT_ACTIVE)) {
4494 4509                  /*
4495 4510                   * We can only display the factory MAC addresses of
4496 4511                   * active data-links.
4497 4512                   */
4498 4513                  die("-m not compatible with -P");
4499 4514          }
4500 4515  
4501 4516          if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
4502 4517                  if (state.ls_mac)
4503 4518                          fields_str = all_mac_fields;
4504 4519                  else if (state.ls_hwgrp)
4505 4520                          fields_str = all_hwgrp_fields;
4506 4521                  else if (state.ls_flags & DLADM_OPT_ACTIVE) {
4507 4522                          fields_str = all_active_fields;
4508 4523                  } else {
4509 4524                          fields_str = all_inactive_fields;
4510 4525                  }
4511 4526          }
4512 4527  
4513 4528          if (state.ls_mac) {
4514 4529                  pf = phys_m_fields;
4515 4530          } else if (state.ls_hwgrp) {
4516 4531                  pf = phys_h_fields;
4517 4532          } else {
4518 4533                  pf = phys_fields;
4519 4534          }
4520 4535  
4521 4536          if (state.ls_parsable)
4522 4537                  ofmtflags |= OFMT_PARSABLE;
4523 4538          oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
4524 4539          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4525 4540          state.ls_ofmt = ofmt;
4526 4541  
4527 4542          if (linkid == DATALINK_ALL_LINKID) {
4528 4543                  (void) dladm_walk_datalink_id(show_phys, handle, &state,
4529 4544                      DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags);
4530 4545          } else {
4531 4546                  (void) show_phys(handle, linkid, &state);
4532 4547                  if (state.ls_status != DLADM_STATUS_OK) {
4533 4548                          die_dlerr(state.ls_status,
4534 4549                              "failed to show physical link %s", argv[optind]);
4535 4550                  }
4536 4551          }
4537 4552          ofmt_close(ofmt);
4538 4553  }
4539 4554  
4540 4555  static void
4541 4556  do_show_vlan(int argc, char *argv[], const char *use)
4542 4557  {
4543 4558          int             option;
4544 4559          uint32_t        flags = DLADM_OPT_ACTIVE;
4545 4560          boolean_t       p_arg = B_FALSE;
4546 4561          datalink_id_t   linkid = DATALINK_ALL_LINKID;
4547 4562          show_state_t    state;
4548 4563          dladm_status_t  status;
4549 4564          boolean_t       o_arg = B_FALSE;
4550 4565          char            *fields_str = NULL;
4551 4566          ofmt_handle_t   ofmt;
4552 4567          ofmt_status_t   oferr;
4553 4568          uint_t          ofmtflags = 0;
4554 4569  
4555 4570          bzero(&state, sizeof (state));
4556 4571  
4557 4572          opterr = 0;
4558 4573          while ((option = getopt_long(argc, argv, ":pPo:",
4559 4574              show_lopts, NULL)) != -1) {
4560 4575                  switch (option) {
4561 4576                  case 'p':
4562 4577                          if (p_arg)
4563 4578                                  die_optdup(option);
4564 4579  
4565 4580                          p_arg = B_TRUE;
4566 4581                          break;
4567 4582                  case 'P':
4568 4583                          if (flags != DLADM_OPT_ACTIVE)
4569 4584                                  die_optdup(option);
4570 4585  
4571 4586                          flags = DLADM_OPT_PERSIST;
4572 4587                          break;
4573 4588                  case 'o':
4574 4589                          o_arg = B_TRUE;
4575 4590                          fields_str = optarg;
4576 4591                          break;
4577 4592                  default:
4578 4593                          die_opterr(optopt, option, use);
4579 4594                          break;
4580 4595                  }
4581 4596          }
4582 4597  
4583 4598          /* get link name (optional last argument) */
4584 4599          if (optind == (argc-1)) {
4585 4600                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
4586 4601                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
4587 4602                          die_dlerr(status, "link %s is not valid", argv[optind]);
4588 4603                  }
4589 4604          } else if (optind != argc) {
4590 4605                  usage();
4591 4606          }
4592 4607  
4593 4608          state.ls_parsable = p_arg;
4594 4609          state.ls_flags = flags;
4595 4610          state.ls_donefirst = B_FALSE;
4596 4611  
4597 4612          if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
4598 4613                  fields_str = NULL;
4599 4614  
4600 4615          if (state.ls_parsable)
4601 4616                  ofmtflags |= OFMT_PARSABLE;
4602 4617          oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt);
4603 4618          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4604 4619          state.ls_ofmt = ofmt;
4605 4620  
4606 4621          if (linkid == DATALINK_ALL_LINKID) {
4607 4622                  (void) dladm_walk_datalink_id(show_vlan, handle, &state,
4608 4623                      DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags);
4609 4624          } else {
4610 4625                  (void) show_vlan(handle, linkid, &state);
4611 4626                  if (state.ls_status != DLADM_STATUS_OK) {
4612 4627                          die_dlerr(state.ls_status, "failed to show vlan %s",
4613 4628                              argv[optind]);
4614 4629                  }
4615 4630          }
4616 4631          ofmt_close(ofmt);
4617 4632  }
4618 4633  
4619 4634  static void
4620 4635  do_create_vnic(int argc, char *argv[], const char *use)
4621 4636  {
4622 4637          datalink_id_t           linkid, dev_linkid;
4623 4638          char                    devname[MAXLINKNAMELEN];
4624 4639          char                    name[MAXLINKNAMELEN];
4625 4640          boolean_t               l_arg = B_FALSE;
4626 4641          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4627 4642          char                    *altroot = NULL;
4628 4643          int                     option;
4629 4644          char                    *endp = NULL;
4630 4645          dladm_status_t          status;
4631 4646          vnic_mac_addr_type_t    mac_addr_type = VNIC_MAC_ADDR_TYPE_UNKNOWN;
4632 4647          uchar_t                 *mac_addr = NULL;
4633 4648          int                     mac_slot = -1;
4634 4649          uint_t                  maclen = 0, mac_prefix_len = 0;
4635 4650          char                    propstr[DLADM_STRSIZE];
4636 4651          dladm_arg_list_t        *proplist = NULL;
4637 4652          int                     vid = 0;
4638 4653          int                     af = AF_UNSPEC;
4639 4654          vrid_t                  vrid = VRRP_VRID_NONE;
4640 4655  
4641 4656          opterr = 0;
4642 4657          bzero(propstr, DLADM_STRSIZE);
4643 4658  
4644 4659          while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:V:A:H",
4645 4660              vnic_lopts, NULL)) != -1) {
4646 4661                  switch (option) {
4647 4662                  case 't':
4648 4663                          flags &= ~DLADM_OPT_PERSIST;
4649 4664                          break;
4650 4665                  case 'R':
4651 4666                          altroot = optarg;
4652 4667                          break;
4653 4668                  case 'l':
4654 4669                          if (strlcpy(devname, optarg, MAXLINKNAMELEN) >=
4655 4670                              MAXLINKNAMELEN)
4656 4671                                  die("link name too long");
4657 4672                          l_arg = B_TRUE;
4658 4673                          break;
4659 4674                  case 'm':
4660 4675                          if (mac_addr_type != VNIC_MAC_ADDR_TYPE_UNKNOWN)
4661 4676                                  die("cannot specify -m option twice");
4662 4677  
4663 4678                          if (strcmp(optarg, "fixed") == 0) {
4664 4679                                  /*
4665 4680                                   * A fixed MAC address must be specified
4666 4681                                   * by its value, not by the keyword 'fixed'.
4667 4682                                   */
4668 4683                                  die("'fixed' is not a valid MAC address");
4669 4684                          }
4670 4685                          if (dladm_vnic_str2macaddrtype(optarg,
4671 4686                              &mac_addr_type) != DLADM_STATUS_OK) {
4672 4687                                  mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED;
4673 4688                                  /* MAC address specified by value */
4674 4689                                  mac_addr = _link_aton(optarg, (int *)&maclen);
4675 4690                                  if (mac_addr == NULL) {
4676 4691                                          if (maclen == (uint_t)-1)
4677 4692                                                  die("invalid MAC address");
4678 4693                                          else
4679 4694                                                  die("out of memory");
4680 4695                                  }
4681 4696                          }
4682 4697                          break;
4683 4698                  case 'n':
4684 4699                          errno = 0;
4685 4700                          mac_slot = (int)strtol(optarg, &endp, 10);
4686 4701                          if (errno != 0 || *endp != '\0')
4687 4702                                  die("invalid slot number");
4688 4703                          break;
4689 4704                  case 'p':
4690 4705                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
4691 4706                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
4692 4707                              DLADM_STRSIZE)
4693 4708                                  die("property list too long '%s'", propstr);
4694 4709                          break;
4695 4710                  case 'r':
4696 4711                          mac_addr = _link_aton(optarg, (int *)&mac_prefix_len);
4697 4712                          if (mac_addr == NULL) {
4698 4713                                  if (mac_prefix_len == (uint_t)-1)
4699 4714                                          die("invalid MAC address");
4700 4715                                  else
4701 4716                                          die("out of memory");
4702 4717                          }
4703 4718                          break;
4704 4719                  case 'V':
4705 4720                          if (!str2int(optarg, (int *)&vrid) ||
4706 4721                              vrid < VRRP_VRID_MIN || vrid > VRRP_VRID_MAX) {
4707 4722                                  die("invalid VRRP identifier '%s'", optarg);
4708 4723                          }
4709 4724  
4710 4725                          break;
4711 4726                  case 'A':
4712 4727                          if (strcmp(optarg, "inet") == 0)
4713 4728                                  af = AF_INET;
4714 4729                          else if (strcmp(optarg, "inet6") == 0)
4715 4730                                  af = AF_INET6;
4716 4731                          else
4717 4732                                  die("invalid address family '%s'", optarg);
4718 4733                          break;
4719 4734                  case 'v':
4720 4735                          if (vid != 0)
4721 4736                                  die_optdup(option);
4722 4737  
4723 4738                          if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
4724 4739                                  die("invalid VLAN identifier '%s'", optarg);
4725 4740  
4726 4741                          break;
4727 4742                  case 'f':
4728 4743                          flags |= DLADM_OPT_FORCE;
4729 4744                          break;
4730 4745                  default:
4731 4746                          die_opterr(optopt, option, use);
4732 4747                  }
4733 4748          }
  
    | 
      ↓ open down ↓ | 
    1244 lines elided | 
    
      ↑ open up ↑ | 
  
4734 4749  
4735 4750          if (mac_addr_type == VNIC_MAC_ADDR_TYPE_UNKNOWN)
4736 4751                  mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO;
4737 4752  
4738 4753          /*
4739 4754           * 'f' - force, flag can be specified only with 'v' - vlan.
4740 4755           */
4741 4756          if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
4742 4757                  die("-f option can only be used with -v");
4743 4758  
     4759 +        /*
     4760 +         * If creating a transient VNIC for a zone, mark it in the kernel.
     4761 +         */
     4762 +        if (strstr(propstr, "zone=") != NULL && !(flags & DLADM_OPT_PERSIST))
     4763 +                flags |= DLADM_OPT_TRANSIENT;
     4764 +
4744 4765          if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
4745 4766              mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
4746 4767                  usage();
4747 4768  
4748 4769          if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) {
4749 4770                  if (vrid == VRRP_VRID_NONE || af == AF_UNSPEC ||
4750 4771                      mac_addr != NULL || maclen != 0 || mac_slot != -1 ||
4751 4772                      mac_prefix_len != 0) {
4752 4773                          usage();
4753 4774                  }
4754 4775          } else if ((af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) {
4755 4776                  usage();
4756 4777          }
4757 4778  
4758 4779          /* check required options */
4759 4780          if (!l_arg)
4760 4781                  usage();
4761 4782  
4762 4783          if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY)
4763 4784                  usage();
4764 4785  
4765 4786          /* the VNIC id is the required operand */
4766 4787          if (optind != (argc - 1))
4767 4788                  usage();
4768 4789  
4769 4790          if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4770 4791                  die("link name too long '%s'", argv[optind]);
4771 4792  
4772 4793          if (!dladm_valid_linkname(name))
4773 4794                  die("invalid link name '%s'", argv[optind]);
4774 4795  
4775 4796          if (altroot != NULL)
4776 4797                  altroot_cmd(altroot, argc, argv);
4777 4798  
4778 4799          if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) !=
4779 4800              DLADM_STATUS_OK)
4780 4801                  die("invalid link name '%s'", devname);
4781 4802  
4782 4803          if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
4783 4804              != DLADM_STATUS_OK)
4784 4805                  die("invalid vnic property");
4785 4806  
4786 4807          status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type,
4787 4808              mac_addr, maclen, &mac_slot, mac_prefix_len, vid, vrid, af,
4788 4809              &linkid, proplist, flags);
4789 4810          switch (status) {
4790 4811          case DLADM_STATUS_OK:
4791 4812                  break;
4792 4813  
4793 4814          case DLADM_STATUS_LINKBUSY:
4794 4815                  die("VLAN over '%s' may not use default_tag ID "
4795 4816                      "(see dladm(1M))", devname);
4796 4817                  break;
4797 4818  
4798 4819          default:
4799 4820                  die_dlerr(status, "vnic creation over %s failed", devname);
4800 4821          }
4801 4822  
4802 4823          dladm_free_props(proplist);
4803 4824          free(mac_addr);
4804 4825  }
4805 4826  
4806 4827  static void
4807 4828  do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub,
4808 4829      uint32_t flags)
4809 4830  {
4810 4831          boolean_t is_etherstub;
4811 4832          dladm_vnic_attr_t attr;
4812 4833  
4813 4834          if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) {
4814 4835                  /*
4815 4836                   * Let the delete continue anyway.
4816 4837                   */
4817 4838                  return;
4818 4839          }
4819 4840          is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID);
4820 4841          if (is_etherstub != etherstub) {
4821 4842                  die("'%s' is not %s", name,
4822 4843                      (is_etherstub ? "a vnic" : "an etherstub"));
4823 4844          }
4824 4845  }
  
    | 
      ↓ open down ↓ | 
    71 lines elided | 
    
      ↑ open up ↑ | 
  
4825 4846  
4826 4847  static void
4827 4848  do_delete_vnic_common(int argc, char *argv[], const char *use,
4828 4849      boolean_t etherstub)
4829 4850  {
4830 4851          int option;
4831 4852          uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4832 4853          datalink_id_t linkid;
4833 4854          char *altroot = NULL;
4834 4855          dladm_status_t status;
     4856 +        char    *zonename = NULL;
4835 4857  
4836 4858          opterr = 0;
4837      -        while ((option = getopt_long(argc, argv, ":R:t", lopts,
     4859 +        while ((option = getopt_long(argc, argv, ":R:tz:", lopts,
4838 4860              NULL)) != -1) {
4839 4861                  switch (option) {
4840 4862                  case 't':
4841 4863                          flags &= ~DLADM_OPT_PERSIST;
4842 4864                          break;
4843 4865                  case 'R':
4844 4866                          altroot = optarg;
4845 4867                          break;
     4868 +                case 'z':
     4869 +                        zonename = optarg;
     4870 +                        break;
4846 4871                  default:
4847 4872                          die_opterr(optopt, option, use);
4848 4873                  }
4849 4874          }
4850 4875  
4851 4876          /* get vnic name (required last argument) */
4852 4877          if (optind != (argc - 1))
4853 4878                  usage();
4854 4879  
4855 4880          if (altroot != NULL)
4856 4881                  altroot_cmd(altroot, argc, argv);
4857 4882  
4858      -        status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
4859      -            NULL);
     4883 +        status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL,
     4884 +            NULL, NULL);
4860 4885          if (status != DLADM_STATUS_OK)
4861 4886                  die("invalid link name '%s'", argv[optind]);
4862 4887  
4863 4888          if ((flags & DLADM_OPT_ACTIVE) != 0) {
4864 4889                  do_etherstub_check(argv[optind], linkid, etherstub,
4865 4890                      DLADM_OPT_ACTIVE);
4866 4891          }
4867 4892          if ((flags & DLADM_OPT_PERSIST) != 0) {
4868 4893                  do_etherstub_check(argv[optind], linkid, etherstub,
4869 4894                      DLADM_OPT_PERSIST);
4870 4895          }
4871 4896  
4872 4897          status = dladm_vnic_delete(handle, linkid, flags);
4873 4898          if (status != DLADM_STATUS_OK)
4874 4899                  die_dlerr(status, "vnic deletion failed");
4875 4900  }
4876 4901  
4877 4902  static void
4878 4903  do_delete_vnic(int argc, char *argv[], const char *use)
4879 4904  {
4880 4905          do_delete_vnic_common(argc, argv, use, B_FALSE);
4881 4906  }
4882 4907  
4883 4908  /* ARGSUSED */
4884 4909  static void
4885 4910  do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan)
4886 4911  {
4887 4912          datalink_id_t   linkid = DATALINK_ALL_LINKID;
4888 4913          dladm_status_t  status;
4889 4914          char            *type;
4890 4915  
4891 4916          type = vlan ? "vlan" : "vnic";
4892 4917  
4893 4918          /*
4894 4919           * get the id or the name of the vnic/vlan (optional last argument)
4895 4920           */
4896 4921          if (argc == 2) {
4897 4922                  status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL,
4898 4923                      NULL);
4899 4924                  if (status != DLADM_STATUS_OK)
4900 4925                          goto done;
4901 4926  
4902 4927          } else if (argc > 2) {
4903 4928                  usage();
4904 4929          }
4905 4930  
4906 4931          if (vlan)
4907 4932                  status = dladm_vlan_up(handle, linkid);
4908 4933          else
4909 4934                  status = dladm_vnic_up(handle, linkid, 0);
4910 4935  
4911 4936  done:
4912 4937          if (status != DLADM_STATUS_OK) {
4913 4938                  if (argc == 2) {
4914 4939                          die_dlerr(status,
4915 4940                              "could not bring up %s '%s'", type, argv[1]);
4916 4941                  } else {
4917 4942                          die_dlerr(status, "could not bring %ss up", type);
4918 4943                  }
4919 4944          }
4920 4945  }
4921 4946  
4922 4947  static void
4923 4948  do_up_vnic(int argc, char *argv[], const char *use)
4924 4949  {
4925 4950          do_up_vnic_common(argc, argv, use, B_FALSE);
4926 4951  }
4927 4952  
4928 4953  static void
4929 4954  dump_vnics_head(const char *dev)
4930 4955  {
4931 4956          if (strlen(dev))
4932 4957                  (void) printf("%s", dev);
4933 4958  
4934 4959          (void) printf("\tipackets  rbytes      opackets  obytes          ");
4935 4960  
4936 4961          if (strlen(dev))
4937 4962                  (void) printf("%%ipkts  %%opkts\n");
4938 4963          else
4939 4964                  (void) printf("\n");
4940 4965  }
4941 4966  
4942 4967  static void
4943 4968  dump_vnic_stat(const char *name, datalink_id_t vnic_id,
4944 4969      show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats)
4945 4970  {
4946 4971          pktsum_t        diff_stats;
4947 4972          pktsum_t        *old_stats = &state->vs_prevstats[vnic_id];
4948 4973  
4949 4974          dladm_stats_diff(&diff_stats, vnic_stats, old_stats);
4950 4975  
4951 4976          (void) printf("%s", name);
4952 4977  
4953 4978          (void) printf("\t%-10llu", diff_stats.ipackets);
4954 4979          (void) printf("%-12llu", diff_stats.rbytes);
4955 4980          (void) printf("%-10llu", diff_stats.opackets);
4956 4981          (void) printf("%-12llu", diff_stats.obytes);
4957 4982  
4958 4983          if (tot_stats) {
4959 4984                  if (tot_stats->ipackets == 0) {
4960 4985                          (void) printf("\t-");
4961 4986                  } else {
4962 4987                          (void) printf("\t%-6.1f", (double)diff_stats.ipackets/
4963 4988                              (double)tot_stats->ipackets * 100);
4964 4989                  }
4965 4990                  if (tot_stats->opackets == 0) {
4966 4991                          (void) printf("\t-");
4967 4992                  } else {
4968 4993                          (void) printf("\t%-6.1f", (double)diff_stats.opackets/
4969 4994                              (double)tot_stats->opackets * 100);
4970 4995                  }
4971 4996          }
4972 4997          (void) printf("\n");
4973 4998  
4974 4999          *old_stats = *vnic_stats;
4975 5000  }
4976 5001  
4977 5002  /*
4978 5003   * Called from the walker dladm_vnic_walk_sys() for each vnic to display
4979 5004   * vnic information or statistics.
4980 5005   */
  
    | 
      ↓ open down ↓ | 
    111 lines elided | 
    
      ↑ open up ↑ | 
  
4981 5006  static dladm_status_t
4982 5007  print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
4983 5008  {
4984 5009          dladm_vnic_attr_t       attr, *vnic = &attr;
4985 5010          dladm_status_t          status;
4986 5011          boolean_t               is_etherstub;
4987 5012          char                    devname[MAXLINKNAMELEN];
4988 5013          char                    vnic_name[MAXLINKNAMELEN];
4989 5014          char                    mstr[MAXMACADDRLEN * 3];
4990 5015          vnic_fields_buf_t       vbuf;
     5016 +        uint_t                  valcnt = 1;
     5017 +        char                    zonename[DLADM_PROP_VAL_MAX + 1];
     5018 +        char                    *valptr[1];
4991 5019  
4992 5020          if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
4993 5021              DLADM_STATUS_OK)
4994 5022                  return (status);
4995 5023  
4996 5024          is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID);
4997 5025          if (state->vs_etherstub != is_etherstub) {
4998 5026                  /*
4999 5027                   * Want all etherstub but it's not one, or want
5000 5028                   * non-etherstub and it's one.
5001 5029                   */
5002 5030                  return (DLADM_STATUS_OK);
5003 5031          }
5004 5032  
5005 5033          if (state->vs_link_id != DATALINK_ALL_LINKID) {
5006 5034                  if (state->vs_link_id != vnic->va_link_id)
5007 5035                          return (DLADM_STATUS_OK);
5008 5036          }
5009 5037  
  
    | 
      ↓ open down ↓ | 
    9 lines elided | 
    
      ↑ open up ↑ | 
  
5010 5038          if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
5011 5039              NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK)
5012 5040                  return (DLADM_STATUS_BADARG);
5013 5041  
5014 5042          bzero(devname, sizeof (devname));
5015 5043          if (!is_etherstub &&
5016 5044              dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL,
5017 5045              NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
5018 5046                  (void) sprintf(devname, "?");
5019 5047  
     5048 +        
     5049 +        zonename[0] = '\0';
     5050 +        if (!is_etherstub) {
     5051 +                valptr[0] = zonename;
     5052 +                (void) dladm_get_linkprop(handle, linkid,
     5053 +                    DLADM_PROP_VAL_CURRENT, "zone", (char **)valptr, &valcnt);
     5054 +        }
     5055 +
     5056 +        if (state->vs_zonename != NULL &&
     5057 +             strcmp(state->vs_zonename, zonename) != 0)
     5058 +                return (DLADM_STATUS_OK);
     5059 +
5020 5060          state->vs_found = B_TRUE;
5021 5061          if (state->vs_stats) {
5022 5062                  /* print vnic statistics */
5023 5063                  pktsum_t vnic_stats;
5024 5064  
5025 5065                  if (state->vs_firstonly) {
5026 5066                          if (state->vs_donefirst)
5027 5067                                  return (0);
5028 5068                          state->vs_donefirst = B_TRUE;
5029 5069                  }
5030 5070  
5031 5071                  if (!state->vs_printstats) {
5032 5072                          /*
5033 5073                           * get vnic statistics and add to the sum for the
5034 5074                           * named device.
5035 5075                           */
5036 5076                          get_link_stats(vnic_name, &vnic_stats);
5037 5077                          dladm_stats_total(&state->vs_totalstats, &vnic_stats,
5038 5078                              &state->vs_prevstats[vnic->va_vnic_id]);
5039 5079                  } else {
5040 5080                          /* get and print vnic statistics */
5041 5081                          get_link_stats(vnic_name, &vnic_stats);
5042 5082                          dump_vnic_stat(vnic_name, linkid, state, &vnic_stats,
5043 5083                              &state->vs_totalstats);
5044 5084                  }
5045 5085                  return (DLADM_STATUS_OK);
5046 5086          } else {
5047 5087                  (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link),
5048 5088                      "%s", vnic_name);
5049 5089  
5050 5090                  if (!is_etherstub) {
5051 5091  
5052 5092                          (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over),
5053 5093                              "%s", devname);
5054 5094                          (void) snprintf(vbuf.vnic_speed,
5055 5095                              sizeof (vbuf.vnic_speed), "%u",
5056 5096                              (uint_t)((get_ifspeed(vnic_name, B_TRUE))
5057 5097                              / 1000000ull));
5058 5098  
5059 5099                          switch (vnic->va_mac_addr_type) {
5060 5100                          case VNIC_MAC_ADDR_TYPE_FIXED:
5061 5101                          case VNIC_MAC_ADDR_TYPE_PRIMARY:
5062 5102                                  (void) snprintf(vbuf.vnic_macaddrtype,
5063 5103                                      sizeof (vbuf.vnic_macaddrtype),
5064 5104                                      gettext("fixed"));
5065 5105                                  break;
5066 5106                          case VNIC_MAC_ADDR_TYPE_RANDOM:
5067 5107                                  (void) snprintf(vbuf.vnic_macaddrtype,
5068 5108                                      sizeof (vbuf.vnic_macaddrtype),
5069 5109                                      gettext("random"));
5070 5110                                  break;
5071 5111                          case VNIC_MAC_ADDR_TYPE_FACTORY:
5072 5112                                  (void) snprintf(vbuf.vnic_macaddrtype,
5073 5113                                      sizeof (vbuf.vnic_macaddrtype),
5074 5114                                      gettext("factory, slot %d"),
5075 5115                                      vnic->va_mac_slot);
5076 5116                                  break;
5077 5117                          case VNIC_MAC_ADDR_TYPE_VRID:
5078 5118                                  (void) snprintf(vbuf.vnic_macaddrtype,
5079 5119                                      sizeof (vbuf.vnic_macaddrtype),
5080 5120                                      gettext("vrrp, %d/%s"),
5081 5121                                      vnic->va_vrid, vnic->va_af == AF_INET ?
5082 5122                                      "inet" : "inet6");
5083 5123                                  break;
5084 5124                          }
  
    | 
      ↓ open down ↓ | 
    55 lines elided | 
    
      ↑ open up ↑ | 
  
5085 5125  
5086 5126                          if (strlen(vbuf.vnic_macaddrtype) > 0) {
5087 5127                                  (void) snprintf(vbuf.vnic_macaddr,
5088 5128                                      sizeof (vbuf.vnic_macaddr), "%s",
5089 5129                                      dladm_aggr_macaddr2str(vnic->va_mac_addr,
5090 5130                                      mstr));
5091 5131                          }
5092 5132  
5093 5133                          (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
5094 5134                              "%d", vnic->va_vid);
     5135 +
     5136 +                        if (zonename[0] != '\0')
     5137 +                                (void) snprintf(vbuf.vnic_zone,
     5138 +                                    sizeof (vbuf.vnic_zone), "%s", zonename);
     5139 +                        else
     5140 +                                (void) strlcpy(vbuf.vnic_zone, "--",
     5141 +                                     sizeof (vbuf.vnic_zone));
5095 5142                  }
5096 5143  
5097 5144                  ofmt_print(state->vs_ofmt, &vbuf);
5098 5145  
5099 5146                  return (DLADM_STATUS_OK);
5100 5147          }
5101 5148  }
5102 5149  
5103 5150  /* ARGSUSED */
5104 5151  static int
5105 5152  show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5106 5153  {
5107 5154          show_vnic_state_t       *state = arg;
5108 5155  
5109 5156          state->vs_status = print_vnic(state, linkid);
5110 5157          return (DLADM_WALK_CONTINUE);
5111 5158  }
5112 5159  
5113 5160  static void
5114 5161  do_show_vnic_common(int argc, char *argv[], const char *use,
5115 5162      boolean_t etherstub)
5116 5163  {
5117 5164          int                     option;
5118 5165          boolean_t               s_arg = B_FALSE;
5119 5166          boolean_t               i_arg = B_FALSE;
5120 5167          boolean_t               l_arg = B_FALSE;
5121 5168          uint32_t                interval = 0, flags = DLADM_OPT_ACTIVE;
5122 5169          datalink_id_t           linkid = DATALINK_ALL_LINKID;
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
5123 5170          datalink_id_t           dev_linkid = DATALINK_ALL_LINKID;
5124 5171          show_vnic_state_t       state;
5125 5172          dladm_status_t          status;
5126 5173          boolean_t               o_arg = B_FALSE;
5127 5174          char                    *fields_str = NULL;
5128 5175          const ofmt_field_t      *pf;
5129 5176          char                    *all_e_fields = "link";
5130 5177          ofmt_handle_t           ofmt;
5131 5178          ofmt_status_t           oferr;
5132 5179          uint_t                  ofmtflags = 0;
     5180 +        char                    *zonename = NULL;
5133 5181  
5134 5182          bzero(&state, sizeof (state));
5135 5183          opterr = 0;
5136      -        while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts,
     5184 +        while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts,
5137 5185              NULL)) != -1) {
5138 5186                  switch (option) {
5139 5187                  case 'p':
5140 5188                          state.vs_parsable = B_TRUE;
5141 5189                          break;
5142 5190                  case 'P':
5143 5191                          flags = DLADM_OPT_PERSIST;
5144 5192                          break;
5145 5193                  case 'l':
5146 5194                          if (etherstub)
5147 5195                                  die("option not supported for this command");
5148 5196  
5149 5197                          if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >=
5150 5198                              MAXLINKNAMELEN)
5151 5199                                  die("link name too long");
5152 5200  
5153 5201                          l_arg = B_TRUE;
5154 5202                          break;
5155 5203                  case 's':
5156 5204                          if (s_arg) {
5157 5205                                  die("the option -s cannot be specified "
5158 5206                                      "more than once");
5159 5207                          }
5160 5208                          s_arg = B_TRUE;
5161 5209                          break;
5162 5210                  case 'i':
5163 5211                          if (i_arg) {
5164 5212                                  die("the option -i cannot be specified "
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
5165 5213                                      "more than once");
5166 5214                          }
5167 5215                          i_arg = B_TRUE;
5168 5216                          if (!dladm_str2interval(optarg, &interval))
5169 5217                                  die("invalid interval value '%s'", optarg);
5170 5218                          break;
5171 5219                  case 'o':
5172 5220                          o_arg = B_TRUE;
5173 5221                          fields_str = optarg;
5174 5222                          break;
     5223 +                case 'z':
     5224 +                        zonename = optarg;
     5225 +                        break;
5175 5226                  default:
5176 5227                          die_opterr(optopt, option, use);
5177 5228                  }
5178 5229          }
5179 5230  
5180 5231          if (i_arg && !s_arg)
5181 5232                  die("the option -i can be used only with -s");
5182 5233  
5183 5234          /* get vnic ID (optional last argument) */
5184 5235          if (optind == (argc - 1)) {
5185      -                status = dladm_name2info(handle, argv[optind], &linkid, NULL,
5186      -                    NULL, NULL);
     5236 +                status = dladm_zname2info(handle, zonename, argv[optind],
     5237 +                    &linkid, NULL, NULL, NULL);
5187 5238                  if (status != DLADM_STATUS_OK) {
5188 5239                          die_dlerr(status, "invalid vnic name '%s'",
5189 5240                              argv[optind]);
5190 5241                  }
5191 5242                  (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN);
5192 5243          } else if (optind != argc) {
5193 5244                  usage();
5194 5245          }
5195 5246  
5196 5247          if (l_arg) {
5197      -                status = dladm_name2info(handle, state.vs_link, &dev_linkid,
5198      -                    NULL, NULL, NULL);
     5248 +                status = dladm_zname2info(handle, zonename, state.vs_link,
     5249 +                    &dev_linkid, NULL, NULL, NULL);
5199 5250                  if (status != DLADM_STATUS_OK) {
5200 5251                          die_dlerr(status, "invalid link name '%s'",
5201 5252                              state.vs_link);
5202 5253                  }
5203 5254          }
5204 5255  
5205 5256          state.vs_vnic_id = linkid;
5206 5257          state.vs_link_id = dev_linkid;
5207 5258          state.vs_etherstub = etherstub;
5208 5259          state.vs_found = B_FALSE;
5209 5260          state.vs_flags = flags;
     5261 +        state.vs_zonename = zonename;
5210 5262  
5211 5263          if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
5212 5264                  if (etherstub)
5213 5265                          fields_str = all_e_fields;
5214 5266          }
5215 5267          pf = vnic_fields;
5216 5268  
5217 5269          if (state.vs_parsable)
5218 5270                  ofmtflags |= OFMT_PARSABLE;
5219 5271          oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
5220 5272          dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
5221 5273          state.vs_ofmt = ofmt;
5222 5274  
5223 5275          if (s_arg) {
5224 5276                  /* Display vnic statistics */
5225 5277                  vnic_stats(&state, interval);
5226 5278                  ofmt_close(ofmt);
5227 5279                  return;
5228 5280          }
5229 5281  
5230 5282          /* Display vnic information */
5231 5283          state.vs_donefirst = B_FALSE;
5232 5284  
5233 5285          if (linkid == DATALINK_ALL_LINKID) {
5234 5286                  (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5235 5287                      DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB,
5236 5288                      DATALINK_ANY_MEDIATYPE, flags);
5237 5289          } else {
5238 5290                  (void) show_vnic(handle, linkid, &state);
5239 5291                  if (state.vs_status != DLADM_STATUS_OK) {
5240 5292                          ofmt_close(ofmt);
5241 5293                          die_dlerr(state.vs_status, "failed to show vnic '%s'",
5242 5294                              state.vs_vnic);
5243 5295                  }
5244 5296          }
5245 5297          ofmt_close(ofmt);
5246 5298  }
5247 5299  
5248 5300  static void
5249 5301  do_show_vnic(int argc, char *argv[], const char *use)
5250 5302  {
5251 5303          do_show_vnic_common(argc, argv, use, B_FALSE);
5252 5304  }
5253 5305  
5254 5306  static void
5255 5307  do_create_etherstub(int argc, char *argv[], const char *use)
5256 5308  {
5257 5309          uint32_t flags;
5258 5310          char *altroot = NULL;
5259 5311          int option;
5260 5312          dladm_status_t status;
5261 5313          char name[MAXLINKNAMELEN];
5262 5314          uchar_t mac_addr[ETHERADDRL];
5263 5315  
5264 5316          name[0] = '\0';
5265 5317          bzero(mac_addr, sizeof (mac_addr));
5266 5318          flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5267 5319  
5268 5320          opterr = 0;
5269 5321          while ((option = getopt_long(argc, argv, "tR:",
5270 5322              etherstub_lopts, NULL)) != -1) {
5271 5323                  switch (option) {
5272 5324                  case 't':
5273 5325                          flags &= ~DLADM_OPT_PERSIST;
5274 5326                          break;
5275 5327                  case 'R':
5276 5328                          altroot = optarg;
5277 5329                          break;
5278 5330                  default:
5279 5331                          die_opterr(optopt, option, use);
5280 5332                  }
5281 5333          }
5282 5334  
5283 5335          /* the etherstub id is the required operand */
5284 5336          if (optind != (argc - 1))
5285 5337                  usage();
5286 5338  
5287 5339          if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
5288 5340                  die("link name too long '%s'", argv[optind]);
5289 5341  
5290 5342          if (!dladm_valid_linkname(name))
5291 5343                  die("invalid link name '%s'", argv[optind]);
5292 5344  
5293 5345          if (altroot != NULL)
5294 5346                  altroot_cmd(altroot, argc, argv);
5295 5347  
5296 5348          status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID,
5297 5349              VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0,
5298 5350              VRRP_VRID_NONE, AF_UNSPEC, NULL, NULL, flags);
5299 5351          if (status != DLADM_STATUS_OK)
5300 5352                  die_dlerr(status, "etherstub creation failed");
5301 5353  }
5302 5354  
5303 5355  static void
5304 5356  do_delete_etherstub(int argc, char *argv[], const char *use)
5305 5357  {
5306 5358          do_delete_vnic_common(argc, argv, use, B_TRUE);
5307 5359  }
5308 5360  
5309 5361  /* ARGSUSED */
5310 5362  static void
5311 5363  do_show_etherstub(int argc, char *argv[], const char *use)
5312 5364  {
5313 5365          do_show_vnic_common(argc, argv, use, B_TRUE);
5314 5366  }
5315 5367  
5316 5368  /* ARGSUSED */
5317 5369  static void
5318 5370  do_up_simnet(int argc, char *argv[], const char *use)
5319 5371  {
5320 5372          (void) dladm_simnet_up(handle, DATALINK_ALL_LINKID, 0);
5321 5373  }
5322 5374  
5323 5375  static void
5324 5376  do_create_simnet(int argc, char *argv[], const char *use)
5325 5377  {
5326 5378          uint32_t flags;
5327 5379          char *altroot = NULL;
5328 5380          char *media = NULL;
5329 5381          uint32_t mtype = DL_ETHER;
5330 5382          int option;
5331 5383          dladm_status_t status;
5332 5384          char name[MAXLINKNAMELEN];
5333 5385  
5334 5386          name[0] = '\0';
5335 5387          flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5336 5388  
5337 5389          opterr = 0;
5338 5390          while ((option = getopt_long(argc, argv, ":tR:m:",
5339 5391              simnet_lopts, NULL)) != -1) {
5340 5392                  switch (option) {
5341 5393                  case 't':
5342 5394                          flags &= ~DLADM_OPT_PERSIST;
5343 5395                          break;
5344 5396                  case 'R':
5345 5397                          altroot = optarg;
5346 5398                          break;
5347 5399                  case 'm':
5348 5400                          media = optarg;
5349 5401                          break;
5350 5402                  default:
5351 5403                          die_opterr(optopt, option, use);
5352 5404                  }
5353 5405          }
5354 5406  
5355 5407          /* the simnet id is the required operand */
5356 5408          if (optind != (argc - 1))
5357 5409                  usage();
5358 5410  
5359 5411          if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
5360 5412                  die("link name too long '%s'", argv[optind]);
5361 5413  
5362 5414          if (!dladm_valid_linkname(name))
5363 5415                  die("invalid link name '%s'", name);
5364 5416  
5365 5417          if (media != NULL) {
5366 5418                  mtype = dladm_str2media(media);
5367 5419                  if (mtype != DL_ETHER && mtype != DL_WIFI)
5368 5420                          die("media type '%s' is not supported", media);
5369 5421          }
5370 5422  
5371 5423          if (altroot != NULL)
5372 5424                  altroot_cmd(altroot, argc, argv);
5373 5425  
5374 5426          status = dladm_simnet_create(handle, name, mtype, flags);
5375 5427          if (status != DLADM_STATUS_OK)
5376 5428                  die_dlerr(status, "simnet creation failed");
5377 5429  }
5378 5430  
5379 5431  static void
5380 5432  do_delete_simnet(int argc, char *argv[], const char *use)
5381 5433  {
5382 5434          int option;
5383 5435          uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5384 5436          datalink_id_t linkid;
5385 5437          char *altroot = NULL;
5386 5438          dladm_status_t status;
5387 5439          dladm_simnet_attr_t slinfo;
5388 5440  
5389 5441          opterr = 0;
5390 5442          while ((option = getopt_long(argc, argv, ":tR:", simnet_lopts,
5391 5443              NULL)) != -1) {
5392 5444                  switch (option) {
5393 5445                  case 't':
5394 5446                          flags &= ~DLADM_OPT_PERSIST;
5395 5447                          break;
5396 5448                  case 'R':
5397 5449                          altroot = optarg;
5398 5450                          break;
5399 5451                  default:
5400 5452                          die_opterr(optopt, option, use);
5401 5453                  }
5402 5454          }
5403 5455  
5404 5456          /* get simnet name (required last argument) */
5405 5457          if (optind != (argc - 1))
5406 5458                  usage();
5407 5459  
5408 5460          if (!dladm_valid_linkname(argv[optind]))
5409 5461                  die("invalid link name '%s'", argv[optind]);
5410 5462  
5411 5463          if (altroot != NULL)
5412 5464                  altroot_cmd(altroot, argc, argv);
5413 5465  
5414 5466          status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
5415 5467              NULL);
5416 5468          if (status != DLADM_STATUS_OK)
5417 5469                  die("simnet '%s' not found", argv[optind]);
5418 5470  
5419 5471          if ((status = dladm_simnet_info(handle, linkid, &slinfo,
5420 5472              flags)) != DLADM_STATUS_OK)
5421 5473                  die_dlerr(status, "failed to retrieve simnet information");
5422 5474  
5423 5475          status = dladm_simnet_delete(handle, linkid, flags);
5424 5476          if (status != DLADM_STATUS_OK)
5425 5477                  die_dlerr(status, "simnet deletion failed");
5426 5478  }
5427 5479  
5428 5480  static void
5429 5481  do_modify_simnet(int argc, char *argv[], const char *use)
5430 5482  {
5431 5483          int option;
5432 5484          uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5433 5485          datalink_id_t linkid;
5434 5486          datalink_id_t peer_linkid;
5435 5487          char *altroot = NULL;
5436 5488          dladm_status_t status;
5437 5489          boolean_t p_arg = B_FALSE;
5438 5490  
5439 5491          opterr = 0;
5440 5492          while ((option = getopt_long(argc, argv, ":tR:p:", simnet_lopts,
5441 5493              NULL)) != -1) {
5442 5494                  switch (option) {
5443 5495                  case 't':
5444 5496                          flags &= ~DLADM_OPT_PERSIST;
5445 5497                          break;
5446 5498                  case 'R':
5447 5499                          altroot = optarg;
5448 5500                          break;
5449 5501                  case 'p':
5450 5502                          if (p_arg)
5451 5503                                  die_optdup(option);
5452 5504                          p_arg = B_TRUE;
5453 5505                          if (strcasecmp(optarg, "none") == 0)
5454 5506                                  peer_linkid = DATALINK_INVALID_LINKID;
5455 5507                          else if (dladm_name2info(handle, optarg, &peer_linkid,
5456 5508                              NULL, NULL, NULL) != DLADM_STATUS_OK)
5457 5509                                  die("invalid peer link name '%s'", optarg);
5458 5510                          break;
5459 5511                  default:
5460 5512                          die_opterr(optopt, option, use);
5461 5513                  }
5462 5514          }
5463 5515  
5464 5516          /* get simnet name (required last argument) */
5465 5517          if (optind != (argc - 1))
5466 5518                  usage();
5467 5519  
5468 5520          /* Nothing to do if no peer link argument */
5469 5521          if (!p_arg)
5470 5522                  return;
5471 5523  
5472 5524          if (altroot != NULL)
5473 5525                  altroot_cmd(altroot, argc, argv);
5474 5526  
5475 5527          status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
5476 5528              NULL);
5477 5529          if (status != DLADM_STATUS_OK)
5478 5530                  die("invalid link name '%s'", argv[optind]);
5479 5531  
5480 5532          status = dladm_simnet_modify(handle, linkid, peer_linkid, flags);
5481 5533          if (status != DLADM_STATUS_OK)
5482 5534                  die_dlerr(status, "simnet modification failed");
5483 5535  }
5484 5536  
5485 5537  static dladm_status_t
5486 5538  print_simnet(show_state_t *state, datalink_id_t linkid)
5487 5539  {
5488 5540          dladm_simnet_attr_t     slinfo;
5489 5541          uint32_t                flags;
5490 5542          dladm_status_t          status;
5491 5543          simnet_fields_buf_t     slbuf;
5492 5544          char                    mstr[ETHERADDRL * 3];
5493 5545  
5494 5546          bzero(&slbuf, sizeof (slbuf));
5495 5547          if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
5496 5548              slbuf.simnet_name, sizeof (slbuf.simnet_name)))
5497 5549              != DLADM_STATUS_OK)
5498 5550                  return (status);
5499 5551  
5500 5552          if (!(state->ls_flags & flags))
5501 5553                  return (DLADM_STATUS_NOTFOUND);
5502 5554  
5503 5555          if ((status = dladm_simnet_info(handle, linkid, &slinfo,
5504 5556              state->ls_flags)) != DLADM_STATUS_OK)
5505 5557                  return (status);
5506 5558  
5507 5559          if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID &&
5508 5560              (status = dladm_datalink_id2info(handle, slinfo.sna_peer_link_id,
5509 5561              NULL, NULL, NULL, slbuf.simnet_otherlink,
5510 5562              sizeof (slbuf.simnet_otherlink))) !=
5511 5563              DLADM_STATUS_OK)
5512 5564                  return (status);
5513 5565  
5514 5566          if (slinfo.sna_mac_len > sizeof (slbuf.simnet_macaddr))
5515 5567                  return (DLADM_STATUS_BADVAL);
5516 5568  
5517 5569          (void) strlcpy(slbuf.simnet_macaddr,
5518 5570              dladm_aggr_macaddr2str(slinfo.sna_mac_addr, mstr),
5519 5571              sizeof (slbuf.simnet_macaddr));
5520 5572          (void) dladm_media2str(slinfo.sna_type, slbuf.simnet_media);
5521 5573  
5522 5574          ofmt_print(state->ls_ofmt, &slbuf);
5523 5575          return (status);
5524 5576  }
5525 5577  
5526 5578  /* ARGSUSED */
5527 5579  static int
5528 5580  show_simnet(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5529 5581  {
5530 5582          show_state_t            *state = arg;
5531 5583  
5532 5584          state->ls_status = print_simnet(state, linkid);
5533 5585          return (DLADM_WALK_CONTINUE);
5534 5586  }
5535 5587  
5536 5588  static void
5537 5589  do_show_simnet(int argc, char *argv[], const char *use)
5538 5590  {
5539 5591          int             option;
5540 5592          uint32_t        flags = DLADM_OPT_ACTIVE;
5541 5593          boolean_t       p_arg = B_FALSE;
5542 5594          datalink_id_t   linkid = DATALINK_ALL_LINKID;
5543 5595          show_state_t    state;
5544 5596          dladm_status_t  status;
5545 5597          boolean_t       o_arg = B_FALSE;
5546 5598          ofmt_handle_t   ofmt;
5547 5599          ofmt_status_t   oferr;
5548 5600          char            *all_fields = "link,media,macaddress,otherlink";
5549 5601          char            *fields_str = all_fields;
5550 5602          uint_t          ofmtflags = 0;
5551 5603  
5552 5604          bzero(&state, sizeof (state));
5553 5605  
5554 5606          opterr = 0;
5555 5607          while ((option = getopt_long(argc, argv, ":pPo:",
5556 5608              show_lopts, NULL)) != -1) {
5557 5609                  switch (option) {
5558 5610                  case 'p':
5559 5611                          if (p_arg)
5560 5612                                  die_optdup(option);
5561 5613  
5562 5614                          p_arg = B_TRUE;
5563 5615                          state.ls_parsable = p_arg;
5564 5616                          break;
5565 5617                  case 'P':
5566 5618                          if (flags != DLADM_OPT_ACTIVE)
5567 5619                                  die_optdup(option);
5568 5620  
5569 5621                          flags = DLADM_OPT_PERSIST;
5570 5622                          break;
5571 5623                  case 'o':
5572 5624                          o_arg = B_TRUE;
5573 5625                          fields_str = optarg;
5574 5626                          break;
5575 5627                  default:
5576 5628                          die_opterr(optopt, option, use);
5577 5629                          break;
5578 5630                  }
5579 5631          }
5580 5632  
5581 5633          if (p_arg && !o_arg)
5582 5634                  die("-p requires -o");
5583 5635  
5584 5636          if (strcasecmp(fields_str, "all") == 0) {
5585 5637                  if (p_arg)
5586 5638                          die("\"-o all\" is invalid with -p");
5587 5639                  fields_str = all_fields;
5588 5640          }
5589 5641  
5590 5642          /* get link name (optional last argument) */
5591 5643          if (optind == (argc-1)) {
5592 5644                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
5593 5645                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5594 5646                          die_dlerr(status, "link %s is not valid", argv[optind]);
5595 5647                  }
5596 5648          } else if (optind != argc) {
5597 5649                  usage();
5598 5650          }
5599 5651  
5600 5652          state.ls_flags = flags;
5601 5653          state.ls_donefirst = B_FALSE;
5602 5654          if (state.ls_parsable)
5603 5655                  ofmtflags |= OFMT_PARSABLE;
5604 5656          oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt);
5605 5657          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
5606 5658          state.ls_ofmt = ofmt;
5607 5659  
5608 5660          if (linkid == DATALINK_ALL_LINKID) {
5609 5661                  (void) dladm_walk_datalink_id(show_simnet, handle, &state,
5610 5662                      DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE, flags);
5611 5663          } else {
5612 5664                  (void) show_simnet(handle, linkid, &state);
5613 5665                  if (state.ls_status != DLADM_STATUS_OK) {
5614 5666                          ofmt_close(ofmt);
5615 5667                          die_dlerr(state.ls_status, "failed to show simnet %s",
5616 5668                              argv[optind]);
5617 5669                  }
5618 5670          }
5619 5671          ofmt_close(ofmt);
5620 5672  }
5621 5673  
5622 5674  static void
5623 5675  link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
5624 5676      show_state_t *state)
5625 5677  {
5626 5678          ofmt_handle_t   ofmt;
5627 5679          ofmt_status_t   oferr;
5628 5680          uint_t          ofmtflags = 0;
5629 5681  
5630 5682          if (state->ls_parsable)
5631 5683                  ofmtflags |= OFMT_PARSABLE;
5632 5684          oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt);
5633 5685          dladm_ofmt_check(oferr, state->ls_parsable, ofmt);
5634 5686          state->ls_ofmt = ofmt;
5635 5687  
5636 5688          /*
5637 5689           * If an interval is specified, continuously show the stats
5638 5690           * only for the first MAC port.
5639 5691           */
5640 5692          state->ls_firstonly = (interval != 0);
5641 5693  
5642 5694          for (;;) {
5643 5695                  state->ls_donefirst = B_FALSE;
5644 5696                  if (linkid == DATALINK_ALL_LINKID) {
5645 5697                          (void) dladm_walk_datalink_id(show_link_stats, handle,
5646 5698                              state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
5647 5699                              DLADM_OPT_ACTIVE);
5648 5700                  } else {
5649 5701                          (void) show_link_stats(handle, linkid, state);
5650 5702                  }
5651 5703  
5652 5704                  if (interval == 0)
5653 5705                          break;
5654 5706  
5655 5707                  (void) fflush(stdout);
5656 5708                  (void) sleep(interval);
5657 5709          }
5658 5710          ofmt_close(ofmt);
5659 5711  }
5660 5712  
5661 5713  static void
5662 5714  aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
5663 5715  {
5664 5716          /*
5665 5717           * If an interval is specified, continuously show the stats
5666 5718           * only for the first group.
5667 5719           */
5668 5720          state->gs_firstonly = (interval != 0);
5669 5721  
5670 5722          for (;;) {
5671 5723                  state->gs_donefirst = B_FALSE;
5672 5724                  if (linkid == DATALINK_ALL_LINKID)
5673 5725                          (void) dladm_walk_datalink_id(show_aggr, handle, state,
5674 5726                              DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
5675 5727                              DLADM_OPT_ACTIVE);
5676 5728                  else
5677 5729                          (void) show_aggr(handle, linkid, state);
5678 5730  
5679 5731                  if (interval == 0)
5680 5732                          break;
5681 5733  
5682 5734                  (void) fflush(stdout);
5683 5735                  (void) sleep(interval);
5684 5736          }
5685 5737  }
5686 5738  
5687 5739  /* ARGSUSED */
5688 5740  static void
5689 5741  vnic_stats(show_vnic_state_t *sp, uint32_t interval)
5690 5742  {
5691 5743          show_vnic_state_t       state;
5692 5744          boolean_t               specific_link, specific_dev;
5693 5745  
5694 5746          /* Display vnic statistics */
5695 5747          dump_vnics_head(sp->vs_link);
5696 5748  
5697 5749          bzero(&state, sizeof (state));
5698 5750          state.vs_stats = B_TRUE;
5699 5751          state.vs_vnic_id = sp->vs_vnic_id;
5700 5752          state.vs_link_id = sp->vs_link_id;
5701 5753  
5702 5754          /*
5703 5755           * If an interval is specified, and a vnic ID is not specified,
5704 5756           * continuously show the stats only for the first vnic.
5705 5757           */
5706 5758          specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID);
5707 5759          specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID);
5708 5760  
5709 5761          for (;;) {
5710 5762                  /* Get stats for each vnic */
5711 5763                  state.vs_found = B_FALSE;
5712 5764                  state.vs_donefirst = B_FALSE;
5713 5765                  state.vs_printstats = B_FALSE;
5714 5766                  state.vs_flags = DLADM_OPT_ACTIVE;
5715 5767  
5716 5768                  if (!specific_link) {
5717 5769                          (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5718 5770                              DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
5719 5771                              DLADM_OPT_ACTIVE);
5720 5772                  } else {
5721 5773                          (void) show_vnic(handle, sp->vs_vnic_id, &state);
5722 5774                          if (state.vs_status != DLADM_STATUS_OK) {
5723 5775                                  die_dlerr(state.vs_status,
5724 5776                                      "failed to show vnic '%s'", sp->vs_vnic);
5725 5777                          }
5726 5778                  }
5727 5779  
5728 5780                  if (specific_link && !state.vs_found)
5729 5781                          die("non-existent vnic '%s'", sp->vs_vnic);
5730 5782                  if (specific_dev && !state.vs_found)
5731 5783                          die("device %s has no vnics", sp->vs_link);
5732 5784  
5733 5785                  /* Show totals */
5734 5786                  if ((specific_link | specific_dev) && !interval) {
5735 5787                          (void) printf("Total");
5736 5788                          (void) printf("\t%-10llu",
5737 5789                              state.vs_totalstats.ipackets);
5738 5790                          (void) printf("%-12llu",
5739 5791                              state.vs_totalstats.rbytes);
5740 5792                          (void) printf("%-10llu",
5741 5793                              state.vs_totalstats.opackets);
5742 5794                          (void) printf("%-12llu\n",
5743 5795                              state.vs_totalstats.obytes);
5744 5796                  }
5745 5797  
5746 5798                  /* Show stats for each vnic */
5747 5799                  state.vs_donefirst = B_FALSE;
5748 5800                  state.vs_printstats = B_TRUE;
5749 5801  
5750 5802                  if (!specific_link) {
5751 5803                          (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5752 5804                              DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
5753 5805                              DLADM_OPT_ACTIVE);
5754 5806                  } else {
5755 5807                          (void) show_vnic(handle, sp->vs_vnic_id, &state);
5756 5808                          if (state.vs_status != DLADM_STATUS_OK) {
5757 5809                                  die_dlerr(state.vs_status,
5758 5810                                      "failed to show vnic '%s'", sp->vs_vnic);
5759 5811                          }
5760 5812                  }
5761 5813  
5762 5814                  if (interval == 0)
5763 5815                          break;
5764 5816  
5765 5817                  (void) fflush(stdout);
5766 5818                  (void) sleep(interval);
5767 5819          }
5768 5820  }
5769 5821  
5770 5822  static void
5771 5823  get_mac_stats(const char *dev, pktsum_t *stats)
5772 5824  {
5773 5825          kstat_ctl_t     *kcp;
5774 5826          kstat_t         *ksp;
5775 5827          char module[DLPI_LINKNAME_MAX];
5776 5828          uint_t instance;
5777 5829  
5778 5830  
5779 5831          bzero(stats, sizeof (*stats));
5780 5832  
5781 5833          if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS)
5782 5834                  return;
5783 5835  
5784 5836          if ((kcp = kstat_open()) == NULL) {
5785 5837                  warn("kstat open operation failed");
5786 5838                  return;
5787 5839          }
5788 5840  
5789 5841          ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL);
5790 5842          if (ksp != NULL)
5791 5843                  dladm_get_stats(kcp, ksp, stats);
5792 5844  
5793 5845          (void) kstat_close(kcp);
5794 5846  
5795 5847  }
5796 5848  
5797 5849  static void
5798 5850  get_link_stats(const char *link, pktsum_t *stats)
5799 5851  {
5800 5852          kstat_ctl_t     *kcp;
5801 5853          kstat_t         *ksp;
5802 5854  
5803 5855          bzero(stats, sizeof (*stats));
5804 5856  
5805 5857          if ((kcp = kstat_open()) == NULL) {
5806 5858                  warn("kstat_open operation failed");
5807 5859                  return;
5808 5860          }
5809 5861  
5810 5862          ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL);
5811 5863  
5812 5864          if (ksp != NULL)
5813 5865                  dladm_get_stats(kcp, ksp, stats);
5814 5866  
5815 5867          (void) kstat_close(kcp);
5816 5868  }
5817 5869  
5818 5870  static int
5819 5871  query_kstat(char *module, int instance, const char *name, const char *stat,
5820 5872      uint8_t type, void *val)
5821 5873  {
5822 5874          kstat_ctl_t     *kcp;
5823 5875          kstat_t         *ksp;
5824 5876  
5825 5877          if ((kcp = kstat_open()) == NULL) {
5826 5878                  warn("kstat open operation failed");
5827 5879                  return (-1);
5828 5880          }
5829 5881  
5830 5882          if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) {
5831 5883                  /*
5832 5884                   * The kstat query could fail if the underlying MAC
5833 5885                   * driver was already detached.
5834 5886                   */
5835 5887                  goto bail;
5836 5888          }
5837 5889  
5838 5890          if (kstat_read(kcp, ksp, NULL) == -1) {
5839 5891                  warn("kstat read failed");
5840 5892                  goto bail;
5841 5893          }
5842 5894  
5843 5895          if (dladm_kstat_value(ksp, stat, type, val) < 0)
5844 5896                  goto bail;
5845 5897  
5846 5898          (void) kstat_close(kcp);
5847 5899          return (0);
5848 5900  
5849 5901  bail:
5850 5902          (void) kstat_close(kcp);
5851 5903          return (-1);
5852 5904  }
5853 5905  
5854 5906  static int
5855 5907  get_one_kstat(const char *name, const char *stat, uint8_t type,
5856 5908      void *val, boolean_t islink)
5857 5909  {
5858 5910          char            module[DLPI_LINKNAME_MAX];
5859 5911          uint_t          instance;
5860 5912  
5861 5913          if (islink) {
5862 5914                  return (query_kstat("link", 0, name, stat, type, val));
5863 5915          } else {
5864 5916                  if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS)
5865 5917                          return (-1);
5866 5918  
5867 5919                  return (query_kstat(module, instance, "mac", stat, type, val));
5868 5920          }
5869 5921  }
5870 5922  
5871 5923  static uint64_t
5872 5924  get_ifspeed(const char *name, boolean_t islink)
5873 5925  {
5874 5926          uint64_t ifspeed = 0;
5875 5927  
5876 5928          (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64,
5877 5929              &ifspeed, islink);
5878 5930  
5879 5931          return (ifspeed);
5880 5932  }
5881 5933  
5882 5934  static const char *
5883 5935  get_linkstate(const char *name, boolean_t islink, char *buf)
5884 5936  {
5885 5937          link_state_t    linkstate;
5886 5938  
5887 5939          if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32,
5888 5940              &linkstate, islink) != 0) {
5889 5941                  (void) strlcpy(buf, "?", DLADM_STRSIZE);
5890 5942                  return (buf);
5891 5943          }
5892 5944          return (dladm_linkstate2str(linkstate, buf));
5893 5945  }
5894 5946  
5895 5947  static const char *
5896 5948  get_linkduplex(const char *name, boolean_t islink, char *buf)
5897 5949  {
5898 5950          link_duplex_t   linkduplex;
5899 5951  
5900 5952          if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32,
5901 5953              &linkduplex, islink) != 0) {
5902 5954                  (void) strlcpy(buf, "unknown", DLADM_STRSIZE);
5903 5955                  return (buf);
5904 5956          }
5905 5957  
5906 5958          return (dladm_linkduplex2str(linkduplex, buf));
5907 5959  }
5908 5960  
5909 5961  static int
5910 5962  parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype,
5911 5963      boolean_t parsable)
5912 5964  {
5913 5965          ofmt_field_t    *template, *of;
5914 5966          ofmt_cb_t       *fn;
5915 5967          ofmt_status_t   oferr;
5916 5968  
5917 5969          if (cmdtype == WIFI_CMD_SCAN) {
5918 5970                  template = wifi_common_fields;
5919 5971                  if (str == NULL)
5920 5972                          str = def_scan_wifi_fields;
5921 5973                  if (strcasecmp(str, "all") == 0)
5922 5974                          str = all_scan_wifi_fields;
5923 5975                  fn = print_wlan_attr_cb;
5924 5976          } else if (cmdtype == WIFI_CMD_SHOW) {
5925 5977                  bcopy(wifi_common_fields, &wifi_show_fields[2],
5926 5978                      sizeof (wifi_common_fields));
5927 5979                  template = wifi_show_fields;
5928 5980                  if (str == NULL)
5929 5981                          str = def_show_wifi_fields;
5930 5982                  if (strcasecmp(str, "all") == 0)
5931 5983                          str = all_show_wifi_fields;
5932 5984                  fn = print_link_attr_cb;
5933 5985          } else {
5934 5986                  return (-1);
5935 5987          }
5936 5988  
5937 5989          for (of = template; of->of_name != NULL; of++) {
5938 5990                  if (of->of_cb == NULL)
5939 5991                          of->of_cb = fn;
5940 5992          }
5941 5993  
5942 5994          oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0),
5943 5995              0, ofmt);
5944 5996          dladm_ofmt_check(oferr, parsable, *ofmt);
5945 5997          return (0);
5946 5998  }
5947 5999  
5948 6000  typedef struct print_wifi_state {
5949 6001          char            *ws_link;
5950 6002          boolean_t       ws_parsable;
5951 6003          boolean_t       ws_header;
5952 6004          ofmt_handle_t   ws_ofmt;
5953 6005  } print_wifi_state_t;
5954 6006  
5955 6007  typedef struct  wlan_scan_args_s {
5956 6008          print_wifi_state_t      *ws_state;
5957 6009          void                    *ws_attr;
5958 6010  } wlan_scan_args_t;
5959 6011  
5960 6012  static boolean_t
5961 6013  print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
5962 6014  {
5963 6015          wlan_scan_args_t        *w = ofarg->ofmt_cbarg;
5964 6016          print_wifi_state_t      *statep = w->ws_state;
5965 6017          dladm_wlan_attr_t       *attrp = w->ws_attr;
5966 6018          char                    tmpbuf[DLADM_STRSIZE];
5967 6019  
5968 6020          if (ofarg->ofmt_id == 0) {
5969 6021                  (void) strlcpy(buf, (char *)statep->ws_link, bufsize);
5970 6022                  return (B_TRUE);
5971 6023          }
5972 6024  
5973 6025          if ((ofarg->ofmt_id & attrp->wa_valid) == 0)
5974 6026                  return (B_TRUE);
5975 6027  
5976 6028          switch (ofarg->ofmt_id) {
5977 6029          case DLADM_WLAN_ATTR_ESSID:
5978 6030                  (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf);
5979 6031                  break;
5980 6032          case DLADM_WLAN_ATTR_BSSID:
5981 6033                  (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf);
5982 6034                  break;
5983 6035          case DLADM_WLAN_ATTR_SECMODE:
5984 6036                  (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf);
5985 6037                  break;
5986 6038          case DLADM_WLAN_ATTR_STRENGTH:
5987 6039                  (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf);
5988 6040                  break;
5989 6041          case DLADM_WLAN_ATTR_MODE:
5990 6042                  (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf);
5991 6043                  break;
5992 6044          case DLADM_WLAN_ATTR_SPEED:
5993 6045                  (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf);
5994 6046                  (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf));
5995 6047                  break;
5996 6048          case DLADM_WLAN_ATTR_AUTH:
5997 6049                  (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf);
5998 6050                  break;
5999 6051          case DLADM_WLAN_ATTR_BSSTYPE:
6000 6052                  (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf);
6001 6053                  break;
6002 6054          }
6003 6055          (void) strlcpy(buf, tmpbuf, bufsize);
6004 6056  
6005 6057          return (B_TRUE);
6006 6058  }
6007 6059  
6008 6060  static boolean_t
6009 6061  print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
6010 6062  {
6011 6063          print_wifi_state_t      *statep = arg;
6012 6064          wlan_scan_args_t        warg;
6013 6065  
6014 6066          bzero(&warg, sizeof (warg));
6015 6067          warg.ws_state = statep;
6016 6068          warg.ws_attr = attrp;
6017 6069          ofmt_print(statep->ws_ofmt, &warg);
6018 6070          return (B_TRUE);
6019 6071  }
6020 6072  
6021 6073  static int
6022 6074  scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6023 6075  {
6024 6076          print_wifi_state_t      *statep = arg;
6025 6077          dladm_status_t          status;
6026 6078          char                    link[MAXLINKNAMELEN];
6027 6079  
6028 6080          if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
6029 6081              sizeof (link))) != DLADM_STATUS_OK) {
6030 6082                  return (DLADM_WALK_CONTINUE);
6031 6083          }
6032 6084  
6033 6085          statep->ws_link = link;
6034 6086          status = dladm_wlan_scan(dh, linkid, statep, print_scan_results);
6035 6087          if (status != DLADM_STATUS_OK)
6036 6088                  die_dlerr(status, "cannot scan link '%s'", statep->ws_link);
6037 6089  
6038 6090          return (DLADM_WALK_CONTINUE);
6039 6091  }
6040 6092  
6041 6093  static boolean_t
6042 6094  print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6043 6095  {
6044 6096          static char             tmpbuf[DLADM_STRSIZE];
6045 6097          wlan_scan_args_t        *w = ofarg->ofmt_cbarg;
6046 6098          dladm_wlan_linkattr_t   *attrp = w->ws_attr;
6047 6099  
6048 6100          if ((ofarg->ofmt_id & attrp->la_valid) != 0) {
6049 6101                  (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf);
6050 6102                  (void) strlcpy(buf, tmpbuf, bufsize);
6051 6103          }
6052 6104          return (B_TRUE);
6053 6105  }
6054 6106  
6055 6107  static boolean_t
6056 6108  print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6057 6109  {
6058 6110          wlan_scan_args_t        *w = ofarg->ofmt_cbarg, w1;
6059 6111          print_wifi_state_t      *statep = w->ws_state;
6060 6112          dladm_wlan_linkattr_t   *attrp = w->ws_attr;
6061 6113  
6062 6114          bzero(&w1, sizeof (w1));
6063 6115          w1.ws_state = statep;
6064 6116          w1.ws_attr = &attrp->la_wlan_attr;
6065 6117          ofarg->ofmt_cbarg = &w1;
6066 6118          return (print_wlan_attr_cb(ofarg, buf, bufsize));
6067 6119  }
6068 6120  
6069 6121  static int
6070 6122  show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6071 6123  {
6072 6124          print_wifi_state_t      *statep = arg;
6073 6125          dladm_wlan_linkattr_t   attr;
6074 6126          dladm_status_t          status;
6075 6127          char                    link[MAXLINKNAMELEN];
6076 6128          wlan_scan_args_t        warg;
6077 6129  
6078 6130          if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
6079 6131              sizeof (link))) != DLADM_STATUS_OK) {
6080 6132                  return (DLADM_WALK_CONTINUE);
6081 6133          }
6082 6134  
6083 6135          /* dladm_wlan_get_linkattr() memsets attr with 0 */
6084 6136          status = dladm_wlan_get_linkattr(dh, linkid, &attr);
6085 6137          if (status != DLADM_STATUS_OK)
6086 6138                  die_dlerr(status, "cannot get link attributes for %s", link);
6087 6139  
6088 6140          statep->ws_link = link;
6089 6141  
6090 6142          bzero(&warg, sizeof (warg));
6091 6143          warg.ws_state = statep;
6092 6144          warg.ws_attr = &attr;
6093 6145          ofmt_print(statep->ws_ofmt, &warg);
6094 6146          return (DLADM_WALK_CONTINUE);
6095 6147  }
6096 6148  
6097 6149  static void
6098 6150  do_display_wifi(int argc, char **argv, int cmd, const char *use)
6099 6151  {
6100 6152          int                     option;
6101 6153          char                    *fields_str = NULL;
6102 6154          int             (*callback)(dladm_handle_t, datalink_id_t, void *);
6103 6155          print_wifi_state_t      state;
6104 6156          datalink_id_t           linkid = DATALINK_ALL_LINKID;
6105 6157          dladm_status_t          status;
6106 6158  
6107 6159          if (cmd == WIFI_CMD_SCAN)
6108 6160                  callback = scan_wifi;
6109 6161          else if (cmd == WIFI_CMD_SHOW)
6110 6162                  callback = show_wifi;
6111 6163          else
6112 6164                  return;
6113 6165  
6114 6166          state.ws_parsable = B_FALSE;
6115 6167          state.ws_header = B_TRUE;
6116 6168          opterr = 0;
6117 6169          while ((option = getopt_long(argc, argv, ":o:p",
6118 6170              wifi_longopts, NULL)) != -1) {
6119 6171                  switch (option) {
6120 6172                  case 'o':
6121 6173                          fields_str = optarg;
6122 6174                          break;
6123 6175                  case 'p':
6124 6176                          state.ws_parsable = B_TRUE;
6125 6177                          break;
6126 6178                  default:
6127 6179                          die_opterr(optopt, option, use);
6128 6180                  }
6129 6181          }
6130 6182  
6131 6183          if (state.ws_parsable && fields_str == NULL)
6132 6184                  die("-p requires -o");
6133 6185  
6134 6186          if (state.ws_parsable && strcasecmp(fields_str, "all") == 0)
6135 6187                  die("\"-o all\" is invalid with -p");
6136 6188  
6137 6189          if (optind == (argc - 1)) {
6138 6190                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
6139 6191                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6140 6192                          die_dlerr(status, "link %s is not valid", argv[optind]);
6141 6193                  }
6142 6194          } else if (optind != argc) {
6143 6195                  usage();
6144 6196          }
6145 6197  
6146 6198          if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd,
6147 6199              state.ws_parsable) < 0)
6148 6200                  die("invalid field(s) specified");
6149 6201  
6150 6202          if (linkid == DATALINK_ALL_LINKID) {
6151 6203                  (void) dladm_walk_datalink_id(callback, handle, &state,
6152 6204                      DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6153 6205                      DL_WIFI, DLADM_OPT_ACTIVE);
6154 6206          } else {
6155 6207                  (void) (*callback)(handle, linkid, &state);
6156 6208          }
6157 6209          ofmt_close(state.ws_ofmt);
6158 6210  }
6159 6211  
6160 6212  static void
6161 6213  do_scan_wifi(int argc, char **argv, const char *use)
6162 6214  {
6163 6215          do_display_wifi(argc, argv, WIFI_CMD_SCAN, use);
6164 6216  }
6165 6217  
6166 6218  static void
6167 6219  do_show_wifi(int argc, char **argv, const char *use)
6168 6220  {
6169 6221          do_display_wifi(argc, argv, WIFI_CMD_SHOW, use);
6170 6222  }
6171 6223  
6172 6224  typedef struct wlan_count_attr {
6173 6225          uint_t          wc_count;
6174 6226          datalink_id_t   wc_linkid;
6175 6227  } wlan_count_attr_t;
6176 6228  
6177 6229  /* ARGSUSED */
6178 6230  static int
6179 6231  do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6180 6232  {
6181 6233          wlan_count_attr_t *cp = arg;
6182 6234  
6183 6235          if (cp->wc_count == 0)
6184 6236                  cp->wc_linkid = linkid;
6185 6237          cp->wc_count++;
6186 6238          return (DLADM_WALK_CONTINUE);
6187 6239  }
6188 6240  
6189 6241  static int
6190 6242  parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp)
6191 6243  {
6192 6244          uint_t                  i;
6193 6245          dladm_wlan_key_t        *wk;
6194 6246          int                     nfields = 1;
6195 6247          char                    *field, *token, *lasts = NULL, c;
6196 6248  
6197 6249          token = str;
6198 6250          while ((c = *token++) != NULL) {
6199 6251                  if (c == ',')
6200 6252                          nfields++;
6201 6253          }
6202 6254          token = strdup(str);
6203 6255          if (token == NULL)
6204 6256                  return (-1);
6205 6257  
6206 6258          wk = malloc(nfields * sizeof (dladm_wlan_key_t));
6207 6259          if (wk == NULL)
6208 6260                  goto fail;
6209 6261  
6210 6262          token = str;
6211 6263          for (i = 0; i < nfields; i++) {
6212 6264                  char                    *s;
6213 6265                  dladm_secobj_class_t    class;
6214 6266                  dladm_status_t          status;
6215 6267  
6216 6268                  field = strtok_r(token, ",", &lasts);
6217 6269                  token = NULL;
6218 6270  
6219 6271                  (void) strlcpy(wk[i].wk_name, field,
6220 6272                      DLADM_WLAN_MAX_KEYNAME_LEN);
6221 6273  
6222 6274                  wk[i].wk_idx = 1;
6223 6275                  if ((s = strrchr(wk[i].wk_name, ':')) != NULL) {
6224 6276                          if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1]))
6225 6277                                  goto fail;
6226 6278  
6227 6279                          wk[i].wk_idx = (uint_t)(s[1] - '0');
6228 6280                          *s = '\0';
6229 6281                  }
6230 6282                  wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN;
6231 6283  
6232 6284                  status = dladm_get_secobj(handle, wk[i].wk_name, &class,
6233 6285                      wk[i].wk_val, &wk[i].wk_len, 0);
6234 6286                  if (status != DLADM_STATUS_OK) {
6235 6287                          if (status == DLADM_STATUS_NOTFOUND) {
6236 6288                                  status = dladm_get_secobj(handle, wk[i].wk_name,
6237 6289                                      &class, wk[i].wk_val, &wk[i].wk_len,
6238 6290                                      DLADM_OPT_PERSIST);
6239 6291                          }
6240 6292                          if (status != DLADM_STATUS_OK)
6241 6293                                  goto fail;
6242 6294                  }
6243 6295                  wk[i].wk_class = class;
6244 6296          }
6245 6297          *keys = wk;
6246 6298          *key_countp = i;
6247 6299          free(token);
6248 6300          return (0);
6249 6301  fail:
6250 6302          free(wk);
6251 6303          free(token);
6252 6304          return (-1);
6253 6305  }
6254 6306  
6255 6307  static void
6256 6308  do_connect_wifi(int argc, char **argv, const char *use)
6257 6309  {
6258 6310          int                     option;
6259 6311          dladm_wlan_attr_t       attr, *attrp;
6260 6312          dladm_status_t          status = DLADM_STATUS_OK;
6261 6313          int                     timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT;
6262 6314          datalink_id_t           linkid = DATALINK_ALL_LINKID;
6263 6315          dladm_wlan_key_t        *keys = NULL;
6264 6316          uint_t                  key_count = 0;
6265 6317          uint_t                  flags = 0;
6266 6318          dladm_wlan_secmode_t    keysecmode = DLADM_WLAN_SECMODE_NONE;
6267 6319          char                    buf[DLADM_STRSIZE];
6268 6320  
6269 6321          opterr = 0;
6270 6322          (void) memset(&attr, 0, sizeof (attr));
6271 6323          while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c",
6272 6324              wifi_longopts, NULL)) != -1) {
6273 6325                  switch (option) {
6274 6326                  case 'e':
6275 6327                          status = dladm_wlan_str2essid(optarg, &attr.wa_essid);
6276 6328                          if (status != DLADM_STATUS_OK)
6277 6329                                  die("invalid ESSID '%s'", optarg);
6278 6330  
6279 6331                          attr.wa_valid |= DLADM_WLAN_ATTR_ESSID;
6280 6332                          /*
6281 6333                           * Try to connect without doing a scan.
6282 6334                           */
6283 6335                          flags |= DLADM_WLAN_CONNECT_NOSCAN;
6284 6336                          break;
6285 6337                  case 'i':
6286 6338                          status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid);
6287 6339                          if (status != DLADM_STATUS_OK)
6288 6340                                  die("invalid BSSID %s", optarg);
6289 6341  
6290 6342                          attr.wa_valid |= DLADM_WLAN_ATTR_BSSID;
6291 6343                          break;
6292 6344                  case 'a':
6293 6345                          status = dladm_wlan_str2auth(optarg, &attr.wa_auth);
6294 6346                          if (status != DLADM_STATUS_OK)
6295 6347                                  die("invalid authentication mode '%s'", optarg);
6296 6348  
6297 6349                          attr.wa_valid |= DLADM_WLAN_ATTR_AUTH;
6298 6350                          break;
6299 6351                  case 'm':
6300 6352                          status = dladm_wlan_str2mode(optarg, &attr.wa_mode);
6301 6353                          if (status != DLADM_STATUS_OK)
6302 6354                                  die("invalid mode '%s'", optarg);
6303 6355  
6304 6356                          attr.wa_valid |= DLADM_WLAN_ATTR_MODE;
6305 6357                          break;
6306 6358                  case 'b':
6307 6359                          if ((status = dladm_wlan_str2bsstype(optarg,
6308 6360                              &attr.wa_bsstype)) != DLADM_STATUS_OK) {
6309 6361                                  die("invalid bsstype '%s'", optarg);
6310 6362                          }
6311 6363  
6312 6364                          attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
6313 6365                          break;
6314 6366                  case 's':
6315 6367                          if ((status = dladm_wlan_str2secmode(optarg,
6316 6368                              &attr.wa_secmode)) != DLADM_STATUS_OK) {
6317 6369                                  die("invalid security mode '%s'", optarg);
6318 6370                          }
6319 6371  
6320 6372                          attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
6321 6373                          break;
6322 6374                  case 'k':
6323 6375                          if (parse_wlan_keys(optarg, &keys, &key_count) < 0)
6324 6376                                  die("invalid key(s) '%s'", optarg);
6325 6377  
6326 6378                          if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP)
6327 6379                                  keysecmode = DLADM_WLAN_SECMODE_WEP;
6328 6380                          else
6329 6381                                  keysecmode = DLADM_WLAN_SECMODE_WPA;
6330 6382                          break;
6331 6383                  case 'T':
6332 6384                          if (strcasecmp(optarg, "forever") == 0) {
6333 6385                                  timeout = -1;
6334 6386                                  break;
6335 6387                          }
6336 6388                          if (!str2int(optarg, &timeout) || timeout < 0)
6337 6389                                  die("invalid timeout value '%s'", optarg);
6338 6390                          break;
6339 6391                  case 'c':
6340 6392                          flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
6341 6393                          flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
6342 6394                          break;
6343 6395                  default:
6344 6396                          die_opterr(optopt, option, use);
6345 6397                          break;
6346 6398                  }
6347 6399          }
6348 6400  
6349 6401          if (keysecmode == DLADM_WLAN_SECMODE_NONE) {
6350 6402                  if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) {
6351 6403                          die("key required for security mode '%s'",
6352 6404                              dladm_wlan_secmode2str(&attr.wa_secmode, buf));
6353 6405                  }
6354 6406          } else {
6355 6407                  if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
6356 6408                      attr.wa_secmode != keysecmode)
6357 6409                          die("incompatible -s and -k options");
6358 6410                  attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
6359 6411                  attr.wa_secmode = keysecmode;
6360 6412          }
6361 6413  
6362 6414          if (optind == (argc - 1)) {
6363 6415                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
6364 6416                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6365 6417                          die_dlerr(status, "link %s is not valid", argv[optind]);
6366 6418                  }
6367 6419          } else if (optind != argc) {
6368 6420                  usage();
6369 6421          }
6370 6422  
6371 6423          if (linkid == DATALINK_ALL_LINKID) {
6372 6424                  wlan_count_attr_t wcattr;
6373 6425  
6374 6426                  wcattr.wc_linkid = DATALINK_INVALID_LINKID;
6375 6427                  wcattr.wc_count = 0;
6376 6428                  (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr,
6377 6429                      DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6378 6430                      DL_WIFI, DLADM_OPT_ACTIVE);
6379 6431                  if (wcattr.wc_count == 0) {
6380 6432                          die("no wifi links are available");
6381 6433                  } else if (wcattr.wc_count > 1) {
6382 6434                          die("link name is required when more than one wifi "
6383 6435                              "link is available");
6384 6436                  }
6385 6437                  linkid = wcattr.wc_linkid;
6386 6438          }
6387 6439          attrp = (attr.wa_valid == 0) ? NULL : &attr;
6388 6440  again:
6389 6441          if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys,
6390 6442              key_count, flags)) != DLADM_STATUS_OK) {
6391 6443                  if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) {
6392 6444                          /*
6393 6445                           * Try again with scanning and filtering.
6394 6446                           */
6395 6447                          flags &= ~DLADM_WLAN_CONNECT_NOSCAN;
6396 6448                          goto again;
6397 6449                  }
6398 6450  
6399 6451                  if (status == DLADM_STATUS_NOTFOUND) {
6400 6452                          if (attr.wa_valid == 0) {
6401 6453                                  die("no wifi networks are available");
6402 6454                          } else {
6403 6455                                  die("no wifi networks with the specified "
6404 6456                                      "criteria are available");
6405 6457                          }
6406 6458                  }
6407 6459                  die_dlerr(status, "cannot connect");
6408 6460          }
6409 6461          free(keys);
6410 6462  }
6411 6463  
6412 6464  /* ARGSUSED */
6413 6465  static int
6414 6466  do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6415 6467  {
6416 6468          dladm_status_t  status;
6417 6469  
6418 6470          status = dladm_wlan_disconnect(dh, linkid);
6419 6471          if (status != DLADM_STATUS_OK)
6420 6472                  warn_dlerr(status, "cannot disconnect link");
6421 6473  
6422 6474          return (DLADM_WALK_CONTINUE);
6423 6475  }
6424 6476  
6425 6477  static void
6426 6478  do_disconnect_wifi(int argc, char **argv, const char *use)
6427 6479  {
6428 6480          int                     option;
6429 6481          datalink_id_t           linkid = DATALINK_ALL_LINKID;
6430 6482          boolean_t               all_links = B_FALSE;
6431 6483          dladm_status_t          status;
6432 6484          wlan_count_attr_t       wcattr;
6433 6485  
6434 6486          opterr = 0;
6435 6487          while ((option = getopt_long(argc, argv, ":a",
6436 6488              wifi_longopts, NULL)) != -1) {
6437 6489                  switch (option) {
6438 6490                  case 'a':
6439 6491                          all_links = B_TRUE;
6440 6492                          break;
6441 6493                  default:
6442 6494                          die_opterr(optopt, option, use);
6443 6495                          break;
6444 6496                  }
6445 6497          }
6446 6498  
6447 6499          if (optind == (argc - 1)) {
6448 6500                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
6449 6501                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6450 6502                          die_dlerr(status, "link %s is not valid", argv[optind]);
6451 6503                  }
6452 6504          } else if (optind != argc) {
6453 6505                  usage();
6454 6506          }
6455 6507  
6456 6508          if (linkid == DATALINK_ALL_LINKID) {
6457 6509                  if (!all_links) {
6458 6510                          wcattr.wc_linkid = linkid;
6459 6511                          wcattr.wc_count = 0;
6460 6512                          (void) dladm_walk_datalink_id(do_count_wlan, handle,
6461 6513                              &wcattr,
6462 6514                              DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6463 6515                              DL_WIFI, DLADM_OPT_ACTIVE);
6464 6516                          if (wcattr.wc_count == 0) {
6465 6517                                  die("no wifi links are available");
6466 6518                          } else if (wcattr.wc_count > 1) {
6467 6519                                  die("link name is required when more than "
6468 6520                                      "one wifi link is available");
6469 6521                          }
6470 6522                          linkid = wcattr.wc_linkid;
6471 6523                  } else {
6472 6524                          (void) dladm_walk_datalink_id(do_all_disconnect_wifi,
6473 6525                              handle, NULL,
6474 6526                              DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6475 6527                              DL_WIFI, DLADM_OPT_ACTIVE);
6476 6528                          return;
6477 6529                  }
6478 6530          }
6479 6531          status = dladm_wlan_disconnect(handle, linkid);
6480 6532          if (status != DLADM_STATUS_OK)
6481 6533                  die_dlerr(status, "cannot disconnect");
6482 6534  }
6483 6535  
6484 6536  static void
6485 6537  print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
6486 6538      const char *propname, dladm_prop_type_t type, const char *format,
6487 6539      char **pptr)
6488 6540  {
6489 6541          int             i;
6490 6542          char            *ptr, *lim;
6491 6543          char            buf[DLADM_STRSIZE];
6492 6544          char            *unknown = "--", *notsup = "";
6493 6545          char            **propvals = statep->ls_propvals;
6494 6546          uint_t          valcnt = DLADM_MAX_PROP_VALCNT;
6495 6547          dladm_status_t  status;
6496 6548  
6497 6549          status = dladm_get_linkprop(handle, linkid, type, propname, propvals,
6498 6550              &valcnt);
6499 6551          if (status != DLADM_STATUS_OK) {
6500 6552                  if (status == DLADM_STATUS_TEMPONLY) {
6501 6553                          if (type == DLADM_PROP_VAL_MODIFIABLE &&
6502 6554                              statep->ls_persist) {
6503 6555                                  valcnt = 1;
6504 6556                                  propvals = &unknown;
6505 6557                          } else {
6506 6558                                  statep->ls_status = status;
6507 6559                                  statep->ls_retstatus = status;
6508 6560                                  return;
6509 6561                          }
6510 6562                  } else if (status == DLADM_STATUS_NOTSUP ||
6511 6563                      statep->ls_persist) {
6512 6564                          valcnt = 1;
6513 6565                          if (type == DLADM_PROP_VAL_CURRENT ||
6514 6566                              type == DLADM_PROP_VAL_PERM)
6515 6567                                  propvals = &unknown;
6516 6568                          else
6517 6569                                  propvals = ¬sup;
6518 6570                  } else if (status == DLADM_STATUS_NOTDEFINED) {
6519 6571                          propvals = ¬sup; /* STR_UNDEF_VAL */
6520 6572                  } else {
6521 6573                          if (statep->ls_proplist &&
6522 6574                              statep->ls_status == DLADM_STATUS_OK) {
6523 6575                                  warn_dlerr(status,
6524 6576                                      "cannot get link property '%s' for %s",
6525 6577                                      propname, statep->ls_link);
6526 6578                          }
6527 6579                          statep->ls_status = status;
6528 6580                          statep->ls_retstatus = status;
6529 6581                          return;
6530 6582                  }
6531 6583          }
6532 6584  
6533 6585          statep->ls_status = DLADM_STATUS_OK;
6534 6586  
6535 6587          buf[0] = '\0';
6536 6588          ptr = buf;
6537 6589          lim = buf + DLADM_STRSIZE;
6538 6590          for (i = 0; i < valcnt; i++) {
6539 6591                  if (propvals[i][0] == '\0' && !statep->ls_parsable)
6540 6592                          ptr += snprintf(ptr, lim - ptr, "--,");
6541 6593                  else
6542 6594                          ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
6543 6595                  if (ptr >= lim)
6544 6596                          break;
6545 6597          }
6546 6598          if (valcnt > 0)
6547 6599                  buf[strlen(buf) - 1] = '\0';
6548 6600  
6549 6601          lim = statep->ls_line + MAX_PROP_LINE;
6550 6602          if (statep->ls_parsable) {
6551 6603                  *pptr += snprintf(*pptr, lim - *pptr,
6552 6604                      "%s", buf);
6553 6605          } else {
6554 6606                  *pptr += snprintf(*pptr, lim - *pptr, format, buf);
6555 6607          }
6556 6608  }
6557 6609  
6558 6610  static boolean_t
6559 6611  print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6560 6612  {
6561 6613          linkprop_args_t         *arg = ofarg->ofmt_cbarg;
6562 6614          char                    *propname = arg->ls_propname;
6563 6615          show_linkprop_state_t   *statep = arg->ls_state;
6564 6616          char                    *ptr = statep->ls_line;
6565 6617          char                    *lim = ptr + MAX_PROP_LINE;
6566 6618          datalink_id_t           linkid = arg->ls_linkid;
6567 6619  
6568 6620          switch (ofarg->ofmt_id) {
6569 6621          case LINKPROP_LINK:
6570 6622                  (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link);
6571 6623                  break;
6572 6624          case LINKPROP_PROPERTY:
6573 6625                  (void) snprintf(ptr, lim - ptr, "%s", propname);
6574 6626                  break;
6575 6627          case LINKPROP_VALUE:
6576 6628                  print_linkprop(linkid, statep, propname,
6577 6629                      statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
6578 6630                      DLADM_PROP_VAL_CURRENT, "%s", &ptr);
6579 6631                  /*
6580 6632                   * If we failed to query the link property, for example, query
6581 6633                   * the persistent value of a non-persistable link property,
6582 6634                   * simply skip the output.
6583 6635                   */
6584 6636                  if (statep->ls_status != DLADM_STATUS_OK) {
6585 6637                          /*
6586 6638                           * Ignore the temponly error when we skip printing
6587 6639                           * link properties to avoid returning failure on exit.
6588 6640                           */
6589 6641                          if (statep->ls_retstatus == DLADM_STATUS_TEMPONLY)
6590 6642                                  statep->ls_retstatus = DLADM_STATUS_OK;
6591 6643                          goto skip;
6592 6644                  }
6593 6645                  ptr = statep->ls_line;
6594 6646                  break;
6595 6647          case LINKPROP_PERM:
6596 6648                  print_linkprop(linkid, statep, propname,
6597 6649                      DLADM_PROP_VAL_PERM, "%s", &ptr);
6598 6650                  if (statep->ls_status != DLADM_STATUS_OK)
6599 6651                          goto skip;
6600 6652                  ptr = statep->ls_line;
6601 6653                  break;
6602 6654          case LINKPROP_DEFAULT:
6603 6655                  print_linkprop(linkid, statep, propname,
6604 6656                      DLADM_PROP_VAL_DEFAULT, "%s", &ptr);
6605 6657                  if (statep->ls_status != DLADM_STATUS_OK)
6606 6658                          goto skip;
6607 6659                  ptr = statep->ls_line;
6608 6660                  break;
6609 6661          case LINKPROP_POSSIBLE:
6610 6662                  print_linkprop(linkid, statep, propname,
6611 6663                      DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr);
6612 6664                  if (statep->ls_status != DLADM_STATUS_OK)
6613 6665                          goto skip;
6614 6666                  ptr = statep->ls_line;
6615 6667                  break;
6616 6668          default:
6617 6669                  die("invalid input");
6618 6670                  break;
6619 6671          }
6620 6672          (void) strlcpy(buf, ptr, bufsize);
6621 6673          return (B_TRUE);
6622 6674  skip:
6623 6675          return ((statep->ls_status == DLADM_STATUS_OK) ?
6624 6676              B_TRUE : B_FALSE);
6625 6677  }
6626 6678  
6627 6679  static boolean_t
6628 6680  linkprop_is_supported(datalink_id_t  linkid, const char *propname,
6629 6681      show_linkprop_state_t *statep)
6630 6682  {
6631 6683          dladm_status_t  status;
6632 6684          uint_t          valcnt = DLADM_MAX_PROP_VALCNT;
6633 6685  
6634 6686          /* if used with -p flag, always print output */
6635 6687          if (statep->ls_proplist != NULL)
6636 6688                  return (B_TRUE);
6637 6689  
6638 6690          status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT,
6639 6691              propname, statep->ls_propvals, &valcnt);
6640 6692  
6641 6693          if (status == DLADM_STATUS_OK)
6642 6694                  return (B_TRUE);
6643 6695  
6644 6696          /*
6645 6697           * A system wide default value is not available for the
6646 6698           * property. Check if current value can be retrieved.
6647 6699           */
6648 6700          status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT,
6649 6701              propname, statep->ls_propvals, &valcnt);
6650 6702  
6651 6703          return (status == DLADM_STATUS_OK);
6652 6704  }
6653 6705  
6654 6706  /* ARGSUSED */
6655 6707  static int
6656 6708  show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname,
6657 6709      void *arg)
6658 6710  {
6659 6711          show_linkprop_state_t   *statep = arg;
6660 6712          linkprop_args_t         ls_arg;
6661 6713  
6662 6714          bzero(&ls_arg, sizeof (ls_arg));
6663 6715          ls_arg.ls_state = statep;
6664 6716          ls_arg.ls_propname = (char *)propname;
6665 6717          ls_arg.ls_linkid = linkid;
6666 6718  
6667 6719          /*
6668 6720           * This will need to be fixed when kernel interfaces are added
6669 6721           * to enable walking of all known private properties. For now,
6670 6722           * we are limited to walking persistent private properties only.
6671 6723           */
6672 6724          if ((propname[0] == '_') && !statep->ls_persist &&
6673 6725              (statep->ls_proplist == NULL))
6674 6726                  return (DLADM_WALK_CONTINUE);
6675 6727          if (!statep->ls_parsable &&
6676 6728              !linkprop_is_supported(linkid, propname, statep))
6677 6729                  return (DLADM_WALK_CONTINUE);
6678 6730  
6679 6731          ofmt_print(statep->ls_ofmt, &ls_arg);
6680 6732  
6681 6733          return (DLADM_WALK_CONTINUE);
6682 6734  }
6683 6735  
6684 6736  static void
6685 6737  do_show_linkprop(int argc, char **argv, const char *use)
6686 6738  {
6687 6739          int                     option;
  
    | 
      ↓ open down ↓ | 
    1468 lines elided | 
    
      ↑ open up ↑ | 
  
6688 6740          char                    propstr[DLADM_STRSIZE];
6689 6741          dladm_arg_list_t        *proplist = NULL;
6690 6742          datalink_id_t           linkid = DATALINK_ALL_LINKID;
6691 6743          show_linkprop_state_t   state;
6692 6744          uint32_t                flags = DLADM_OPT_ACTIVE;
6693 6745          dladm_status_t          status;
6694 6746          char                    *fields_str = NULL;
6695 6747          ofmt_handle_t           ofmt;
6696 6748          ofmt_status_t           oferr;
6697 6749          uint_t                  ofmtflags = 0;
     6750 +        char                    *zonename = NULL;
6698 6751  
6699 6752          bzero(propstr, DLADM_STRSIZE);
6700 6753          opterr = 0;
6701 6754          state.ls_propvals = NULL;
6702 6755          state.ls_line = NULL;
6703 6756          state.ls_parsable = B_FALSE;
6704 6757          state.ls_persist = B_FALSE;
6705 6758          state.ls_header = B_TRUE;
6706 6759          state.ls_retstatus = DLADM_STATUS_OK;
6707 6760  
6708      -        while ((option = getopt_long(argc, argv, ":p:cPo:",
     6761 +        while ((option = getopt_long(argc, argv, ":p:cPo:z:",
6709 6762              prop_longopts, NULL)) != -1) {
6710 6763                  switch (option) {
6711 6764                  case 'p':
6712 6765                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6713 6766                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6714 6767                              DLADM_STRSIZE)
6715 6768                                  die("property list too long '%s'", propstr);
6716 6769                          break;
6717 6770                  case 'c':
6718 6771                          state.ls_parsable = B_TRUE;
6719 6772                          break;
6720 6773                  case 'P':
6721 6774                          state.ls_persist = B_TRUE;
6722 6775                          flags = DLADM_OPT_PERSIST;
6723 6776                          break;
6724 6777                  case 'o':
6725 6778                          fields_str = optarg;
6726 6779                          break;
     6780 +                case 'z':
     6781 +                        zonename = optarg;
     6782 +                        break;
6727 6783                  default:
6728 6784                          die_opterr(optopt, option, use);
6729 6785                          break;
6730 6786                  }
6731 6787          }
6732 6788  
6733 6789          if (optind == (argc - 1)) {
6734      -                if ((status = dladm_name2info(handle, argv[optind], &linkid,
6735      -                    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
     6790 +                if ((status = dladm_zname2info(handle, zonename, argv[optind],
     6791 +                    &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6736 6792                          die_dlerr(status, "link %s is not valid", argv[optind]);
6737 6793                  }
6738 6794          } else if (optind != argc) {
6739 6795                  usage();
6740 6796          }
6741 6797  
6742 6798          if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
6743 6799              != DLADM_STATUS_OK)
6744 6800                  die("invalid link properties specified");
6745 6801          state.ls_proplist = proplist;
     6802 +        state.ls_zonename = zonename;
6746 6803          state.ls_status = DLADM_STATUS_OK;
6747 6804  
6748 6805          if (state.ls_parsable)
6749 6806                  ofmtflags |= OFMT_PARSABLE;
6750 6807          else
6751 6808                  ofmtflags |= OFMT_WRAP;
6752 6809  
6753 6810          oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
6754 6811          dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
6755 6812          state.ls_ofmt = ofmt;
6756 6813  
6757 6814          if (linkid == DATALINK_ALL_LINKID) {
6758 6815                  (void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
6759 6816                      &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
6760 6817          } else {
6761 6818                  (void) show_linkprop_onelink(handle, linkid, &state);
6762 6819          }
6763 6820          ofmt_close(ofmt);
6764 6821          dladm_free_props(proplist);
6765 6822  
6766 6823          if (state.ls_retstatus != DLADM_STATUS_OK) {
6767 6824                  dladm_close(handle);
6768 6825                  exit(EXIT_FAILURE);
6769 6826          }
6770 6827  }
6771 6828  
6772 6829  static int
6773 6830  show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
6774 6831  {
6775 6832          int                     i;
6776 6833          char                    *buf;
6777 6834          uint32_t                flags;
6778 6835          dladm_arg_list_t        *proplist = NULL;
6779 6836          show_linkprop_state_t   *statep = arg;
  
    | 
      ↓ open down ↓ | 
    24 lines elided | 
    
      ↑ open up ↑ | 
  
6780 6837          dlpi_handle_t           dh = NULL;
6781 6838  
6782 6839          statep->ls_status = DLADM_STATUS_OK;
6783 6840  
6784 6841          if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL,
6785 6842              statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) {
6786 6843                  statep->ls_status = DLADM_STATUS_NOTFOUND;
6787 6844                  return (DLADM_WALK_CONTINUE);
6788 6845          }
6789 6846  
     6847 +        if (statep->ls_zonename != NULL) {
     6848 +                datalink_id_t   tlinkid;
     6849 +
     6850 +                if (dladm_zname2info(hdl, statep->ls_zonename, statep->ls_link,
     6851 +                    &tlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK ||
     6852 +                    linkid != tlinkid) {
     6853 +                        statep->ls_status = DLADM_STATUS_NOTFOUND;
     6854 +                        return (DLADM_WALK_CONTINUE);
     6855 +                }
     6856 +        }
     6857 +
6790 6858          if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
6791 6859              (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
6792 6860                  statep->ls_status = DLADM_STATUS_BADARG;
6793 6861                  return (DLADM_WALK_CONTINUE);
6794 6862          }
6795 6863  
6796 6864          proplist = statep->ls_proplist;
6797 6865  
6798 6866          /*
6799 6867           * When some WiFi links are opened for the first time, their hardware
6800 6868           * automatically scans for APs and does other slow operations.  Thus,
6801 6869           * if there are no open links, the retrieval of link properties
6802 6870           * (below) will proceed slowly unless we hold the link open.
6803 6871           *
6804 6872           * Note that failure of dlpi_open() does not necessarily mean invalid
6805 6873           * link properties, because dlpi_open() may fail because of incorrect
6806 6874           * autopush configuration. Therefore, we ingore the return value of
6807 6875           * dlpi_open().
6808 6876           */
6809 6877          if (!statep->ls_persist)
6810 6878                  (void) dlpi_open(statep->ls_link, &dh, 0);
6811 6879  
6812 6880          buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
6813 6881              DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE);
6814 6882          if (buf == NULL)
6815 6883                  die("insufficient memory");
6816 6884  
6817 6885          statep->ls_propvals = (char **)(void *)buf;
6818 6886          for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
6819 6887                  statep->ls_propvals[i] = buf +
6820 6888                      sizeof (char *) * DLADM_MAX_PROP_VALCNT +
6821 6889                      i * DLADM_PROP_VAL_MAX;
6822 6890          }
6823 6891          statep->ls_line = buf +
6824 6892              (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
6825 6893  
6826 6894          if (proplist != NULL) {
6827 6895                  for (i = 0; i < proplist->al_count; i++) {
6828 6896                          (void) show_linkprop(hdl, linkid,
6829 6897                              proplist->al_info[i].ai_name, statep);
6830 6898                  }
6831 6899          } else {
6832 6900                  (void) dladm_walk_linkprop(hdl, linkid, statep,
6833 6901                      show_linkprop);
6834 6902          }
6835 6903          if (dh != NULL)
6836 6904                  dlpi_close(dh);
6837 6905          free(buf);
6838 6906          return (DLADM_WALK_CONTINUE);
6839 6907  }
6840 6908  
6841 6909  static int
6842 6910  reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid,
6843 6911      const char *propname, void *arg)
6844 6912  {
6845 6913          set_linkprop_state_t    *statep = arg;
6846 6914          dladm_status_t          status;
6847 6915  
6848 6916          status = dladm_set_linkprop(dh, linkid, propname, NULL, 0,
6849 6917              DLADM_OPT_ACTIVE | (statep->ls_temp ? 0 : DLADM_OPT_PERSIST));
6850 6918          if (status != DLADM_STATUS_OK &&
6851 6919              status != DLADM_STATUS_PROPRDONLY &&
6852 6920              status != DLADM_STATUS_NOTSUP) {
6853 6921                  warn_dlerr(status, "cannot reset link property '%s' on '%s'",
6854 6922                      propname, statep->ls_name);
6855 6923                  statep->ls_status = status;
6856 6924          }
6857 6925  
6858 6926          return (DLADM_WALK_CONTINUE);
6859 6927  }
6860 6928  
6861 6929  static void
  
    | 
      ↓ open down ↓ | 
    62 lines elided | 
    
      ↑ open up ↑ | 
  
6862 6930  set_linkprop(int argc, char **argv, boolean_t reset, const char *use)
6863 6931  {
6864 6932          int                     i, option;
6865 6933          char                    errmsg[DLADM_STRSIZE];
6866 6934          char                    *altroot = NULL;
6867 6935          datalink_id_t           linkid;
6868 6936          boolean_t               temp = B_FALSE;
6869 6937          dladm_status_t          status = DLADM_STATUS_OK;
6870 6938          char                    propstr[DLADM_STRSIZE];
6871 6939          dladm_arg_list_t        *proplist = NULL;
     6940 +        char                    *zonename = NULL;
6872 6941  
6873 6942          opterr = 0;
6874 6943          bzero(propstr, DLADM_STRSIZE);
6875 6944  
6876      -        while ((option = getopt_long(argc, argv, ":p:R:t",
     6945 +        while ((option = getopt_long(argc, argv, ":p:R:tz:",
6877 6946              prop_longopts, NULL)) != -1) {
6878 6947                  switch (option) {
6879 6948                  case 'p':
6880 6949                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6881 6950                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6882 6951                              DLADM_STRSIZE)
6883 6952                                  die("property list too long '%s'", propstr);
6884 6953                          break;
6885 6954                  case 't':
6886 6955                          temp = B_TRUE;
6887 6956                          break;
6888 6957                  case 'R':
6889 6958                          altroot = optarg;
6890 6959                          break;
     6960 +                case 'z':
     6961 +                        zonename = optarg;
     6962 +                        break;
6891 6963                  default:
6892 6964                          die_opterr(optopt, option, use);
6893 6965  
6894 6966                  }
6895 6967          }
6896 6968  
6897 6969          /* get link name (required last argument) */
6898 6970          if (optind != (argc - 1))
6899 6971                  usage();
6900 6972  
6901 6973          if (dladm_parse_link_props(propstr, &proplist, reset) !=
6902 6974              DLADM_STATUS_OK)
  
    | 
      ↓ open down ↓ | 
    2 lines elided | 
    
      ↑ open up ↑ | 
  
6903 6975                  die("invalid link properties specified");
6904 6976  
6905 6977          if (proplist == NULL && !reset)
6906 6978                  die("link property must be specified");
6907 6979  
6908 6980          if (altroot != NULL) {
6909 6981                  dladm_free_props(proplist);
6910 6982                  altroot_cmd(altroot, argc, argv);
6911 6983          }
6912 6984  
6913      -        status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
6914      -            NULL);
     6985 +        status = dladm_zname2info(handle, zonename, argv[optind], &linkid,
     6986 +            NULL, NULL, NULL);
6915 6987          if (status != DLADM_STATUS_OK)
6916 6988                  die_dlerr(status, "link %s is not valid", argv[optind]);
6917 6989  
6918 6990          if (proplist == NULL) {
6919 6991                  set_linkprop_state_t    state;
6920 6992  
6921 6993                  state.ls_name = argv[optind];
6922 6994                  state.ls_reset = reset;
6923 6995                  state.ls_temp = temp;
6924 6996                  state.ls_status = DLADM_STATUS_OK;
6925 6997  
6926 6998                  (void) dladm_walk_linkprop(handle, linkid, &state,
6927 6999                      reset_one_linkprop);
6928 7000  
6929 7001                  status = state.ls_status;
6930 7002                  goto done;
6931 7003          }
6932 7004  
6933 7005          for (i = 0; i < proplist->al_count; i++) {
6934 7006                  dladm_arg_info_t        *aip = &proplist->al_info[i];
6935 7007                  char            **val;
6936 7008                  uint_t          count;
6937 7009  
6938 7010                  if (reset) {
6939 7011                          val = NULL;
6940 7012                          count = 0;
6941 7013                  } else {
6942 7014                          val = aip->ai_val;
6943 7015                          count = aip->ai_count;
6944 7016                          if (count == 0) {
6945 7017                                  warn("no value specified for '%s'",
6946 7018                                      aip->ai_name);
6947 7019                                  status = DLADM_STATUS_BADARG;
6948 7020                                  continue;
6949 7021                          }
6950 7022                  }
6951 7023                  status = dladm_set_linkprop(handle, linkid, aip->ai_name, val,
6952 7024                      count, DLADM_OPT_ACTIVE | (temp ? 0 : DLADM_OPT_PERSIST));
6953 7025                  switch (status) {
6954 7026                  case DLADM_STATUS_OK:
6955 7027                          break;
6956 7028                  case DLADM_STATUS_NOTFOUND:
6957 7029                          warn("invalid link property '%s'", aip->ai_name);
6958 7030                          break;
6959 7031                  case DLADM_STATUS_BADVAL: {
6960 7032                          int             j;
6961 7033                          char            *ptr, *lim;
6962 7034                          char            **propvals = NULL;
6963 7035                          uint_t          valcnt = DLADM_MAX_PROP_VALCNT;
6964 7036                          dladm_status_t  s;
6965 7037  
6966 7038                          ptr = malloc((sizeof (char *) +
6967 7039                              DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
6968 7040                              MAX_PROP_LINE);
6969 7041  
6970 7042                          propvals = (char **)(void *)ptr;
6971 7043                          if (propvals == NULL)
6972 7044                                  die("insufficient memory");
6973 7045  
6974 7046                          for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
6975 7047                                  propvals[j] = ptr + sizeof (char *) *
6976 7048                                      DLADM_MAX_PROP_VALCNT +
6977 7049                                      j * DLADM_PROP_VAL_MAX;
6978 7050                          }
6979 7051                          s = dladm_get_linkprop(handle, linkid,
6980 7052                              DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals,
6981 7053                              &valcnt);
6982 7054  
6983 7055                          if (s != DLADM_STATUS_OK) {
6984 7056                                  warn_dlerr(status, "cannot set link property "
6985 7057                                      "'%s' on '%s'", aip->ai_name, argv[optind]);
6986 7058                                  free(propvals);
6987 7059                                  break;
6988 7060                          }
6989 7061  
6990 7062                          ptr = errmsg;
6991 7063                          lim = ptr + DLADM_STRSIZE;
6992 7064                          *ptr = '\0';
6993 7065                          for (j = 0; j < valcnt; j++) {
6994 7066                                  ptr += snprintf(ptr, lim - ptr, "%s,",
6995 7067                                      propvals[j]);
6996 7068                                  if (ptr >= lim)
6997 7069                                          break;
6998 7070                          }
6999 7071                          if (ptr > errmsg) {
7000 7072                                  *(ptr - 1) = '\0';
7001 7073                                  warn("link property '%s' must be one of: %s",
7002 7074                                      aip->ai_name, errmsg);
7003 7075                          } else
7004 7076                                  warn("invalid link property '%s'", *val);
7005 7077                          free(propvals);
7006 7078                          break;
7007 7079                  }
7008 7080                  default:
7009 7081                          if (reset) {
7010 7082                                  warn_dlerr(status, "cannot reset link property "
7011 7083                                      "'%s' on '%s'", aip->ai_name, argv[optind]);
7012 7084                          } else {
7013 7085                                  warn_dlerr(status, "cannot set link property "
7014 7086                                      "'%s' on '%s'", aip->ai_name, argv[optind]);
7015 7087                          }
7016 7088                          break;
7017 7089                  }
7018 7090          }
7019 7091  done:
7020 7092          dladm_free_props(proplist);
7021 7093          if (status != DLADM_STATUS_OK) {
7022 7094                  dladm_close(handle);
7023 7095                  exit(EXIT_FAILURE);
7024 7096          }
7025 7097  }
7026 7098  
7027 7099  static void
7028 7100  do_set_linkprop(int argc, char **argv, const char *use)
7029 7101  {
7030 7102          set_linkprop(argc, argv, B_FALSE, use);
7031 7103  }
7032 7104  
7033 7105  static void
7034 7106  do_reset_linkprop(int argc, char **argv, const char *use)
7035 7107  {
7036 7108          set_linkprop(argc, argv, B_TRUE, use);
7037 7109  }
7038 7110  
7039 7111  static int
7040 7112  convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp,
7041 7113      dladm_secobj_class_t class)
7042 7114  {
7043 7115          int error = 0;
7044 7116  
7045 7117          if (class == DLADM_SECOBJ_CLASS_WPA) {
7046 7118                  if (len < 8 || len > 63)
7047 7119                          return (EINVAL);
7048 7120                  (void) memcpy(obj_val, buf, len);
7049 7121                  *obj_lenp = len;
7050 7122                  return (error);
7051 7123          }
7052 7124  
7053 7125          if (class == DLADM_SECOBJ_CLASS_WEP) {
7054 7126                  switch (len) {
7055 7127                  case 5:                 /* ASCII key sizes */
7056 7128                  case 13:
7057 7129                          (void) memcpy(obj_val, buf, len);
7058 7130                          *obj_lenp = len;
7059 7131                          break;
7060 7132                  case 10:                /* Hex key sizes, not preceded by 0x */
7061 7133                  case 26:
7062 7134                          error = hexascii_to_octet(buf, len, obj_val, obj_lenp);
7063 7135                          break;
7064 7136                  case 12:                /* Hex key sizes, preceded by 0x */
7065 7137                  case 28:
7066 7138                          if (strncmp(buf, "0x", 2) != 0)
7067 7139                                  return (EINVAL);
7068 7140                          error = hexascii_to_octet(buf + 2, len - 2,
7069 7141                              obj_val, obj_lenp);
7070 7142                          break;
7071 7143                  default:
7072 7144                          return (EINVAL);
7073 7145                  }
7074 7146                  return (error);
7075 7147          }
7076 7148  
7077 7149          return (ENOENT);
7078 7150  }
7079 7151  
7080 7152  static void
7081 7153  defersig(int sig)
7082 7154  {
7083 7155          signalled = sig;
7084 7156  }
7085 7157  
7086 7158  static int
7087 7159  get_secobj_from_tty(uint_t try, const char *objname, char *buf)
7088 7160  {
7089 7161          uint_t          len = 0;
7090 7162          int             c;
7091 7163          struct termios  stored, current;
7092 7164          void            (*sigfunc)(int);
7093 7165  
7094 7166          /*
7095 7167           * Turn off echo -- but before we do so, defer SIGINT handling
7096 7168           * so that a ^C doesn't leave the terminal corrupted.
7097 7169           */
7098 7170          sigfunc = signal(SIGINT, defersig);
7099 7171          (void) fflush(stdin);
7100 7172          (void) tcgetattr(0, &stored);
7101 7173          current = stored;
7102 7174          current.c_lflag &= ~(ICANON|ECHO);
7103 7175          current.c_cc[VTIME] = 0;
7104 7176          current.c_cc[VMIN] = 1;
7105 7177          (void) tcsetattr(0, TCSANOW, ¤t);
7106 7178  again:
7107 7179          if (try == 1)
7108 7180                  (void) printf(gettext("provide value for '%s': "), objname);
7109 7181          else
7110 7182                  (void) printf(gettext("confirm value for '%s': "), objname);
7111 7183  
7112 7184          (void) fflush(stdout);
7113 7185          while (signalled == 0) {
7114 7186                  c = getchar();
7115 7187                  if (c == '\n' || c == '\r') {
7116 7188                          if (len != 0)
7117 7189                                  break;
7118 7190                          (void) putchar('\n');
7119 7191                          goto again;
7120 7192                  }
7121 7193  
7122 7194                  buf[len++] = c;
7123 7195                  if (len >= DLADM_SECOBJ_VAL_MAX - 1)
7124 7196                          break;
7125 7197                  (void) putchar('*');
7126 7198          }
7127 7199  
7128 7200          (void) putchar('\n');
7129 7201          (void) fflush(stdin);
7130 7202  
7131 7203          /*
7132 7204           * Restore terminal setting and handle deferred signals.
7133 7205           */
7134 7206          (void) tcsetattr(0, TCSANOW, &stored);
7135 7207  
7136 7208          (void) signal(SIGINT, sigfunc);
7137 7209          if (signalled != 0)
7138 7210                  (void) kill(getpid(), signalled);
7139 7211  
7140 7212          return (len);
7141 7213  }
7142 7214  
7143 7215  static int
7144 7216  get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp,
7145 7217      dladm_secobj_class_t class, FILE *filep)
7146 7218  {
7147 7219          int             rval;
7148 7220          uint_t          len, len2;
7149 7221          char            buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX];
7150 7222  
7151 7223          if (filep == NULL) {
7152 7224                  len = get_secobj_from_tty(1, obj_name, buf);
7153 7225                  rval = convert_secobj(buf, len, obj_val, obj_lenp, class);
7154 7226                  if (rval == 0) {
7155 7227                          len2 = get_secobj_from_tty(2, obj_name, buf2);
7156 7228                          if (len != len2 || memcmp(buf, buf2, len) != 0)
7157 7229                                  rval = ENOTSUP;
7158 7230                  }
7159 7231                  return (rval);
7160 7232          } else {
7161 7233                  for (;;) {
7162 7234                          if (fgets(buf, sizeof (buf), filep) == NULL)
7163 7235                                  break;
7164 7236                          if (isspace(buf[0]))
7165 7237                                  continue;
7166 7238  
7167 7239                          len = strlen(buf);
7168 7240                          if (buf[len - 1] == '\n') {
7169 7241                                  buf[len - 1] = '\0';
7170 7242                                  len--;
7171 7243                          }
7172 7244                          break;
7173 7245                  }
7174 7246                  (void) fclose(filep);
7175 7247          }
7176 7248          return (convert_secobj(buf, len, obj_val, obj_lenp, class));
7177 7249  }
7178 7250  
7179 7251  static boolean_t
7180 7252  check_auth(const char *auth)
7181 7253  {
7182 7254          struct passwd   *pw;
7183 7255  
7184 7256          if ((pw = getpwuid(getuid())) == NULL)
7185 7257                  return (B_FALSE);
7186 7258  
7187 7259          return (chkauthattr(auth, pw->pw_name) != 0);
7188 7260  }
7189 7261  
7190 7262  static void
7191 7263  audit_secobj(char *auth, char *class, char *obj,
7192 7264      boolean_t success, boolean_t create)
7193 7265  {
7194 7266          adt_session_data_t      *ah;
7195 7267          adt_event_data_t        *event;
7196 7268          au_event_t              flag;
7197 7269          char                    *errstr;
7198 7270  
7199 7271          if (create) {
7200 7272                  flag = ADT_dladm_create_secobj;
7201 7273                  errstr = "ADT_dladm_create_secobj";
7202 7274          } else {
7203 7275                  flag = ADT_dladm_delete_secobj;
7204 7276                  errstr = "ADT_dladm_delete_secobj";
7205 7277          }
7206 7278  
7207 7279          if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0)
7208 7280                  die("adt_start_session: %s", strerror(errno));
7209 7281  
7210 7282          if ((event = adt_alloc_event(ah, flag)) == NULL)
7211 7283                  die("adt_alloc_event (%s): %s", errstr, strerror(errno));
7212 7284  
7213 7285          /* fill in audit info */
7214 7286          if (create) {
7215 7287                  event->adt_dladm_create_secobj.auth_used = auth;
7216 7288                  event->adt_dladm_create_secobj.obj_class = class;
7217 7289                  event->adt_dladm_create_secobj.obj_name = obj;
7218 7290          } else {
7219 7291                  event->adt_dladm_delete_secobj.auth_used = auth;
7220 7292                  event->adt_dladm_delete_secobj.obj_class = class;
7221 7293                  event->adt_dladm_delete_secobj.obj_name = obj;
7222 7294          }
7223 7295  
7224 7296          if (success) {
7225 7297                  if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
7226 7298                          die("adt_put_event (%s, success): %s", errstr,
7227 7299                              strerror(errno));
7228 7300                  }
7229 7301          } else {
7230 7302                  if (adt_put_event(event, ADT_FAILURE,
7231 7303                      ADT_FAIL_VALUE_AUTH) != 0) {
7232 7304                          die("adt_put_event: (%s, failure): %s", errstr,
7233 7305                              strerror(errno));
7234 7306                  }
7235 7307          }
7236 7308  
7237 7309          adt_free_event(event);
7238 7310          (void) adt_end_session(ah);
7239 7311  }
7240 7312  
7241 7313  static void
7242 7314  do_create_secobj(int argc, char **argv, const char *use)
7243 7315  {
7244 7316          int                     option, rval;
7245 7317          FILE                    *filep = NULL;
7246 7318          char                    *obj_name = NULL;
7247 7319          char                    *class_name = NULL;
7248 7320          uint8_t                 obj_val[DLADM_SECOBJ_VAL_MAX];
7249 7321          uint_t                  obj_len;
7250 7322          boolean_t               success, temp = B_FALSE;
7251 7323          dladm_status_t          status;
7252 7324          dladm_secobj_class_t    class = -1;
7253 7325          uid_t                   euid;
7254 7326  
7255 7327          opterr = 0;
7256 7328          (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX);
7257 7329          while ((option = getopt_long(argc, argv, ":f:c:R:t",
7258 7330              wifi_longopts, NULL)) != -1) {
7259 7331                  switch (option) {
7260 7332                  case 'f':
7261 7333                          euid = geteuid();
7262 7334                          (void) seteuid(getuid());
7263 7335                          filep = fopen(optarg, "r");
7264 7336                          if (filep == NULL) {
7265 7337                                  die("cannot open %s: %s", optarg,
7266 7338                                      strerror(errno));
7267 7339                          }
7268 7340                          (void) seteuid(euid);
7269 7341                          break;
7270 7342                  case 'c':
7271 7343                          class_name = optarg;
7272 7344                          status = dladm_str2secobjclass(optarg, &class);
7273 7345                          if (status != DLADM_STATUS_OK) {
7274 7346                                  die("invalid secure object class '%s', "
7275 7347                                      "valid values are: wep, wpa", optarg);
7276 7348                          }
7277 7349                          break;
7278 7350                  case 't':
7279 7351                          temp = B_TRUE;
7280 7352                          break;
7281 7353                  case 'R':
7282 7354                          status = dladm_set_rootdir(optarg);
7283 7355                          if (status != DLADM_STATUS_OK) {
7284 7356                                  die_dlerr(status, "invalid directory "
7285 7357                                      "specified");
7286 7358                          }
7287 7359                          break;
7288 7360                  default:
7289 7361                          die_opterr(optopt, option, use);
7290 7362                          break;
7291 7363                  }
7292 7364          }
7293 7365  
7294 7366          if (optind == (argc - 1))
7295 7367                  obj_name = argv[optind];
7296 7368          else if (optind != argc)
7297 7369                  usage();
7298 7370  
7299 7371          if (class == -1)
7300 7372                  die("secure object class required");
7301 7373  
7302 7374          if (obj_name == NULL)
7303 7375                  die("secure object name required");
7304 7376  
7305 7377          if (!dladm_valid_secobj_name(obj_name))
7306 7378                  die("invalid secure object name '%s'", obj_name);
7307 7379  
7308 7380          success = check_auth(LINK_SEC_AUTH);
7309 7381          audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE);
7310 7382          if (!success)
7311 7383                  die("authorization '%s' is required", LINK_SEC_AUTH);
7312 7384  
7313 7385          rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep);
7314 7386          if (rval != 0) {
7315 7387                  switch (rval) {
7316 7388                  case ENOENT:
7317 7389                          die("invalid secure object class");
7318 7390                          break;
7319 7391                  case EINVAL:
7320 7392                          die("invalid secure object value");
7321 7393                          break;
7322 7394                  case ENOTSUP:
7323 7395                          die("verification failed");
7324 7396                          break;
7325 7397                  default:
7326 7398                          die("invalid secure object: %s", strerror(rval));
7327 7399                          break;
7328 7400                  }
7329 7401          }
7330 7402  
7331 7403          status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
7332 7404              DLADM_OPT_CREATE | DLADM_OPT_ACTIVE);
7333 7405          if (status != DLADM_STATUS_OK) {
7334 7406                  die_dlerr(status, "could not create secure object '%s'",
7335 7407                      obj_name);
7336 7408          }
7337 7409          if (temp)
7338 7410                  return;
7339 7411  
7340 7412          status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
7341 7413              DLADM_OPT_PERSIST);
7342 7414          if (status != DLADM_STATUS_OK) {
7343 7415                  warn_dlerr(status, "could not persistently create secure "
7344 7416                      "object '%s'", obj_name);
7345 7417          }
7346 7418  }
7347 7419  
7348 7420  static void
7349 7421  do_delete_secobj(int argc, char **argv, const char *use)
7350 7422  {
7351 7423          int             i, option;
7352 7424          boolean_t       temp = B_FALSE;
7353 7425          boolean_t       success;
7354 7426          dladm_status_t  status, pstatus;
7355 7427          int             nfields = 1;
7356 7428          char            *field, *token, *lasts = NULL, c;
7357 7429  
7358 7430          opterr = 0;
7359 7431          status = pstatus = DLADM_STATUS_OK;
7360 7432          while ((option = getopt_long(argc, argv, ":R:t",
7361 7433              wifi_longopts, NULL)) != -1) {
7362 7434                  switch (option) {
7363 7435                  case 't':
7364 7436                          temp = B_TRUE;
7365 7437                          break;
7366 7438                  case 'R':
7367 7439                          status = dladm_set_rootdir(optarg);
7368 7440                          if (status != DLADM_STATUS_OK) {
7369 7441                                  die_dlerr(status, "invalid directory "
7370 7442                                      "specified");
7371 7443                          }
7372 7444                          break;
7373 7445                  default:
7374 7446                          die_opterr(optopt, option, use);
7375 7447                          break;
7376 7448                  }
7377 7449          }
7378 7450  
7379 7451          if (optind != (argc - 1))
7380 7452                  die("secure object name required");
7381 7453  
7382 7454          token = argv[optind];
7383 7455          while ((c = *token++) != NULL) {
7384 7456                  if (c == ',')
7385 7457                          nfields++;
7386 7458          }
7387 7459          token = strdup(argv[optind]);
7388 7460          if (token == NULL)
7389 7461                  die("no memory");
7390 7462  
7391 7463          success = check_auth(LINK_SEC_AUTH);
7392 7464          audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE);
7393 7465          if (!success)
7394 7466                  die("authorization '%s' is required", LINK_SEC_AUTH);
7395 7467  
7396 7468          for (i = 0; i < nfields; i++) {
7397 7469  
7398 7470                  field = strtok_r(token, ",", &lasts);
7399 7471                  token = NULL;
7400 7472                  status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE);
7401 7473                  if (!temp) {
7402 7474                          pstatus = dladm_unset_secobj(handle, field,
7403 7475                              DLADM_OPT_PERSIST);
7404 7476                  } else {
7405 7477                          pstatus = DLADM_STATUS_OK;
7406 7478                  }
7407 7479  
7408 7480                  if (status != DLADM_STATUS_OK) {
7409 7481                          warn_dlerr(status, "could not delete secure object "
7410 7482                              "'%s'", field);
7411 7483                  }
7412 7484                  if (pstatus != DLADM_STATUS_OK) {
7413 7485                          warn_dlerr(pstatus, "could not persistently delete "
7414 7486                              "secure object '%s'", field);
7415 7487                  }
7416 7488          }
7417 7489          free(token);
7418 7490  
7419 7491          if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) {
7420 7492                  dladm_close(handle);
7421 7493                  exit(EXIT_FAILURE);
7422 7494          }
7423 7495  }
7424 7496  
7425 7497  typedef struct show_secobj_state {
7426 7498          boolean_t       ss_persist;
7427 7499          boolean_t       ss_parsable;
7428 7500          boolean_t       ss_header;
7429 7501          ofmt_handle_t   ss_ofmt;
7430 7502  } show_secobj_state_t;
7431 7503  
7432 7504  
7433 7505  static boolean_t
7434 7506  show_secobj(dladm_handle_t dh, void *arg, const char *obj_name)
7435 7507  {
7436 7508          uint_t                  obj_len = DLADM_SECOBJ_VAL_MAX;
7437 7509          uint8_t                 obj_val[DLADM_SECOBJ_VAL_MAX];
7438 7510          char                    buf[DLADM_STRSIZE];
7439 7511          uint_t                  flags = 0;
7440 7512          dladm_secobj_class_t    class;
7441 7513          show_secobj_state_t     *statep = arg;
7442 7514          dladm_status_t          status;
7443 7515          secobj_fields_buf_t     sbuf;
7444 7516  
7445 7517          bzero(&sbuf, sizeof (secobj_fields_buf_t));
7446 7518          if (statep->ss_persist)
7447 7519                  flags |= DLADM_OPT_PERSIST;
7448 7520  
7449 7521          status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len,
7450 7522              flags);
7451 7523          if (status != DLADM_STATUS_OK)
7452 7524                  die_dlerr(status, "cannot get secure object '%s'", obj_name);
7453 7525  
7454 7526          (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name),
7455 7527              obj_name);
7456 7528          (void) dladm_secobjclass2str(class, buf);
7457 7529          (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf);
7458 7530          if (getuid() == 0) {
7459 7531                  char    val[DLADM_SECOBJ_VAL_MAX * 2];
7460 7532                  uint_t  len = sizeof (val);
7461 7533  
7462 7534                  if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0)
7463 7535                          (void) snprintf(sbuf.ss_val,
7464 7536                              sizeof (sbuf.ss_val), "%s", val);
7465 7537          }
7466 7538          ofmt_print(statep->ss_ofmt, &sbuf);
7467 7539          return (B_TRUE);
7468 7540  }
7469 7541  
7470 7542  static void
7471 7543  do_show_secobj(int argc, char **argv, const char *use)
7472 7544  {
7473 7545          int                     option;
7474 7546          show_secobj_state_t     state;
7475 7547          dladm_status_t          status;
7476 7548          boolean_t               o_arg = B_FALSE;
7477 7549          uint_t                  i;
7478 7550          uint_t                  flags;
7479 7551          char                    *fields_str = NULL;
7480 7552          char                    *def_fields = "object,class";
7481 7553          char                    *all_fields = "object,class,value";
7482 7554          char                    *field, *token, *lasts = NULL, c;
7483 7555          ofmt_handle_t           ofmt;
7484 7556          ofmt_status_t           oferr;
7485 7557          uint_t                  ofmtflags = 0;
7486 7558  
7487 7559          opterr = 0;
7488 7560          bzero(&state, sizeof (state));
7489 7561          state.ss_parsable = B_FALSE;
7490 7562          fields_str = def_fields;
7491 7563          state.ss_persist = B_FALSE;
7492 7564          state.ss_parsable = B_FALSE;
7493 7565          state.ss_header = B_TRUE;
7494 7566          while ((option = getopt_long(argc, argv, ":pPo:",
7495 7567              wifi_longopts, NULL)) != -1) {
7496 7568                  switch (option) {
7497 7569                  case 'p':
7498 7570                          state.ss_parsable = B_TRUE;
7499 7571                          break;
7500 7572                  case 'P':
7501 7573                          state.ss_persist = B_TRUE;
7502 7574                          break;
7503 7575                  case 'o':
7504 7576                          o_arg = B_TRUE;
7505 7577                          if (strcasecmp(optarg, "all") == 0)
7506 7578                                  fields_str = all_fields;
7507 7579                          else
7508 7580                                  fields_str = optarg;
7509 7581                          break;
7510 7582                  default:
7511 7583                          die_opterr(optopt, option, use);
7512 7584                          break;
7513 7585                  }
7514 7586          }
7515 7587  
7516 7588          if (state.ss_parsable && !o_arg)
7517 7589                  die("option -c requires -o");
7518 7590  
7519 7591          if (state.ss_parsable && fields_str == all_fields)
7520 7592                  die("\"-o all\" is invalid with -p");
7521 7593  
7522 7594          if (state.ss_parsable)
7523 7595                  ofmtflags |= OFMT_PARSABLE;
7524 7596          oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt);
7525 7597          dladm_ofmt_check(oferr, state.ss_parsable, ofmt);
7526 7598          state.ss_ofmt = ofmt;
7527 7599  
7528 7600          flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
7529 7601  
7530 7602          if (optind == (argc - 1)) {
7531 7603                  uint_t obj_fields = 1;
7532 7604  
7533 7605                  token = argv[optind];
7534 7606                  if (token == NULL)
7535 7607                          die("secure object name required");
7536 7608                  while ((c = *token++) != NULL) {
7537 7609                          if (c == ',')
7538 7610                                  obj_fields++;
7539 7611                  }
7540 7612                  token = strdup(argv[optind]);
7541 7613                  if (token == NULL)
7542 7614                          die("no memory");
7543 7615                  for (i = 0; i < obj_fields; i++) {
7544 7616                          field = strtok_r(token, ",", &lasts);
7545 7617                          token = NULL;
7546 7618                          if (!show_secobj(handle, &state, field))
7547 7619                                  break;
7548 7620                  }
7549 7621                  free(token);
7550 7622                  ofmt_close(ofmt);
7551 7623                  return;
7552 7624          } else if (optind != argc)
7553 7625                  usage();
7554 7626  
7555 7627          status = dladm_walk_secobj(handle, &state, show_secobj, flags);
7556 7628  
7557 7629          if (status != DLADM_STATUS_OK)
7558 7630                  die_dlerr(status, "show-secobj");
7559 7631          ofmt_close(ofmt);
7560 7632  }
7561 7633  
7562 7634  /*ARGSUSED*/
7563 7635  static int
7564 7636  i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
7565 7637  {
7566 7638          (void) dladm_init_linkprop(dh, linkid, B_TRUE);
7567 7639          return (DLADM_WALK_CONTINUE);
7568 7640  }
7569 7641  
7570 7642  /*ARGSUSED*/
7571 7643  void
7572 7644  do_init_linkprop(int argc, char **argv, const char *use)
7573 7645  {
7574 7646          int                     option;
7575 7647          dladm_status_t          status;
7576 7648          datalink_id_t           linkid = DATALINK_ALL_LINKID;
7577 7649          datalink_media_t        media = DATALINK_ANY_MEDIATYPE;
7578 7650          uint_t                  any_media = B_TRUE;
7579 7651  
7580 7652          opterr = 0;
7581 7653          while ((option = getopt(argc, argv, ":w")) != -1) {
7582 7654                  switch (option) {
7583 7655                  case 'w':
7584 7656                          media = DL_WIFI;
7585 7657                          any_media = B_FALSE;
7586 7658                          break;
7587 7659                  default:
7588 7660                          /*
7589 7661                           * Because init-linkprop is not a public command,
7590 7662                           * print the usage instead.
7591 7663                           */
7592 7664                          usage();
7593 7665                          break;
7594 7666                  }
7595 7667          }
7596 7668  
7597 7669          if (optind == (argc - 1)) {
7598 7670                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
7599 7671                      NULL, NULL, NULL)) != DLADM_STATUS_OK)
7600 7672                          die_dlerr(status, "link %s is not valid", argv[optind]);
7601 7673          } else if (optind != argc) {
7602 7674                  usage();
7603 7675          }
7604 7676  
7605 7677          if (linkid == DATALINK_ALL_LINKID) {
7606 7678                  /*
7607 7679                   * linkprops of links of other classes have been initialized as
7608 7680                   * part of the dladm up-xxx operation.
7609 7681                   */
7610 7682                  (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
7611 7683                      NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST);
7612 7684          } else {
7613 7685                  (void) dladm_init_linkprop(handle, linkid, any_media);
7614 7686          }
7615 7687  }
7616 7688  
7617 7689  static void
7618 7690  do_show_ether(int argc, char **argv, const char *use)
7619 7691  {
7620 7692          int                     option;
7621 7693          datalink_id_t           linkid;
7622 7694          print_ether_state_t     state;
7623 7695          char                    *fields_str = NULL;
7624 7696          ofmt_handle_t           ofmt;
7625 7697          ofmt_status_t           oferr;
7626 7698          uint_t                  ofmtflags = 0;
7627 7699  
7628 7700          bzero(&state, sizeof (state));
7629 7701          state.es_link = NULL;
7630 7702          state.es_parsable = B_FALSE;
7631 7703  
7632 7704          while ((option = getopt_long(argc, argv, "o:px",
7633 7705              showeth_lopts, NULL)) != -1) {
7634 7706                  switch (option) {
7635 7707                          case 'x':
7636 7708                                  state.es_extended = B_TRUE;
7637 7709                                  break;
7638 7710                          case 'p':
7639 7711                                  state.es_parsable = B_TRUE;
7640 7712                                  break;
7641 7713                          case 'o':
7642 7714                                  fields_str = optarg;
7643 7715                                  break;
7644 7716                          default:
7645 7717                                  die_opterr(optopt, option, use);
7646 7718                                  break;
7647 7719                  }
7648 7720          }
7649 7721  
7650 7722          if (optind == (argc - 1))
7651 7723                  state.es_link = argv[optind];
7652 7724  
7653 7725          if (state.es_parsable)
7654 7726                  ofmtflags |= OFMT_PARSABLE;
7655 7727          oferr = ofmt_open(fields_str, ether_fields, ofmtflags,
7656 7728              DLADM_DEFAULT_COL, &ofmt);
7657 7729          dladm_ofmt_check(oferr, state.es_parsable, ofmt);
7658 7730          state.es_ofmt = ofmt;
7659 7731  
7660 7732          if (state.es_link == NULL) {
7661 7733                  (void) dladm_walk_datalink_id(show_etherprop, handle, &state,
7662 7734                      DATALINK_CLASS_PHYS, DL_ETHER, DLADM_OPT_ACTIVE);
7663 7735          } else {
7664 7736                  if (!link_is_ether(state.es_link, &linkid))
7665 7737                          die("invalid link specified");
7666 7738                  (void) show_etherprop(handle, linkid, &state);
7667 7739          }
7668 7740          ofmt_close(ofmt);
7669 7741  }
7670 7742  
7671 7743  static int
7672 7744  show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
7673 7745  {
7674 7746          print_ether_state_t     *statep = arg;
7675 7747          ether_fields_buf_t      ebuf;
7676 7748          dladm_ether_info_t      eattr;
7677 7749          dladm_status_t          status;
7678 7750  
7679 7751          bzero(&ebuf, sizeof (ether_fields_buf_t));
7680 7752          if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL,
7681 7753              ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) {
7682 7754                  return (DLADM_WALK_CONTINUE);
7683 7755          }
7684 7756  
7685 7757          status = dladm_ether_info(dh, linkid, &eattr);
7686 7758          if (status != DLADM_STATUS_OK)
7687 7759                  goto cleanup;
7688 7760  
7689 7761          (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype));
7690 7762  
7691 7763          (void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
7692 7764              sizeof (ebuf.eth_autoneg), &eattr, CURRENT);
7693 7765          (void) dladm_ether_pause2str(ebuf.eth_pause,
7694 7766              sizeof (ebuf.eth_pause), &eattr, CURRENT);
7695 7767          (void) dladm_ether_spdx2str(ebuf.eth_spdx,
7696 7768              sizeof (ebuf.eth_spdx), &eattr, CURRENT);
7697 7769          (void) strlcpy(ebuf.eth_state,
7698 7770              dladm_linkstate2str(eattr.lei_state, ebuf.eth_state),
7699 7771              sizeof (ebuf.eth_state));
7700 7772          (void) strlcpy(ebuf.eth_rem_fault,
7701 7773              (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"),
7702 7774              sizeof (ebuf.eth_rem_fault));
7703 7775  
7704 7776          ofmt_print(statep->es_ofmt, &ebuf);
7705 7777  
7706 7778          if (statep->es_extended)
7707 7779                  show_ether_xprop(arg, &eattr);
7708 7780  
7709 7781  cleanup:
7710 7782          dladm_ether_info_done(&eattr);
7711 7783          return (DLADM_WALK_CONTINUE);
7712 7784  }
7713 7785  
7714 7786  /* ARGSUSED */
7715 7787  static void
7716 7788  do_init_secobj(int argc, char **argv, const char *use)
7717 7789  {
7718 7790          dladm_status_t  status;
7719 7791  
7720 7792          status = dladm_init_secobj(handle);
7721 7793          if (status != DLADM_STATUS_OK)
7722 7794                  die_dlerr(status, "secure object initialization failed");
7723 7795  }
7724 7796  
7725 7797  enum bridge_func {
7726 7798          brCreate, brAdd, brModify
7727 7799  };
7728 7800  
7729 7801  static void
7730 7802  create_modify_add_bridge(int argc, char **argv, const char *use,
7731 7803      enum bridge_func func)
7732 7804  {
7733 7805          int                     option;
7734 7806          uint_t                  n, i, nlink;
7735 7807          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
7736 7808          char                    *altroot = NULL;
7737 7809          char                    *links[MAXPORT];
7738 7810          datalink_id_t           linkids[MAXPORT];
7739 7811          dladm_status_t          status;
7740 7812          const char              *bridge;
7741 7813          UID_STP_CFG_T           cfg, cfg_old;
7742 7814          dladm_bridge_prot_t     brprot = DLADM_BRIDGE_PROT_UNKNOWN;
7743 7815          dladm_bridge_prot_t     brprot_old;
7744 7816  
7745 7817          /* Set up the default configuration values */
7746 7818          cfg.field_mask = 0;
7747 7819          cfg.bridge_priority = DEF_BR_PRIO;
7748 7820          cfg.max_age = DEF_BR_MAXAGE;
7749 7821          cfg.hello_time = DEF_BR_HELLOT;
7750 7822          cfg.forward_delay = DEF_BR_FWDELAY;
7751 7823          cfg.force_version = DEF_FORCE_VERS;
7752 7824  
7753 7825          nlink = opterr = 0;
7754 7826          while ((option = getopt_long(argc, argv, ":P:R:d:f:h:l:m:p:",
7755 7827              bridge_lopts, NULL)) != -1) {
7756 7828                  switch (option) {
7757 7829                  case 'P':
7758 7830                          if (func == brAdd)
7759 7831                                  die_opterr(optopt, option, use);
7760 7832                          status = dladm_bridge_str2prot(optarg, &brprot);
7761 7833                          if (status != DLADM_STATUS_OK)
7762 7834                                  die_dlerr(status, "protection %s", optarg);
7763 7835                          break;
7764 7836                  case 'R':
7765 7837                          altroot = optarg;
7766 7838                          break;
7767 7839                  case 'd':
7768 7840                          if (func == brAdd)
7769 7841                                  die_opterr(optopt, option, use);
7770 7842                          if (cfg.field_mask & BR_CFG_DELAY)
7771 7843                                  die("forwarding delay set more than once");
7772 7844                          if (!str2int(optarg, &cfg.forward_delay) ||
7773 7845                              cfg.forward_delay < MIN_BR_FWDELAY ||
7774 7846                              cfg.forward_delay > MAX_BR_FWDELAY)
7775 7847                                  die("incorrect forwarding delay");
7776 7848                          cfg.field_mask |= BR_CFG_DELAY;
7777 7849                          break;
7778 7850                  case 'f':
7779 7851                          if (func == brAdd)
7780 7852                                  die_opterr(optopt, option, use);
7781 7853                          if (cfg.field_mask & BR_CFG_FORCE_VER)
7782 7854                                  die("force protocol set more than once");
7783 7855                          if (!str2int(optarg, &cfg.force_version) ||
7784 7856                              cfg.force_version < 0)
7785 7857                                  die("incorrect force protocol");
7786 7858                          cfg.field_mask |= BR_CFG_FORCE_VER;
7787 7859                          break;
7788 7860                  case 'h':
7789 7861                          if (func == brAdd)
7790 7862                                  die_opterr(optopt, option, use);
7791 7863                          if (cfg.field_mask & BR_CFG_HELLO)
7792 7864                                  die("hello time set more than once");
7793 7865                          if (!str2int(optarg, &cfg.hello_time) ||
7794 7866                              cfg.hello_time < MIN_BR_HELLOT ||
7795 7867                              cfg.hello_time > MAX_BR_HELLOT)
7796 7868                                  die("incorrect hello time");
7797 7869                          cfg.field_mask |= BR_CFG_HELLO;
7798 7870                          break;
7799 7871                  case 'l':
7800 7872                          if (func == brModify)
7801 7873                                  die_opterr(optopt, option, use);
7802 7874                          if (nlink >= MAXPORT)
7803 7875                                  die("too many links specified");
7804 7876                          links[nlink++] = optarg;
7805 7877                          break;
7806 7878                  case 'm':
7807 7879                          if (func == brAdd)
7808 7880                                  die_opterr(optopt, option, use);
7809 7881                          if (cfg.field_mask & BR_CFG_AGE)
7810 7882                                  die("max age set more than once");
7811 7883                          if (!str2int(optarg, &cfg.max_age) ||
7812 7884                              cfg.max_age < MIN_BR_MAXAGE ||
7813 7885                              cfg.max_age > MAX_BR_MAXAGE)
7814 7886                                  die("incorrect max age");
7815 7887                          cfg.field_mask |= BR_CFG_AGE;
7816 7888                          break;
7817 7889                  case 'p':
7818 7890                          if (func == brAdd)
7819 7891                                  die_opterr(optopt, option, use);
7820 7892                          if (cfg.field_mask & BR_CFG_PRIO)
7821 7893                                  die("priority set more than once");
7822 7894                          if (!str2int(optarg, &cfg.bridge_priority) ||
7823 7895                              cfg.bridge_priority < MIN_BR_PRIO ||
7824 7896                              cfg.bridge_priority > MAX_BR_PRIO)
7825 7897                                  die("incorrect priority");
7826 7898                          cfg.bridge_priority &= 0xF000;
7827 7899                          cfg.field_mask |= BR_CFG_PRIO;
7828 7900                          break;
7829 7901                  default:
7830 7902                          die_opterr(optopt, option, use);
7831 7903                          break;
7832 7904                  }
7833 7905          }
7834 7906  
7835 7907          /* get the bridge name (required last argument) */
7836 7908          if (optind != (argc-1))
7837 7909                  usage();
7838 7910  
7839 7911          bridge = argv[optind];
7840 7912          if (!dladm_valid_bridgename(bridge))
7841 7913                  die("invalid bridge name '%s'", bridge);
7842 7914  
7843 7915          /*
7844 7916           * Get the current properties, if any, and merge in with changes.  This
7845 7917           * is necessary (even with the field_mask feature) so that the
7846 7918           * value-checking macros will produce the right results with proposed
7847 7919           * changes to existing configuration.  We only need it for those
7848 7920           * parameters, though.
7849 7921           */
7850 7922          (void) dladm_bridge_get_properties(bridge, &cfg_old, &brprot_old);
7851 7923          if (brprot == DLADM_BRIDGE_PROT_UNKNOWN)
7852 7924                  brprot = brprot_old;
7853 7925          if (!(cfg.field_mask & BR_CFG_AGE))
7854 7926                  cfg.max_age = cfg_old.max_age;
7855 7927          if (!(cfg.field_mask & BR_CFG_HELLO))
7856 7928                  cfg.hello_time = cfg_old.hello_time;
7857 7929          if (!(cfg.field_mask & BR_CFG_DELAY))
7858 7930                  cfg.forward_delay = cfg_old.forward_delay;
7859 7931  
7860 7932          if (!CHECK_BRIDGE_CONFIG(cfg)) {
7861 7933                  warn("illegal forward delay / max age / hello time "
7862 7934                      "combination");
7863 7935                  if (NO_MAXAGE(cfg)) {
7864 7936                          die("no max age possible: need forward delay >= %d or "
7865 7937                              "hello time <= %d", MIN_FWDELAY_NOM(cfg),
7866 7938                              MAX_HELLOTIME_NOM(cfg));
7867 7939                  } else if (SMALL_MAXAGE(cfg)) {
7868 7940                          if (CAPPED_MAXAGE(cfg))
7869 7941                                  die("max age too small: need age >= %d and "
7870 7942                                      "<= %d or hello time <= %d",
7871 7943                                      MIN_MAXAGE(cfg), MAX_MAXAGE(cfg),
7872 7944                                      MAX_HELLOTIME(cfg));
7873 7945                          else
7874 7946                                  die("max age too small: need age >= %d or "
7875 7947                                      "hello time <= %d",
7876 7948                                      MIN_MAXAGE(cfg), MAX_HELLOTIME(cfg));
7877 7949                  } else if (FLOORED_MAXAGE(cfg)) {
7878 7950                          die("max age too large: need age >= %d and <= %d or "
7879 7951                              "forward delay >= %d",
7880 7952                              MIN_MAXAGE(cfg), MAX_MAXAGE(cfg),
7881 7953                              MIN_FWDELAY(cfg));
7882 7954                  } else {
7883 7955                          die("max age too large: need age <= %d or forward "
7884 7956                              "delay >= %d",
7885 7957                              MAX_MAXAGE(cfg), MIN_FWDELAY(cfg));
7886 7958                  }
7887 7959          }
7888 7960  
7889 7961          if (altroot != NULL)
7890 7962                  altroot_cmd(altroot, argc, argv);
7891 7963  
7892 7964          for (n = 0; n < nlink; n++) {
7893 7965                  datalink_class_t class;
7894 7966                  uint32_t media;
7895 7967                  char pointless[DLADM_STRSIZE];
7896 7968  
7897 7969                  if (dladm_name2info(handle, links[n], &linkids[n], NULL, &class,
7898 7970                      &media) != DLADM_STATUS_OK)
7899 7971                          die("invalid link name '%s'", links[n]);
7900 7972                  if (class & ~(DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR |
7901 7973                      DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET))
7902 7974                          die("%s %s cannot be bridged",
7903 7975                              dladm_class2str(class, pointless), links[n]);
7904 7976                  if (media != DL_ETHER && media != DL_100VG &&
7905 7977                      media != DL_ETH_CSMA && media != DL_100BT)
7906 7978                          die("%s interface %s cannot be bridged",
7907 7979                              dladm_media2str(media, pointless), links[n]);
7908 7980          }
7909 7981  
7910 7982          if (func == brCreate)
7911 7983                  flags |= DLADM_OPT_CREATE;
7912 7984  
7913 7985          if (func != brAdd) {
7914 7986                  status = dladm_bridge_configure(handle, bridge, &cfg, brprot,
7915 7987                      flags);
7916 7988                  if (status != DLADM_STATUS_OK)
7917 7989                          die_dlerr(status, "create operation failed");
7918 7990          }
7919 7991  
7920 7992          status = DLADM_STATUS_OK;
7921 7993          for (n = 0; n < nlink; n++) {
7922 7994                  status = dladm_bridge_setlink(handle, linkids[n], bridge);
7923 7995                  if (status != DLADM_STATUS_OK)
7924 7996                          break;
7925 7997          }
7926 7998  
7927 7999          if (n >= nlink) {
7928 8000                  /*
7929 8001                   * We were successful.  If we're creating a new bridge, then
7930 8002                   * there's just one more step: enabling.  If we're modifying or
7931 8003                   * just adding links, then we're done.
7932 8004                   */
7933 8005                  if (func != brCreate ||
7934 8006                      (status = dladm_bridge_enable(bridge)) == DLADM_STATUS_OK)
7935 8007                          return;
7936 8008          }
7937 8009  
7938 8010          /* clean up the partial configuration */
7939 8011          for (i = 0; i < n; i++)
7940 8012                  (void) dladm_bridge_setlink(handle, linkids[i], "");
7941 8013  
7942 8014          /* if failure for brCreate, then delete the bridge */
7943 8015          if (func == brCreate)
7944 8016                  (void) dladm_bridge_delete(handle, bridge, flags);
7945 8017  
7946 8018          if (n < nlink)
7947 8019                  die_dlerr(status, "unable to add link %s to bridge %s",
7948 8020                      links[n], bridge);
7949 8021          else
7950 8022                  die_dlerr(status, "unable to enable bridge %s", bridge);
7951 8023  }
7952 8024  
7953 8025  static void
7954 8026  do_create_bridge(int argc, char **argv, const char *use)
7955 8027  {
7956 8028          create_modify_add_bridge(argc, argv, use, brCreate);
7957 8029  }
7958 8030  
7959 8031  static void
7960 8032  do_modify_bridge(int argc, char **argv, const char *use)
7961 8033  {
7962 8034          create_modify_add_bridge(argc, argv, use, brModify);
7963 8035  }
7964 8036  
7965 8037  static void
7966 8038  do_add_bridge(int argc, char **argv, const char *use)
7967 8039  {
7968 8040          create_modify_add_bridge(argc, argv, use, brAdd);
7969 8041  }
7970 8042  
7971 8043  static void
7972 8044  do_delete_bridge(int argc, char **argv, const char *use)
7973 8045  {
7974 8046          char                    option;
7975 8047          char                    *altroot = NULL;
7976 8048          uint32_t                flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
7977 8049          dladm_status_t          status;
7978 8050  
7979 8051          opterr = 0;
7980 8052          while ((option = getopt_long(argc, argv, ":R:", bridge_lopts, NULL)) !=
7981 8053              -1) {
7982 8054                  switch (option) {
7983 8055                  case 'R':
7984 8056                          altroot = optarg;
7985 8057                          break;
7986 8058                  default:
7987 8059                          die_opterr(optopt, option, use);
7988 8060                          break;
7989 8061                  }
7990 8062          }
7991 8063  
7992 8064          /* get the bridge name (required last argument) */
7993 8065          if (optind != (argc-1))
7994 8066                  usage();
7995 8067  
7996 8068          if (altroot != NULL)
7997 8069                  altroot_cmd(altroot, argc, argv);
7998 8070  
7999 8071          status = dladm_bridge_delete(handle, argv[optind], flags);
8000 8072          if (status != DLADM_STATUS_OK)
8001 8073                  die_dlerr(status, "delete operation failed");
8002 8074  }
8003 8075  
8004 8076  static void
8005 8077  do_remove_bridge(int argc, char **argv, const char *use)
8006 8078  {
8007 8079          char            option;
8008 8080          uint_t          n, nlink;
8009 8081          char            *links[MAXPORT];
8010 8082          datalink_id_t   linkids[MAXPORT];
8011 8083          char            *altroot = NULL;
8012 8084          dladm_status_t  status;
8013 8085          boolean_t       removed_one;
8014 8086  
8015 8087          nlink = opterr = 0;
8016 8088          while ((option = getopt_long(argc, argv, ":R:l:", bridge_lopts,
8017 8089              NULL)) != -1) {
8018 8090                  switch (option) {
8019 8091                  case 'R':
8020 8092                          altroot = optarg;
8021 8093                          break;
8022 8094                  case 'l':
8023 8095                          if (nlink >= MAXPORT)
8024 8096                                  die("too many links specified");
8025 8097                          links[nlink++] = optarg;
8026 8098                          break;
8027 8099                  default:
8028 8100                          die_opterr(optopt, option, use);
8029 8101                          break;
8030 8102                  }
8031 8103          }
8032 8104  
8033 8105          if (nlink == 0)
8034 8106                  usage();
8035 8107  
8036 8108          /* get the bridge name (required last argument) */
8037 8109          if (optind != (argc-1))
8038 8110                  usage();
8039 8111  
8040 8112          if (altroot != NULL)
8041 8113                  altroot_cmd(altroot, argc, argv);
8042 8114  
8043 8115          for (n = 0; n < nlink; n++) {
8044 8116                  char bridge[MAXLINKNAMELEN];
8045 8117  
8046 8118                  if (dladm_name2info(handle, links[n], &linkids[n], NULL, NULL,
8047 8119                      NULL) != DLADM_STATUS_OK)
8048 8120                          die("invalid link name '%s'", links[n]);
8049 8121                  status = dladm_bridge_getlink(handle, linkids[n], bridge,
8050 8122                      sizeof (bridge));
8051 8123                  if (status != DLADM_STATUS_OK &&
8052 8124                      status != DLADM_STATUS_NOTFOUND) {
8053 8125                          die_dlerr(status, "cannot get bridge status on %s",
8054 8126                              links[n]);
8055 8127                  }
8056 8128                  if (status == DLADM_STATUS_NOTFOUND ||
8057 8129                      strcmp(bridge, argv[optind]) != 0)
8058 8130                          die("link %s is not on bridge %s", links[n],
8059 8131                              argv[optind]);
8060 8132          }
8061 8133  
8062 8134          removed_one = B_FALSE;
8063 8135          for (n = 0; n < nlink; n++) {
8064 8136                  status = dladm_bridge_setlink(handle, linkids[n], "");
8065 8137                  if (status == DLADM_STATUS_OK) {
8066 8138                          removed_one = B_TRUE;
8067 8139                  } else {
8068 8140                          warn_dlerr(status,
8069 8141                              "cannot remove link %s from bridge %s",
8070 8142                              links[n], argv[optind]);
8071 8143                  }
8072 8144          }
8073 8145          if (!removed_one)
8074 8146                  die("unable to remove any links from bridge %s", argv[optind]);
8075 8147  }
8076 8148  
8077 8149  static void
8078 8150  fmt_int(char *buf, size_t buflen, int value, int runvalue,
8079 8151      boolean_t printstar)
8080 8152  {
8081 8153          (void) snprintf(buf, buflen, "%d", value);
8082 8154          if (value != runvalue && printstar)
8083 8155                  (void) strlcat(buf, "*", buflen);
8084 8156  }
8085 8157  
8086 8158  static void
8087 8159  fmt_bridge_id(char *buf, size_t buflen, UID_BRIDGE_ID_T *bid)
8088 8160  {
8089 8161          (void) snprintf(buf, buflen, "%u/%x:%x:%x:%x:%x:%x", bid->prio,
8090 8162              bid->addr[0], bid->addr[1], bid->addr[2], bid->addr[3],
8091 8163              bid->addr[4], bid->addr[5]);
8092 8164  }
8093 8165  
8094 8166  static dladm_status_t
8095 8167  print_bridge(show_state_t *state, datalink_id_t linkid,
8096 8168      bridge_fields_buf_t *bbuf)
8097 8169  {
8098 8170          char                    link[MAXLINKNAMELEN];
8099 8171          datalink_class_t        class;
8100 8172          uint32_t                flags;
8101 8173          dladm_status_t          status;
8102 8174          UID_STP_CFG_T           smfcfg, runcfg;
8103 8175          UID_STP_STATE_T         stpstate;
8104 8176          dladm_bridge_prot_t     smfprot, runprot;
8105 8177  
8106 8178          if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
8107 8179              NULL, link, sizeof (link))) != DLADM_STATUS_OK)
8108 8180                  return (status);
8109 8181  
8110 8182          if (!(state->ls_flags & flags))
8111 8183                  return (DLADM_STATUS_NOTFOUND);
8112 8184  
8113 8185          /* Convert observability node name back to bridge name */
8114 8186          if (!dladm_observe_to_bridge(link))
8115 8187                  return (DLADM_STATUS_NOTFOUND);
8116 8188          (void) strlcpy(bbuf->bridge_name, link, sizeof (bbuf->bridge_name));
8117 8189  
8118 8190          /*
8119 8191           * If the running value differs from the one in SMF, and parsable
8120 8192           * output is not requested, then we show the running value with an
8121 8193           * asterisk.
8122 8194           */
8123 8195          (void) dladm_bridge_get_properties(bbuf->bridge_name, &smfcfg,
8124 8196              &smfprot);
8125 8197          (void) dladm_bridge_run_properties(bbuf->bridge_name, &runcfg,
8126 8198              &runprot);
8127 8199          (void) snprintf(bbuf->bridge_protect, sizeof (bbuf->bridge_protect),
8128 8200              "%s%s", state->ls_parsable || smfprot == runprot ? "" : "*",
8129 8201              dladm_bridge_prot2str(runprot));
8130 8202          fmt_int(bbuf->bridge_priority, sizeof (bbuf->bridge_priority),
8131 8203              smfcfg.bridge_priority, runcfg.bridge_priority,
8132 8204              !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE));
8133 8205          fmt_int(bbuf->bridge_bmaxage, sizeof (bbuf->bridge_bmaxage),
8134 8206              smfcfg.max_age, runcfg.max_age,
8135 8207              !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE));
8136 8208          fmt_int(bbuf->bridge_bhellotime,
8137 8209              sizeof (bbuf->bridge_bhellotime), smfcfg.hello_time,
8138 8210              runcfg.hello_time,
8139 8211              !state->ls_parsable && (runcfg.field_mask & BR_CFG_HELLO));
8140 8212          fmt_int(bbuf->bridge_bfwddelay, sizeof (bbuf->bridge_bfwddelay),
8141 8213              smfcfg.forward_delay, runcfg.forward_delay,
8142 8214              !state->ls_parsable && (runcfg.field_mask & BR_CFG_DELAY));
8143 8215          fmt_int(bbuf->bridge_forceproto, sizeof (bbuf->bridge_forceproto),
8144 8216              smfcfg.force_version, runcfg.force_version,
8145 8217              !state->ls_parsable && (runcfg.field_mask & BR_CFG_FORCE_VER));
8146 8218          fmt_int(bbuf->bridge_holdtime, sizeof (bbuf->bridge_holdtime),
8147 8219              smfcfg.hold_time, runcfg.hold_time,
8148 8220              !state->ls_parsable && (runcfg.field_mask & BR_CFG_HOLD_TIME));
8149 8221  
8150 8222          if (dladm_bridge_state(bbuf->bridge_name, &stpstate) ==
8151 8223              DLADM_STATUS_OK) {
8152 8224                  fmt_bridge_id(bbuf->bridge_address,
8153 8225                      sizeof (bbuf->bridge_address), &stpstate.bridge_id);
8154 8226                  (void) snprintf(bbuf->bridge_tctime,
8155 8227                      sizeof (bbuf->bridge_tctime), "%lu",
8156 8228                      stpstate.timeSince_Topo_Change);
8157 8229                  (void) snprintf(bbuf->bridge_tccount,
8158 8230                      sizeof (bbuf->bridge_tccount), "%lu",
8159 8231                      stpstate.Topo_Change_Count);
8160 8232                  (void) snprintf(bbuf->bridge_tchange,
8161 8233                      sizeof (bbuf->bridge_tchange), "%u", stpstate.Topo_Change);
8162 8234                  fmt_bridge_id(bbuf->bridge_desroot,
8163 8235                      sizeof (bbuf->bridge_desroot), &stpstate.designated_root);
8164 8236                  (void) snprintf(bbuf->bridge_rootcost,
8165 8237                      sizeof (bbuf->bridge_rootcost), "%lu",
8166 8238                      stpstate.root_path_cost);
8167 8239                  (void) snprintf(bbuf->bridge_rootport,
8168 8240                      sizeof (bbuf->bridge_rootport), "%u", stpstate.root_port);
8169 8241                  (void) snprintf(bbuf->bridge_maxage,
8170 8242                      sizeof (bbuf->bridge_maxage), "%d", stpstate.max_age);
8171 8243                  (void) snprintf(bbuf->bridge_hellotime,
8172 8244                      sizeof (bbuf->bridge_hellotime), "%d", stpstate.hello_time);
8173 8245                  (void) snprintf(bbuf->bridge_fwddelay,
8174 8246                      sizeof (bbuf->bridge_fwddelay), "%d",
8175 8247                      stpstate.forward_delay);
8176 8248          }
8177 8249          return (DLADM_STATUS_OK);
8178 8250  }
8179 8251  
8180 8252  static dladm_status_t
8181 8253  print_bridge_stats(show_state_t *state, datalink_id_t linkid,
8182 8254      bridge_statfields_buf_t *bbuf)
8183 8255  {
8184 8256          char                    link[MAXLINKNAMELEN];
8185 8257          datalink_class_t        class;
8186 8258          uint32_t                flags;
8187 8259          dladm_status_t          status;
8188 8260          kstat_ctl_t             *kcp;
8189 8261          kstat_t                 *ksp;
8190 8262          brsum_t                 *brsum = (brsum_t *)&state->ls_prevstats;
8191 8263          brsum_t                 newval;
8192 8264  
8193 8265  #ifndef lint
8194 8266          /* This is a compile-time assertion; optimizer normally fixes this */
8195 8267          extern void brsum_t_is_too_large(void);
8196 8268  
8197 8269          if (sizeof (*brsum) > sizeof (state->ls_prevstats))
8198 8270                  brsum_t_is_too_large();
8199 8271  #endif
8200 8272  
8201 8273          if (state->ls_firstonly) {
8202 8274                  if (state->ls_donefirst)
8203 8275                          return (DLADM_WALK_CONTINUE);
8204 8276                  state->ls_donefirst = B_TRUE;
8205 8277          } else {
8206 8278                  bzero(brsum, sizeof (*brsum));
8207 8279          }
8208 8280          bzero(&newval, sizeof (newval));
8209 8281  
8210 8282          if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
8211 8283              NULL, link, sizeof (link))) != DLADM_STATUS_OK)
8212 8284                  return (status);
8213 8285  
8214 8286          if (!(state->ls_flags & flags))
8215 8287                  return (DLADM_STATUS_NOTFOUND);
8216 8288  
8217 8289          if ((kcp = kstat_open()) == NULL) {
8218 8290                  warn("kstat open operation failed");
8219 8291                  return (DLADM_STATUS_OK);
8220 8292          }
8221 8293          if ((ksp = kstat_lookup(kcp, "bridge", 0, link)) != NULL &&
8222 8294              kstat_read(kcp, ksp, NULL) != -1) {
8223 8295                  if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64,
8224 8296                      &newval.drops) == DLADM_STATUS_OK) {
8225 8297                          (void) snprintf(bbuf->bridges_drops,
8226 8298                              sizeof (bbuf->bridges_drops), "%llu",
8227 8299                              newval.drops - brsum->drops);
8228 8300                  }
8229 8301                  if (dladm_kstat_value(ksp, "forward_direct", KSTAT_DATA_UINT64,
8230 8302                      &newval.forward_dir) == DLADM_STATUS_OK) {
8231 8303                          (void) snprintf(bbuf->bridges_forwards,
8232 8304                              sizeof (bbuf->bridges_forwards), "%llu",
8233 8305                              newval.forward_dir - brsum->forward_dir);
8234 8306                  }
8235 8307                  if (dladm_kstat_value(ksp, "forward_mbcast", KSTAT_DATA_UINT64,
8236 8308                      &newval.forward_mb) == DLADM_STATUS_OK) {
8237 8309                          (void) snprintf(bbuf->bridges_mbcast,
8238 8310                              sizeof (bbuf->bridges_mbcast), "%llu",
8239 8311                              newval.forward_mb - brsum->forward_mb);
8240 8312                  }
8241 8313                  if (dladm_kstat_value(ksp, "forward_unknown", KSTAT_DATA_UINT64,
8242 8314                      &newval.forward_unk) == DLADM_STATUS_OK) {
8243 8315                          (void) snprintf(bbuf->bridges_unknown,
8244 8316                              sizeof (bbuf->bridges_unknown), "%llu",
8245 8317                              newval.forward_unk - brsum->forward_unk);
8246 8318                  }
8247 8319                  if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64,
8248 8320                      &newval.recv) == DLADM_STATUS_OK) {
8249 8321                          (void) snprintf(bbuf->bridges_recv,
8250 8322                              sizeof (bbuf->bridges_recv), "%llu",
8251 8323                              newval.recv - brsum->recv);
8252 8324                  }
8253 8325                  if (dladm_kstat_value(ksp, "sent", KSTAT_DATA_UINT64,
8254 8326                      &newval.sent) == DLADM_STATUS_OK) {
8255 8327                          (void) snprintf(bbuf->bridges_sent,
8256 8328                              sizeof (bbuf->bridges_sent), "%llu",
8257 8329                              newval.sent - brsum->sent);
8258 8330                  }
8259 8331          }
8260 8332          (void) kstat_close(kcp);
8261 8333  
8262 8334          /* Convert observability node name back to bridge name */
8263 8335          if (!dladm_observe_to_bridge(link))
8264 8336                  return (DLADM_STATUS_NOTFOUND);
8265 8337          (void) strlcpy(bbuf->bridges_name, link, sizeof (bbuf->bridges_name));
8266 8338  
8267 8339          *brsum = newval;
8268 8340  
8269 8341          return (DLADM_STATUS_OK);
8270 8342  }
8271 8343  
8272 8344  /*
8273 8345   * This structure carries around extra state information for the show-bridge
8274 8346   * command and allows us to use common support functions.
8275 8347   */
8276 8348  typedef struct {
8277 8349          show_state_t    state;
8278 8350          boolean_t       show_stats;
8279 8351          const char      *bridge;
8280 8352  } show_brstate_t;
8281 8353  
8282 8354  /* ARGSUSED */
8283 8355  static int
8284 8356  show_bridge(dladm_handle_t handle, datalink_id_t linkid, void *arg)
8285 8357  {
8286 8358          show_brstate_t  *brstate = arg;
8287 8359          void *buf;
8288 8360  
8289 8361          if (brstate->show_stats) {
8290 8362                  bridge_statfields_buf_t bbuf;
8291 8363  
8292 8364                  bzero(&bbuf, sizeof (bbuf));
8293 8365                  brstate->state.ls_status = print_bridge_stats(&brstate->state,
8294 8366                      linkid, &bbuf);
8295 8367                  buf = &bbuf;
8296 8368          } else {
8297 8369                  bridge_fields_buf_t bbuf;
8298 8370  
8299 8371                  bzero(&bbuf, sizeof (bbuf));
8300 8372                  brstate->state.ls_status = print_bridge(&brstate->state, linkid,
8301 8373                      &bbuf);
8302 8374                  buf = &bbuf;
8303 8375          }
8304 8376          if (brstate->state.ls_status == DLADM_STATUS_OK)
8305 8377                  ofmt_print(brstate->state.ls_ofmt, buf);
8306 8378          return (DLADM_WALK_CONTINUE);
8307 8379  }
8308 8380  
8309 8381  static void
8310 8382  fmt_bool(char *buf, size_t buflen, int val)
8311 8383  {
8312 8384          (void) strlcpy(buf, val ? "yes" : "no", buflen);
8313 8385  }
8314 8386  
8315 8387  static dladm_status_t
8316 8388  print_bridge_link(show_state_t *state, datalink_id_t linkid,
8317 8389      bridge_link_fields_buf_t *bbuf)
8318 8390  {
8319 8391          datalink_class_t        class;
8320 8392          uint32_t                flags;
8321 8393          dladm_status_t          status;
8322 8394          UID_STP_PORT_STATE_T    stpstate;
8323 8395  
8324 8396          status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL,
8325 8397              bbuf->bridgel_link, sizeof (bbuf->bridgel_link));
8326 8398          if (status != DLADM_STATUS_OK)
8327 8399                  return (status);
8328 8400  
8329 8401          if (!(state->ls_flags & flags))
8330 8402                  return (DLADM_STATUS_NOTFOUND);
8331 8403  
8332 8404          if (dladm_bridge_link_state(handle, linkid, &stpstate) ==
8333 8405              DLADM_STATUS_OK) {
8334 8406                  (void) snprintf(bbuf->bridgel_index,
8335 8407                      sizeof (bbuf->bridgel_index), "%u", stpstate.port_no);
8336 8408                  if (dlsym(RTLD_PROBE, "STP_IN_state2str")) {
8337 8409                          (void) strlcpy(bbuf->bridgel_state,
8338 8410                              STP_IN_state2str(stpstate.state),
8339 8411                              sizeof (bbuf->bridgel_state));
8340 8412                  } else {
8341 8413                          (void) snprintf(bbuf->bridgel_state,
8342 8414                              sizeof (bbuf->bridgel_state), "%u",
8343 8415                              stpstate.state);
8344 8416                  }
8345 8417                  (void) snprintf(bbuf->bridgel_uptime,
8346 8418                      sizeof (bbuf->bridgel_uptime), "%lu", stpstate.uptime);
8347 8419                  (void) snprintf(bbuf->bridgel_opercost,
8348 8420                      sizeof (bbuf->bridgel_opercost), "%lu",
8349 8421                      stpstate.oper_port_path_cost);
8350 8422                  fmt_bool(bbuf->bridgel_operp2p, sizeof (bbuf->bridgel_operp2p),
8351 8423                      stpstate.oper_point2point);
8352 8424                  fmt_bool(bbuf->bridgel_operedge,
8353 8425                      sizeof (bbuf->bridgel_operedge), stpstate.oper_edge);
8354 8426                  fmt_bridge_id(bbuf->bridgel_desroot,
8355 8427                      sizeof (bbuf->bridgel_desroot), &stpstate.designated_root);
8356 8428                  (void) snprintf(bbuf->bridgel_descost,
8357 8429                      sizeof (bbuf->bridgel_descost), "%lu",
8358 8430                      stpstate.designated_cost);
8359 8431                  fmt_bridge_id(bbuf->bridgel_desbridge,
8360 8432                      sizeof (bbuf->bridgel_desbridge),
8361 8433                      &stpstate.designated_bridge);
8362 8434                  (void) snprintf(bbuf->bridgel_desport,
8363 8435                      sizeof (bbuf->bridgel_desport), "%u",
8364 8436                      stpstate.designated_port);
8365 8437                  fmt_bool(bbuf->bridgel_tcack, sizeof (bbuf->bridgel_tcack),
8366 8438                      stpstate.top_change_ack);
8367 8439          }
8368 8440          return (DLADM_STATUS_OK);
8369 8441  }
8370 8442  
8371 8443  static dladm_status_t
8372 8444  print_bridge_link_stats(show_state_t *state, datalink_id_t linkid,
8373 8445      bridge_link_statfields_buf_t *bbuf)
8374 8446  {
8375 8447          datalink_class_t        class;
8376 8448          uint32_t                flags;
8377 8449          dladm_status_t          status;
8378 8450          UID_STP_PORT_STATE_T    stpstate;
8379 8451          kstat_ctl_t             *kcp;
8380 8452          kstat_t                 *ksp;
8381 8453          char                    bridge[MAXLINKNAMELEN];
8382 8454          char                    kstatname[MAXLINKNAMELEN*2 + 1];
8383 8455          brlsum_t                *brlsum = (brlsum_t *)&state->ls_prevstats;
8384 8456          brlsum_t                newval;
8385 8457  
8386 8458  #ifndef lint
8387 8459          /* This is a compile-time assertion; optimizer normally fixes this */
8388 8460          extern void brlsum_t_is_too_large(void);
8389 8461  
8390 8462          if (sizeof (*brlsum) > sizeof (state->ls_prevstats))
8391 8463                  brlsum_t_is_too_large();
8392 8464  #endif
8393 8465  
8394 8466          if (state->ls_firstonly) {
8395 8467                  if (state->ls_donefirst)
8396 8468                          return (DLADM_WALK_CONTINUE);
8397 8469                  state->ls_donefirst = B_TRUE;
8398 8470          } else {
8399 8471                  bzero(brlsum, sizeof (*brlsum));
8400 8472          }
8401 8473          bzero(&newval, sizeof (newval));
8402 8474  
8403 8475          status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL,
8404 8476              bbuf->bridgels_link, sizeof (bbuf->bridgels_link));
8405 8477          if (status != DLADM_STATUS_OK)
8406 8478                  return (status);
8407 8479  
8408 8480          if (!(state->ls_flags & flags))
8409 8481                  return (DLADM_STATUS_NOTFOUND);
8410 8482  
8411 8483          if (dladm_bridge_link_state(handle, linkid, &stpstate) ==
8412 8484              DLADM_STATUS_OK) {
8413 8485                  newval.cfgbpdu = stpstate.rx_cfg_bpdu_cnt;
8414 8486                  newval.tcnbpdu = stpstate.rx_tcn_bpdu_cnt;
8415 8487                  newval.rstpbpdu = stpstate.rx_rstp_bpdu_cnt;
8416 8488                  newval.txbpdu = stpstate.txCount;
8417 8489  
8418 8490                  (void) snprintf(bbuf->bridgels_cfgbpdu,
8419 8491                      sizeof (bbuf->bridgels_cfgbpdu), "%lu",
8420 8492                      newval.cfgbpdu - brlsum->cfgbpdu);
8421 8493                  (void) snprintf(bbuf->bridgels_tcnbpdu,
8422 8494                      sizeof (bbuf->bridgels_tcnbpdu), "%lu",
8423 8495                      newval.tcnbpdu - brlsum->tcnbpdu);
8424 8496                  (void) snprintf(bbuf->bridgels_rstpbpdu,
8425 8497                      sizeof (bbuf->bridgels_rstpbpdu), "%lu",
8426 8498                      newval.rstpbpdu - brlsum->rstpbpdu);
8427 8499                  (void) snprintf(bbuf->bridgels_txbpdu,
8428 8500                      sizeof (bbuf->bridgels_txbpdu), "%lu",
8429 8501                      newval.txbpdu - brlsum->txbpdu);
8430 8502          }
8431 8503  
8432 8504          if ((status = dladm_bridge_getlink(handle, linkid, bridge,
8433 8505              sizeof (bridge))) != DLADM_STATUS_OK)
8434 8506                  goto bls_out;
8435 8507          (void) snprintf(kstatname, sizeof (kstatname), "%s0-%s", bridge,
8436 8508              bbuf->bridgels_link);
8437 8509          if ((kcp = kstat_open()) == NULL) {
8438 8510                  warn("kstat open operation failed");
8439 8511                  goto bls_out;
8440 8512          }
8441 8513          if ((ksp = kstat_lookup(kcp, "bridge", 0, kstatname)) != NULL &&
8442 8514              kstat_read(kcp, ksp, NULL) != -1) {
8443 8515                  if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64,
8444 8516                      &newval.drops) != -1) {
8445 8517                          (void) snprintf(bbuf->bridgels_drops,
8446 8518                              sizeof (bbuf->bridgels_drops), "%llu",
8447 8519                              newval.drops - brlsum->drops);
8448 8520                  }
8449 8521                  if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64,
8450 8522                      &newval.recv) != -1) {
8451 8523                          (void) snprintf(bbuf->bridgels_recv,
8452 8524                              sizeof (bbuf->bridgels_recv), "%llu",
8453 8525                              newval.recv - brlsum->recv);
8454 8526                  }
8455 8527                  if (dladm_kstat_value(ksp, "xmit", KSTAT_DATA_UINT64,
8456 8528                      &newval.xmit) != -1) {
8457 8529                          (void) snprintf(bbuf->bridgels_xmit,
8458 8530                              sizeof (bbuf->bridgels_xmit), "%llu",
8459 8531                              newval.xmit - brlsum->xmit);
8460 8532                  }
8461 8533          }
8462 8534          (void) kstat_close(kcp);
8463 8535  bls_out:
8464 8536          *brlsum = newval;
8465 8537  
8466 8538          return (status);
8467 8539  }
8468 8540  
8469 8541  static void
8470 8542  show_bridge_link(datalink_id_t linkid, show_brstate_t *brstate)
8471 8543  {
8472 8544          void *buf;
8473 8545  
8474 8546          if (brstate->show_stats) {
8475 8547                  bridge_link_statfields_buf_t bbuf;
8476 8548  
8477 8549                  bzero(&bbuf, sizeof (bbuf));
8478 8550                  brstate->state.ls_status = print_bridge_link_stats(
8479 8551                      &brstate->state, linkid, &bbuf);
8480 8552                  buf = &bbuf;
8481 8553          } else {
8482 8554                  bridge_link_fields_buf_t bbuf;
8483 8555  
8484 8556                  bzero(&bbuf, sizeof (bbuf));
8485 8557                  brstate->state.ls_status = print_bridge_link(&brstate->state,
8486 8558                      linkid, &bbuf);
8487 8559                  buf = &bbuf;
8488 8560          }
8489 8561          if (brstate->state.ls_status == DLADM_STATUS_OK)
8490 8562                  ofmt_print(brstate->state.ls_ofmt, buf);
8491 8563  }
8492 8564  
8493 8565  /* ARGSUSED */
8494 8566  static int
8495 8567  show_bridge_link_walk(dladm_handle_t handle, datalink_id_t linkid, void *arg)
8496 8568  {
8497 8569          show_brstate_t  *brstate = arg;
8498 8570          char bridge[MAXLINKNAMELEN];
8499 8571  
8500 8572          if (dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge)) ==
8501 8573              DLADM_STATUS_OK && strcmp(bridge, brstate->bridge) == 0) {
8502 8574                  show_bridge_link(linkid, brstate);
8503 8575          }
8504 8576          return (DLADM_WALK_CONTINUE);
8505 8577  }
8506 8578  
8507 8579  static void
8508 8580  show_bridge_fwd(dladm_handle_t handle, bridge_listfwd_t *blf,
8509 8581      show_state_t *state)
8510 8582  {
8511 8583          bridge_fwd_fields_buf_t bbuf;
8512 8584  
8513 8585          bzero(&bbuf, sizeof (bbuf));
8514 8586          (void) snprintf(bbuf.bridgef_dest, sizeof (bbuf.bridgef_dest),
8515 8587              "%s", ether_ntoa((struct ether_addr *)blf->blf_dest));
8516 8588          if (blf->blf_is_local) {
8517 8589                  (void) strlcpy(bbuf.bridgef_flags, "L",
8518 8590                      sizeof (bbuf.bridgef_flags));
8519 8591          } else {
8520 8592                  (void) snprintf(bbuf.bridgef_age, sizeof (bbuf.bridgef_age),
8521 8593                      "%2d.%03d", blf->blf_ms_age / 1000, blf->blf_ms_age % 1000);
8522 8594                  if (blf->blf_trill_nick != 0) {
8523 8595                          (void) snprintf(bbuf.bridgef_output,
8524 8596                              sizeof (bbuf.bridgef_output), "%u",
8525 8597                              blf->blf_trill_nick);
8526 8598                  }
8527 8599          }
8528 8600          if (blf->blf_linkid != DATALINK_INVALID_LINKID &&
8529 8601              blf->blf_trill_nick == 0) {
8530 8602                  state->ls_status = dladm_datalink_id2info(handle,
8531 8603                      blf->blf_linkid, NULL, NULL, NULL, bbuf.bridgef_output,
8532 8604                      sizeof (bbuf.bridgef_output));
8533 8605          }
8534 8606          if (state->ls_status == DLADM_STATUS_OK)
8535 8607                  ofmt_print(state->ls_ofmt, &bbuf);
8536 8608  }
8537 8609  
8538 8610  static void
8539 8611  show_bridge_trillnick(trill_listnick_t *tln, show_state_t *state)
8540 8612  {
8541 8613          bridge_trill_fields_buf_t bbuf;
8542 8614  
8543 8615          bzero(&bbuf, sizeof (bbuf));
8544 8616          (void) snprintf(bbuf.bridget_nick, sizeof (bbuf.bridget_nick),
8545 8617              "%u", tln->tln_nick);
8546 8618          if (tln->tln_ours) {
8547 8619                  (void) strlcpy(bbuf.bridget_flags, "L",
8548 8620                      sizeof (bbuf.bridget_flags));
8549 8621          } else {
8550 8622                  state->ls_status = dladm_datalink_id2info(handle,
8551 8623                      tln->tln_linkid, NULL, NULL, NULL, bbuf.bridget_link,
8552 8624                      sizeof (bbuf.bridget_link));
8553 8625                  (void) snprintf(bbuf.bridget_nexthop,
8554 8626                      sizeof (bbuf.bridget_nexthop), "%s",
8555 8627                      ether_ntoa((struct ether_addr *)tln->tln_nexthop));
8556 8628          }
8557 8629          if (state->ls_status == DLADM_STATUS_OK)
8558 8630                  ofmt_print(state->ls_ofmt, &bbuf);
8559 8631  }
8560 8632  
8561 8633  static void
8562 8634  do_show_bridge(int argc, char **argv, const char *use)
8563 8635  {
8564 8636          int             option;
8565 8637          enum {
8566 8638                  bridgeMode, linkMode, fwdMode, trillMode
8567 8639          }               op_mode = bridgeMode;
8568 8640          uint32_t        flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
8569 8641          boolean_t       parsable = B_FALSE;
8570 8642          datalink_id_t   linkid = DATALINK_ALL_LINKID;
8571 8643          int             interval = 0;
8572 8644          show_brstate_t  brstate;
8573 8645          dladm_status_t  status;
8574 8646          char            *fields_str = NULL;
8575 8647          /* default: bridge-related data */
8576 8648          char            *all_fields = "bridge,protect,address,priority,bmaxage,"
8577 8649              "bhellotime,bfwddelay,forceproto,tctime,tccount,tchange,"
8578 8650              "desroot,rootcost,rootport,maxage,hellotime,fwddelay,holdtime";
8579 8651          char            *default_fields = "bridge,protect,address,priority,"
8580 8652              "desroot";
8581 8653          char            *all_statfields = "bridge,drops,forwards,mbcast,"
8582 8654              "unknown,recv,sent";
8583 8655          char            *default_statfields = "bridge,drops,forwards,mbcast,"
8584 8656              "unknown";
8585 8657          /* -l: link-related data */
8586 8658          char            *all_link_fields = "link,index,state,uptime,opercost,"
8587 8659              "operp2p,operedge,desroot,descost,desbridge,desport,tcack";
8588 8660          char            *default_link_fields = "link,state,uptime,desroot";
8589 8661          char            *all_link_statfields = "link,cfgbpdu,tcnbpdu,rstpbpdu,"
8590 8662              "txbpdu,drops,recv,xmit";
8591 8663          char            *default_link_statfields = "link,drops,recv,xmit";
8592 8664          /* -f: bridge forwarding table related data */
8593 8665          char            *default_fwd_fields = "dest,age,flags,output";
8594 8666          /* -t: TRILL nickname table related data */
8595 8667          char            *default_trill_fields = "nick,flags,link,nexthop";
8596 8668          char            *default_str;
8597 8669          char            *all_str;
8598 8670          ofmt_field_t    *field_arr;
8599 8671          ofmt_handle_t   ofmt;
8600 8672          ofmt_status_t   oferr;
8601 8673          uint_t          ofmtflags = 0;
8602 8674  
8603 8675          bzero(&brstate, sizeof (brstate));
8604 8676  
8605 8677          opterr = 0;
8606 8678          while ((option = getopt_long(argc, argv, ":fi:lo:pst",
8607 8679              bridge_show_lopts, NULL)) != -1) {
8608 8680                  switch (option) {
8609 8681                  case 'f':
8610 8682                          if (op_mode != bridgeMode && op_mode != fwdMode)
8611 8683                                  die("-f is incompatible with -l or -t");
8612 8684                          op_mode = fwdMode;
8613 8685                          break;
8614 8686                  case 'i':
8615 8687                          if (interval != 0)
8616 8688                                  die_optdup(option);
8617 8689                          if (!str2int(optarg, &interval) || interval == 0)
8618 8690                                  die("invalid interval value '%s'", optarg);
8619 8691                          break;
8620 8692                  case 'l':
8621 8693                          if (op_mode != bridgeMode && op_mode != linkMode)
8622 8694                                  die("-l is incompatible with -f or -t");
8623 8695                          op_mode = linkMode;
8624 8696                          break;
8625 8697                  case 'o':
8626 8698                          fields_str = optarg;
8627 8699                          break;
8628 8700                  case 'p':
8629 8701                          if (parsable)
8630 8702                                  die_optdup(option);
8631 8703                          parsable = B_TRUE;
8632 8704                          break;
8633 8705                  case 's':
8634 8706                          if (brstate.show_stats)
8635 8707                                  die_optdup(option);
8636 8708                          brstate.show_stats = B_TRUE;
8637 8709                          break;
8638 8710                  case 't':
8639 8711                          if (op_mode != bridgeMode && op_mode != trillMode)
8640 8712                                  die("-t is incompatible with -f or -l");
8641 8713                          op_mode = trillMode;
8642 8714                          break;
8643 8715                  default:
8644 8716                          die_opterr(optopt, option, use);
8645 8717                          break;
8646 8718                  }
8647 8719          }
8648 8720  
8649 8721          if (interval != 0 && !brstate.show_stats)
8650 8722                  die("the -i option can be used only with -s");
8651 8723  
8652 8724          if ((op_mode == fwdMode || op_mode == trillMode) && brstate.show_stats)
8653 8725                  die("the -f/-t and -s options cannot be used together");
8654 8726  
8655 8727          /* get the bridge name (optional last argument) */
8656 8728          if (optind == (argc-1)) {
8657 8729                  char lname[MAXLINKNAMELEN];
8658 8730                  uint32_t lnkflg;
8659 8731                  datalink_class_t class;
8660 8732  
8661 8733                  brstate.bridge = argv[optind];
8662 8734                  (void) snprintf(lname, sizeof (lname), "%s0", brstate.bridge);
8663 8735                  if ((status = dladm_name2info(handle, lname, &linkid, &lnkflg,
8664 8736                      &class, NULL)) != DLADM_STATUS_OK) {
8665 8737                          die_dlerr(status, "bridge %s is not valid",
8666 8738                              brstate.bridge);
8667 8739                  }
8668 8740  
8669 8741                  if (class != DATALINK_CLASS_BRIDGE)
8670 8742                          die("%s is not a bridge", brstate.bridge);
8671 8743  
8672 8744                  if (!(lnkflg & flags)) {
8673 8745                          die_dlerr(DLADM_STATUS_BADARG,
8674 8746                              "bridge %s is temporarily removed", brstate.bridge);
8675 8747                  }
8676 8748          } else if (optind != argc) {
8677 8749                  usage();
8678 8750          } else if (op_mode != bridgeMode) {
8679 8751                  die("bridge name required for -l, -f, or -t");
8680 8752                  return;
8681 8753          }
8682 8754  
8683 8755          brstate.state.ls_parsable = parsable;
8684 8756          brstate.state.ls_flags = flags;
8685 8757          brstate.state.ls_firstonly = (interval != 0);
8686 8758  
8687 8759          switch (op_mode) {
8688 8760          case bridgeMode:
8689 8761                  if (brstate.show_stats) {
8690 8762                          default_str = default_statfields;
8691 8763                          all_str = all_statfields;
8692 8764                          field_arr = bridge_statfields;
8693 8765                  } else {
8694 8766                          default_str = default_fields;
8695 8767                          all_str = all_fields;
8696 8768                          field_arr = bridge_fields;
8697 8769                  }
8698 8770                  break;
8699 8771  
8700 8772          case linkMode:
8701 8773                  if (brstate.show_stats) {
8702 8774                          default_str = default_link_statfields;
8703 8775                          all_str = all_link_statfields;
8704 8776                          field_arr = bridge_link_statfields;
8705 8777                  } else {
8706 8778                          default_str = default_link_fields;
8707 8779                          all_str = all_link_fields;
8708 8780                          field_arr = bridge_link_fields;
8709 8781                  }
8710 8782                  break;
8711 8783  
8712 8784          case fwdMode:
8713 8785                  default_str = all_str = default_fwd_fields;
8714 8786                  field_arr = bridge_fwd_fields;
8715 8787                  break;
8716 8788  
8717 8789          case trillMode:
8718 8790                  default_str = all_str = default_trill_fields;
8719 8791                  field_arr = bridge_trill_fields;
8720 8792                  break;
8721 8793          }
8722 8794  
8723 8795          if (fields_str == NULL)
8724 8796                  fields_str = default_str;
8725 8797          else if (strcasecmp(fields_str, "all") == 0)
8726 8798                  fields_str = all_str;
8727 8799  
8728 8800          if (parsable)
8729 8801                  ofmtflags |= OFMT_PARSABLE;
8730 8802          oferr = ofmt_open(fields_str, field_arr, ofmtflags, 0, &ofmt);
8731 8803          dladm_ofmt_check(oferr, brstate.state.ls_parsable, ofmt);
8732 8804          brstate.state.ls_ofmt = ofmt;
8733 8805  
8734 8806          for (;;) {
8735 8807                  brstate.state.ls_donefirst = B_FALSE;
8736 8808                  switch (op_mode) {
8737 8809                  case bridgeMode:
8738 8810                          if (linkid == DATALINK_ALL_LINKID) {
8739 8811                                  (void) dladm_walk_datalink_id(show_bridge,
8740 8812                                      handle, &brstate, DATALINK_CLASS_BRIDGE,
8741 8813                                      DATALINK_ANY_MEDIATYPE, flags);
8742 8814                          } else {
8743 8815                                  (void) show_bridge(handle, linkid, &brstate);
8744 8816                                  if (brstate.state.ls_status !=
8745 8817                                      DLADM_STATUS_OK) {
8746 8818                                          die_dlerr(brstate.state.ls_status,
8747 8819                                              "failed to show bridge %s",
8748 8820                                              brstate.bridge);
8749 8821                                  }
8750 8822                          }
8751 8823                          break;
8752 8824  
8753 8825                  case linkMode: {
8754 8826                          datalink_id_t *dlp;
8755 8827                          uint_t i, nlinks;
8756 8828  
8757 8829                          dlp = dladm_bridge_get_portlist(brstate.bridge,
8758 8830                              &nlinks);
8759 8831                          if (dlp != NULL) {
8760 8832                                  for (i = 0; i < nlinks; i++)
8761 8833                                          show_bridge_link(dlp[i], &brstate);
8762 8834                                  dladm_bridge_free_portlist(dlp);
8763 8835                          } else if (errno == ENOENT) {
8764 8836                                  /* bridge not running; iterate on libdladm */
8765 8837                                  (void) dladm_walk_datalink_id(
8766 8838                                      show_bridge_link_walk, handle,
8767 8839                                      &brstate, DATALINK_CLASS_PHYS |
8768 8840                                      DATALINK_CLASS_AGGR |
8769 8841                                      DATALINK_CLASS_ETHERSTUB,
8770 8842                                      DATALINK_ANY_MEDIATYPE, flags);
8771 8843                          } else {
8772 8844                                  die("unable to get port list for bridge %s: %s",
8773 8845                                      brstate.bridge, strerror(errno));
8774 8846                          }
8775 8847                          break;
8776 8848                  }
8777 8849  
8778 8850                  case fwdMode: {
8779 8851                          bridge_listfwd_t *blf;
8780 8852                          uint_t i, nfwd;
8781 8853  
8782 8854                          blf = dladm_bridge_get_fwdtable(handle, brstate.bridge,
8783 8855                              &nfwd);
8784 8856                          if (blf == NULL) {
8785 8857                                  die("unable to get forwarding entries for "
8786 8858                                      "bridge %s", brstate.bridge);
8787 8859                          } else {
8788 8860                                  for (i = 0; i < nfwd; i++)
8789 8861                                          show_bridge_fwd(handle, blf + i,
8790 8862                                              &brstate.state);
8791 8863                                  dladm_bridge_free_fwdtable(blf);
8792 8864                          }
8793 8865                          break;
8794 8866                  }
8795 8867  
8796 8868                  case trillMode: {
8797 8869                          trill_listnick_t *tln;
8798 8870                          uint_t i, nnick;
8799 8871  
8800 8872                          tln = dladm_bridge_get_trillnick(brstate.bridge,
8801 8873                              &nnick);
8802 8874                          if (tln == NULL) {
8803 8875                                  if (errno == ENOENT)
8804 8876                                          die("bridge %s is not running TRILL",
8805 8877                                              brstate.bridge);
8806 8878                                  else
8807 8879                                          die("unable to get TRILL nickname "
8808 8880                                              "entries for bridge %s",
8809 8881                                              brstate.bridge);
8810 8882                          } else {
8811 8883                                  for (i = 0; i < nnick; i++)
8812 8884                                          show_bridge_trillnick(tln + i,
8813 8885                                              &brstate.state);
8814 8886                                  dladm_bridge_free_trillnick(tln);
8815 8887                          }
8816 8888                          break;
8817 8889                  }
8818 8890                  }
8819 8891                  if (interval == 0)
8820 8892                          break;
8821 8893                  (void) sleep(interval);
8822 8894          }
8823 8895  }
8824 8896  
8825 8897  /*
8826 8898   * "-R" option support. It is used for live upgrading. Append dladm commands
8827 8899   * to a upgrade script which will be run when the alternative root boots up:
8828 8900   *
8829 8901   * - If the /etc/dladm/datalink.conf file exists on the alternative root,
8830 8902   * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink
8831 8903   * script. This script will be run as part of the network/physical service.
8832 8904   * We cannot defer this to /var/svc/profile/upgrade because then the
8833 8905   * configuration will not be able to take effect before network/physical
8834 8906   * plumbs various interfaces.
8835 8907   *
8836 8908   * - If the /etc/dladm/datalink.conf file does not exist on the alternative
8837 8909   * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script,
8838 8910   * which will be run in the manifest-import service.
8839 8911   *
8840 8912   * Note that the SMF team is considering to move the manifest-import service
8841 8913   * to be run at the very begining of boot. Once that is done, the need for
8842 8914   * the /var/svc/profile/upgrade_datalink script will not exist any more.
8843 8915   */
8844 8916  static void
8845 8917  altroot_cmd(char *altroot, int argc, char *argv[])
8846 8918  {
8847 8919          char            path[MAXPATHLEN];
8848 8920          struct stat     stbuf;
8849 8921          FILE            *fp;
8850 8922          int             i;
8851 8923  
8852 8924          /*
8853 8925           * Check for the existence of the /etc/dladm/datalink.conf
8854 8926           * configuration file, and determine the name of script file.
8855 8927           */
8856 8928          (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf",
8857 8929              altroot);
8858 8930          if (stat(path, &stbuf) < 0) {
8859 8931                  (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
8860 8932                      SMF_UPGRADE_FILE);
8861 8933          } else {
8862 8934                  (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
8863 8935                      SMF_UPGRADEDATALINK_FILE);
8864 8936          }
8865 8937  
8866 8938          if ((fp = fopen(path, "a+")) == NULL)
8867 8939                  die("operation not supported on %s", altroot);
8868 8940  
8869 8941          (void) fprintf(fp, "/sbin/dladm ");
8870 8942          for (i = 0; i < argc; i++) {
8871 8943                  /*
8872 8944                   * Directly write to the file if it is not the "-R <altroot>"
8873 8945                   * option. In which case, skip it.
8874 8946                   */
8875 8947                  if (strcmp(argv[i], "-R") != 0)
8876 8948                          (void) fprintf(fp, "%s ", argv[i]);
8877 8949                  else
8878 8950                          i ++;
8879 8951          }
8880 8952          (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG);
8881 8953          (void) fclose(fp);
8882 8954          dladm_close(handle);
8883 8955          exit(EXIT_SUCCESS);
8884 8956  }
8885 8957  
8886 8958  /*
8887 8959   * Convert the string to an integer. Note that the string must not have any
8888 8960   * trailing non-integer characters.
8889 8961   */
8890 8962  static boolean_t
8891 8963  str2int(const char *str, int *valp)
8892 8964  {
8893 8965          int     val;
8894 8966          char    *endp = NULL;
8895 8967  
8896 8968          errno = 0;
8897 8969          val = strtol(str, &endp, 10);
8898 8970          if (errno != 0 || *endp != '\0')
8899 8971                  return (B_FALSE);
8900 8972  
8901 8973          *valp = val;
8902 8974          return (B_TRUE);
8903 8975  }
8904 8976  
8905 8977  /* PRINTFLIKE1 */
8906 8978  static void
8907 8979  warn(const char *format, ...)
8908 8980  {
8909 8981          va_list alist;
8910 8982  
8911 8983          format = gettext(format);
8912 8984          (void) fprintf(stderr, "%s: warning: ", progname);
8913 8985  
8914 8986          va_start(alist, format);
8915 8987          (void) vfprintf(stderr, format, alist);
8916 8988          va_end(alist);
8917 8989  
8918 8990          (void) putc('\n', stderr);
8919 8991  }
8920 8992  
8921 8993  /* PRINTFLIKE2 */
8922 8994  static void
8923 8995  warn_dlerr(dladm_status_t err, const char *format, ...)
8924 8996  {
8925 8997          va_list alist;
8926 8998          char    errmsg[DLADM_STRSIZE];
8927 8999  
8928 9000          format = gettext(format);
8929 9001          (void) fprintf(stderr, gettext("%s: warning: "), progname);
8930 9002  
8931 9003          va_start(alist, format);
8932 9004          (void) vfprintf(stderr, format, alist);
8933 9005          va_end(alist);
8934 9006          (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
8935 9007  }
8936 9008  
8937 9009  /*
8938 9010   * Also closes the dladm handle if it is not NULL.
8939 9011   */
8940 9012  /* PRINTFLIKE2 */
8941 9013  static void
8942 9014  die_dlerr(dladm_status_t err, const char *format, ...)
8943 9015  {
8944 9016          va_list alist;
8945 9017          char    errmsg[DLADM_STRSIZE];
8946 9018  
8947 9019          format = gettext(format);
8948 9020          (void) fprintf(stderr, "%s: ", progname);
8949 9021  
8950 9022          va_start(alist, format);
8951 9023          (void) vfprintf(stderr, format, alist);
8952 9024          va_end(alist);
8953 9025          (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
8954 9026  
8955 9027          /* close dladm handle if it was opened */
8956 9028          if (handle != NULL)
8957 9029                  dladm_close(handle);
8958 9030  
8959 9031          exit(EXIT_FAILURE);
8960 9032  }
8961 9033  
8962 9034  /* PRINTFLIKE1 */
8963 9035  static void
8964 9036  die(const char *format, ...)
8965 9037  {
8966 9038          va_list alist;
8967 9039  
8968 9040          format = gettext(format);
8969 9041          (void) fprintf(stderr, "%s: ", progname);
8970 9042  
8971 9043          va_start(alist, format);
8972 9044          (void) vfprintf(stderr, format, alist);
8973 9045          va_end(alist);
8974 9046  
8975 9047          (void) putc('\n', stderr);
8976 9048  
8977 9049          /* close dladm handle if it was opened */
8978 9050          if (handle != NULL)
8979 9051                  dladm_close(handle);
8980 9052  
8981 9053          exit(EXIT_FAILURE);
8982 9054  }
8983 9055  
8984 9056  static void
8985 9057  die_optdup(int opt)
8986 9058  {
8987 9059          die("the option -%c cannot be specified more than once", opt);
8988 9060  }
8989 9061  
8990 9062  static void
8991 9063  die_opterr(int opt, int opterr, const char *usage)
8992 9064  {
8993 9065          switch (opterr) {
8994 9066          case ':':
8995 9067                  die("option '-%c' requires a value\nusage: %s", opt,
8996 9068                      gettext(usage));
8997 9069                  break;
8998 9070          case '?':
8999 9071          default:
9000 9072                  die("unrecognized option '-%c'\nusage: %s", opt,
9001 9073                      gettext(usage));
9002 9074                  break;
9003 9075          }
9004 9076  }
9005 9077  
9006 9078  static void
9007 9079  show_ether_xprop(void *arg, dladm_ether_info_t *eattr)
9008 9080  {
9009 9081          print_ether_state_t     *statep = arg;
9010 9082          ether_fields_buf_t      ebuf;
9011 9083          int                     i;
9012 9084  
9013 9085          for (i = CAPABLE; i <= PEERADV; i++)  {
9014 9086                  bzero(&ebuf, sizeof (ebuf));
9015 9087                  (void) strlcpy(ebuf.eth_ptype, ptype[i],
9016 9088                      sizeof (ebuf.eth_ptype));
9017 9089                  (void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
9018 9090                      sizeof (ebuf.eth_autoneg), eattr, i);
9019 9091                  (void) dladm_ether_spdx2str(ebuf.eth_spdx,
9020 9092                      sizeof (ebuf.eth_spdx), eattr, i);
9021 9093                  (void) dladm_ether_pause2str(ebuf.eth_pause,
9022 9094                      sizeof (ebuf.eth_pause), eattr, i);
9023 9095                  (void) strlcpy(ebuf.eth_rem_fault,
9024 9096                      (eattr->lei_attr[i].le_fault ? "fault" : "none"),
9025 9097                      sizeof (ebuf.eth_rem_fault));
9026 9098                  ofmt_print(statep->es_ofmt, &ebuf);
9027 9099          }
9028 9100  
9029 9101  }
9030 9102  
9031 9103  static boolean_t
9032 9104  link_is_ether(const char *link, datalink_id_t *linkid)
9033 9105  {
9034 9106          uint32_t media;
9035 9107          datalink_class_t class;
9036 9108  
9037 9109          if (dladm_name2info(handle, link, linkid, NULL, &class, &media) ==
9038 9110              DLADM_STATUS_OK) {
9039 9111                  if (class == DATALINK_CLASS_PHYS && media == DL_ETHER)
9040 9112                          return (B_TRUE);
9041 9113          }
9042 9114          return (B_FALSE);
9043 9115  }
9044 9116  
9045 9117  /*
9046 9118   * default output callback function that, when invoked,
9047 9119   * prints string which is offset by ofmt_arg->ofmt_id within buf.
9048 9120   */
9049 9121  static boolean_t
9050 9122  print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
9051 9123  {
9052 9124          char *value;
9053 9125  
9054 9126          value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
9055 9127          (void) strlcpy(buf, value, bufsize);
9056 9128          return (B_TRUE);
9057 9129  }
9058 9130  
9059 9131  static void
9060 9132  dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
9061 9133      ofmt_handle_t ofmt)
9062 9134  {
9063 9135          char buf[OFMT_BUFSIZE];
9064 9136  
9065 9137          if (oferr == OFMT_SUCCESS)
9066 9138                  return;
9067 9139          (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
9068 9140          /*
9069 9141           * All errors are considered fatal in parsable mode.
9070 9142           * NOMEM errors are always fatal, regardless of mode.
9071 9143           * For other errors, we print diagnostics in human-readable
9072 9144           * mode and processs what we can.
9073 9145           */
9074 9146          if (parsable || oferr == OFMT_ENOFIELDS) {
9075 9147                  ofmt_close(ofmt);
9076 9148                  die(buf);
9077 9149          } else {
9078 9150                  warn(buf);
9079 9151          }
9080 9152  }
9081 9153  
9082 9154  /*
9083 9155   * Called from the walker dladm_walk_datalink_id() for each IB partition to
9084 9156   * display IB partition specific information.
9085 9157   */
9086 9158  static dladm_status_t
9087 9159  print_part(show_part_state_t *state, datalink_id_t linkid)
9088 9160  {
9089 9161          dladm_part_attr_t       attr;
9090 9162          dladm_status_t          status;
9091 9163          dladm_conf_t            conf;
9092 9164          char                    part_over[MAXLINKNAMELEN];
9093 9165          char                    part_name[MAXLINKNAMELEN];
9094 9166          part_fields_buf_t       pbuf;
9095 9167          boolean_t               force_in_conf = B_FALSE;
9096 9168  
9097 9169          /*
9098 9170           * Get the information about the IB partition from the partition
9099 9171           * datlink ID 'linkid'.
9100 9172           */
9101 9173          if ((status = dladm_part_info(handle, linkid, &attr, state->ps_flags))
9102 9174              != DLADM_STATUS_OK)
9103 9175                  return (status);
9104 9176  
9105 9177          /*
9106 9178           * If an IB Phys link name was provided on the command line we have
9107 9179           * the Phys link's datalink ID in the ps_over_id field of the state
9108 9180           * structure. Proceed only if the IB partition represented by 'linkid'
9109 9181           * was created over Phys link denoted by ps_over_id. The
9110 9182           * 'dia_physlinkid' field of dladm_part_attr_t represents the IB Phys
9111 9183           * link over which the partition was created.
9112 9184           */
9113 9185          if (state->ps_over_id != DATALINK_ALL_LINKID)
9114 9186                  if (state->ps_over_id != attr.dia_physlinkid)
9115 9187                          return (DLADM_STATUS_OK);
9116 9188  
9117 9189          /*
9118 9190           * The linkid argument passed to this function is the datalink ID
9119 9191           * of the IB Partition. Get the partitions name from this linkid.
9120 9192           */
9121 9193          if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
9122 9194              NULL, part_name, sizeof (part_name)) != DLADM_STATUS_OK)
9123 9195                  return (DLADM_STATUS_BADARG);
9124 9196  
9125 9197          bzero(part_over, sizeof (part_over));
9126 9198  
9127 9199          /*
9128 9200           * The 'dia_physlinkid' field contains the datalink ID of the IB Phys
9129 9201           * link over which the partition was created. Use this linkid to get the
9130 9202           * linkover field.
9131 9203           */
9132 9204          if (dladm_datalink_id2info(handle, attr.dia_physlinkid, NULL, NULL,
9133 9205              NULL, part_over, sizeof (part_over)) != DLADM_STATUS_OK)
9134 9206                  (void) sprintf(part_over, "?");
9135 9207          state->ps_found = B_TRUE;
9136 9208  
9137 9209          /*
9138 9210           * Read the FFORCE field from this datalink's persistent configuration
9139 9211           * database line to determine if this datalink was created forcibly.
9140 9212           * If this datalink is a temporary datalink, then it will not have an
9141 9213           * entry in the persistent configuration, so check if force create flag
9142 9214           * is set in the partition attributes.
9143 9215           *
9144 9216           * We need this two level check since persistent partitions brought up
9145 9217           * by up-part during boot will have force create flag always set, since
9146 9218           * we want up-part to always succeed even if the port is currently down
9147 9219           * or P_Key is not yet available in the subnet.
9148 9220           */
9149 9221          if ((status = dladm_getsnap_conf(handle, linkid, &conf)) ==
9150 9222              DLADM_STATUS_OK) {
9151 9223                  (void) dladm_get_conf_field(handle, conf, FFORCE,
9152 9224                      &force_in_conf, sizeof (boolean_t));
9153 9225                  dladm_destroy_conf(handle, conf);
9154 9226          } else if (status == DLADM_STATUS_NOTFOUND) {
9155 9227                  /*
9156 9228                   * for a temp link the force create flag will determine
9157 9229                   * whether it was created with force flag.
9158 9230                   */
9159 9231                  force_in_conf = ((attr.dia_flags & DLADM_PART_FORCE_CREATE)
9160 9232                      != 0);
9161 9233          }
9162 9234  
9163 9235          (void) snprintf(pbuf.part_link, sizeof (pbuf.part_link),
9164 9236              "%s", part_name);
9165 9237  
9166 9238          (void) snprintf(pbuf.part_over, sizeof (pbuf.part_over),
9167 9239              "%s", part_over);
9168 9240  
9169 9241          (void) snprintf(pbuf.part_pkey, sizeof (pbuf.part_pkey),
9170 9242              "%X", attr.dia_pkey);
9171 9243  
9172 9244          (void) get_linkstate(pbuf.part_link, B_TRUE, pbuf.part_state);
9173 9245  
9174 9246          (void) snprintf(pbuf.part_flags, sizeof (pbuf.part_flags),
9175 9247              "%c----", force_in_conf ? 'f' : '-');
9176 9248  
9177 9249          ofmt_print(state->ps_ofmt, &pbuf);
9178 9250  
9179 9251          return (DLADM_STATUS_OK);
9180 9252  }
9181 9253  
9182 9254  /* ARGSUSED */
9183 9255  static int
9184 9256  show_part(dladm_handle_t dh, datalink_id_t linkid, void *arg)
9185 9257  {
9186 9258          ((show_part_state_t *)arg)->ps_status = print_part(arg, linkid);
9187 9259          return (DLADM_WALK_CONTINUE);
9188 9260  }
9189 9261  
9190 9262  /*
9191 9263   * Show the information about the IB partition objects.
9192 9264   */
9193 9265  static void
9194 9266  do_show_part(int argc, char *argv[], const char *use)
9195 9267  {
9196 9268          int                     option;
9197 9269          boolean_t               l_arg = B_FALSE;
9198 9270          uint32_t                flags = DLADM_OPT_ACTIVE;
9199 9271          datalink_id_t           linkid = DATALINK_ALL_LINKID;
9200 9272          datalink_id_t           over_linkid = DATALINK_ALL_LINKID;
9201 9273          char                    over_link[MAXLINKNAMELEN];
9202 9274          show_part_state_t       state;
9203 9275          dladm_status_t          status;
9204 9276          boolean_t               o_arg = B_FALSE;
9205 9277          char                    *fields_str = NULL;
9206 9278          ofmt_handle_t           ofmt;
9207 9279          ofmt_status_t           oferr;
9208 9280          uint_t                  ofmtflags = 0;
9209 9281  
9210 9282          bzero(&state, sizeof (state));
9211 9283          opterr = 0;
9212 9284          while ((option = getopt_long(argc, argv, ":pPl:o:", show_part_lopts,
9213 9285              NULL)) != -1) {
9214 9286                  switch (option) {
9215 9287                  case 'p':
9216 9288                          state.ps_parsable = B_TRUE;
9217 9289                          break;
9218 9290                  case 'P':
9219 9291                          flags = DLADM_OPT_PERSIST;
9220 9292                          break;
9221 9293                  case 'l':
9222 9294                          /*
9223 9295                           * The data link ID of the IB Phys link. When this
9224 9296                           * argument is provided we list only the partition
9225 9297                           * objects created over this IB Phys link.
9226 9298                           */
9227 9299                          if (strlcpy(over_link, optarg, MAXLINKNAMELEN) >=
9228 9300                              MAXLINKNAMELEN)
9229 9301                                  die("link name too long");
9230 9302  
9231 9303                          l_arg = B_TRUE;
9232 9304                          break;
9233 9305                  case 'o':
9234 9306                          o_arg = B_TRUE;
9235 9307                          fields_str = optarg;
9236 9308                          break;
9237 9309                  default:
9238 9310                          die_opterr(optopt, option, use);
9239 9311                  }
9240 9312          }
9241 9313  
9242 9314          /*
9243 9315           * Get the partition ID (optional last argument).
9244 9316           */
9245 9317          if (optind == (argc - 1)) {
9246 9318                  status = dladm_name2info(handle, argv[optind], &linkid, NULL,
9247 9319                      NULL, NULL);
9248 9320                  if (status != DLADM_STATUS_OK) {
9249 9321                          die_dlerr(status, "invalid partition link name '%s'",
9250 9322                              argv[optind]);
9251 9323                  }
9252 9324                  (void) strlcpy(state.ps_part, argv[optind], MAXLINKNAMELEN);
9253 9325          } else if (optind != argc) {
9254 9326                  usage();
9255 9327          }
9256 9328  
9257 9329          if (state.ps_parsable && !o_arg)
9258 9330                  die("-p requires -o");
9259 9331  
9260 9332          /*
9261 9333           * If an IB Phys link name was provided as an argument, then get its
9262 9334           * datalink ID.
9263 9335           */
9264 9336          if (l_arg) {
9265 9337                  status = dladm_name2info(handle, over_link, &over_linkid, NULL,
9266 9338                      NULL, NULL);
9267 9339                  if (status != DLADM_STATUS_OK) {
9268 9340                          die_dlerr(status, "invalid link name '%s'", over_link);
9269 9341                  }
9270 9342          }
9271 9343  
9272 9344          state.ps_over_id = over_linkid; /* IB Phys link ID */
9273 9345          state.ps_found = B_FALSE;
9274 9346          state.ps_flags = flags;
9275 9347  
9276 9348          if (state.ps_parsable)
9277 9349                  ofmtflags |= OFMT_PARSABLE;
9278 9350          oferr = ofmt_open(fields_str, part_fields, ofmtflags, 0, &ofmt);
9279 9351          dladm_ofmt_check(oferr, state.ps_parsable, ofmt);
9280 9352          state.ps_ofmt = ofmt;
9281 9353  
9282 9354          /*
9283 9355           * If a specific IB partition name was not provided as an argument,
9284 9356           * walk all the datalinks and display the information for all
9285 9357           * IB partitions. If IB Phys link was provided limit it to only
9286 9358           * IB partitions created over that IB Phys link.
9287 9359           */
9288 9360          if (linkid == DATALINK_ALL_LINKID) {
9289 9361                  (void) dladm_walk_datalink_id(show_part, handle, &state,
9290 9362                      DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, flags);
9291 9363          } else {
9292 9364                  (void) show_part(handle, linkid, &state);
9293 9365                  if (state.ps_status != DLADM_STATUS_OK) {
9294 9366                          ofmt_close(ofmt);
9295 9367                          die_dlerr(state.ps_status, "failed to show IB partition"
9296 9368                              " '%s'", state.ps_part);
9297 9369                  }
9298 9370          }
9299 9371          ofmt_close(ofmt);
9300 9372  }
9301 9373  
9302 9374  
9303 9375  /*
9304 9376   * Called from the walker dladm_walk_datalink_id() for each IB Phys link to
9305 9377   * display IB specific information for these Phys links.
9306 9378   */
9307 9379  static dladm_status_t
9308 9380  print_ib(show_ib_state_t *state, datalink_id_t phys_linkid)
9309 9381  {
9310 9382          dladm_ib_attr_t         attr;
9311 9383          dladm_status_t          status;
9312 9384          char                    linkname[MAXLINKNAMELEN];
9313 9385          char                    pkeystr[MAXPKEYLEN];
9314 9386          int                     i;
9315 9387          ib_fields_buf_t         ibuf;
9316 9388  
9317 9389          bzero(&attr, sizeof (attr));
9318 9390  
9319 9391          /*
9320 9392           * Get the attributes of the IB Phys link from active/Persistent config
9321 9393           * based on the flag passed.
9322 9394           */
9323 9395          if ((status = dladm_ib_info(handle, phys_linkid, &attr,
9324 9396              state->is_flags)) != DLADM_STATUS_OK)
9325 9397                  return (status);
9326 9398  
9327 9399          if ((state->is_link_id != DATALINK_ALL_LINKID) && (state->is_link_id
9328 9400              != attr.dia_physlinkid)) {
9329 9401                  dladm_free_ib_info(&attr);
9330 9402                  return (DLADM_STATUS_OK);
9331 9403          }
9332 9404  
9333 9405          /*
9334 9406           * Get the data link name for the phys_linkid. If we are doing show-ib
9335 9407           * for all IB Phys links, we have only the datalink IDs not the
9336 9408           * datalink name.
9337 9409           */
9338 9410          if (dladm_datalink_id2info(handle, phys_linkid, NULL, NULL, NULL,
9339 9411              linkname, MAXLINKNAMELEN) != DLADM_STATUS_OK)
9340 9412                  return (status);
9341 9413  
9342 9414          (void) snprintf(ibuf.ib_link, sizeof (ibuf.ib_link),
9343 9415              "%s", linkname);
9344 9416  
9345 9417          (void) snprintf(ibuf.ib_portnum, sizeof (ibuf.ib_portnum),
9346 9418              "%d", attr.dia_portnum);
9347 9419  
9348 9420          (void) snprintf(ibuf.ib_hcaguid, sizeof (ibuf.ib_hcaguid),
9349 9421              "%llX", attr.dia_hca_guid);
9350 9422  
9351 9423          (void) snprintf(ibuf.ib_portguid, sizeof (ibuf.ib_portguid),
9352 9424              "%llX", attr.dia_port_guid);
9353 9425  
9354 9426          (void) get_linkstate(linkname, B_TRUE, ibuf.ib_state);
9355 9427  
9356 9428          /*
9357 9429           * Create a comma separated list of pkeys from the pkey table returned
9358 9430           * by the IP over IB driver instance.
9359 9431           */
9360 9432          bzero(ibuf.ib_pkeys, attr.dia_port_pkey_tbl_sz * sizeof (ib_pkey_t));
9361 9433          for (i = 0; i < attr.dia_port_pkey_tbl_sz; i++) {
9362 9434                  if (attr.dia_port_pkeys[i] != IB_PKEY_INVALID_FULL &&
9363 9435                      attr.dia_port_pkeys[i] != IB_PKEY_INVALID_LIMITED) {
9364 9436                          if (i == 0)
9365 9437                                  (void) snprintf(pkeystr, MAXPKEYLEN, "%X",
9366 9438                                      attr.dia_port_pkeys[i]);
9367 9439                          else
9368 9440                                  (void) snprintf(pkeystr, MAXPKEYLEN, ",%X",
9369 9441                                      attr.dia_port_pkeys[i]);
9370 9442                          (void) strlcat(ibuf.ib_pkeys, pkeystr, MAXPKEYSTRSZ);
9371 9443                  }
9372 9444          }
9373 9445  
9374 9446          dladm_free_ib_info(&attr);
9375 9447  
9376 9448          ofmt_print(state->is_ofmt, &ibuf);
9377 9449  
9378 9450          return (DLADM_STATUS_OK);
9379 9451  }
9380 9452  
9381 9453  /* ARGSUSED */
9382 9454  static int
9383 9455  show_ib(dladm_handle_t dh, datalink_id_t linkid, void *arg)
9384 9456  {
9385 9457          ((show_ib_state_t *)arg)->is_status = print_ib(arg, linkid);
9386 9458          return (DLADM_WALK_CONTINUE);
9387 9459  }
9388 9460  
9389 9461  /*
9390 9462   * Show the properties of one/all IB Phys links. This is different from
9391 9463   * show-phys command since this will display IB specific information about the
9392 9464   * Phys link like, HCA GUID, PORT GUID, PKEYS active for this port etc.
9393 9465   */
9394 9466  static void
9395 9467  do_show_ib(int argc, char *argv[], const char *use)
9396 9468  {
9397 9469          int                     option;
9398 9470          uint32_t                flags = DLADM_OPT_ACTIVE;
9399 9471          datalink_id_t           linkid = DATALINK_ALL_LINKID;
9400 9472          show_ib_state_t         state;
9401 9473          dladm_status_t          status;
9402 9474          boolean_t               o_arg = B_FALSE;
9403 9475          char                    *fields_str = NULL;
9404 9476          ofmt_handle_t           ofmt;
9405 9477          ofmt_status_t           oferr;
9406 9478          uint_t                  ofmtflags = 0;
9407 9479  
9408 9480          bzero(&state, sizeof (state));
9409 9481          opterr = 0;
9410 9482          while ((option = getopt_long(argc, argv, ":po:", show_lopts,
9411 9483              NULL)) != -1) {
9412 9484                  switch (option) {
9413 9485                  case 'p':
9414 9486                          state.is_parsable = B_TRUE;
9415 9487                          break;
9416 9488                  case 'o':
9417 9489                          o_arg = B_TRUE;
9418 9490                          fields_str = optarg;
9419 9491                          break;
9420 9492                  default:
9421 9493                          die_opterr(optopt, option, use);
9422 9494                  }
9423 9495          }
9424 9496  
9425 9497          /* get IB Phys link ID (optional last argument) */
9426 9498          if (optind == (argc - 1)) {
9427 9499                  status = dladm_name2info(handle, argv[optind], &linkid, NULL,
9428 9500                      NULL, NULL);
9429 9501                  if (status != DLADM_STATUS_OK) {
9430 9502                          die_dlerr(status, "invalid IB port name '%s'",
9431 9503                              argv[optind]);
9432 9504                  }
9433 9505                  (void) strlcpy(state.is_link, argv[optind], MAXLINKNAMELEN);
9434 9506          } else if (optind != argc) {
9435 9507                  usage();
9436 9508          }
9437 9509  
9438 9510          if (state.is_parsable && !o_arg)
9439 9511                  die("-p requires -o");
9440 9512  
9441 9513          /*
9442 9514           * linkid is the data link ID of the IB Phys link. By default it will
9443 9515           * be DATALINK_ALL_LINKID.
9444 9516           */
9445 9517          state.is_link_id = linkid;
9446 9518          state.is_flags = flags;
9447 9519  
9448 9520          if (state.is_parsable)
9449 9521                  ofmtflags |= OFMT_PARSABLE;
9450 9522          oferr = ofmt_open(fields_str, ib_fields, ofmtflags, 0, &ofmt);
9451 9523          dladm_ofmt_check(oferr, state.is_parsable, ofmt);
9452 9524          state.is_ofmt = ofmt;
9453 9525  
9454 9526          /*
9455 9527           * If we are going to display the information for all IB Phys links
9456 9528           * then we'll walk through all the datalinks for datalinks of Phys
9457 9529           * class and media type IB.
9458 9530           */
9459 9531          if (linkid == DATALINK_ALL_LINKID) {
9460 9532                  (void) dladm_walk_datalink_id(show_ib, handle, &state,
9461 9533                      DATALINK_CLASS_PHYS, DL_IB, flags);
9462 9534          } else {
9463 9535                  /*
9464 9536                   * We need to display the information only for the IB phys link
9465 9537                   * linkid. Call show_ib for this link.
9466 9538                   */
9467 9539                  (void) show_ib(handle, linkid, &state);
9468 9540                  if (state.is_status != DLADM_STATUS_OK) {
9469 9541                          ofmt_close(ofmt);
9470 9542                          die_dlerr(state.is_status, "failed to show IB Phys link"
9471 9543                              " '%s'", state.is_link);
9472 9544                  }
9473 9545          }
9474 9546          ofmt_close(ofmt);
9475 9547  }
9476 9548  
9477 9549  /*
9478 9550   * Create an IP over Infiniband partition object over an IB Phys link. The IB
9479 9551   * Phys link is associated with an Infiniband HCA port. The IB partition object
9480 9552   * is created over a port, pkey combination. This partition object represents
9481 9553   * an instance of IP over IB interface.
9482 9554   */
9483 9555  /* ARGSUSED */
9484 9556  static void
9485 9557  do_create_part(int argc, char *argv[], const char *use)
9486 9558  {
9487 9559          int             status, option;
9488 9560          int             flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
9489 9561          char            *pname;
9490 9562          char            *l_arg = NULL;
9491 9563          char            *altroot = NULL;
9492 9564          datalink_id_t   physlinkid = 0;
9493 9565          datalink_id_t   partlinkid = 0;
9494 9566          unsigned long   opt_pkey;
9495 9567          ib_pkey_t       pkey = 0;
9496 9568          char            *endp = NULL;
9497 9569          char            propstr[DLADM_STRSIZE];
9498 9570          dladm_arg_list_t        *proplist = NULL;
9499 9571  
9500 9572          propstr[0] = '\0';
9501 9573          while ((option = getopt_long(argc, argv, ":tfl:P:R:p:",
9502 9574              part_lopts, NULL)) != -1) {
9503 9575                  switch (option) {
9504 9576                  case 't':
9505 9577                          /*
9506 9578                           * Create a temporary IB partition object. This
9507 9579                           * instance is not entered into the persistent database
9508 9580                           * so it will not be recreated automatically on a
9509 9581                           * reboot.
9510 9582                           */
9511 9583                          flags &= ~DLADM_OPT_PERSIST;
9512 9584                          break;
9513 9585                  case 'l':
9514 9586                          /*
9515 9587                           * The IB phys link over which the partition object will
9516 9588                           * be created.
9517 9589                           */
9518 9590                          l_arg = optarg;
9519 9591                          break;
9520 9592                  case 'R':
9521 9593                          altroot = optarg;
9522 9594                          break;
9523 9595                  case 'p':
9524 9596                          (void) strlcat(propstr, optarg, DLADM_STRSIZE);
9525 9597                          if (strlcat(propstr, ",", DLADM_STRSIZE) >=
9526 9598                              DLADM_STRSIZE)
9527 9599                                  die("property list too long '%s'", propstr);
9528 9600                          break;
9529 9601                  case 'P':
9530 9602                          /*
9531 9603                           * The P_Key for the port, pkey tuple of the partition
9532 9604                           * object. This P_Key should exist in the IB subnet.
9533 9605                           * The partition creation for a non-existent P_Key will
9534 9606                           * fail unless the -f option is used.
9535 9607                           *
9536 9608                           * The P_Key is expected to be a hexadecimal number.
9537 9609                           */
9538 9610                          opt_pkey = strtoul(optarg, &endp, 16);
9539 9611                          if (errno == ERANGE || opt_pkey > USHRT_MAX ||
9540 9612                              *endp != '\0')
9541 9613                                  die("Invalid pkey");
9542 9614  
9543 9615                          pkey = (ib_pkey_t)opt_pkey;
9544 9616                          break;
9545 9617                  case 'f':
9546 9618                          flags |= DLADM_OPT_FORCE;
9547 9619                          break;
9548 9620                  default:
9549 9621                          die_opterr(optopt, option, use);
9550 9622                          break;
9551 9623                  }
9552 9624          }
9553 9625  
9554 9626          /* check required options */
9555 9627          if (!l_arg)
9556 9628                  usage();
9557 9629  
9558 9630          /* the partition name is a required operand */
9559 9631          if (optind != (argc - 1))
9560 9632                  usage();
9561 9633  
9562 9634          pname = argv[argc - 1];
9563 9635  
9564 9636          /*
9565 9637           * Verify that the partition object's name is in the valid link name
9566 9638           * format.
9567 9639           */
9568 9640          if (!dladm_valid_linkname(pname))
9569 9641                  die("Invalid link name '%s'", pname);
9570 9642  
9571 9643          /* pkey is a mandatory argument */
9572 9644          if (pkey == 0)
9573 9645                  usage();
9574 9646  
9575 9647          if (altroot != NULL)
9576 9648                  altroot_cmd(altroot, argc, argv);
9577 9649  
9578 9650          /*
9579 9651           * Get the data link id of the IB Phys link over which we will be
9580 9652           * creating partition object.
9581 9653           */
9582 9654          if (dladm_name2info(handle, l_arg,
9583 9655              &physlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK)
9584 9656                  die("invalid link name '%s'", l_arg);
9585 9657  
9586 9658          /*
9587 9659           * parse the property list provided with -p option.
9588 9660           */
9589 9661          if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
9590 9662              != DLADM_STATUS_OK)
9591 9663                  die("invalid IB partition property");
9592 9664  
9593 9665          /*
9594 9666           * Call the library routine to create the partition object.
9595 9667           */
9596 9668          status = dladm_part_create(handle, physlinkid, pkey, flags, pname,
9597 9669              &partlinkid, proplist);
9598 9670          if (status != DLADM_STATUS_OK)
9599 9671                  die_dlerr(status,
9600 9672                      "partition %x creation over %s failed", pkey, l_arg);
9601 9673  }
9602 9674  
9603 9675  /*
9604 9676   * Delete an IP over Infiniband partition object. The partition object should
9605 9677   * be unplumbed before attempting the delete.
9606 9678   */
9607 9679  static void
9608 9680  do_delete_part(int argc, char *argv[], const char *use)
9609 9681  {
9610 9682          int option, flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
9611 9683          int status;
9612 9684          char *altroot = NULL;
9613 9685          datalink_id_t   partid;
9614 9686  
9615 9687          opterr = 0;
9616 9688          while ((option = getopt_long(argc, argv, "R:t", part_lopts,
9617 9689              NULL)) != -1) {
9618 9690                  switch (option) {
9619 9691                  case 't':
9620 9692                          flags &= ~DLADM_OPT_PERSIST;
9621 9693                          break;
9622 9694                  case 'R':
9623 9695                          altroot = optarg;
9624 9696                          break;
9625 9697                  default:
9626 9698                          die_opterr(optopt, option, use);
9627 9699                  }
9628 9700          }
9629 9701  
9630 9702          /* get partition name (required last argument) */
9631 9703          if (optind != (argc - 1))
9632 9704                  usage();
9633 9705  
9634 9706          if (altroot != NULL)
9635 9707                  altroot_cmd(altroot, argc, argv);
9636 9708  
9637 9709          /*
9638 9710           * Get the data link id of the partition object given the partition
9639 9711           * name.
9640 9712           */
9641 9713          status = dladm_name2info(handle, argv[optind], &partid, NULL, NULL,
9642 9714              NULL);
9643 9715          if (status != DLADM_STATUS_OK)
9644 9716                  die("invalid link name '%s'", argv[optind]);
9645 9717  
9646 9718          /*
9647 9719           * Call the library routine to delete the IB partition. This will
9648 9720           * result in the IB partition object and all its resources getting
9649 9721           * deleted.
9650 9722           */
9651 9723          status = dladm_part_delete(handle, partid, flags);
9652 9724          if (status != DLADM_STATUS_OK)
9653 9725                  die_dlerr(status, "%s: partition deletion failed",
9654 9726                      argv[optind]);
9655 9727  }
9656 9728  
9657 9729  /*
9658 9730   * Bring up all or one IB partition already present in the persistent database
9659 9731   * but not active yet.
9660 9732   *
9661 9733   * This sub-command is used during the system boot up to bring up all IB
9662 9734   * partitions present in the persistent database. This is similar to a
9663 9735   * create partition except that, the partitions are always created even if the
9664 9736   * HCA port is down or P_Key is not present in the IB subnet. This is similar
9665 9737   * to using the 'force' option while creating the partition except that the 'f'
9666 9738   * flag will be set in the flags field only if the create-part for this command
9667 9739   * was called with '-f' option.
9668 9740   */
9669 9741  /* ARGSUSED */
9670 9742  static void
9671 9743  do_up_part(int argc, char *argv[], const char *use)
9672 9744  {
9673 9745          datalink_id_t   partid = DATALINK_ALL_LINKID;
9674 9746          dladm_status_t status;
9675 9747  
9676 9748          /*
9677 9749           * If a partition name was passed as an argument, get its data link
9678 9750           * id. By default we'll attempt to bring up all IB partition data
9679 9751           * links.
9680 9752           */
9681 9753          if (argc == 2) {
9682 9754                  status = dladm_name2info(handle, argv[argc - 1], &partid, NULL,
9683 9755                      NULL, NULL);
9684 9756                  if (status != DLADM_STATUS_OK)
9685 9757                          return;
9686 9758          } else if (argc > 2) {
9687 9759                  usage();
9688 9760          }
9689 9761  
9690 9762          (void) dladm_part_up(handle, partid, 0);
9691 9763  }
  
    | 
      ↓ open down ↓ | 
    2767 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX