Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libdladm/common/linkprop.c
          +++ new/usr/src/lib/libdladm/common/linkprop.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  24   24   * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  25   25   */
  26   26  
  27   27  #include <stdlib.h>
  28   28  #include <string.h>
  29   29  #include <strings.h>
  30   30  #include <errno.h>
  31   31  #include <ctype.h>
  32   32  #include <stddef.h>
  33   33  #include <sys/types.h>
  34   34  #include <sys/stat.h>
  35   35  #include <sys/dld.h>
  36   36  #include <sys/zone.h>
  37   37  #include <fcntl.h>
  38   38  #include <unistd.h>
  39   39  #include <libdevinfo.h>
  40   40  #include <zone.h>
  41   41  #include <libdllink.h>
  42   42  #include <libdladm_impl.h>
  43   43  #include <libdlwlan_impl.h>
  44   44  #include <libdlwlan.h>
  45   45  #include <libdlvlan.h>
  46   46  #include <libdlvnic.h>
  47   47  #include <libdlib.h>
  48   48  #include <libintl.h>
  49   49  #include <dlfcn.h>
  50   50  #include <link.h>
  51   51  #include <inet/wifi_ioctl.h>
  52   52  #include <libdladm.h>
  53   53  #include <libdlstat.h>
  54   54  #include <sys/param.h>
  55   55  #include <sys/debug.h>
  56   56  #include <sys/dld.h>
  57   57  #include <inttypes.h>
  58   58  #include <sys/ethernet.h>
  59   59  #include <inet/iptun.h>
  60   60  #include <net/wpa.h>
  61   61  #include <sys/sysmacros.h>
  62   62  #include <sys/vlan.h>
  63   63  #include <libdlbridge.h>
  64   64  #include <stp_in.h>
  65   65  #include <netinet/dhcp.h>
  66   66  #include <netinet/dhcp6.h>
  67   67  #include <net/if_types.h>
  68   68  #include <libinetutil.h>
  69   69  #include <pool.h>
  70   70  #include <libdlaggr.h>
  71   71  
  72   72  /*
  73   73   * The linkprop get() callback.
  74   74   * - pd:        pointer to the prop_desc_t
  75   75   * - propstrp:  a property string array to keep the returned property.
  76   76   *              Caller allocated.
  77   77   * - cntp:      number of returned properties.
  78   78   *              Caller also uses it to indicate how many it expects.
  79   79   */
  80   80  struct prop_desc;
  81   81  typedef struct prop_desc prop_desc_t;
  82   82  
  83   83  typedef dladm_status_t  pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
  84   84                          datalink_id_t, char **propstp, uint_t *cntp,
  85   85                          datalink_media_t, uint_t, uint_t *);
  86   86  
  87   87  /*
  88   88   * The linkprop set() callback.
  89   89   * - propval:   a val_desc_t array which keeps the property values to be set.
  90   90   * - cnt:       number of properties to be set.
  91   91   * - flags:     additional flags passed down the system call.
  92   92   *
  93   93   * pd_set takes val_desc_t given by pd_check(), translates it into
  94   94   * a format suitable for kernel consumption. This may require allocation
  95   95   * of ioctl buffers etc. pd_set() may call another common routine (used
  96   96   * by all other pd_sets) which invokes the ioctl.
  97   97   */
  98   98  typedef dladm_status_t  pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
  99   99                              val_desc_t *propval, uint_t cnt, uint_t flags,
 100  100                              datalink_media_t);
 101  101  
 102  102  /*
 103  103   * The linkprop check() callback.
 104  104   * - propstrp:  property string array which keeps the property to be checked.
 105  105   * - cnt:       number of properties.
 106  106   * - propval:   return value; the property values of the given property strings.
 107  107   *
 108  108   * pd_check checks that the input values are valid. It does so by
 109  109   * iteraring through the pd_modval list for the property. If
 110  110   * the modifiable values cannot be expressed as a list, a pd_check
 111  111   * specific to this property can be used. If the input values are
 112  112   * verified to be valid, pd_check allocates a val_desc_t and fills it
 113  113   * with either a val_desc_t found on the pd_modval list or something
 114  114   * generated on the fly.
 115  115   */
 116  116  typedef dladm_status_t  pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
 117  117                              datalink_id_t, char **propstrp, uint_t *cnt,
 118  118                              uint_t flags, val_desc_t **propval,
 119  119                              datalink_media_t);
 120  120  
 121  121  typedef struct link_attr_s {
 122  122          mac_prop_id_t   pp_id;
 123  123          size_t          pp_valsize;
 124  124          char            *pp_name;
 125  125  } link_attr_t;
 126  126  
 127  127  typedef struct dladm_linkprop_args_s {
 128  128          dladm_status_t  dla_status;
 129  129          uint_t          dla_flags;
 130  130  } dladm_linkprop_args_t;
 131  131  
 132  132  static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
 133  133                              const char *, uint_t, dladm_status_t *);
 134  134  static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
 135  135                              mac_prop_id_t, uint_t, dladm_status_t *);
 136  136  static dladm_status_t   i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
 137  137                              char *, uint_t, uint_t *, void *, size_t);
 138  138  
 139  139  static dladm_status_t   i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
 140  140                              const char *, char **, uint_t, uint_t);
 141  141  static dladm_status_t   i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
 142  142                              const char *, char **, uint_t *, dladm_prop_type_t,
 143  143                              uint_t);
 144  144  static dladm_status_t   i_dladm_macprop(dladm_handle_t, void *, boolean_t);
 145  145  static const char       *dladm_perm2str(uint_t, char *);
 146  146  static link_attr_t      *dladm_name2prop(const char *);
  
    | 
      ↓ open down ↓ | 
    146 lines elided | 
    
      ↑ open up ↑ | 
  
 147  147  static link_attr_t      *dladm_id2prop(mac_prop_id_t);
 148  148  
 149  149  static pd_getf_t        get_zone, get_autopush, get_rate_mod, get_rate,
 150  150                          get_speed, get_channel, get_powermode, get_radio,
 151  151                          get_duplex, get_link_state, get_binary, get_uint32,
 152  152                          get_flowctl, get_maxbw, get_cpus, get_priority,
 153  153                          get_tagmode, get_range, get_stp, get_bridge_forward,
 154  154                          get_bridge_pvid, get_protection, get_rxrings,
 155  155                          get_txrings, get_cntavail, get_secondary_macs,
 156  156                          get_allowedips, get_allowedcids, get_pool,
 157      -                        get_rings_range, get_linkmode_prop,
 158      -                        get_promisc_filtered;
      157 +                        get_rings_range, get_linkmode_prop;
 159  158  
 160  159  static pd_setf_t        set_zone, set_rate, set_powermode, set_radio,
 161  160                          set_public_prop, set_resource, set_stp_prop,
 162      -                        set_bridge_forward, set_bridge_pvid, set_secondary_macs,
 163      -                        set_promisc_filtered;
      161 +                        set_bridge_forward, set_bridge_pvid, set_secondary_macs;
 164  162  
 165  163  static pd_checkf_t      check_zone, check_autopush, check_rate, check_hoplimit,
 166  164                          check_encaplim, check_uint32, check_maxbw, check_cpus,
 167  165                          check_stp_prop, check_bridge_pvid, check_allowedips,
 168  166                          check_allowedcids, check_secondary_macs, check_rings,
 169  167                          check_pool, check_prop;
 170  168  
 171  169  struct prop_desc {
 172  170          /*
 173  171           * link property name
 174  172           */
 175  173          char                    *pd_name;
 176  174  
 177  175          /*
 178  176           * default property value, can be set to { "", NULL }
 179  177           */
 180  178          val_desc_t              pd_defval;
 181  179  
 182  180          /*
 183  181           * list of optional property values, can be NULL.
 184  182           *
 185  183           * This is set to non-NULL if there is a list of possible property
 186  184           * values.  pd_optval would point to the array of possible values.
 187  185           */
 188  186          val_desc_t              *pd_optval;
 189  187  
 190  188          /*
 191  189           * count of the above optional property values. 0 if pd_optval is NULL.
 192  190           */
 193  191          uint_t                  pd_noptval;
 194  192  
 195  193          /*
 196  194           * callback to set link property; set to NULL if this property is
 197  195           * read-only and may be called before or after permanent update; see
 198  196           * flags.
 199  197           */
 200  198          pd_setf_t               *pd_set;
 201  199  
 202  200          /*
 203  201           * callback to get modifiable link property
 204  202           */
 205  203          pd_getf_t               *pd_getmod;
 206  204  
 207  205          /*
 208  206           * callback to get current link property
 209  207           */
 210  208          pd_getf_t               *pd_get;
 211  209  
 212  210          /*
 213  211           * callback to validate link property value, set to NULL if pd_optval
 214  212           * is not NULL. In that case, validate the value by comparing it with
 215  213           * the pd_optval. Return a val_desc_t array pointer if the value is
 216  214           * valid.
 217  215           */
 218  216          pd_checkf_t             *pd_check;
 219  217  
 220  218          uint_t                  pd_flags;
 221  219  #define PD_TEMPONLY     0x1     /* property is temporary only */
 222  220  #define PD_CHECK_ALLOC  0x2     /* alloc vd_val as part of pd_check */
 223  221  #define PD_AFTER_PERM   0x4     /* pd_set after db update; no temporary */
 224  222          /*
 225  223           * indicate link classes this property applies to.
 226  224           */
 227  225          datalink_class_t        pd_class;
 228  226  
 229  227          /*
 230  228           * indicate link media type this property applies to.
 231  229           */
 232  230          datalink_media_t        pd_dmedia;
 233  231  };
 234  232  
 235  233  #define MAC_PROP_BUFSIZE(v)     sizeof (dld_ioc_macprop_t) + (v) - 1
 236  234  
 237  235  /*
 238  236   * Supported link properties enumerated in the prop_table[] array are
 239  237   * computed using the callback functions in that array. To compute the
 240  238   * property value, multiple distinct system calls may be needed (e.g.,
 241  239   * for wifi speed, we need to issue system calls to get desired/supported
 242  240   * rates). The link_attr[] table enumerates the interfaces to the kernel,
 243  241   * and the type/size of the data passed in the user-kernel interface.
 244  242   */
 245  243  static link_attr_t link_attr[] = {
 246  244          { MAC_PROP_DUPLEX,      sizeof (link_duplex_t), "duplex"},
 247  245  
 248  246          { MAC_PROP_SPEED,       sizeof (uint64_t),      "speed"},
 249  247  
 250  248          { MAC_PROP_STATUS,      sizeof (link_state_t),  "state"},
 251  249  
 252  250          { MAC_PROP_AUTONEG,     sizeof (uint8_t),       "adv_autoneg_cap"},
 253  251  
 254  252          { MAC_PROP_MTU,         sizeof (uint32_t),      "mtu"},
 255  253  
 256  254          { MAC_PROP_FLOWCTRL,    sizeof (link_flowctrl_t), "flowctrl"},
 257  255  
 258  256          { MAC_PROP_ZONE,        sizeof (dld_ioc_zid_t), "zone"},
 259  257  
 260  258          { MAC_PROP_AUTOPUSH,    sizeof (struct dlautopush), "autopush"},
 261  259  
 262  260          { MAC_PROP_ADV_5000FDX_CAP, sizeof (uint8_t),   "adv_5000fdx_cap"},
 263  261  
 264  262          { MAC_PROP_EN_5000FDX_CAP, sizeof (uint8_t),    "en_5000fdx_cap"},
 265  263  
 266  264          { MAC_PROP_ADV_2500FDX_CAP, sizeof (uint8_t),   "adv_2500fdx_cap"},
 267  265  
 268  266          { MAC_PROP_EN_2500FDX_CAP, sizeof (uint8_t),    "en_2500fdx_cap"},
 269  267  
 270  268          { MAC_PROP_ADV_100GFDX_CAP, sizeof (uint8_t),   "adv_100gfdx_cap"},
 271  269  
 272  270          { MAC_PROP_EN_100GFDX_CAP, sizeof (uint8_t),    "en_100gfdx_cap"},
 273  271  
 274  272          { MAC_PROP_ADV_40GFDX_CAP, sizeof (uint8_t),    "adv_40gfdx_cap"},
 275  273  
 276  274          { MAC_PROP_EN_40GFDX_CAP, sizeof (uint8_t),     "en_40gfdx_cap"},
 277  275  
 278  276          { MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),    "adv_10gfdx_cap"},
 279  277  
 280  278          { MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),     "en_10gfdx_cap"},
 281  279  
 282  280          { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),   "adv_1000fdx_cap"},
 283  281  
 284  282          { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),    "en_1000fdx_cap"},
 285  283  
 286  284          { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),   "adv_1000hdx_cap"},
 287  285  
 288  286          { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),    "en_1000hdx_cap"},
 289  287  
 290  288          { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),    "adv_100fdx_cap"},
 291  289  
 292  290          { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),     "en_100fdx_cap"},
 293  291  
 294  292          { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),    "adv_100hdx_cap"},
 295  293  
 296  294          { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),     "en_100hdx_cap"},
 297  295  
 298  296          { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),     "adv_10fdx_cap"},
 299  297  
 300  298          { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),      "en_10fdx_cap"},
 301  299  
 302  300          { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),     "adv_10hdx_cap"},
 303  301  
 304  302          { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),      "en_10hdx_cap"},
 305  303  
 306  304          { MAC_PROP_WL_ESSID,    sizeof (wl_linkstatus_t), "essid"},
 307  305  
 308  306          { MAC_PROP_WL_BSSID,    sizeof (wl_bssid_t),    "bssid"},
 309  307  
 310  308          { MAC_PROP_WL_BSSTYPE,  sizeof (wl_bss_type_t), "bsstype"},
 311  309  
 312  310          { MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
 313  311  
 314  312          /* wl_rates_t has variable length */
 315  313          { MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
 316  314  
 317  315          /* wl_rates_t has variable length */
 318  316          { MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
 319  317  
 320  318          { MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
 321  319  
 322  320          { MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
 323  321  
 324  322          { MAC_PROP_WL_RSSI,     sizeof (wl_rssi_t),     "signal"},
 325  323  
 326  324          { MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
 327  325  
 328  326          { MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
 329  327  
 330  328          { MAC_PROP_WL_WPA,      sizeof (wl_wpa_t),      "wpa"},
 331  329  
 332  330          /*  wl_wpa_ess_t has variable length */
 333  331          { MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
 334  332  
 335  333          { MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
 336  334  
 337  335          { MAC_PROP_WL_RADIO,    sizeof (dladm_wlan_radio_t), "wl_radio"},
 338  336  
 339  337          { MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t), "wl_ess_list"},
 340  338  
 341  339          { MAC_PROP_WL_KEY_TAB,  sizeof (wl_wep_key_tab_t), "wl_wep_key"},
 342  340  
 343  341          { MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
 344  342  
 345  343          /* wl_wpa_ie_t has variable length */
 346  344          { MAC_PROP_WL_SETOPTIE, sizeof (wl_wpa_ie_t),   "set_ie"},
 347  345  
 348  346          { MAC_PROP_WL_DELKEY,   sizeof (wl_del_key_t),  "wpa_del_key"},
 349  347  
 350  348          { MAC_PROP_WL_KEY,      sizeof (wl_key_t),      "wl_key"},
 351  349  
 352  350          { MAC_PROP_WL_MLME,     sizeof (wl_mlme_t),     "mlme"},
 353  351  
 354  352          { MAC_PROP_TAGMODE,     sizeof (link_tagmode_t),        "tagmode"},
 355  353  
 356  354          { MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t),   "hoplimit"},
 357  355  
 358  356          { MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t), "encaplimit"},
 359  357  
 360  358          { MAC_PROP_PVID,        sizeof (uint16_t),      "default_tag"},
 361  359  
 362  360          { MAC_PROP_LLIMIT,      sizeof (uint32_t),      "learn_limit"},
 363  361  
 364  362          { MAC_PROP_LDECAY,      sizeof (uint32_t),      "learn_decay"},
 365  363  
 366  364          { MAC_PROP_RESOURCE,    sizeof (mac_resource_props_t),  "resource"},
 367  365  
 368  366          { MAC_PROP_RESOURCE_EFF, sizeof (mac_resource_props_t),
 369  367              "resource-effective"},
 370  368  
 371  369          { MAC_PROP_RXRINGSRANGE, sizeof (mac_propval_range_t),  "rxrings"},
 372  370  
 373  371          { MAC_PROP_TXRINGSRANGE, sizeof (mac_propval_range_t),  "txrings"},
 374  372  
 375  373          { MAC_PROP_MAX_TX_RINGS_AVAIL,  sizeof (uint_t),
 376  374              "txrings-available"},
  
    | 
      ↓ open down ↓ | 
    203 lines elided | 
    
      ↑ open up ↑ | 
  
 377  375  
 378  376          { MAC_PROP_MAX_RX_RINGS_AVAIL,  sizeof (uint_t),
 379  377              "rxrings-available"},
 380  378  
 381  379          { MAC_PROP_MAX_RXHWCLNT_AVAIL,  sizeof (uint_t), "rxhwclnt-available"},
 382  380  
 383  381          { MAC_PROP_MAX_TXHWCLNT_AVAIL,  sizeof (uint_t), "txhwclnt-available"},
 384  382  
 385  383          { MAC_PROP_IB_LINKMODE, sizeof (uint32_t),      "linkmode"},
 386  384  
 387      -        { MAC_PROP_VN_PROMISC_FILTERED, sizeof (boolean_t), "promisc-filtered"},
 388      -
 389  385          { MAC_PROP_SECONDARY_ADDRS, sizeof (mac_secondary_addr_t),
 390  386              "secondary-macs"},
 391  387  
 392  388          { MAC_PROP_PRIVATE,     0,                      "driver-private"}
 393  389  };
 394  390  
 395  391  typedef struct bridge_public_prop_s {
 396  392          const char      *bpp_name;
 397  393          int             bpp_code;
 398  394  } bridge_public_prop_t;
 399  395  
 400  396  static const bridge_public_prop_t bridge_prop[] = {
 401  397          { "stp", PT_CFG_NON_STP },
 402  398          { "stp_priority", PT_CFG_PRIO },
 403  399          { "stp_cost", PT_CFG_COST },
 404  400          { "stp_edge", PT_CFG_EDGE },
 405  401          { "stp_p2p", PT_CFG_P2P },
 406  402          { "stp_mcheck", PT_CFG_MCHECK },
 407  403          { NULL, 0 }
 408  404  };
 409  405  
 410  406  static  val_desc_t      link_duplex_vals[] = {
 411  407          { "half",       LINK_DUPLEX_HALF        },
 412  408          { "full",       LINK_DUPLEX_HALF        }
 413  409  };
 414  410  static  val_desc_t      link_status_vals[] = {
 415  411          { "up",         LINK_STATE_UP           },
 416  412          { "down",       LINK_STATE_DOWN         }
 417  413  };
 418  414  static  val_desc_t      link_01_vals[] = {
 419  415          { "1",          1                       },
 420  416          { "0",          0                       }
 421  417  };
 422  418  static  val_desc_t      link_flow_vals[] = {
 423  419          { "no",         LINK_FLOWCTRL_NONE      },
 424  420          { "tx",         LINK_FLOWCTRL_TX        },
 425  421          { "rx",         LINK_FLOWCTRL_RX        },
 426  422          { "bi",         LINK_FLOWCTRL_BI        }
 427  423  };
 428  424  static  val_desc_t      link_priority_vals[] = {
 429  425          { "low",        MPL_LOW },
 430  426          { "medium",     MPL_MEDIUM      },
 431  427          { "high",       MPL_HIGH        }
 432  428  };
 433  429  
 434  430  static val_desc_t       link_tagmode_vals[] = {
 435  431          { "normal",     LINK_TAGMODE_NORMAL     },
  
    | 
      ↓ open down ↓ | 
    37 lines elided | 
    
      ↑ open up ↑ | 
  
 436  432          { "vlanonly",   LINK_TAGMODE_VLANONLY   }
 437  433  };
 438  434  
 439  435  static  val_desc_t      link_protect_vals[] = {
 440  436          { "mac-nospoof",        MPT_MACNOSPOOF  },
 441  437          { "restricted",         MPT_RESTRICTED  },
 442  438          { "ip-nospoof",         MPT_IPNOSPOOF   },
 443  439          { "dhcp-nospoof",       MPT_DHCPNOSPOOF },
 444  440  };
 445  441  
 446      -static  val_desc_t      link_promisc_filtered_vals[] = {
 447      -        { "off",        B_FALSE },
 448      -        { "on",         B_TRUE },
 449      -};
 450      -
 451  442  static val_desc_t       dladm_wlan_radio_vals[] = {
 452  443          { "on",         DLADM_WLAN_RADIO_ON     },
 453  444          { "off",        DLADM_WLAN_RADIO_OFF    }
 454  445  };
 455  446  
 456  447  static val_desc_t       dladm_wlan_powermode_vals[] = {
 457  448          { "off",        DLADM_WLAN_PM_OFF       },
 458  449          { "fast",       DLADM_WLAN_PM_FAST      },
 459  450          { "max",        DLADM_WLAN_PM_MAX       }
 460  451  };
 461  452  
 462  453  static  val_desc_t      stp_p2p_vals[] = {
 463  454          { "true",       P2P_FORCE_TRUE          },
 464  455          { "false",      P2P_FORCE_FALSE         },
 465  456          { "auto",       P2P_AUTO                }
 466  457  };
 467  458  
 468  459  static  val_desc_t      dladm_part_linkmode_vals[] = {
 469  460          { "cm",         DLADM_PART_CM_MODE      },
 470  461          { "ud",         DLADM_PART_UD_MODE      },
 471  462  };
 472  463  
 473  464  #define VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
 474  465  #define RESET_VAL       ((uintptr_t)-1)
 475  466  #define UNSPEC_VAL      ((uintptr_t)-2)
 476  467  
 477  468  /*
 478  469   * For the default, if defaults are not defined for the property,
 479  470   * pd_defval.vd_name should be null. If the driver has to be contacted for the
 480  471   * value, vd_name should be the empty string (""). Otherwise, dladm will
 481  472   * just print whatever is in the table.
 482  473   */
 483  474  static prop_desc_t      prop_table[] = {
 484  475          { "channel",    { NULL, 0 },
 485  476              NULL, 0, NULL, NULL,
 486  477              get_channel, NULL, 0,
 487  478              DATALINK_CLASS_PHYS, DL_WIFI },
 488  479  
 489  480          { "powermode",  { "off", DLADM_WLAN_PM_OFF },
 490  481              dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
 491  482              set_powermode, NULL,
 492  483              get_powermode, NULL, 0,
 493  484              DATALINK_CLASS_PHYS, DL_WIFI },
 494  485  
 495  486          { "radio",      { "on", DLADM_WLAN_RADIO_ON },
 496  487              dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
 497  488              set_radio, NULL,
 498  489              get_radio, NULL, 0,
 499  490              DATALINK_CLASS_PHYS, DL_WIFI },
 500  491  
 501  492          { "linkmode",   { "cm", DLADM_PART_CM_MODE },
 502  493              dladm_part_linkmode_vals, VALCNT(dladm_part_linkmode_vals),
 503  494              set_public_prop, NULL, get_linkmode_prop, NULL, 0,
 504  495              DATALINK_CLASS_PART, DL_IB },
 505  496  
 506  497          { "speed",      { "", 0 }, NULL, 0,
 507  498              set_rate, get_rate_mod,
 508  499              get_rate, check_rate, 0,
 509  500              DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
 510  501  
 511  502          { "autopush",   { "", 0 }, NULL, 0,
 512  503              set_public_prop, NULL,
 513  504              get_autopush, check_autopush, PD_CHECK_ALLOC,
 514  505              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 515  506  
 516  507          { "zone",       { "", 0 }, NULL, 0,
 517  508              set_zone, NULL,
 518  509              get_zone, check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
 519  510              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 520  511  
 521  512          { "duplex",     { "", 0 },
 522  513              link_duplex_vals, VALCNT(link_duplex_vals),
 523  514              NULL, NULL, get_duplex, NULL,
 524  515              0, DATALINK_CLASS_PHYS, DL_ETHER },
 525  516  
 526  517          { "state",      { "up", LINK_STATE_UP },
 527  518              link_status_vals, VALCNT(link_status_vals),
 528  519              NULL, NULL, get_link_state, NULL,
 529  520              0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 530  521  
 531  522          { "adv_autoneg_cap", { "", 0 },
 532  523              link_01_vals, VALCNT(link_01_vals),
 533  524              set_public_prop, NULL, get_binary, NULL,
 534  525              0, DATALINK_CLASS_PHYS, DL_ETHER },
 535  526  
 536  527          { "mtu", { "", 0 }, NULL, 0,
 537  528              set_public_prop, get_range,
 538  529              get_uint32, check_uint32, 0, DATALINK_CLASS_ALL,
 539  530              DATALINK_ANY_MEDIATYPE },
 540  531  
 541  532          { "flowctrl", { "", 0 },
 542  533              link_flow_vals, VALCNT(link_flow_vals),
 543  534              set_public_prop, NULL, get_flowctl, NULL,
 544  535              0, DATALINK_CLASS_PHYS, DL_ETHER },
 545  536  
 546  537          { "secondary-macs", { "--", 0 }, NULL, 0,
 547  538              set_secondary_macs, NULL,
 548  539              get_secondary_macs, check_secondary_macs, PD_CHECK_ALLOC,
 549  540              DATALINK_CLASS_VNIC, DL_ETHER },
 550  541  
 551  542          { "adv_100gfdx_cap", { "", 0 },
 552  543              link_01_vals, VALCNT(link_01_vals),
 553  544              NULL, NULL, get_binary, NULL,
 554  545              0, DATALINK_CLASS_PHYS, DL_ETHER },
 555  546  
 556  547          { "en_100gfdx_cap", { "", 0 },
 557  548              link_01_vals, VALCNT(link_01_vals),
 558  549              set_public_prop, NULL, get_binary, NULL,
 559  550              0, DATALINK_CLASS_PHYS, DL_ETHER },
 560  551  
 561  552          { "adv_40gfdx_cap", { "", 0 },
 562  553              link_01_vals, VALCNT(link_01_vals),
 563  554              NULL, NULL, get_binary, NULL,
 564  555              0, DATALINK_CLASS_PHYS, DL_ETHER },
 565  556  
 566  557          { "en_40gfdx_cap", { "", 0 },
 567  558              link_01_vals, VALCNT(link_01_vals),
 568  559              set_public_prop, NULL, get_binary, NULL,
 569  560              0, DATALINK_CLASS_PHYS, DL_ETHER },
 570  561  
 571  562          { "adv_10gfdx_cap", { "", 0 },
 572  563              link_01_vals, VALCNT(link_01_vals),
 573  564              NULL, NULL, get_binary, NULL,
 574  565              0, DATALINK_CLASS_PHYS, DL_ETHER },
 575  566  
 576  567          { "en_10gfdx_cap", { "", 0 },
 577  568              link_01_vals, VALCNT(link_01_vals),
 578  569              set_public_prop, NULL, get_binary, NULL,
 579  570              0, DATALINK_CLASS_PHYS, DL_ETHER },
 580  571  
 581  572          { "adv_5000fdx_cap", { "", 0 },
 582  573              link_01_vals, VALCNT(link_01_vals),
 583  574              NULL, NULL, get_binary, NULL,
 584  575              0, DATALINK_CLASS_PHYS, DL_ETHER },
 585  576  
 586  577          { "en_5000fdx_cap", { "", 0 },
 587  578              link_01_vals, VALCNT(link_01_vals),
 588  579              set_public_prop, NULL, get_binary, NULL,
 589  580              0, DATALINK_CLASS_PHYS, DL_ETHER },
 590  581  
 591  582          { "adv_2500fdx_cap", { "", 0 },
 592  583              link_01_vals, VALCNT(link_01_vals),
 593  584              NULL, NULL, get_binary, NULL,
 594  585              0, DATALINK_CLASS_PHYS, DL_ETHER },
 595  586  
 596  587          { "en_2500fdx_cap", { "", 0 },
 597  588              link_01_vals, VALCNT(link_01_vals),
 598  589              set_public_prop, NULL, get_binary, NULL,
 599  590              0, DATALINK_CLASS_PHYS, DL_ETHER },
 600  591  
 601  592          { "adv_1000fdx_cap", { "", 0 },
 602  593              link_01_vals, VALCNT(link_01_vals),
 603  594              NULL, NULL, get_binary, NULL,
 604  595              0, DATALINK_CLASS_PHYS, DL_ETHER },
 605  596  
 606  597          { "en_1000fdx_cap", { "", 0 },
 607  598              link_01_vals, VALCNT(link_01_vals),
 608  599              set_public_prop, NULL, get_binary, NULL,
 609  600              0, DATALINK_CLASS_PHYS, DL_ETHER },
 610  601  
 611  602          { "adv_1000hdx_cap", { "", 0 },
 612  603              link_01_vals, VALCNT(link_01_vals),
 613  604              NULL, NULL, get_binary, NULL,
 614  605              0, DATALINK_CLASS_PHYS, DL_ETHER },
 615  606  
 616  607          { "en_1000hdx_cap", { "", 0 },
 617  608              link_01_vals, VALCNT(link_01_vals),
 618  609              set_public_prop, NULL, get_binary, NULL,
 619  610              0, DATALINK_CLASS_PHYS, DL_ETHER },
 620  611  
 621  612          { "adv_100fdx_cap", { "", 0 },
 622  613              link_01_vals, VALCNT(link_01_vals),
 623  614              NULL, NULL, get_binary, NULL,
 624  615              0, DATALINK_CLASS_PHYS, DL_ETHER },
 625  616  
 626  617          { "en_100fdx_cap", { "", 0 },
 627  618              link_01_vals, VALCNT(link_01_vals),
 628  619              set_public_prop, NULL, get_binary, NULL,
 629  620              0, DATALINK_CLASS_PHYS, DL_ETHER },
 630  621  
 631  622          { "adv_100hdx_cap", { "", 0 },
 632  623              link_01_vals, VALCNT(link_01_vals),
 633  624              NULL, NULL, get_binary, NULL,
 634  625              0, DATALINK_CLASS_PHYS, DL_ETHER },
 635  626  
 636  627          { "en_100hdx_cap", { "", 0 },
 637  628              link_01_vals, VALCNT(link_01_vals),
 638  629              set_public_prop, NULL, get_binary, NULL,
 639  630              0, DATALINK_CLASS_PHYS, DL_ETHER },
 640  631  
 641  632          { "adv_10fdx_cap", { "", 0 },
 642  633              link_01_vals, VALCNT(link_01_vals),
 643  634              NULL, NULL, get_binary, NULL,
 644  635              0, DATALINK_CLASS_PHYS, DL_ETHER },
 645  636  
 646  637          { "en_10fdx_cap", { "", 0 },
 647  638              link_01_vals, VALCNT(link_01_vals),
 648  639              set_public_prop, NULL, get_binary, NULL,
 649  640              0, DATALINK_CLASS_PHYS, DL_ETHER },
 650  641  
 651  642          { "adv_10hdx_cap", { "", 0 },
 652  643              link_01_vals, VALCNT(link_01_vals),
 653  644              NULL, NULL, get_binary, NULL,
 654  645              0, DATALINK_CLASS_PHYS, DL_ETHER },
 655  646  
 656  647          { "en_10hdx_cap", { "", 0 },
 657  648              link_01_vals, VALCNT(link_01_vals),
 658  649              set_public_prop, NULL, get_binary, NULL,
 659  650              0, DATALINK_CLASS_PHYS, DL_ETHER },
 660  651  
 661  652          { "maxbw", { "--", RESET_VAL }, NULL, 0,
 662  653              set_resource, NULL,
 663  654              get_maxbw, check_maxbw, PD_CHECK_ALLOC,
 664  655              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 665  656  
 666  657          { "cpus", { "--", RESET_VAL }, NULL, 0,
 667  658              set_resource, NULL,
 668  659              get_cpus, check_cpus, 0,
 669  660              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 670  661  
 671  662          { "cpus-effective", { "--", 0 },
 672  663              NULL, 0, NULL, NULL,
 673  664              get_cpus, 0, 0,
 674  665              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 675  666  
 676  667          { "pool", { "--", RESET_VAL }, NULL, 0,
 677  668              set_resource, NULL,
 678  669              get_pool, check_pool, 0,
 679  670              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 680  671  
 681  672          { "pool-effective", { "--", 0 },
 682  673              NULL, 0, NULL, NULL,
 683  674              get_pool, 0, 0,
 684  675              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 685  676  
 686  677          { "priority", { "high", MPL_RESET },
 687  678              link_priority_vals, VALCNT(link_priority_vals), set_resource,
 688  679              NULL, get_priority, check_prop, 0,
 689  680              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 690  681  
 691  682          { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
 692  683              link_tagmode_vals, VALCNT(link_tagmode_vals),
 693  684              set_public_prop, NULL, get_tagmode,
 694  685              NULL, 0,
 695  686              DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
 696  687              DL_ETHER },
 697  688  
 698  689          { "hoplimit", { "", 0 }, NULL, 0,
 699  690              set_public_prop, get_range, get_uint32,
 700  691              check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
 701  692  
 702  693          { "encaplimit", { "", 0 }, NULL, 0,
 703  694              set_public_prop, get_range, get_uint32,
 704  695              check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
 705  696  
 706  697          { "forward", { "1", 1 },
 707  698              link_01_vals, VALCNT(link_01_vals),
 708  699              set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
 709  700              DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
 710  701  
 711  702          { "default_tag", { "1", 1 }, NULL, 0,
 712  703              set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
 713  704              0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 714  705              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 715  706  
 716  707          { "learn_limit", { "1000", 1000 }, NULL, 0,
 717  708              set_public_prop, NULL, get_uint32,
 718  709              check_uint32, 0,
 719  710              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 720  711              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 721  712  
 722  713          { "learn_decay", { "200", 200 }, NULL, 0,
 723  714              set_public_prop, NULL, get_uint32,
 724  715              check_uint32, 0,
 725  716              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 726  717              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 727  718  
 728  719          { "stp", { "1", 1 },
 729  720              link_01_vals, VALCNT(link_01_vals),
 730  721              set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
 731  722              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 732  723              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 733  724  
 734  725          { "stp_priority", { "128", 128 }, NULL, 0,
 735  726              set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
 736  727              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 737  728              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 738  729  
 739  730          { "stp_cost", { "auto", 0 }, NULL, 0,
 740  731              set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
 741  732              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 742  733              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 743  734  
 744  735          { "stp_edge", { "1", 1 },
 745  736              link_01_vals, VALCNT(link_01_vals),
 746  737              set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
 747  738              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 748  739              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 749  740  
 750  741          { "stp_p2p", { "auto", P2P_AUTO },
 751  742              stp_p2p_vals, VALCNT(stp_p2p_vals),
 752  743              set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
 753  744              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 754  745              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 755  746  
 756  747          { "stp_mcheck", { "0", 0 },
  
    | 
      ↓ open down ↓ | 
    296 lines elided | 
    
      ↑ open up ↑ | 
  
 757  748              link_01_vals, VALCNT(link_01_vals),
 758  749              set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
 759  750              DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
 760  751              DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
 761  752  
 762  753          { "protection", { "--", RESET_VAL },
 763  754              link_protect_vals, VALCNT(link_protect_vals),
 764  755              set_resource, NULL, get_protection, check_prop, 0,
 765  756              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 766  757  
 767      -        { "promisc-filtered", { "on", 1 },
 768      -            link_promisc_filtered_vals, VALCNT(link_promisc_filtered_vals),
 769      -            set_promisc_filtered, NULL, get_promisc_filtered, check_prop, 0,
 770      -            DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE },
 771      -
 772      -
 773  758          { "allowed-ips", { "--", 0 },
 774  759              NULL, 0, set_resource, NULL,
 775  760              get_allowedips, check_allowedips, PD_CHECK_ALLOC,
 776  761              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 777  762  
 778  763          { "allowed-dhcp-cids", { "--", 0 },
 779  764              NULL, 0, set_resource, NULL,
 780  765              get_allowedcids, check_allowedcids, PD_CHECK_ALLOC,
 781  766              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 782  767  
 783  768          { "rxrings", { "--", RESET_VAL }, NULL, 0,
 784  769              set_resource, get_rings_range, get_rxrings, check_rings, 0,
 785  770              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 786  771  
 787  772          { "rxrings-effective", { "--", 0 },
 788  773              NULL, 0, NULL, NULL,
 789  774              get_rxrings, NULL, 0,
 790  775              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 791  776  
 792  777          { "txrings", { "--", RESET_VAL }, NULL, 0,
 793  778              set_resource, get_rings_range, get_txrings, check_rings, 0,
 794  779              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 795  780  
 796  781          { "txrings-effective", { "--", 0 },
 797  782              NULL, 0, NULL, NULL,
 798  783              get_txrings, NULL, 0,
 799  784              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 800  785  
 801  786          { "txrings-available", { "", 0 }, NULL, 0,
 802  787              NULL, NULL, get_cntavail, NULL, 0,
 803  788              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 804  789  
 805  790          { "rxrings-available", { "", 0 }, NULL, 0,
 806  791              NULL, NULL, get_cntavail, NULL, 0,
 807  792              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 808  793  
 809  794          { "rxhwclnt-available", { "", 0 }, NULL, 0,
 810  795              NULL, NULL, get_cntavail, NULL, 0,
 811  796              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 812  797  
 813  798          { "txhwclnt-available", { "", 0 }, NULL, 0,
 814  799              NULL, NULL, get_cntavail, NULL, 0,
 815  800              DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
 816  801  
 817  802  };
 818  803  
 819  804  #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
 820  805  
 821  806  static resource_prop_t rsrc_prop_table[] = {
 822  807          {"maxbw",               extract_maxbw},
 823  808          {"priority",            extract_priority},
 824  809          {"cpus",                extract_cpus},
 825  810          {"cpus-effective",      extract_cpus},
 826  811          {"pool",                extract_pool},
 827  812          {"pool-effective",      extract_pool},
 828  813          {"protection",          extract_protection},
 829  814          {"allowed-ips",         extract_allowedips},
 830  815          {"allowed-dhcp-cids",   extract_allowedcids},
 831  816          {"rxrings",             extract_rxrings},
 832  817          {"rxrings-effective",   extract_rxrings},
 833  818          {"txrings",             extract_txrings},
 834  819          {"txrings-effective",   extract_txrings}
 835  820  };
 836  821  #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
 837  822          sizeof (resource_prop_t))
 838  823  
 839  824  /*
 840  825   * when retrieving  private properties, we pass down a buffer with
 841  826   * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
 842  827   */
 843  828  #define DLADM_PROP_BUF_CHUNK    1024
 844  829  
 845  830  static dladm_status_t   i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
 846  831                              const char *, char **, uint_t);
 847  832  static dladm_status_t   i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
 848  833                              const char *, char **, uint_t *);
 849  834  static dladm_status_t   i_dladm_walk_linkprop_priv_db(dladm_handle_t,
 850  835                              datalink_id_t, void *, int (*)(dladm_handle_t,
 851  836                              datalink_id_t, const char *, void *));
 852  837  static dladm_status_t   i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
 853  838                              datalink_class_t, uint32_t, prop_desc_t *, char **,
 854  839                              uint_t, uint_t);
 855  840  static dladm_status_t   i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
 856  841                              const char *, char **, uint_t, uint_t);
 857  842  static dladm_status_t   i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
 858  843                              datalink_id_t, datalink_media_t, uint_t);
 859  844  
 860  845  /*
 861  846   * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
 862  847   * rates to be retrieved. However, we cannot increase it at this
 863  848   * time because it will break binary compatibility with unbundled
 864  849   * WiFi drivers and utilities. So for now we define an additional
 865  850   * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
 866  851   */
 867  852  #define MAX_SUPPORT_RATES       64
 868  853  
 869  854  #define AP_ANCHOR       "[anchor]"
 870  855  #define AP_DELIMITER    '.'
 871  856  
 872  857  /* ARGSUSED */
 873  858  static dladm_status_t
 874  859  check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
 875  860      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
 876  861      datalink_media_t media)
 877  862  {
 878  863          int             i, j;
 879  864          uint_t          val_cnt = *val_cntp;
 880  865          val_desc_t      *vdp = *vdpp;
 881  866  
 882  867          for (j = 0; j < val_cnt; j++) {
 883  868                  for (i = 0; i < pdp->pd_noptval; i++) {
 884  869                          if (strcasecmp(prop_val[j],
 885  870                              pdp->pd_optval[i].vd_name) == 0) {
 886  871                                  break;
 887  872                          }
 888  873                  }
 889  874                  if (i == pdp->pd_noptval)
 890  875                          return (DLADM_STATUS_BADVAL);
 891  876  
 892  877                  (void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
 893  878          }
 894  879          return (DLADM_STATUS_OK);
 895  880  }
 896  881  
 897  882  static dladm_status_t
 898  883  i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
 899  884      datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
 900  885      uint_t val_cnt, uint_t flags)
 901  886  {
 902  887          dladm_status_t  status = DLADM_STATUS_OK;
 903  888          val_desc_t      *vdp = NULL;
 904  889          boolean_t       needfree = B_FALSE;
 905  890          uint_t          cnt, i;
 906  891  
 907  892          if (!(pdp->pd_class & class))
 908  893                  return (DLADM_STATUS_BADARG);
 909  894  
 910  895          if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
 911  896                  return (DLADM_STATUS_BADARG);
 912  897  
 913  898          if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
 914  899                  return (DLADM_STATUS_TEMPONLY);
 915  900  
 916  901          if (!(flags & DLADM_OPT_ACTIVE))
 917  902                  return (DLADM_STATUS_OK);
 918  903  
 919  904          if (pdp->pd_set == NULL)
 920  905                  return (DLADM_STATUS_PROPRDONLY);
 921  906  
 922  907          if (prop_val != NULL) {
 923  908                  vdp = calloc(val_cnt, sizeof (val_desc_t));
 924  909                  if (vdp == NULL)
 925  910                          return (DLADM_STATUS_NOMEM);
 926  911  
 927  912                  if (pdp->pd_check != NULL) {
 928  913                          needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
 929  914                          status = pdp->pd_check(handle, pdp, linkid, prop_val,
 930  915                              &val_cnt, flags, &vdp, media);
 931  916                  } else if (pdp->pd_optval != NULL) {
 932  917                          status = check_prop(handle, pdp, linkid, prop_val,
 933  918                              &val_cnt, flags, &vdp, media);
 934  919                  } else {
 935  920                          status = DLADM_STATUS_BADARG;
 936  921                  }
 937  922  
 938  923                  if (status != DLADM_STATUS_OK)
 939  924                          goto done;
 940  925  
 941  926                  cnt = val_cnt;
 942  927          } else {
 943  928                  boolean_t       defval = B_FALSE;
 944  929  
 945  930                  if (pdp->pd_defval.vd_name == NULL)
 946  931                          return (DLADM_STATUS_NOTSUP);
 947  932  
 948  933                  cnt = 1;
 949  934                  defval = (strlen(pdp->pd_defval.vd_name) > 0);
 950  935                  if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
 951  936                          if ((vdp = calloc(1, sizeof (val_desc_t))) == NULL)
 952  937                                  return (DLADM_STATUS_NOMEM);
 953  938  
 954  939                          if (defval) {
 955  940                                  (void) memcpy(vdp, &pdp->pd_defval,
 956  941                                      sizeof (val_desc_t));
 957  942                          } else if (pdp->pd_check != NULL) {
 958  943                                  status = pdp->pd_check(handle, pdp, linkid,
 959  944                                      prop_val, &cnt, flags, &vdp, media);
 960  945                                  if (status != DLADM_STATUS_OK)
 961  946                                          goto done;
 962  947                          }
 963  948                  } else {
 964  949                          status = i_dladm_getset_defval(handle, pdp, linkid,
 965  950                              media, flags);
 966  951                          return (status);
 967  952                  }
 968  953          }
 969  954          if (pdp->pd_flags & PD_AFTER_PERM)
 970  955                  status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
 971  956                      DLADM_STATUS_PERMONLY;
 972  957          else
 973  958                  status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
 974  959                      media);
 975  960          if (needfree) {
 976  961                  for (i = 0; i < cnt; i++)
 977  962                          free((void *)((val_desc_t *)vdp + i)->vd_val);
 978  963          }
 979  964  done:
 980  965          free(vdp);
 981  966          return (status);
 982  967  }
 983  968  
 984  969  static dladm_status_t
 985  970  i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
 986  971      const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
 987  972  {
 988  973          int                     i;
 989  974          boolean_t               found = B_FALSE;
 990  975          datalink_class_t        class;
 991  976          uint32_t                media;
 992  977          dladm_status_t          status = DLADM_STATUS_OK;
 993  978  
 994  979          status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
 995  980              NULL, 0);
 996  981          if (status != DLADM_STATUS_OK)
 997  982                  return (status);
 998  983  
 999  984          for (i = 0; i < DLADM_MAX_PROPS; i++) {
1000  985                  prop_desc_t     *pdp = &prop_table[i];
1001  986                  dladm_status_t  s;
1002  987  
1003  988                  if (prop_name != NULL &&
1004  989                      (strcasecmp(prop_name, pdp->pd_name) != 0))
1005  990                          continue;
1006  991                  found = B_TRUE;
1007  992                  s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
1008  993                      prop_val, val_cnt, flags);
1009  994  
1010  995                  if (prop_name != NULL) {
1011  996                          status = s;
1012  997                          break;
1013  998                  } else {
1014  999                          if (s != DLADM_STATUS_OK &&
1015 1000                              s != DLADM_STATUS_NOTSUP)
1016 1001                                  status = s;
1017 1002                  }
1018 1003          }
1019 1004          if (!found) {
1020 1005                  if (prop_name[0] == '_') {
1021 1006                          /* other private properties */
1022 1007                          status = i_dladm_set_private_prop(handle, linkid,
1023 1008                              prop_name, prop_val, val_cnt, flags);
1024 1009                  } else  {
1025 1010                          status = DLADM_STATUS_NOTFOUND;
1026 1011                  }
1027 1012          }
1028 1013          return (status);
1029 1014  }
1030 1015  
1031 1016  /*
1032 1017   * Set/reset link property for specific link
1033 1018   */
1034 1019  dladm_status_t
1035 1020  dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
1036 1021      const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
1037 1022  {
1038 1023          dladm_status_t  status = DLADM_STATUS_OK;
1039 1024  
1040 1025          if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
1041 1026              (prop_val == NULL && val_cnt > 0) ||
1042 1027              (prop_val != NULL && val_cnt == 0) ||
1043 1028              (prop_name == NULL && prop_val != NULL)) {
1044 1029                  return (DLADM_STATUS_BADARG);
1045 1030          }
1046 1031  
1047 1032          /*
1048 1033           * Check for valid link property against the flags passed
1049 1034           * and set the link property when active flag is passed.
1050 1035           */
1051 1036          status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
1052 1037              val_cnt, flags);
1053 1038          if (status != DLADM_STATUS_OK)
1054 1039                  return (status);
1055 1040  
1056 1041          if (flags & DLADM_OPT_PERSIST) {
1057 1042                  status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
1058 1043                      prop_val, val_cnt);
1059 1044  
1060 1045                  if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
1061 1046                          prop_desc_t *pdp = prop_table;
1062 1047                          int i;
1063 1048  
1064 1049                          for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
1065 1050                                  if (!(pdp->pd_flags & PD_AFTER_PERM))
1066 1051                                          continue;
1067 1052                                  if (prop_name != NULL &&
1068 1053                                      strcasecmp(prop_name, pdp->pd_name) != 0)
1069 1054                                          continue;
1070 1055                                  status = pdp->pd_set(handle, pdp, linkid, NULL,
1071 1056                                      0, flags, 0);
1072 1057                          }
1073 1058                  }
1074 1059          }
1075 1060          return (status);
1076 1061  }
1077 1062  
1078 1063  /*
1079 1064   * Walk all link properties of the given specific link.
1080 1065   *
1081 1066   * Note: this function currently lacks the ability to walk _all_ private
1082 1067   * properties if the link, because there is no kernel interface to
1083 1068   * retrieve all known private property names. Once such an interface
1084 1069   * is added, this function should be fixed accordingly.
1085 1070   */
1086 1071  dladm_status_t
1087 1072  dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
1088 1073      int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
1089 1074  {
1090 1075          dladm_status_t          status;
1091 1076          datalink_class_t        class;
1092 1077          uint_t                  media;
1093 1078          int                     i;
1094 1079  
1095 1080          if (linkid == DATALINK_INVALID_LINKID || func == NULL)
1096 1081                  return (DLADM_STATUS_BADARG);
1097 1082  
1098 1083          status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1099 1084              NULL, 0);
1100 1085          if (status != DLADM_STATUS_OK)
1101 1086                  return (status);
1102 1087  
1103 1088          /* public */
1104 1089          for (i = 0; i < DLADM_MAX_PROPS; i++) {
1105 1090                  if (!(prop_table[i].pd_class & class))
1106 1091                          continue;
1107 1092  
1108 1093                  if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
1109 1094                          continue;
1110 1095  
1111 1096                  if (func(handle, linkid, prop_table[i].pd_name, arg) ==
1112 1097                      DLADM_WALK_TERMINATE) {
1113 1098                          break;
1114 1099                  }
1115 1100          }
1116 1101  
1117 1102          /* private */
1118 1103          status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
1119 1104  
1120 1105          return (status);
1121 1106  }
1122 1107  
1123 1108  /*
1124 1109   * Get linkprop of the given specific link.
1125 1110   */
1126 1111  dladm_status_t
1127 1112  dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
1128 1113      dladm_prop_type_t type, const char *prop_name, char **prop_val,
1129 1114      uint_t *val_cntp)
1130 1115  {
1131 1116          dladm_status_t          status = DLADM_STATUS_OK;
1132 1117          datalink_class_t        class;
1133 1118          uint_t                  media;
1134 1119          prop_desc_t             *pdp;
1135 1120          uint_t                  cnt, dld_flags = 0;
1136 1121          int                     i;
1137 1122          uint_t                  perm_flags;
1138 1123  
1139 1124          if (type == DLADM_PROP_VAL_DEFAULT)
1140 1125                  dld_flags |= DLD_PROP_DEFAULT;
1141 1126          else if (type == DLADM_PROP_VAL_MODIFIABLE)
1142 1127                  dld_flags |= DLD_PROP_POSSIBLE;
1143 1128  
1144 1129          if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
1145 1130              prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
1146 1131                  return (DLADM_STATUS_BADARG);
1147 1132  
1148 1133          for (i = 0; i < DLADM_MAX_PROPS; i++)
1149 1134                  if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
1150 1135                          break;
1151 1136  
1152 1137          if (i == DLADM_MAX_PROPS) {
1153 1138                  if (prop_name[0] == '_') {
1154 1139                          /*
1155 1140                           * private property.
1156 1141                           */
1157 1142                          if (type == DLADM_PROP_VAL_PERSISTENT)
1158 1143                                  return (i_dladm_get_linkprop_db(handle, linkid,
1159 1144                                      prop_name, prop_val, val_cntp));
1160 1145                          else
1161 1146                                  return (i_dladm_get_priv_prop(handle, linkid,
1162 1147                                      prop_name, prop_val, val_cntp, type,
1163 1148                                      dld_flags));
1164 1149                  } else {
1165 1150                          return (DLADM_STATUS_NOTFOUND);
1166 1151                  }
1167 1152          }
1168 1153  
1169 1154          pdp = &prop_table[i];
1170 1155  
1171 1156          status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1172 1157              NULL, 0);
1173 1158          if (status != DLADM_STATUS_OK)
1174 1159                  return (status);
1175 1160  
1176 1161          if (!(pdp->pd_class & class))
1177 1162                  return (DLADM_STATUS_BADARG);
1178 1163  
1179 1164          if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
1180 1165                  return (DLADM_STATUS_BADARG);
1181 1166  
1182 1167          switch (type) {
1183 1168          case DLADM_PROP_VAL_CURRENT:
1184 1169                  status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1185 1170                      media, dld_flags, &perm_flags);
1186 1171                  break;
1187 1172  
1188 1173          case DLADM_PROP_VAL_PERM:
1189 1174                  if (pdp->pd_set == NULL) {
1190 1175                          perm_flags = MAC_PROP_PERM_READ;
1191 1176                  } else {
1192 1177                          status = pdp->pd_get(handle, pdp, linkid, prop_val,
1193 1178                              val_cntp, media, dld_flags, &perm_flags);
1194 1179                  }
1195 1180  
1196 1181                  *prop_val[0] = '\0';
1197 1182                  *val_cntp = 1;
1198 1183                  if (status == DLADM_STATUS_OK)
1199 1184                          (void) dladm_perm2str(perm_flags, *prop_val);
1200 1185                  break;
1201 1186  
1202 1187          case DLADM_PROP_VAL_DEFAULT:
1203 1188                  /*
1204 1189                   * If defaults are not defined for the property,
1205 1190                   * pd_defval.vd_name should be null. If the driver
1206 1191                   * has to be contacted for the value, vd_name should
1207 1192                   * be the empty string (""). Otherwise, dladm will
1208 1193                   * just print whatever is in the table.
1209 1194                   */
1210 1195                  if (pdp->pd_defval.vd_name == NULL) {
1211 1196                          status = DLADM_STATUS_NOTSUP;
1212 1197                          break;
1213 1198                  }
1214 1199  
1215 1200                  if (strlen(pdp->pd_defval.vd_name) == 0) {
1216 1201                          status = pdp->pd_get(handle, pdp, linkid, prop_val,
1217 1202                              val_cntp, media, dld_flags, &perm_flags);
1218 1203                  } else {
1219 1204                          (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
1220 1205                  }
1221 1206                  *val_cntp = 1;
1222 1207                  break;
1223 1208  
1224 1209          case DLADM_PROP_VAL_MODIFIABLE:
1225 1210                  if (pdp->pd_getmod != NULL) {
1226 1211                          status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
1227 1212                              val_cntp, media, dld_flags, &perm_flags);
1228 1213                          break;
1229 1214                  }
1230 1215                  cnt = pdp->pd_noptval;
1231 1216                  if (cnt == 0) {
1232 1217                          status = DLADM_STATUS_NOTSUP;
1233 1218                  } else if (cnt > *val_cntp) {
1234 1219                          status = DLADM_STATUS_TOOSMALL;
1235 1220                  } else {
1236 1221                          for (i = 0; i < cnt; i++) {
1237 1222                                  (void) strcpy(prop_val[i],
1238 1223                                      pdp->pd_optval[i].vd_name);
1239 1224                          }
1240 1225                          *val_cntp = cnt;
1241 1226                  }
1242 1227                  break;
1243 1228          case DLADM_PROP_VAL_PERSISTENT:
1244 1229                  if (pdp->pd_flags & PD_TEMPONLY)
1245 1230                          return (DLADM_STATUS_TEMPONLY);
1246 1231                  status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
1247 1232                      prop_val, val_cntp);
1248 1233                  break;
1249 1234          default:
1250 1235                  status = DLADM_STATUS_BADARG;
1251 1236                  break;
1252 1237          }
1253 1238  
1254 1239          return (status);
1255 1240  }
1256 1241  
1257 1242  /*
1258 1243   * Get linkprop of the given specific link and run any possible conversion
1259 1244   * of the values using the check function for the property. Fails if the
1260 1245   * check function doesn't succeed for the property value.
1261 1246   */
1262 1247  dladm_status_t
1263 1248  dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
1264 1249      dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
1265 1250      uint_t *val_cntp)
1266 1251  {
1267 1252          dladm_status_t          status;
1268 1253          datalink_class_t        class;
1269 1254          uint_t                  media;
1270 1255          prop_desc_t             *pdp;
1271 1256          uint_t                  dld_flags;
1272 1257          int                     valc, i;
1273 1258          char                    **prop_val;
1274 1259          uint_t                  perm_flags;
1275 1260  
1276 1261          if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
1277 1262              ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
1278 1263                  return (DLADM_STATUS_BADARG);
1279 1264  
1280 1265          for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
1281 1266                  if (strcasecmp(prop_name, pdp->pd_name) == 0)
1282 1267                          break;
1283 1268  
1284 1269          if (pdp == prop_table + DLADM_MAX_PROPS)
1285 1270                  return (DLADM_STATUS_NOTFOUND);
1286 1271  
1287 1272          if (pdp->pd_flags & PD_CHECK_ALLOC)
1288 1273                  return (DLADM_STATUS_BADARG);
1289 1274  
1290 1275          status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1291 1276              NULL, 0);
1292 1277          if (status != DLADM_STATUS_OK)
1293 1278                  return (status);
1294 1279  
1295 1280          if (!(pdp->pd_class & class))
1296 1281                  return (DLADM_STATUS_BADARG);
1297 1282  
1298 1283          if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
1299 1284                  return (DLADM_STATUS_BADARG);
1300 1285  
1301 1286          prop_val = malloc(*val_cntp * sizeof (*prop_val) +
1302 1287              *val_cntp * DLADM_PROP_VAL_MAX);
1303 1288          if (prop_val == NULL)
1304 1289                  return (DLADM_STATUS_NOMEM);
1305 1290          for (valc = 0; valc < *val_cntp; valc++)
1306 1291                  prop_val[valc] = (char *)(prop_val + *val_cntp) +
1307 1292                      valc * DLADM_PROP_VAL_MAX;
1308 1293  
1309 1294          dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? DLD_PROP_DEFAULT : 0;
1310 1295  
1311 1296          switch (type) {
1312 1297          case DLADM_PROP_VAL_CURRENT:
1313 1298                  status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1314 1299                      media, dld_flags, &perm_flags);
1315 1300                  break;
1316 1301  
1317 1302          case DLADM_PROP_VAL_DEFAULT:
1318 1303                  /*
1319 1304                   * If defaults are not defined for the property,
1320 1305                   * pd_defval.vd_name should be null. If the driver
1321 1306                   * has to be contacted for the value, vd_name should
1322 1307                   * be the empty string (""). Otherwise, dladm will
1323 1308                   * just print whatever is in the table.
1324 1309                   */
1325 1310                  if (pdp->pd_defval.vd_name == NULL) {
1326 1311                          status = DLADM_STATUS_NOTSUP;
1327 1312                          break;
1328 1313                  }
1329 1314  
1330 1315                  if (pdp->pd_defval.vd_name[0] != '\0') {
1331 1316                          *val_cntp = 1;
1332 1317                          *ret_val = pdp->pd_defval.vd_val;
1333 1318                          free(prop_val);
1334 1319                          return (DLADM_STATUS_OK);
1335 1320                  }
1336 1321                  status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1337 1322                      media, dld_flags, &perm_flags);
1338 1323                  break;
1339 1324  
1340 1325          case DLADM_PROP_VAL_PERSISTENT:
1341 1326                  if (pdp->pd_flags & PD_TEMPONLY)
1342 1327                          status = DLADM_STATUS_TEMPONLY;
1343 1328                  else
1344 1329                          status = i_dladm_get_linkprop_db(handle, linkid,
1345 1330                              prop_name, prop_val, val_cntp);
1346 1331                  break;
1347 1332  
1348 1333          default:
1349 1334                  status = DLADM_STATUS_BADARG;
1350 1335                  break;
1351 1336          }
1352 1337  
1353 1338          if (status == DLADM_STATUS_OK) {
1354 1339                  if (pdp->pd_check != NULL) {
1355 1340                          val_desc_t *vdp;
1356 1341  
1357 1342                          vdp = malloc(sizeof (val_desc_t) * *val_cntp);
1358 1343                          if (vdp == NULL)
1359 1344                                  status = DLADM_STATUS_NOMEM;
1360 1345                          else
1361 1346                                  status = pdp->pd_check(handle, pdp, linkid,
1362 1347                                      prop_val, val_cntp, 0, &vdp, media);
1363 1348                          if (status == DLADM_STATUS_OK) {
1364 1349                                  for (valc = 0; valc < *val_cntp; valc++)
1365 1350                                          ret_val[valc] = vdp[valc].vd_val;
1366 1351                          }
1367 1352                          free(vdp);
1368 1353                  } else {
1369 1354                          for (valc = 0; valc < *val_cntp; valc++) {
1370 1355                                  for (i = 0; i < pdp->pd_noptval; i++) {
1371 1356                                          if (strcmp(pdp->pd_optval[i].vd_name,
1372 1357                                              prop_val[valc]) == 0) {
1373 1358                                                  ret_val[valc] =
1374 1359                                                      pdp->pd_optval[i].vd_val;
1375 1360                                                  break;
1376 1361                                          }
1377 1362                                  }
1378 1363                                  if (i == pdp->pd_noptval) {
1379 1364                                          status = DLADM_STATUS_FAILED;
1380 1365                                          break;
1381 1366                                  }
1382 1367                          }
1383 1368                  }
1384 1369          }
1385 1370  
1386 1371          free(prop_val);
1387 1372  
1388 1373          return (status);
1389 1374  }
1390 1375  
1391 1376  /*ARGSUSED*/
1392 1377  static int
1393 1378  i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
1394 1379      const char *prop_name, void *arg)
1395 1380  {
1396 1381          char                    *buf, **propvals;
1397 1382          uint_t                  i, valcnt = DLADM_MAX_PROP_VALCNT;
1398 1383          dladm_status_t          status;
1399 1384          dladm_linkprop_args_t   *dla = arg;
1400 1385  
1401 1386          if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
1402 1387              DLADM_MAX_PROP_VALCNT)) == NULL) {
1403 1388                  return (DLADM_WALK_CONTINUE);
1404 1389          }
1405 1390  
1406 1391          propvals = (char **)(void *)buf;
1407 1392          for (i = 0; i < valcnt; i++) {
1408 1393                  propvals[i] = buf +
1409 1394                      sizeof (char *) * DLADM_MAX_PROP_VALCNT +
1410 1395                      i * DLADM_PROP_VAL_MAX;
1411 1396          }
1412 1397  
1413 1398          if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
1414 1399              prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
1415 1400                  goto done;
1416 1401          }
1417 1402  
1418 1403          status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
1419 1404              valcnt, dla->dla_flags | DLADM_OPT_ACTIVE);
1420 1405  
1421 1406          if (status != DLADM_STATUS_OK)
1422 1407                  dla->dla_status = status;
1423 1408  
1424 1409  done:
1425 1410          if (buf != NULL)
1426 1411                  free(buf);
1427 1412  
1428 1413          return (DLADM_WALK_CONTINUE);
1429 1414  }
1430 1415  
1431 1416  /*ARGSUSED*/
1432 1417  static int
1433 1418  i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
1434 1419  {
1435 1420          datalink_class_t        class;
1436 1421          dladm_status_t          status;
1437 1422  
1438 1423          status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
1439 1424              NULL, 0);
1440 1425          if (status != DLADM_STATUS_OK)
1441 1426                  return (DLADM_WALK_TERMINATE);
1442 1427  
1443 1428          if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
1444 1429                  (void) dladm_init_linkprop(handle, linkid, B_TRUE);
1445 1430  
1446 1431          return (DLADM_WALK_CONTINUE);
1447 1432  }
1448 1433  
1449 1434  dladm_status_t
1450 1435  dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
1451 1436      boolean_t any_media)
1452 1437  {
1453 1438          dladm_status_t          status = DLADM_STATUS_OK;
1454 1439          datalink_media_t        dmedia;
1455 1440          uint32_t                media;
1456 1441          dladm_linkprop_args_t   *dla;
1457 1442  
1458 1443          dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
1459 1444  
1460 1445          dla = malloc(sizeof (dladm_linkprop_args_t));
1461 1446          if (dla == NULL)
1462 1447                  return (DLADM_STATUS_NOMEM);
1463 1448          dla->dla_flags = DLADM_OPT_BOOT;
1464 1449          dla->dla_status = DLADM_STATUS_OK;
1465 1450  
1466 1451          if (linkid == DATALINK_ALL_LINKID) {
1467 1452                  (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
1468 1453                      NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
1469 1454          } else if (any_media ||
1470 1455              ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
1471 1456              0) == DLADM_STATUS_OK) &&
1472 1457              DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
1473 1458                  (void) dladm_walk_linkprop(handle, linkid, (void *)dla,
1474 1459                      i_dladm_init_one_prop);
1475 1460                  status = dla->dla_status;
1476 1461          }
1477 1462          free(dla);
1478 1463          return (status);
1479 1464  }
1480 1465  
1481 1466  /* ARGSUSED */
1482 1467  static dladm_status_t
1483 1468  get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1484 1469      char **prop_val, uint_t *val_cnt, datalink_media_t media,
1485 1470      uint_t flags, uint_t *perm_flags)
1486 1471  {
1487 1472          char                    zone_name[ZONENAME_MAX];
1488 1473          zoneid_t                zid;
1489 1474          dladm_status_t          status;
1490 1475  
1491 1476          if (flags != 0)
1492 1477                  return (DLADM_STATUS_NOTSUP);
1493 1478  
1494 1479          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1495 1480              perm_flags, &zid, sizeof (zid));
1496 1481          if (status != DLADM_STATUS_OK)
1497 1482                  return (status);
1498 1483  
1499 1484          *val_cnt = 1;
1500 1485          if (zid != GLOBAL_ZONEID) {
1501 1486                  if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
1502 1487                          return (dladm_errno2status(errno));
1503 1488                  }
  
    | 
      ↓ open down ↓ | 
    721 lines elided | 
    
      ↑ open up ↑ | 
  
1504 1489  
1505 1490                  (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
1506 1491          } else {
1507 1492                  *prop_val[0] = '\0';
1508 1493          }
1509 1494  
1510 1495          return (DLADM_STATUS_OK);
1511 1496  }
1512 1497  
1513 1498  typedef int (*zone_get_devroot_t)(char *, char *, size_t);
     1499 +typedef int (*zone_get_brand_t)(char *, char *, size_t);
1514 1500  
1515 1501  static int
1516 1502  i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
1517 1503  {
1518 1504          char                    root[MAXPATHLEN];
     1505 +        char                    brand[MAXPATHLEN]; /* Overkill, for sure. */
     1506 +        static char             *full_native_path = "/native/dev";
     1507 +        char                    *native_dev_path = full_native_path;
1519 1508          zone_get_devroot_t      real_zone_get_devroot;
     1509 +        zone_get_brand_t        real_zone_get_brand;
1520 1510          void                    *dlhandle;
1521 1511          void                    *sym;
1522 1512          int                     ret;
1523 1513  
1524 1514          if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
1525 1515                  return (-1);
1526 1516  
1527 1517          if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
1528 1518                  (void) dlclose(dlhandle);
1529 1519                  return (-1);
1530 1520          }
1531      -
1532 1521          real_zone_get_devroot = (zone_get_devroot_t)sym;
1533 1522  
     1523 +        if ((sym = dlsym(dlhandle, "zone_get_brand")) == NULL) {
     1524 +                (void) dlclose(dlhandle);
     1525 +                return (-1);
     1526 +        }
     1527 +        real_zone_get_brand = (zone_get_devroot_t)sym;
     1528 +
     1529 +        /* Have "/dev" be LX-agile for possibility of "/native/dev". */
     1530 +        ret = real_zone_get_brand(zone_name, brand, sizeof (brand));
     1531 +        if (ret != 0) {
     1532 +                (void) dlclose(dlhandle);
     1533 +                return (ret);
     1534 +        }
     1535 +        /* Can use strcmp with constant string... */
     1536 +        if (strcmp(brand, "lx") != 0) {
     1537 +                /* Non-LX zone, don't use "/native/dev" */
     1538 +                native_dev_path += 7;   /* strlen("/native") */
     1539 +        }
     1540 +
1534 1541          if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
1535      -                (void) snprintf(dev, devlen, "%s%s", root, "/dev");
     1542 +                (void) snprintf(dev, devlen, "%s%s", root, native_dev_path);
1536 1543          (void) dlclose(dlhandle);
1537 1544          return (ret);
1538 1545  }
1539 1546  
1540 1547  static dladm_status_t
1541 1548  i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
1542 1549      datalink_id_t linkid, boolean_t add)
1543 1550  {
1544 1551          char            path[MAXPATHLEN];
1545 1552          char            name[MAXLINKNAMELEN];
1546 1553          di_prof_t       prof = NULL;
1547 1554          char            zone_name[ZONENAME_MAX];
1548 1555          dladm_status_t  status;
1549 1556          int             ret;
1550 1557  
1551 1558          if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
1552 1559                  return (dladm_errno2status(errno));
1553 1560          if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
1554 1561                  return (dladm_errno2status(errno));
1555 1562          if (di_prof_init(path, &prof) != 0)
1556 1563                  return (dladm_errno2status(errno));
1557 1564  
1558 1565          status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
1559 1566          if (status != DLADM_STATUS_OK)
1560 1567                  goto cleanup;
1561 1568  
1562 1569          if (add)
1563 1570                  ret = di_prof_add_dev(prof, name);
1564 1571          else
1565 1572                  ret = di_prof_add_exclude(prof, name);
1566 1573  
1567 1574          if (ret != 0) {
1568 1575                  status = dladm_errno2status(errno);
1569 1576                  goto cleanup;
1570 1577          }
1571 1578  
1572 1579          if (di_prof_commit(prof) != 0)
1573 1580                  status = dladm_errno2status(errno);
1574 1581  cleanup:
1575 1582          if (prof)
1576 1583                  di_prof_fini(prof);
1577 1584  
1578 1585          return (status);
1579 1586  }
1580 1587  
1581 1588  /* ARGSUSED */
1582 1589  static dladm_status_t
1583 1590  set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1584 1591      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1585 1592  {
1586 1593          dladm_status_t          status = DLADM_STATUS_OK;
1587 1594          zoneid_t                zid_old, zid_new;
1588 1595          dld_ioc_zid_t           *dzp;
1589 1596  
1590 1597          if (val_cnt != 1)
1591 1598                  return (DLADM_STATUS_BADVALCNT);
1592 1599  
1593 1600          dzp = (dld_ioc_zid_t *)vdp->vd_val;
  
    | 
      ↓ open down ↓ | 
    48 lines elided | 
    
      ↑ open up ↑ | 
  
1594 1601  
1595 1602          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1596 1603              NULL, &zid_old, sizeof (zid_old));
1597 1604          if (status != DLADM_STATUS_OK)
1598 1605                  return (status);
1599 1606  
1600 1607          zid_new = dzp->diz_zid;
1601 1608          if (zid_new == zid_old)
1602 1609                  return (DLADM_STATUS_OK);
1603 1610  
1604      -        if (flags & DLADM_OPT_TRANSIENT)
1605      -                dzp->diz_transient = B_TRUE;
1606      -
1607 1611          if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt,
1608 1612              flags, media)) != DLADM_STATUS_OK)
1609 1613                  return (status);
1610 1614  
1611 1615          /*
1612 1616           * It is okay to fail to update the /dev entry (some vanity-named
1613 1617           * links do not have a /dev entry).
1614 1618           */
1615 1619          if (zid_old != GLOBAL_ZONEID) {
1616 1620                  (void) i_dladm_update_deventry(handle, zid_old, linkid,
1617 1621                      B_FALSE);
1618 1622          }
1619 1623          if (zid_new != GLOBAL_ZONEID)
1620 1624                  (void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
1621 1625  
1622 1626          return (DLADM_STATUS_OK);
1623 1627  }
1624 1628  
1625 1629  /* ARGSUSED */
1626 1630  static dladm_status_t
1627 1631  check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1628 1632      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1629 1633      datalink_media_t media)
1630 1634  {
1631 1635          char            *zone_name;
1632 1636          zoneid_t        zoneid;
1633 1637          dladm_status_t  status = DLADM_STATUS_OK;
1634 1638          dld_ioc_zid_t   *dzp;
1635 1639          uint_t          val_cnt = *val_cntp;
1636 1640          val_desc_t      *vdp = *vdpp;
1637 1641  
1638 1642          if (val_cnt != 1)
1639 1643                  return (DLADM_STATUS_BADVALCNT);
1640 1644  
1641 1645          dzp = malloc(sizeof (dld_ioc_zid_t));
1642 1646          if (dzp == NULL)
1643 1647                  return (DLADM_STATUS_NOMEM);
1644 1648  
1645 1649          zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
1646 1650          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1647 1651                  status = DLADM_STATUS_BADVAL;
1648 1652                  goto done;
1649 1653          }
1650 1654  
1651 1655          if (zoneid != GLOBAL_ZONEID) {
1652 1656                  ushort_t        flags;
1653 1657  
1654 1658                  if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
1655 1659                      sizeof (flags)) < 0) {
1656 1660                          status = dladm_errno2status(errno);
1657 1661                          goto done;
1658 1662                  }
1659 1663  
1660 1664                  if (!(flags & ZF_NET_EXCL)) {
1661 1665                          status = DLADM_STATUS_BADVAL;
1662 1666                          goto done;
1663 1667                  }
1664 1668          }
1665 1669  
1666 1670          (void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
1667 1671  
1668 1672          dzp->diz_zid = zoneid;
1669 1673          dzp->diz_linkid = linkid;
1670 1674  
1671 1675          vdp->vd_val = (uintptr_t)dzp;
1672 1676          return (DLADM_STATUS_OK);
1673 1677  done:
1674 1678          free(dzp);
1675 1679          return (status);
1676 1680  }
1677 1681  
1678 1682  /* ARGSUSED */
1679 1683  static dladm_status_t
1680 1684  get_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1681 1685      char **prop_val, uint_t *val_cnt, datalink_media_t media,
1682 1686      uint_t flags, uint_t *perm_flags)
1683 1687  {
1684 1688          mac_resource_props_t    mrp;
1685 1689          dladm_status_t          status;
1686 1690  
1687 1691          status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
1688 1692              perm_flags, &mrp, sizeof (mrp));
1689 1693          if (status != DLADM_STATUS_OK)
1690 1694                  return (status);
1691 1695  
1692 1696          if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
1693 1697                  *val_cnt = 0;
1694 1698                  return (DLADM_STATUS_OK);
1695 1699          }
1696 1700  
1697 1701          (void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
1698 1702          *val_cnt = 1;
1699 1703          return (DLADM_STATUS_OK);
1700 1704  }
1701 1705  
1702 1706  /* ARGSUSED */
1703 1707  static dladm_status_t
1704 1708  check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1705 1709      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1706 1710      datalink_media_t media)
1707 1711  {
1708 1712          uint64_t        *maxbw;
1709 1713          dladm_status_t  status = DLADM_STATUS_OK;
1710 1714          uint_t          val_cnt = *val_cntp;
1711 1715          val_desc_t      *vdp = *vdpp;
1712 1716  
1713 1717          if (val_cnt != 1)
1714 1718                  return (DLADM_STATUS_BADVALCNT);
1715 1719  
1716 1720          maxbw = malloc(sizeof (uint64_t));
1717 1721          if (maxbw == NULL)
1718 1722                  return (DLADM_STATUS_NOMEM);
1719 1723  
1720 1724          status = dladm_str2bw(*prop_val, maxbw);
1721 1725          if (status != DLADM_STATUS_OK) {
1722 1726                  free(maxbw);
1723 1727                  return (status);
1724 1728          }
1725 1729  
1726 1730          if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
1727 1731                  free(maxbw);
1728 1732                  return (DLADM_STATUS_MINMAXBW);
1729 1733          }
1730 1734  
1731 1735          vdp->vd_val = (uintptr_t)maxbw;
1732 1736          return (DLADM_STATUS_OK);
1733 1737  }
1734 1738  
1735 1739  /* ARGSUSED */
1736 1740  dladm_status_t
1737 1741  extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
1738 1742  {
1739 1743          mac_resource_props_t *mrp = arg;
1740 1744  
1741 1745          if (vdp->vd_val == RESET_VAL) {
1742 1746                  mrp->mrp_maxbw = MRP_MAXBW_RESETVAL;
1743 1747          } else {
1744 1748                  bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
1745 1749          }
1746 1750          mrp->mrp_mask |= MRP_MAXBW;
1747 1751  
1748 1752          return (DLADM_STATUS_OK);
1749 1753  }
1750 1754  
1751 1755  /* ARGSUSED */
1752 1756  static dladm_status_t
1753 1757  get_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1754 1758      char **prop_val, uint_t *val_cnt, datalink_media_t media,
1755 1759      uint_t flags, uint_t *perm_flags)
1756 1760  {
1757 1761          dladm_status_t          status;
1758 1762          mac_resource_props_t    mrp;
1759 1763          mac_propval_range_t     *pv_range;
1760 1764          int                     err;
1761 1765  
1762 1766          if (strcmp(pdp->pd_name, "cpus-effective") == 0) {
1763 1767                  status = i_dladm_get_public_prop(handle, linkid,
1764 1768                      "resource-effective", flags, perm_flags, &mrp,
1765 1769                      sizeof (mrp));
1766 1770          } else {
1767 1771                  status = i_dladm_get_public_prop(handle, linkid,
1768 1772                      "resource", flags, perm_flags, &mrp, sizeof (mrp));
1769 1773          }
1770 1774  
1771 1775          if (status != DLADM_STATUS_OK)
1772 1776                  return (status);
1773 1777  
1774 1778          if (mrp.mrp_ncpus > *val_cnt)
1775 1779                  return (DLADM_STATUS_TOOSMALL);
1776 1780  
1777 1781          if (mrp.mrp_ncpus == 0) {
1778 1782                  *val_cnt = 0;
1779 1783                  return (DLADM_STATUS_OK);
1780 1784          }
1781 1785  
1782 1786          /* Sort CPU list and convert it to a mac_propval_range */
1783 1787          status = dladm_list2range(mrp.mrp_cpu, mrp.mrp_ncpus,
1784 1788              MAC_PROPVAL_UINT32, &pv_range);
1785 1789          if (status != DLADM_STATUS_OK)
1786 1790                  return (status);
1787 1791  
1788 1792          /* Write CPU ranges and individual CPUs */
1789 1793          err = dladm_range2strs(pv_range, prop_val);
1790 1794          if (err != 0) {
1791 1795                  free(pv_range);
1792 1796                  return (dladm_errno2status(err));
1793 1797          }
1794 1798  
1795 1799          *val_cnt = pv_range->mpr_count;
1796 1800          free(pv_range);
1797 1801  
1798 1802          return (DLADM_STATUS_OK);
1799 1803  }
1800 1804  
1801 1805  /* ARGSUSED */
1802 1806  static dladm_status_t
1803 1807  check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1804 1808      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1805 1809      datalink_media_t media)
1806 1810  {
1807 1811          int                     i, j, rc;
1808 1812          long                    nproc = sysconf(_SC_NPROCESSORS_CONF);
1809 1813          mac_resource_props_t    mrp;
1810 1814          mac_propval_range_t     *pv_range;
1811 1815          uint_t                  perm_flags;
1812 1816          uint32_t                ncpus;
1813 1817          uint32_t                *cpus = mrp.mrp_cpu;
1814 1818          val_desc_t              *vdp = *vdpp;
1815 1819          val_desc_t              *newvdp;
1816 1820          uint_t                  val_cnt = *val_cntp;
1817 1821          dladm_status_t          status = DLADM_STATUS_OK;
1818 1822  
1819 1823          /* Get the current pool property */
1820 1824          status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1821 1825              &perm_flags, &mrp, sizeof (mrp));
1822 1826  
1823 1827          if (status == DLADM_STATUS_OK) {
1824 1828                  /* Can't set cpus if a pool is set */
1825 1829                  if (strlen(mrp.mrp_pool) != 0)
1826 1830                          return (DLADM_STATUS_POOLCPU);
1827 1831          }
1828 1832  
1829 1833          /* Read ranges and convert to mac_propval_range */
1830 1834          status = dladm_strs2range(prop_val, val_cnt, MAC_PROPVAL_UINT32,
1831 1835              &pv_range);
1832 1836          if (status != DLADM_STATUS_OK)
1833 1837                  goto done1;
1834 1838  
1835 1839          /* Convert mac_propval_range to a single CPU list */
1836 1840          ncpus = MRP_NCPUS;
1837 1841          status = dladm_range2list(pv_range, cpus, &ncpus);
1838 1842          if (status != DLADM_STATUS_OK)
1839 1843                  goto done1;
1840 1844  
1841 1845          /*
1842 1846           * If a range of CPUs was entered, update value count and reallocate
1843 1847           * the array of val_desc_t's.  The array allocated was sized for
1844 1848           * indvidual elements, but needs to be reallocated to accomodate the
1845 1849           * expanded list of CPUs.
1846 1850           */
1847 1851          if (val_cnt < ncpus) {
1848 1852                  newvdp = calloc(*val_cntp, sizeof (val_desc_t));
1849 1853                  if (newvdp == NULL) {
1850 1854                          status = DLADM_STATUS_NOMEM;
1851 1855                          goto done1;
1852 1856                  }
1853 1857                  vdp = newvdp;
1854 1858          }
1855 1859  
1856 1860          /* Check if all CPUs in the list are online */
1857 1861          for (i = 0; i < ncpus; i++) {
1858 1862                  if (cpus[i] >= nproc) {
1859 1863                          status = DLADM_STATUS_BADCPUID;
1860 1864                          goto done2;
1861 1865                  }
1862 1866  
1863 1867                  rc = p_online(cpus[i], P_STATUS);
1864 1868                  if (rc < 1) {
1865 1869                          status = DLADM_STATUS_CPUERR;
1866 1870                          goto done2;
1867 1871                  }
1868 1872  
1869 1873                  if (rc != P_ONLINE) {
1870 1874                          status = DLADM_STATUS_CPUNOTONLINE;
1871 1875                          goto done2;
1872 1876                  }
1873 1877  
1874 1878                  vdp[i].vd_val = (uintptr_t)cpus[i];
1875 1879          }
1876 1880  
1877 1881          /* Check for duplicate CPUs */
1878 1882          for (i = 0; i < *val_cntp; i++) {
1879 1883                  for (j = 0; j < *val_cntp; j++) {
1880 1884                          if (i != j && vdp[i].vd_val == vdp[j].vd_val) {
1881 1885                                  status = DLADM_STATUS_BADVAL;
1882 1886                                  goto done2;
1883 1887                          }
1884 1888                  }
1885 1889          }
1886 1890  
1887 1891          /* Update *val_cntp and *vdpp if everything was OK */
1888 1892          if (val_cnt < ncpus) {
1889 1893                  *val_cntp = ncpus;
1890 1894                  free(*vdpp);
1891 1895                  *vdpp = newvdp;
1892 1896          }
1893 1897  
1894 1898          status = DLADM_STATUS_OK;
1895 1899          goto done1;
1896 1900  
1897 1901  done2:
1898 1902          free(newvdp);
1899 1903  done1:
1900 1904          free(pv_range);
1901 1905          return (status);
1902 1906  }
1903 1907  
1904 1908  /* ARGSUSED */
1905 1909  dladm_status_t
1906 1910  extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
1907 1911  {
1908 1912          mac_resource_props_t    *mrp = arg;
1909 1913          int                     i;
1910 1914  
1911 1915          if (vdp[0].vd_val == RESET_VAL) {
1912 1916                  bzero(&mrp->mrp_cpus, sizeof (mac_cpus_t));
1913 1917                  mrp->mrp_mask |= MRP_CPUS;
1914 1918                  return (DLADM_STATUS_OK);
1915 1919          }
1916 1920  
1917 1921          for (i = 0; i < cnt; i++)
1918 1922                  mrp->mrp_cpu[i] = (uint32_t)vdp[i].vd_val;
1919 1923  
1920 1924          mrp->mrp_ncpus = cnt;
1921 1925          mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
1922 1926          mrp->mrp_fanout_mode = MCM_CPUS;
1923 1927          mrp->mrp_rx_intr_cpu = -1;
1924 1928  
1925 1929          return (DLADM_STATUS_OK);
1926 1930  }
1927 1931  
1928 1932  /*
1929 1933   * Get the pool datalink property from the kernel.  This is used
1930 1934   * for both the user specified pool and effective pool properties.
1931 1935   */
1932 1936  /* ARGSUSED */
1933 1937  static dladm_status_t
1934 1938  get_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1935 1939      char **prop_val, uint_t *val_cnt, datalink_media_t media,
1936 1940      uint_t flags, uint_t *perm_flags)
1937 1941  {
1938 1942          mac_resource_props_t    mrp;
1939 1943          dladm_status_t          status;
1940 1944  
1941 1945          if (strcmp(pdp->pd_name, "pool-effective") == 0) {
1942 1946                  status = i_dladm_get_public_prop(handle, linkid,
1943 1947                      "resource-effective", flags, perm_flags, &mrp,
1944 1948                      sizeof (mrp));
1945 1949          } else {
1946 1950                  status = i_dladm_get_public_prop(handle, linkid,
1947 1951                      "resource", flags, perm_flags, &mrp, sizeof (mrp));
1948 1952          }
1949 1953  
1950 1954          if (status != DLADM_STATUS_OK)
1951 1955                  return (status);
1952 1956  
1953 1957          if (strlen(mrp.mrp_pool) == 0) {
1954 1958                  (*prop_val)[0] = '\0';
1955 1959          } else {
1956 1960                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
1957 1961                      "%s", mrp.mrp_pool);
1958 1962          }
1959 1963          *val_cnt = 1;
1960 1964  
1961 1965          return (DLADM_STATUS_OK);
1962 1966  }
1963 1967  
1964 1968  /* ARGSUSED */
1965 1969  static dladm_status_t
1966 1970  check_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1967 1971      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
1968 1972      datalink_media_t media)
1969 1973  {
1970 1974          pool_conf_t             *poolconf;
1971 1975          pool_t                  *pool;
1972 1976          mac_resource_props_t    mrp;
1973 1977          dladm_status_t          status;
1974 1978          uint_t                  perm_flags;
1975 1979          char                    *poolname;
1976 1980          val_desc_t              *vdp = *vdpp;
1977 1981  
1978 1982          /* Get the current cpus property */
1979 1983          status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1980 1984              &perm_flags, &mrp, sizeof (mrp));
1981 1985  
1982 1986          if (status == DLADM_STATUS_OK) {
1983 1987                  /* Can't set pool if cpus are set */
1984 1988                  if (mrp.mrp_ncpus != 0)
1985 1989                          return (DLADM_STATUS_POOLCPU);
1986 1990          }
1987 1991  
1988 1992          poolname = malloc(sizeof (mrp.mrp_pool));
1989 1993          if (poolname == NULL)
1990 1994                  return (DLADM_STATUS_NOMEM);
1991 1995  
1992 1996          /* Check for pool's availability if not booting */
1993 1997          if ((flags & DLADM_OPT_BOOT) == 0) {
1994 1998  
1995 1999                  /* Allocate and open pool configuration */
1996 2000                  if ((poolconf = pool_conf_alloc()) == NULL)
1997 2001                          return (DLADM_STATUS_BADVAL);
1998 2002  
1999 2003                  if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY)
2000 2004                      != PO_SUCCESS) {
2001 2005                          pool_conf_free(poolconf);
2002 2006                          return (DLADM_STATUS_BADVAL);
2003 2007                  }
2004 2008  
2005 2009                  /* Look for pool name */
2006 2010                  if ((pool = pool_get_pool(poolconf, *prop_val)) == NULL) {
2007 2011                          pool_conf_free(poolconf);
2008 2012                          return (DLADM_STATUS_BADVAL);
2009 2013                  }
2010 2014  
2011 2015                  pool_conf_free(poolconf);
2012 2016                  free(pool);
2013 2017          }
2014 2018  
2015 2019          (void) strlcpy(poolname, *prop_val, sizeof (mrp.mrp_pool));
2016 2020          vdp->vd_val = (uintptr_t)poolname;
2017 2021  
2018 2022          return (DLADM_STATUS_OK);
2019 2023  }
2020 2024  
2021 2025  /* ARGSUSED */
2022 2026  dladm_status_t
2023 2027  extract_pool(val_desc_t *vdp, uint_t cnt, void *arg)
2024 2028  {
2025 2029          mac_resource_props_t    *mrp = (mac_resource_props_t *)arg;
2026 2030  
2027 2031          if (vdp->vd_val == RESET_VAL) {
2028 2032                  bzero(&mrp->mrp_pool, sizeof (mrp->mrp_pool));
2029 2033                  mrp->mrp_mask |= MRP_POOL;
2030 2034                  return (DLADM_STATUS_OK);
2031 2035          }
2032 2036  
2033 2037          (void) strlcpy(mrp->mrp_pool, (char *)vdp->vd_val,
2034 2038              sizeof (mrp->mrp_pool));
2035 2039          mrp->mrp_mask |= MRP_POOL;
2036 2040          /*
2037 2041           * Use MCM_CPUS since the fanout count is not user specified
2038 2042           * and will be determined by the cpu list generated from the
2039 2043           * pool.
2040 2044           */
2041 2045          mrp->mrp_fanout_mode = MCM_CPUS;
2042 2046  
2043 2047          return (DLADM_STATUS_OK);
2044 2048  }
2045 2049  
2046 2050  /* ARGSUSED */
2047 2051  static dladm_status_t
2048 2052  get_priority(dladm_handle_t handle, prop_desc_t *pdp,
2049 2053      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2050 2054      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2051 2055  {
2052 2056          mac_resource_props_t    mrp;
2053 2057          mac_priority_level_t    pri;
2054 2058          dladm_status_t          status;
2055 2059  
2056 2060          status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2057 2061              perm_flags, &mrp, sizeof (mrp));
2058 2062          if (status != DLADM_STATUS_OK)
2059 2063                  return (status);
2060 2064  
2061 2065          pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
2062 2066              mrp.mrp_priority;
2063 2067  
2064 2068          (void) dladm_pri2str(pri, prop_val[0]);
2065 2069          *val_cnt = 1;
2066 2070          return (DLADM_STATUS_OK);
2067 2071  }
2068 2072  
2069 2073  /* ARGSUSED */
2070 2074  dladm_status_t
2071 2075  extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
2072 2076  {
2073 2077          mac_resource_props_t *mrp = arg;
2074 2078  
2075 2079          if (cnt != 1)
2076 2080                  return (DLADM_STATUS_BADVAL);
2077 2081  
2078 2082          mrp->mrp_priority = (mac_priority_level_t)vdp->vd_val;
2079 2083          mrp->mrp_mask |= MRP_PRIORITY;
2080 2084  
2081 2085          return (DLADM_STATUS_OK);
2082 2086  }
2083 2087  
2084 2088  /*
2085 2089   * Determines the size of the structure that needs to be sent to drivers
2086 2090   * for retrieving the property range values.
2087 2091   */
2088 2092  static int
2089 2093  i_dladm_range_size(mac_propval_range_t *r, size_t *sz, uint_t *rcount)
2090 2094  {
2091 2095          uint_t count = r->mpr_count;
2092 2096  
2093 2097          *sz = sizeof (mac_propval_range_t);
2094 2098          *rcount = count;
2095 2099          --count;
2096 2100  
2097 2101          switch (r->mpr_type) {
2098 2102          case MAC_PROPVAL_UINT32:
2099 2103                  *sz += (count * sizeof (mac_propval_uint32_range_t));
2100 2104                  return (0);
2101 2105          default:
2102 2106                  break;
2103 2107          }
2104 2108          *sz = 0;
2105 2109          *rcount = 0;
2106 2110          return (EINVAL);
2107 2111  }
2108 2112  
2109 2113  
2110 2114  /* ARGSUSED */
2111 2115  static dladm_status_t
2112 2116  check_rings(dladm_handle_t handle, prop_desc_t *pdp,
2113 2117      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2114 2118      val_desc_t **vp, datalink_media_t media)
2115 2119  {
2116 2120          uint_t          val_cnt = *val_cntp;
2117 2121          val_desc_t      *v = *vp;
2118 2122  
2119 2123          if (val_cnt != 1)
2120 2124                  return (DLADM_STATUS_BADVAL);
2121 2125          if (strncasecmp(prop_val[0], "hw", strlen("hw")) == 0) {
2122 2126                  v->vd_val = UNSPEC_VAL;
2123 2127          } else if (strncasecmp(prop_val[0], "sw", strlen("sw")) == 0) {
2124 2128                  v->vd_val = 0;
2125 2129          } else {
2126 2130                  v->vd_val = strtoul(prop_val[0], NULL, 0);
2127 2131                  if (v->vd_val == 0)
2128 2132                          return (DLADM_STATUS_BADVAL);
2129 2133          }
2130 2134          return (DLADM_STATUS_OK);
2131 2135  }
2132 2136  
2133 2137  /* ARGSUSED */
2134 2138  static dladm_status_t
2135 2139  get_rings_range(dladm_handle_t handle, prop_desc_t *pdp,
2136 2140      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2137 2141      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2138 2142  {
2139 2143          dld_ioc_macprop_t *dip;
2140 2144          dladm_status_t status = DLADM_STATUS_OK;
2141 2145          mac_propval_range_t *rangep;
2142 2146          size_t  sz;
2143 2147          mac_propval_uint32_range_t *ur;
2144 2148  
2145 2149          sz = sizeof (mac_propval_range_t);
2146 2150  
2147 2151          if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
2148 2152              &status)) == NULL)
2149 2153                  return (status);
2150 2154  
2151 2155          status = i_dladm_macprop(handle, dip, B_FALSE);
2152 2156          if (status != DLADM_STATUS_OK)
2153 2157                  return (status);
2154 2158  
2155 2159          rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
2156 2160          *val_cnt = 1;
2157 2161          ur = &rangep->mpr_range_uint32[0];
2158 2162          /* This is the case where the dev doesn't have any rings/groups */
2159 2163          if (rangep->mpr_count == 0) {
2160 2164                  (*prop_val)[0] = '\0';
2161 2165          /*
2162 2166           * This is the case where the dev supports rings, but static
2163 2167           * grouping.
2164 2168           */
2165 2169          } else if (ur->mpur_min == ur->mpur_max &&
2166 2170              ur->mpur_max == 0) {
2167 2171                  (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw");
2168 2172          /*
2169 2173           * This is the case where the dev supports rings and dynamic
2170 2174           * grouping, but has only one value (say 2 rings and 2 groups).
2171 2175           */
2172 2176          } else if (ur->mpur_min == ur->mpur_max) {
2173 2177                  (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw,%d",
2174 2178                      ur->mpur_min);
2175 2179          /*
2176 2180           * This is the case where the dev supports rings and dynamic
2177 2181           * grouping and has a range of rings.
2178 2182           */
2179 2183          } else {
2180 2184                  (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX,
2181 2185                      "sw,hw,<%ld-%ld>", ur->mpur_min, ur->mpur_max);
2182 2186          }
2183 2187          free(dip);
2184 2188          return (status);
2185 2189  }
2186 2190  
2187 2191  
2188 2192  /* ARGSUSED */
2189 2193  static dladm_status_t
2190 2194  get_rxrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2191 2195      char **prop_val, uint_t *val_cnt, datalink_media_t media,
2192 2196      uint_t flags, uint_t *perm_flags)
2193 2197  {
2194 2198          mac_resource_props_t    mrp;
2195 2199          dladm_status_t          status;
2196 2200          uint32_t                nrings = 0;
2197 2201  
2198 2202          /*
2199 2203           * Get the number of (effective-)rings from the resource property.
2200 2204           */
2201 2205          if (strcmp(pdp->pd_name, "rxrings-effective") == 0) {
2202 2206                  status = i_dladm_get_public_prop(handle, linkid,
2203 2207                      "resource-effective", flags, perm_flags, &mrp,
2204 2208                      sizeof (mrp));
2205 2209          } else {
2206 2210                  /*
2207 2211                   * Get the permissions from the "rxrings" property.
2208 2212                   */
2209 2213                  status = i_dladm_get_public_prop(handle, linkid, "rxrings",
2210 2214                      flags, perm_flags, NULL, 0);
2211 2215                  if (status != DLADM_STATUS_OK)
2212 2216                          return (status);
2213 2217  
2214 2218                  status = i_dladm_get_public_prop(handle, linkid,
2215 2219                      "resource", flags, NULL, &mrp, sizeof (mrp));
2216 2220          }
2217 2221  
2218 2222          if (status != DLADM_STATUS_OK)
2219 2223                  return (status);
2220 2224  
2221 2225          if ((mrp.mrp_mask & MRP_RX_RINGS) == 0) {
2222 2226                  *val_cnt = 0;
2223 2227                  return (DLADM_STATUS_OK);
2224 2228          }
2225 2229          nrings = mrp.mrp_nrxrings;
2226 2230          *val_cnt = 1;
2227 2231          if (mrp.mrp_mask & MRP_RXRINGS_UNSPEC)
2228 2232                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2229 2233          else if (nrings == 0)
2230 2234                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2231 2235          else
2232 2236                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
2233 2237          return (DLADM_STATUS_OK);
2234 2238  }
2235 2239  
2236 2240  /* ARGSUSED */
2237 2241  dladm_status_t
2238 2242  extract_rxrings(val_desc_t *vdp, uint_t cnt, void *arg)
2239 2243  {
2240 2244          mac_resource_props_t    *mrp = (mac_resource_props_t *)arg;
2241 2245  
2242 2246          mrp->mrp_nrxrings = 0;
2243 2247          if (vdp->vd_val == RESET_VAL)
2244 2248                  mrp->mrp_mask = MRP_RINGS_RESET;
2245 2249          else if (vdp->vd_val == UNSPEC_VAL)
2246 2250                  mrp->mrp_mask = MRP_RXRINGS_UNSPEC;
2247 2251          else
2248 2252                  mrp->mrp_nrxrings = vdp->vd_val;
2249 2253          mrp->mrp_mask |= MRP_RX_RINGS;
2250 2254  
2251 2255          return (DLADM_STATUS_OK);
2252 2256  }
2253 2257  
2254 2258  /* ARGSUSED */
2255 2259  static dladm_status_t
2256 2260  get_txrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2257 2261      char **prop_val, uint_t *val_cnt, datalink_media_t media,
2258 2262      uint_t flags, uint_t *perm_flags)
2259 2263  {
2260 2264          mac_resource_props_t    mrp;
2261 2265          dladm_status_t          status;
2262 2266          uint32_t                nrings = 0;
2263 2267  
2264 2268  
2265 2269          /*
2266 2270           * Get the number of (effective-)rings from the resource property.
2267 2271           */
2268 2272          if (strcmp(pdp->pd_name, "txrings-effective") == 0) {
2269 2273                  status = i_dladm_get_public_prop(handle, linkid,
2270 2274                      "resource-effective", flags, perm_flags, &mrp,
2271 2275                      sizeof (mrp));
2272 2276          } else {
2273 2277                  /*
2274 2278                   * Get the permissions from the "txrings" property.
2275 2279                   */
2276 2280                  status = i_dladm_get_public_prop(handle, linkid, "txrings",
2277 2281                      flags, perm_flags, NULL, 0);
2278 2282                  if (status != DLADM_STATUS_OK)
2279 2283                          return (status);
2280 2284  
2281 2285                  /*
2282 2286                   * Get the number of rings from the "resource" property.
2283 2287                   */
2284 2288                  status = i_dladm_get_public_prop(handle, linkid, "resource",
2285 2289                      flags, NULL, &mrp, sizeof (mrp));
2286 2290          }
2287 2291  
2288 2292          if (status != DLADM_STATUS_OK)
2289 2293                  return (status);
2290 2294  
2291 2295          if ((mrp.mrp_mask & MRP_TX_RINGS) == 0) {
2292 2296                  *val_cnt = 0;
2293 2297                  return (DLADM_STATUS_OK);
2294 2298          }
2295 2299          nrings = mrp.mrp_ntxrings;
2296 2300          *val_cnt = 1;
2297 2301          if (mrp.mrp_mask & MRP_TXRINGS_UNSPEC)
2298 2302                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2299 2303          else if (nrings == 0)
2300 2304                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2301 2305          else
2302 2306                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
2303 2307          return (DLADM_STATUS_OK);
2304 2308  }
2305 2309  
2306 2310  /* ARGSUSED */
2307 2311  dladm_status_t
2308 2312  extract_txrings(val_desc_t *vdp, uint_t cnt, void *arg)
2309 2313  {
2310 2314          mac_resource_props_t    *mrp = (mac_resource_props_t *)arg;
2311 2315  
2312 2316          mrp->mrp_ntxrings = 0;
2313 2317          if (vdp->vd_val == RESET_VAL)
2314 2318                  mrp->mrp_mask = MRP_RINGS_RESET;
2315 2319          else if (vdp->vd_val == UNSPEC_VAL)
2316 2320                  mrp->mrp_mask = MRP_TXRINGS_UNSPEC;
2317 2321          else
2318 2322                  mrp->mrp_ntxrings = vdp->vd_val;
2319 2323          mrp->mrp_mask |= MRP_TX_RINGS;
2320 2324  
2321 2325          return (DLADM_STATUS_OK);
2322 2326  }
2323 2327  
2324 2328  /* ARGSUSED */
2325 2329  static dladm_status_t
2326 2330  get_cntavail(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2327 2331      char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
2328 2332      uint_t *perm_flags)
2329 2333  {
2330 2334          if (flags & DLD_PROP_DEFAULT)
2331 2335                  return (DLADM_STATUS_NOTDEFINED);
2332 2336  
2333 2337          return (get_uint32(handle, pdp, linkid, prop_val, val_cnt, media,
2334 2338              flags, perm_flags));
2335 2339  }
2336 2340  
2337 2341  /* ARGSUSED */
2338 2342  static dladm_status_t
2339 2343  set_resource(dladm_handle_t handle, prop_desc_t *pdp,
2340 2344      datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
2341 2345      uint_t flags, datalink_media_t media)
2342 2346  {
2343 2347          mac_resource_props_t    mrp;
2344 2348          dladm_status_t          status = DLADM_STATUS_OK;
2345 2349          dld_ioc_macprop_t       *dip;
2346 2350          int                     i;
2347 2351  
2348 2352          bzero(&mrp, sizeof (mac_resource_props_t));
2349 2353          dip = i_dladm_buf_alloc_by_name(0, linkid, "resource",
2350 2354              flags, &status);
2351 2355  
2352 2356          if (dip == NULL)
2353 2357                  return (status);
2354 2358  
2355 2359          for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
2356 2360                  resource_prop_t *rp = &rsrc_prop_table[i];
2357 2361  
2358 2362                  if (strcmp(pdp->pd_name, rp->rp_name) != 0)
2359 2363                          continue;
2360 2364  
2361 2365                  status = rp->rp_extract(vdp, val_cnt, &mrp);
2362 2366                  if (status != DLADM_STATUS_OK)
2363 2367                          goto done;
2364 2368  
2365 2369                  break;
2366 2370          }
2367 2371  
2368 2372          (void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
2369 2373          status = i_dladm_macprop(handle, dip, B_TRUE);
2370 2374  
2371 2375  done:
2372 2376          free(dip);
2373 2377          return (status);
2374 2378  }
2375 2379  
2376 2380  /* ARGSUSED */
2377 2381  static dladm_status_t
2378 2382  get_protection(dladm_handle_t handle, prop_desc_t *pdp,
2379 2383      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2380 2384      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2381 2385  {
2382 2386          mac_resource_props_t    mrp;
2383 2387          mac_protect_t           *p;
2384 2388          dladm_status_t          status;
2385 2389          uint32_t                i, cnt = 0, setbits[32];
2386 2390  
2387 2391          status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2388 2392              perm_flags, &mrp, sizeof (mrp));
2389 2393          if (status != DLADM_STATUS_OK)
2390 2394                  return (status);
2391 2395  
2392 2396          p = &mrp.mrp_protect;
2393 2397          if ((mrp.mrp_mask & MRP_PROTECT) == 0) {
2394 2398                  *val_cnt = 0;
2395 2399                  return (DLADM_STATUS_OK);
2396 2400          }
2397 2401          dladm_find_setbits32(p->mp_types, setbits, &cnt);
2398 2402          if (cnt > *val_cnt)
2399 2403                  return (DLADM_STATUS_BADVALCNT);
2400 2404  
2401 2405          for (i = 0; i < cnt; i++)
2402 2406                  (void) dladm_protect2str(setbits[i], prop_val[i]);
2403 2407  
2404 2408          *val_cnt = cnt;
2405 2409          return (DLADM_STATUS_OK);
2406 2410  }
2407 2411  
2408 2412  /* ARGSUSED */
2409 2413  static dladm_status_t
2410 2414  get_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2411 2415      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2412 2416      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2413 2417  {
2414 2418          mac_resource_props_t    mrp;
2415 2419          mac_protect_t           *p;
2416 2420          dladm_status_t          status;
2417 2421          int                     i;
2418 2422  
2419 2423          status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2420 2424              perm_flags, &mrp, sizeof (mrp));
2421 2425          if (status != DLADM_STATUS_OK)
2422 2426                  return (status);
2423 2427  
2424 2428          p = &mrp.mrp_protect;
2425 2429          if (p->mp_ipaddrcnt == 0) {
2426 2430                  *val_cnt = 0;
2427 2431                  return (DLADM_STATUS_OK);
2428 2432          }
2429 2433          if (p->mp_ipaddrcnt > *val_cnt)
2430 2434                  return (DLADM_STATUS_BADVALCNT);
2431 2435  
2432 2436          for (i = 0; i < p->mp_ipaddrcnt; i++) {
2433 2437                  int len;
2434 2438                  if (p->mp_ipaddrs[i].ip_version == IPV4_VERSION) {
2435 2439                          ipaddr_t        v4addr;
2436 2440  
2437 2441                          v4addr = V4_PART_OF_V6(p->mp_ipaddrs[i].ip_addr);
2438 2442                          (void) dladm_ipv4addr2str(&v4addr, prop_val[i]);
2439 2443                  } else {
2440 2444                          (void) dladm_ipv6addr2str(&p->mp_ipaddrs[i].ip_addr,
2441 2445                              prop_val[i]);
2442 2446                  }
2443 2447                  len = strlen(prop_val[i]);
2444 2448                  (void) sprintf(prop_val[i] + len, "/%d",
2445 2449                      p->mp_ipaddrs[i].ip_netmask);
2446 2450          }
2447 2451          *val_cnt = p->mp_ipaddrcnt;
2448 2452          return (DLADM_STATUS_OK);
2449 2453  }
2450 2454  
2451 2455  dladm_status_t
2452 2456  extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
2453 2457  {
2454 2458          mac_resource_props_t    *mrp = arg;
2455 2459          uint32_t                types = 0;
2456 2460          int                     i;
2457 2461  
2458 2462          for (i = 0; i < cnt; i++)
2459 2463                  types |= (uint32_t)vdp[i].vd_val;
2460 2464  
2461 2465          mrp->mrp_protect.mp_types = types;
2462 2466          mrp->mrp_mask |= MRP_PROTECT;
2463 2467          return (DLADM_STATUS_OK);
2464 2468  }
2465 2469  
2466 2470  dladm_status_t
2467 2471  extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
2468 2472  {
2469 2473          mac_resource_props_t    *mrp = arg;
2470 2474          mac_protect_t           *p = &mrp->mrp_protect;
2471 2475          int                     i;
2472 2476  
2473 2477          if (vdp->vd_val == 0) {
2474 2478                  cnt = (uint_t)-1;
2475 2479          } else {
2476 2480                  for (i = 0; i < cnt; i++) {
2477 2481                          bcopy((void *)vdp[i].vd_val, &p->mp_ipaddrs[i],
2478 2482                              sizeof (mac_ipaddr_t));
2479 2483                  }
2480 2484          }
2481 2485          p->mp_ipaddrcnt = cnt;
2482 2486          mrp->mrp_mask |= MRP_PROTECT;
2483 2487          return (DLADM_STATUS_OK);
2484 2488  }
2485 2489  
2486 2490  static dladm_status_t
2487 2491  check_single_ip(char *buf, mac_ipaddr_t *addr)
2488 2492  {
2489 2493          dladm_status_t  status;
2490 2494          ipaddr_t        v4addr;
2491 2495          in6_addr_t      v6addr;
2492 2496          boolean_t       isv4 = B_TRUE;
2493 2497          char            *p;
2494 2498          uint32_t        mask = 0;
2495 2499  
2496 2500          /*
2497 2501           * If the IP address is in CIDR format, parse the bits component
2498 2502           * seperately. An address in this style will be used to indicate an
2499 2503           * entire subnet, so it must be a network number with no host address.
2500 2504           */
2501 2505          if ((p = strchr(buf, '/')) != NULL) {
2502 2506                  char *end = NULL;
2503 2507  
2504 2508                  *p++ = '\0';
2505 2509                  if (!isdigit(*p))
2506 2510                          return (DLADM_STATUS_INVALID_IP);
2507 2511                  mask = strtol(p, &end, 10);
2508 2512                  if (end != NULL && *end != '\0')
2509 2513                          return (DLADM_STATUS_INVALID_IP);
2510 2514                  if (mask > 128|| mask < 1)
2511 2515                          return (DLADM_STATUS_INVALID_IP);
2512 2516          }
2513 2517  
2514 2518          status = dladm_str2ipv4addr(buf, &v4addr);
2515 2519          if (status == DLADM_STATUS_INVALID_IP) {
2516 2520                  status = dladm_str2ipv6addr(buf, &v6addr);
2517 2521                  if (status == DLADM_STATUS_OK)
2518 2522                          isv4 = B_FALSE;
2519 2523          }
2520 2524          if (status != DLADM_STATUS_OK)
2521 2525                  return (status);
2522 2526  
2523 2527          if (isv4) {
2524 2528                  if (v4addr == INADDR_ANY)
2525 2529                          return (DLADM_STATUS_INVALID_IP);
2526 2530  
2527 2531                  IN6_IPADDR_TO_V4MAPPED(v4addr, &addr->ip_addr);
2528 2532                  addr->ip_version = IPV4_VERSION;
2529 2533                  if (p != NULL) {
2530 2534                          uint32_t smask;
2531 2535  
2532 2536                          /*
2533 2537                           * Validate the netmask is in the proper range for v4
2534 2538                           */
2535 2539                          if (mask > 32 || mask < 1)
2536 2540                                  return (DLADM_STATUS_INVALID_IP);
2537 2541  
2538 2542                          /*
2539 2543                           * We have a CIDR style address, confirm that only the
2540 2544                           * network number is set.
2541 2545                           */
2542 2546                          smask = 0xFFFFFFFFu << (32 - mask);
2543 2547                          if (htonl(v4addr) & ~smask)
2544 2548                                  return (DLADM_STATUS_INVALID_IP);
2545 2549                  } else {
2546 2550                          mask = 32;
2547 2551                  }
2548 2552                  addr->ip_netmask = mask;
2549 2553          } else {
2550 2554                  if (IN6_IS_ADDR_UNSPECIFIED(&v6addr))
2551 2555                          return (DLADM_STATUS_INVALID_IP);
2552 2556  
2553 2557                  if (IN6_IS_ADDR_V4MAPPED_ANY(&v6addr))
2554 2558                          return (DLADM_STATUS_INVALID_IP);
2555 2559  
2556 2560                  if (p != NULL) {
2557 2561                          int i, off, high;
2558 2562  
2559 2563                          /*
2560 2564                           * Note that the address in our buffer is stored in
2561 2565                           * network byte order.
2562 2566                           */
2563 2567                          off = 0;
2564 2568                          for (i = 3; i >= 0; i--) {
2565 2569                                  high = ffsl(ntohl(v6addr._S6_un._S6_u32[i]));
2566 2570                                  if (high != 0)
2567 2571                                          break;
2568 2572                                  off += 32;
2569 2573                          }
2570 2574                          off += high;
2571 2575                          if (128 - off >= mask)
2572 2576                                  return (DLADM_STATUS_INVALID_IP);
2573 2577                  } else {
2574 2578                          mask = 128;
2575 2579                  }
2576 2580  
2577 2581                  addr->ip_addr = v6addr;
2578 2582                  addr->ip_version = IPV6_VERSION;
2579 2583                  addr->ip_netmask = mask;
2580 2584          }
2581 2585          return (DLADM_STATUS_OK);
2582 2586  }
2583 2587  
2584 2588  /* ARGSUSED */
2585 2589  static dladm_status_t
2586 2590  check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2587 2591      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2588 2592      val_desc_t **vdpp, datalink_media_t media)
2589 2593  {
2590 2594          dladm_status_t  status;
2591 2595          mac_ipaddr_t    *addr;
2592 2596          int             i;
2593 2597          uint_t          val_cnt = *val_cntp;
2594 2598          val_desc_t      *vdp = *vdpp;
2595 2599  
2596 2600          if (val_cnt > MPT_MAXIPADDR)
2597 2601                  return (DLADM_STATUS_BADVALCNT);
2598 2602  
2599 2603          for (i = 0; i < val_cnt; i++) {
2600 2604                  if ((addr = calloc(1, sizeof (mac_ipaddr_t))) == NULL) {
2601 2605                          status = DLADM_STATUS_NOMEM;
2602 2606                          goto fail;
2603 2607                  }
2604 2608                  vdp[i].vd_val = (uintptr_t)addr;
2605 2609  
2606 2610                  status = check_single_ip(prop_val[i], addr);
2607 2611                  if (status != DLADM_STATUS_OK)
2608 2612                          goto fail;
2609 2613          }
2610 2614          return (DLADM_STATUS_OK);
2611 2615  
2612 2616  fail:
2613 2617          for (i = 0; i < val_cnt; i++) {
2614 2618                  free((void *)vdp[i].vd_val);
2615 2619                  vdp[i].vd_val = NULL;
2616 2620          }
2617 2621          return (status);
2618 2622  }
2619 2623  
2620 2624  static void
2621 2625  dladm_cid2str(mac_dhcpcid_t *cid, char *buf)
2622 2626  {
2623 2627          char    tmp_buf[DLADM_STRSIZE];
2624 2628          uint_t  hexlen;
2625 2629  
2626 2630          switch (cid->dc_form) {
2627 2631          case CIDFORM_TYPED: {
2628 2632                  uint16_t        duidtype, hwtype;
2629 2633                  uint32_t        timestamp, ennum;
2630 2634                  char            *lladdr;
2631 2635  
2632 2636                  if (cid->dc_len < sizeof (duidtype))
2633 2637                          goto fail;
2634 2638  
2635 2639                  bcopy(cid->dc_id, &duidtype, sizeof (duidtype));
2636 2640                  duidtype = ntohs(duidtype);
2637 2641                  switch (duidtype) {
2638 2642                  case DHCPV6_DUID_LLT: {
2639 2643                          duid_llt_t      llt;
2640 2644  
2641 2645                          if (cid->dc_len < sizeof (llt))
2642 2646                                  goto fail;
2643 2647  
2644 2648                          bcopy(cid->dc_id, &llt, sizeof (llt));
2645 2649                          hwtype = ntohs(llt.dllt_hwtype);
2646 2650                          timestamp = ntohl(llt.dllt_time);
2647 2651                          lladdr = _link_ntoa(cid->dc_id + sizeof (llt),
2648 2652                              NULL, cid->dc_len - sizeof (llt), IFT_OTHER);
2649 2653                          if (lladdr == NULL)
2650 2654                                  goto fail;
2651 2655  
2652 2656                          (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%d.%s",
2653 2657                              duidtype, hwtype, timestamp, lladdr);
2654 2658                          free(lladdr);
2655 2659                          break;
2656 2660                  }
2657 2661                  case DHCPV6_DUID_EN: {
2658 2662                          duid_en_t       en;
2659 2663  
2660 2664                          if (cid->dc_len < sizeof (en))
2661 2665                                  goto fail;
2662 2666  
2663 2667                          bcopy(cid->dc_id, &en, sizeof (en));
2664 2668                          ennum = DHCPV6_GET_ENTNUM(&en);
2665 2669                          hexlen = sizeof (tmp_buf);
2666 2670                          if (octet_to_hexascii(cid->dc_id + sizeof (en),
2667 2671                              cid->dc_len - sizeof (en), tmp_buf, &hexlen) != 0)
2668 2672                                  goto fail;
2669 2673  
2670 2674                          (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2671 2675                              duidtype, ennum, tmp_buf);
2672 2676                          break;
2673 2677                  }
2674 2678                  case DHCPV6_DUID_LL: {
2675 2679                          duid_ll_t       ll;
2676 2680  
2677 2681                          if (cid->dc_len < sizeof (ll))
2678 2682                                  goto fail;
2679 2683  
2680 2684                          bcopy(cid->dc_id, &ll, sizeof (ll));
2681 2685                          hwtype = ntohs(ll.dll_hwtype);
2682 2686                          lladdr = _link_ntoa(cid->dc_id + sizeof (ll),
2683 2687                              NULL, cid->dc_len - sizeof (ll), IFT_OTHER);
2684 2688                          if (lladdr == NULL)
2685 2689                                  goto fail;
2686 2690  
2687 2691                          (void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2688 2692                              duidtype, hwtype, lladdr);
2689 2693                          free(lladdr);
2690 2694                          break;
2691 2695                  }
2692 2696                  default: {
2693 2697                          hexlen = sizeof (tmp_buf);
2694 2698                          if (octet_to_hexascii(cid->dc_id + sizeof (duidtype),
2695 2699                              cid->dc_len - sizeof (duidtype),
2696 2700                              tmp_buf, &hexlen) != 0)
2697 2701                                  goto fail;
2698 2702  
2699 2703                          (void) snprintf(buf, DLADM_STRSIZE, "%d.%s",
2700 2704                              duidtype, tmp_buf);
2701 2705                  }
2702 2706                  }
2703 2707                  break;
2704 2708          }
2705 2709          case CIDFORM_HEX: {
2706 2710                  hexlen = sizeof (tmp_buf);
2707 2711                  if (octet_to_hexascii(cid->dc_id, cid->dc_len,
2708 2712                      tmp_buf, &hexlen) != 0)
2709 2713                          goto fail;
2710 2714  
2711 2715                  (void) snprintf(buf, DLADM_STRSIZE, "0x%s", tmp_buf);
2712 2716                  break;
2713 2717          }
2714 2718          case CIDFORM_STR: {
2715 2719                  int     i;
2716 2720  
2717 2721                  for (i = 0; i < cid->dc_len; i++) {
2718 2722                          if (!isprint(cid->dc_id[i]))
2719 2723                                  goto fail;
2720 2724                  }
2721 2725                  (void) snprintf(buf, DLADM_STRSIZE, "%s", cid->dc_id);
2722 2726                  break;
2723 2727          }
2724 2728          default:
2725 2729                  goto fail;
2726 2730          }
2727 2731          return;
2728 2732  
2729 2733  fail:
2730 2734          (void) snprintf(buf, DLADM_STRSIZE, "<unknown>");
2731 2735  }
2732 2736  
2733 2737  static dladm_status_t
2734 2738  dladm_str2cid(char *buf, mac_dhcpcid_t *cid)
2735 2739  {
2736 2740          char    *ptr = buf;
2737 2741          char    tmp_buf[DLADM_STRSIZE];
2738 2742          uint_t  hexlen, cidlen;
2739 2743  
2740 2744          bzero(cid, sizeof (*cid));
2741 2745          if (isdigit(*ptr) &&
2742 2746              ptr[strspn(ptr, "0123456789")] == '.') {
2743 2747                  char    *cp;
2744 2748                  ulong_t duidtype;
2745 2749                  ulong_t subtype;
2746 2750                  ulong_t timestamp;
2747 2751                  uchar_t *lladdr;
2748 2752                  int     addrlen;
2749 2753  
2750 2754                  errno = 0;
2751 2755                  duidtype = strtoul(ptr, &cp, 0);
2752 2756                  if (ptr == cp || errno != 0 || *cp != '.' ||
2753 2757                      duidtype > USHRT_MAX)
2754 2758                          return (DLADM_STATUS_BADARG);
2755 2759                  ptr = cp + 1;
2756 2760  
2757 2761                  if (duidtype != 0 && duidtype <= DHCPV6_DUID_LL) {
2758 2762                          errno = 0;
2759 2763                          subtype = strtoul(ptr, &cp, 0);
2760 2764                          if (ptr == cp || errno != 0 || *cp != '.')
2761 2765                                  return (DLADM_STATUS_BADARG);
2762 2766                          ptr = cp + 1;
2763 2767                  }
2764 2768                  switch (duidtype) {
2765 2769                  case DHCPV6_DUID_LLT: {
2766 2770                          duid_llt_t      llt;
2767 2771  
2768 2772                          errno = 0;
2769 2773                          timestamp = strtoul(ptr, &cp, 0);
2770 2774                          if (ptr == cp || errno != 0 || *cp != '.')
2771 2775                                  return (DLADM_STATUS_BADARG);
2772 2776  
2773 2777                          ptr = cp + 1;
2774 2778                          lladdr = _link_aton(ptr, &addrlen);
2775 2779                          if (lladdr == NULL)
2776 2780                                  return (DLADM_STATUS_BADARG);
2777 2781  
2778 2782                          cidlen = sizeof (llt) + addrlen;
2779 2783                          if (cidlen > sizeof (cid->dc_id)) {
2780 2784                                  free(lladdr);
2781 2785                                  return (DLADM_STATUS_TOOSMALL);
2782 2786                          }
2783 2787                          llt.dllt_dutype = htons(duidtype);
2784 2788                          llt.dllt_hwtype = htons(subtype);
2785 2789                          llt.dllt_time = htonl(timestamp);
2786 2790                          bcopy(&llt, cid->dc_id, sizeof (llt));
2787 2791                          bcopy(lladdr, cid->dc_id + sizeof (llt), addrlen);
2788 2792                          free(lladdr);
2789 2793                          break;
2790 2794                  }
2791 2795                  case DHCPV6_DUID_LL: {
2792 2796                          duid_ll_t       ll;
2793 2797  
2794 2798                          lladdr = _link_aton(ptr, &addrlen);
2795 2799                          if (lladdr == NULL)
2796 2800                                  return (DLADM_STATUS_BADARG);
2797 2801  
2798 2802                          cidlen = sizeof (ll) + addrlen;
2799 2803                          if (cidlen > sizeof (cid->dc_id)) {
2800 2804                                  free(lladdr);
2801 2805                                  return (DLADM_STATUS_TOOSMALL);
2802 2806                          }
2803 2807                          ll.dll_dutype = htons(duidtype);
2804 2808                          ll.dll_hwtype = htons(subtype);
2805 2809                          bcopy(&ll, cid->dc_id, sizeof (ll));
2806 2810                          bcopy(lladdr, cid->dc_id + sizeof (ll), addrlen);
2807 2811                          free(lladdr);
2808 2812                          break;
2809 2813                  }
2810 2814                  default: {
2811 2815                          hexlen = sizeof (tmp_buf);
2812 2816                          if (hexascii_to_octet(ptr, strlen(ptr),
2813 2817                              tmp_buf, &hexlen) != 0)
2814 2818                                  return (DLADM_STATUS_BADARG);
2815 2819  
2816 2820                          if (duidtype == DHCPV6_DUID_EN) {
2817 2821                                  duid_en_t       en;
2818 2822  
2819 2823                                  en.den_dutype = htons(duidtype);
2820 2824                                  DHCPV6_SET_ENTNUM(&en, subtype);
2821 2825  
2822 2826                                  cidlen = sizeof (en) + hexlen;
2823 2827                                  if (cidlen > sizeof (cid->dc_id))
2824 2828                                          return (DLADM_STATUS_TOOSMALL);
2825 2829  
2826 2830                                  bcopy(&en, cid->dc_id, sizeof (en));
2827 2831                                  bcopy(tmp_buf, cid->dc_id + sizeof (en),
2828 2832                                      hexlen);
2829 2833                          } else {
2830 2834                                  uint16_t        dutype = htons(duidtype);
2831 2835  
2832 2836                                  cidlen = sizeof (dutype) + hexlen;
2833 2837                                  if (cidlen > sizeof (cid->dc_id))
2834 2838                                          return (DLADM_STATUS_TOOSMALL);
2835 2839  
2836 2840                                  bcopy(&dutype, cid->dc_id, sizeof (dutype));
2837 2841                                  bcopy(tmp_buf, cid->dc_id + sizeof (dutype),
2838 2842                                      hexlen);
2839 2843                          }
2840 2844                          break;
2841 2845                  }
2842 2846                  }
2843 2847                  cid->dc_form = CIDFORM_TYPED;
2844 2848          } else if (strncasecmp("0x", ptr, 2) == 0 && ptr[2] != '\0') {
2845 2849                  ptr += 2;
2846 2850                  hexlen = sizeof (tmp_buf);
2847 2851                  if (hexascii_to_octet(ptr, strlen(ptr), tmp_buf,
2848 2852                      &hexlen) != 0) {
2849 2853                          return (DLADM_STATUS_BADARG);
2850 2854                  }
2851 2855                  cidlen = hexlen;
2852 2856                  if (cidlen > sizeof (cid->dc_id))
2853 2857                          return (DLADM_STATUS_TOOSMALL);
2854 2858  
2855 2859                  bcopy(tmp_buf, cid->dc_id, cidlen);
2856 2860                  cid->dc_form = CIDFORM_HEX;
2857 2861          } else {
2858 2862                  cidlen = strlen(ptr);
2859 2863                  if (cidlen > sizeof (cid->dc_id))
2860 2864                          return (DLADM_STATUS_TOOSMALL);
2861 2865  
2862 2866                  bcopy(ptr, cid->dc_id, cidlen);
2863 2867                  cid->dc_form = CIDFORM_STR;
2864 2868          }
2865 2869          cid->dc_len = cidlen;
2866 2870          return (DLADM_STATUS_OK);
2867 2871  }
2868 2872  
2869 2873  /* ARGSUSED */
2870 2874  static dladm_status_t
2871 2875  get_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2872 2876      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2873 2877      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2874 2878  {
2875 2879          mac_resource_props_t    mrp;
2876 2880          mac_protect_t           *p;
2877 2881          dladm_status_t          status;
2878 2882          int                     i;
2879 2883  
2880 2884          status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2881 2885              perm_flags, &mrp, sizeof (mrp));
2882 2886          if (status != DLADM_STATUS_OK)
2883 2887                  return (status);
2884 2888  
2885 2889          p = &mrp.mrp_protect;
2886 2890          if (p->mp_cidcnt == 0) {
2887 2891                  *val_cnt = 0;
2888 2892                  return (DLADM_STATUS_OK);
2889 2893          }
2890 2894          if (p->mp_cidcnt > *val_cnt)
2891 2895                  return (DLADM_STATUS_BADVALCNT);
2892 2896  
2893 2897          for (i = 0; i < p->mp_cidcnt; i++) {
2894 2898                  mac_dhcpcid_t   *cid = &p->mp_cids[i];
2895 2899  
2896 2900                  dladm_cid2str(cid, prop_val[i]);
2897 2901          }
2898 2902          *val_cnt = p->mp_cidcnt;
2899 2903          return (DLADM_STATUS_OK);
2900 2904  }
2901 2905  
2902 2906  dladm_status_t
2903 2907  extract_allowedcids(val_desc_t *vdp, uint_t cnt, void *arg)
2904 2908  {
2905 2909          mac_resource_props_t    *mrp = arg;
2906 2910          mac_protect_t           *p = &mrp->mrp_protect;
2907 2911          int                     i;
2908 2912  
2909 2913          if (vdp->vd_val == 0) {
2910 2914                  cnt = (uint_t)-1;
2911 2915          } else {
2912 2916                  for (i = 0; i < cnt; i++) {
2913 2917                          bcopy((void *)vdp[i].vd_val, &p->mp_cids[i],
2914 2918                              sizeof (mac_dhcpcid_t));
2915 2919                  }
2916 2920          }
2917 2921          p->mp_cidcnt = cnt;
2918 2922          mrp->mrp_mask |= MRP_PROTECT;
2919 2923          return (DLADM_STATUS_OK);
2920 2924  }
2921 2925  
2922 2926  /* ARGSUSED */
2923 2927  static dladm_status_t
2924 2928  check_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2925 2929      datalink_id_t linkid, char **prop_val, uint_t *val_cntp,
2926 2930      uint_t flags, val_desc_t **vdpp, datalink_media_t media)
2927 2931  {
2928 2932          dladm_status_t  status;
2929 2933          mac_dhcpcid_t   *cid;
2930 2934          int             i;
2931 2935          uint_t          val_cnt = *val_cntp;
2932 2936          val_desc_t      *vdp = *vdpp;
2933 2937  
2934 2938          if (val_cnt > MPT_MAXCID)
2935 2939                  return (DLADM_STATUS_BADVALCNT);
2936 2940  
2937 2941          for (i = 0; i < val_cnt; i++) {
2938 2942                  if ((cid = calloc(1, sizeof (mac_dhcpcid_t))) == NULL) {
2939 2943                          status = DLADM_STATUS_NOMEM;
2940 2944                          goto fail;
2941 2945                  }
2942 2946                  vdp[i].vd_val = (uintptr_t)cid;
2943 2947  
2944 2948                  status = dladm_str2cid(prop_val[i], cid);
2945 2949                  if (status != DLADM_STATUS_OK)
2946 2950                          goto fail;
2947 2951          }
2948 2952          return (DLADM_STATUS_OK);
2949 2953  
2950 2954  fail:
2951 2955          for (i = 0; i < val_cnt; i++) {
2952 2956                  free((void *)vdp[i].vd_val);
2953 2957                  vdp[i].vd_val = NULL;
2954 2958          }
2955 2959          return (status);
2956 2960  }
2957 2961  
2958 2962  /* ARGSUSED */
2959 2963  static dladm_status_t
2960 2964  get_secondary_macs(dladm_handle_t handle, prop_desc_t *pdp,
2961 2965      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2962 2966      datalink_media_t media, uint_t flags, uint_t *perm_flags)
2963 2967  {
2964 2968          mac_secondary_addr_t    sa;
2965 2969          dladm_status_t          status;
2966 2970          int                     i;
2967 2971  
2968 2972          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
2969 2973              perm_flags, &sa, sizeof (sa));
2970 2974          if (status != DLADM_STATUS_OK)
2971 2975                  return (status);
2972 2976  
2973 2977          if (sa.ms_addrcnt > *val_cnt)
2974 2978                  return (DLADM_STATUS_BADVALCNT);
2975 2979  
2976 2980          for (i = 0; i < sa.ms_addrcnt; i++) {
2977 2981                  if (dladm_aggr_macaddr2str(
2978 2982                      (const unsigned char *)&sa.ms_addrs[i], prop_val[i]) ==
2979 2983                      NULL) {
2980 2984                          *val_cnt = i;
2981 2985                          return (DLADM_STATUS_NOMEM);
2982 2986                  }
2983 2987          }
2984 2988          *val_cnt = sa.ms_addrcnt;
2985 2989          return (DLADM_STATUS_OK);
2986 2990  }
2987 2991  
2988 2992  /* ARGSUSED */
2989 2993  static dladm_status_t
2990 2994  check_secondary_macs(dladm_handle_t handle, prop_desc_t *pdp,
2991 2995      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
2992 2996      val_desc_t **vdpp, datalink_media_t media)
2993 2997  {
2994 2998          dladm_status_t  status;
2995 2999          uchar_t         *addr;
2996 3000          uint_t          len = 0;
2997 3001          int             i;
2998 3002          uint_t          val_cnt = *val_cntp;
2999 3003          val_desc_t      *vdp = *vdpp;
3000 3004  
3001 3005          if (val_cnt >= MPT_MAXMACADDR)
3002 3006                  return (DLADM_STATUS_BADVALCNT);
3003 3007  
3004 3008          for (i = 0; i < val_cnt; i++) {
3005 3009                  addr = _link_aton(prop_val[i], (int *)&len);
3006 3010                  if (addr == NULL) {
3007 3011                          if (len == (uint_t)-1)
3008 3012                                  status = DLADM_STATUS_MACADDRINVAL;
3009 3013                          else
3010 3014                                  status = DLADM_STATUS_NOMEM;
3011 3015                          goto fail;
3012 3016                  }
3013 3017  
3014 3018                  vdp[i].vd_val = (uintptr_t)addr;
3015 3019          }
3016 3020          return (DLADM_STATUS_OK);
3017 3021  
3018 3022  fail:
3019 3023          for (i = 0; i < val_cnt; i++) {
3020 3024                  free((void *)vdp[i].vd_val);
3021 3025                  vdp[i].vd_val = NULL;
3022 3026          }
3023 3027          return (status);
3024 3028  }
3025 3029  
3026 3030  /* ARGSUSED */
3027 3031  static dladm_status_t
3028 3032  set_secondary_macs(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
3029 3033      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3030 3034  {
3031 3035          dladm_status_t status;
3032 3036          dld_ioc_macprop_t *dip;
3033 3037          int i;
3034 3038          mac_secondary_addr_t msa;
3035 3039  
3036 3040          dip = i_dladm_buf_alloc_by_name(0, linkid, "secondary-macs", 0,
3037 3041              &status);
3038 3042          if (dip == NULL)
3039 3043                  return (status);
3040 3044  
3041 3045          if (vdp->vd_val == 0) {
3042 3046                  val_cnt = (uint_t)-1;
3043 3047          } else {
3044 3048                  for (i = 0; i < val_cnt; i++) {
3045 3049                          bcopy((void *)vdp[i].vd_val, msa.ms_addrs[i],
3046 3050                              MAXMACADDRLEN);
3047 3051                  }
3048 3052          }
3049 3053          msa.ms_addrcnt = val_cnt;
3050 3054          bcopy(&msa, dip->pr_val, dip->pr_valsize);
3051 3055  
3052 3056          status = i_dladm_macprop(handle, dip, B_TRUE);
3053 3057  
3054 3058          free(dip);
3055 3059          return (status);
3056 3060  }
3057 3061  
3058 3062  /* ARGSUSED */
3059 3063  static dladm_status_t
3060 3064  get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3061 3065      char **prop_val, uint_t *val_cnt, datalink_media_t media,
3062 3066      uint_t flags, uint_t *perm_flags)
3063 3067  {
3064 3068          struct          dlautopush dlap;
3065 3069          int             i, len;
3066 3070          dladm_status_t  status;
3067 3071  
3068 3072          if (flags & DLD_PROP_DEFAULT)
3069 3073                  return (DLADM_STATUS_NOTDEFINED);
3070 3074  
3071 3075          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3072 3076              perm_flags, &dlap, sizeof (dlap));
3073 3077          if (status != DLADM_STATUS_OK)
3074 3078                  return (status);
3075 3079  
3076 3080          if (dlap.dap_npush == 0) {
3077 3081                  *val_cnt = 0;
3078 3082                  return (DLADM_STATUS_OK);
3079 3083          }
3080 3084          for (i = 0, len = 0; i < dlap.dap_npush; i++) {
3081 3085                  if (i != 0) {
3082 3086                          (void) snprintf(*prop_val + len,
3083 3087                              DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
3084 3088                          len += 1;
3085 3089                  }
3086 3090                  (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
3087 3091                      "%s", dlap.dap_aplist[i]);
3088 3092                  len += strlen(dlap.dap_aplist[i]);
3089 3093                  if (dlap.dap_anchor - 1 == i) {
3090 3094                          (void) snprintf(*prop_val + len,
3091 3095                              DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
3092 3096                              AP_ANCHOR);
3093 3097                          len += (strlen(AP_ANCHOR) + 1);
3094 3098                  }
3095 3099          }
3096 3100          *val_cnt = 1;
3097 3101          return (DLADM_STATUS_OK);
3098 3102  }
3099 3103  
3100 3104  /*
3101 3105   * Add the specified module to the dlautopush structure; returns a
3102 3106   * DLADM_STATUS_* code.
3103 3107   */
3104 3108  dladm_status_t
3105 3109  i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
3106 3110  {
3107 3111          if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
3108 3112                  return (DLADM_STATUS_BADVAL);
3109 3113  
3110 3114          if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
3111 3115                  /*
3112 3116                   * We don't allow multiple anchors, and the anchor must
3113 3117                   * be after at least one module.
3114 3118                   */
3115 3119                  if (dlap->dap_anchor != 0)
3116 3120                          return (DLADM_STATUS_BADVAL);
3117 3121                  if (dlap->dap_npush == 0)
3118 3122                          return (DLADM_STATUS_BADVAL);
3119 3123  
3120 3124                  dlap->dap_anchor = dlap->dap_npush;
3121 3125                  return (DLADM_STATUS_OK);
3122 3126          }
3123 3127          if (dlap->dap_npush >= MAXAPUSH)
3124 3128                  return (DLADM_STATUS_BADVALCNT);
3125 3129  
3126 3130          (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
3127 3131              FMNAMESZ + 1);
3128 3132  
3129 3133          return (DLADM_STATUS_OK);
3130 3134  }
3131 3135  
3132 3136  /*
3133 3137   * Currently, both '.' and ' '(space) can be used as the delimiters between
3134 3138   * autopush modules. The former is used in dladm set-linkprop, and the
3135 3139   * latter is used in the autopush(1M) file.
3136 3140   */
3137 3141  /* ARGSUSED */
3138 3142  static dladm_status_t
3139 3143  check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3140 3144      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3141 3145      datalink_media_t media)
3142 3146  {
3143 3147          char                    *module;
3144 3148          struct dlautopush       *dlap;
3145 3149          dladm_status_t          status;
3146 3150          char                    val[DLADM_PROP_VAL_MAX];
3147 3151          char                    delimiters[4];
3148 3152          uint_t                  val_cnt = *val_cntp;
3149 3153          val_desc_t              *vdp = *vdpp;
3150 3154  
3151 3155          if (val_cnt != 1)
3152 3156                  return (DLADM_STATUS_BADVALCNT);
3153 3157  
3154 3158          if (prop_val != NULL) {
3155 3159                  dlap = malloc(sizeof (struct dlautopush));
3156 3160                  if (dlap == NULL)
3157 3161                          return (DLADM_STATUS_NOMEM);
3158 3162  
3159 3163                  (void) memset(dlap, 0, sizeof (struct dlautopush));
3160 3164                  (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
3161 3165                  bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
3162 3166                  module = strtok(val, delimiters);
3163 3167                  while (module != NULL) {
3164 3168                          status = i_dladm_add_ap_module(module, dlap);
3165 3169                          if (status != DLADM_STATUS_OK)
3166 3170                                  return (status);
3167 3171                          module = strtok(NULL, delimiters);
3168 3172                  }
3169 3173  
3170 3174                  vdp->vd_val = (uintptr_t)dlap;
3171 3175          } else {
3172 3176                  vdp->vd_val = 0;
3173 3177          }
3174 3178          return (DLADM_STATUS_OK);
3175 3179  }
3176 3180  
3177 3181  #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
3178 3182  
3179 3183  /* ARGSUSED */
3180 3184  static dladm_status_t
3181 3185  get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
3182 3186      datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
3183 3187      uint_t *perm_flags)
3184 3188  {
3185 3189          wl_rates_t      *wrp;
3186 3190          uint_t          i;
3187 3191          dladm_status_t  status = DLADM_STATUS_OK;
3188 3192  
3189 3193          wrp = malloc(WLDP_BUFSIZE);
3190 3194          if (wrp == NULL)
3191 3195                  return (DLADM_STATUS_NOMEM);
3192 3196  
3193 3197          status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
3194 3198              B_FALSE);
3195 3199          if (status != DLADM_STATUS_OK)
3196 3200                  goto done;
3197 3201  
3198 3202          if (wrp->wl_rates_num > *val_cnt) {
3199 3203                  status = DLADM_STATUS_TOOSMALL;
3200 3204                  goto done;
3201 3205          }
3202 3206  
3203 3207          if (wrp->wl_rates_rates[0] == 0) {
3204 3208                  prop_val[0][0] = '\0';
3205 3209                  *val_cnt = 1;
3206 3210                  goto done;
3207 3211          }
3208 3212  
3209 3213          for (i = 0; i < wrp->wl_rates_num; i++) {
3210 3214                  (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
3211 3215                      wrp->wl_rates_rates[i] % 2,
3212 3216                      (float)wrp->wl_rates_rates[i] / 2);
3213 3217          }
3214 3218          *val_cnt = wrp->wl_rates_num;
3215 3219          *perm_flags = MAC_PROP_PERM_RW;
3216 3220  
3217 3221  done:
3218 3222          free(wrp);
3219 3223          return (status);
3220 3224  }
3221 3225  
3222 3226  static dladm_status_t
3223 3227  get_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3224 3228      char **prop_val, uint_t *val_cnt, datalink_media_t media,
3225 3229      uint_t flags, uint_t *perm_flags)
3226 3230  {
3227 3231          if (media != DL_WIFI) {
3228 3232                  return (get_speed(handle, pdp, linkid, prop_val,
3229 3233                      val_cnt, media, flags, perm_flags));
3230 3234          }
3231 3235  
3232 3236          return (get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
3233 3237              MAC_PROP_WL_DESIRED_RATES, perm_flags));
3234 3238  }
3235 3239  
3236 3240  /* ARGSUSED */
3237 3241  static dladm_status_t
3238 3242  get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3239 3243      char **prop_val, uint_t *val_cnt, datalink_media_t media,
3240 3244      uint_t flags, uint_t *perm_flags)
3241 3245  {
3242 3246          switch (media) {
3243 3247          case DL_ETHER:
3244 3248                  /*
3245 3249                   * Speed for ethernet links is unbounded. E.g., 802.11b
3246 3250                   * links can have a speed of 5.5 Gbps.
3247 3251                   */
3248 3252                  return (DLADM_STATUS_NOTSUP);
3249 3253  
3250 3254          case DL_WIFI:
3251 3255                  return (get_rate_common(handle, pdp, linkid, prop_val,
3252 3256                      val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
3253 3257          default:
3254 3258                  return (DLADM_STATUS_BADARG);
3255 3259          }
3256 3260  }
3257 3261  
3258 3262  static dladm_status_t
3259 3263  set_wlan_rate(dladm_handle_t handle, datalink_id_t linkid,
3260 3264      dladm_wlan_rates_t *rates)
3261 3265  {
3262 3266          int             i;
3263 3267          uint_t          len;
3264 3268          wl_rates_t      *wrp;
3265 3269          dladm_status_t  status = DLADM_STATUS_OK;
3266 3270  
3267 3271          wrp = malloc(WLDP_BUFSIZE);
3268 3272          if (wrp == NULL)
3269 3273                  return (DLADM_STATUS_NOMEM);
3270 3274  
3271 3275          bzero(wrp, WLDP_BUFSIZE);
3272 3276          for (i = 0; i < rates->wr_cnt; i++)
3273 3277                  wrp->wl_rates_rates[i] = rates->wr_rates[i];
3274 3278          wrp->wl_rates_num = rates->wr_cnt;
3275 3279  
3276 3280          len = offsetof(wl_rates_t, wl_rates_rates) +
3277 3281              (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
3278 3282          status = i_dladm_wlan_param(handle, linkid, wrp,
3279 3283              MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
3280 3284  
3281 3285          free(wrp);
3282 3286          return (status);
3283 3287  }
3284 3288  
3285 3289  /* ARGSUSED */
3286 3290  static dladm_status_t
3287 3291  set_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3288 3292      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3289 3293  {
3290 3294          dladm_wlan_rates_t      rates;
3291 3295          dladm_status_t          status;
3292 3296  
3293 3297          /*
3294 3298           * can currently set rate on WIFI links only.
3295 3299           */
3296 3300          if (media != DL_WIFI)
3297 3301                  return (DLADM_STATUS_PROPRDONLY);
3298 3302  
3299 3303          if (val_cnt != 1)
3300 3304                  return (DLADM_STATUS_BADVALCNT);
3301 3305  
3302 3306          rates.wr_cnt = 1;
3303 3307          rates.wr_rates[0] = vdp[0].vd_val;
3304 3308  
3305 3309          status = set_wlan_rate(handle, linkid, &rates);
3306 3310  
3307 3311          return (status);
3308 3312  }
3309 3313  
3310 3314  /* ARGSUSED */
3311 3315  static dladm_status_t
3312 3316  check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3313 3317      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3314 3318      datalink_media_t media)
3315 3319  {
3316 3320          int             i;
3317 3321          uint_t          modval_cnt = MAX_SUPPORT_RATES;
3318 3322          char            *buf, **modval;
3319 3323          dladm_status_t  status;
3320 3324          uint_t          perm_flags;
3321 3325          uint_t          val_cnt = *val_cntp;
3322 3326          val_desc_t      *vdp = *vdpp;
3323 3327  
3324 3328          if (val_cnt != 1)
3325 3329                  return (DLADM_STATUS_BADVALCNT);
3326 3330  
3327 3331          buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
3328 3332              MAX_SUPPORT_RATES);
3329 3333          if (buf == NULL) {
3330 3334                  status = DLADM_STATUS_NOMEM;
3331 3335                  goto done;
3332 3336          }
3333 3337  
3334 3338          modval = (char **)(void *)buf;
3335 3339          for (i = 0; i < MAX_SUPPORT_RATES; i++) {
3336 3340                  modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
3337 3341                      i * DLADM_STRSIZE;
3338 3342          }
3339 3343  
3340 3344          status = get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
3341 3345              media, 0, &perm_flags);
3342 3346          if (status != DLADM_STATUS_OK)
3343 3347                  goto done;
3344 3348  
3345 3349          for (i = 0; i < modval_cnt; i++) {
3346 3350                  if (strcasecmp(*prop_val, modval[i]) == 0) {
3347 3351                          vdp->vd_val = (uintptr_t)(uint_t)
3348 3352                              (atof(*prop_val) * 2);
3349 3353                          status = DLADM_STATUS_OK;
3350 3354                          break;
3351 3355                  }
3352 3356          }
3353 3357          if (i == modval_cnt)
3354 3358                  status = DLADM_STATUS_BADVAL;
3355 3359  done:
3356 3360          free(buf);
3357 3361          return (status);
3358 3362  }
3359 3363  
3360 3364  static dladm_status_t
3361 3365  get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
3362 3366      int buflen)
3363 3367  {
3364 3368          return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
3365 3369              buflen, B_FALSE));
3366 3370  }
3367 3371  
3368 3372  /* ARGSUSED */
3369 3373  static dladm_status_t
3370 3374  get_channel(dladm_handle_t handle, prop_desc_t *pdp,
3371 3375      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3372 3376      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3373 3377  {
3374 3378          uint32_t        channel;
3375 3379          char            buf[WLDP_BUFSIZE];
3376 3380          dladm_status_t  status;
3377 3381          wl_phy_conf_t   wl_phy_conf;
3378 3382  
3379 3383          if ((status = get_phyconf(handle, linkid, buf, sizeof (buf)))
3380 3384              != DLADM_STATUS_OK)
3381 3385                  return (status);
3382 3386  
3383 3387          (void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
3384 3388          if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel))
3385 3389                  return (DLADM_STATUS_NOTFOUND);
3386 3390  
3387 3391          (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
3388 3392          *val_cnt = 1;
3389 3393          *perm_flags = MAC_PROP_PERM_READ;
3390 3394          return (DLADM_STATUS_OK);
3391 3395  }
3392 3396  
3393 3397  /* ARGSUSED */
3394 3398  static dladm_status_t
3395 3399  get_powermode(dladm_handle_t handle, prop_desc_t *pdp,
3396 3400      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3397 3401      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3398 3402  {
3399 3403          wl_ps_mode_t    mode;
3400 3404          const char      *s;
3401 3405          char            buf[WLDP_BUFSIZE];
3402 3406          dladm_status_t  status;
3403 3407  
3404 3408          if ((status = i_dladm_wlan_param(handle, linkid, buf,
3405 3409              MAC_PROP_WL_POWER_MODE, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3406 3410                  return (status);
3407 3411  
3408 3412          (void) memcpy(&mode, buf, sizeof (mode));
3409 3413          switch (mode.wl_ps_mode) {
3410 3414          case WL_PM_AM:
3411 3415                  s = "off";
3412 3416                  break;
3413 3417          case WL_PM_MPS:
3414 3418                  s = "max";
3415 3419                  break;
3416 3420          case WL_PM_FAST:
3417 3421                  s = "fast";
3418 3422                  break;
3419 3423          default:
3420 3424                  return (DLADM_STATUS_NOTFOUND);
3421 3425          }
3422 3426          (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
3423 3427          *val_cnt = 1;
3424 3428          *perm_flags = MAC_PROP_PERM_RW;
3425 3429          return (DLADM_STATUS_OK);
3426 3430  }
3427 3431  
3428 3432  /* ARGSUSED */
3429 3433  static dladm_status_t
3430 3434  set_powermode(dladm_handle_t handle, prop_desc_t *pdp,
3431 3435      datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
3432 3436      datalink_media_t media)
3433 3437  {
3434 3438          dladm_wlan_powermode_t  powermode = vdp->vd_val;
3435 3439          wl_ps_mode_t            ps_mode;
3436 3440  
3437 3441          if (val_cnt != 1)
3438 3442                  return (DLADM_STATUS_BADVALCNT);
3439 3443  
3440 3444          (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
3441 3445  
3442 3446          switch (powermode) {
3443 3447          case DLADM_WLAN_PM_OFF:
3444 3448                  ps_mode.wl_ps_mode = WL_PM_AM;
3445 3449                  break;
3446 3450          case DLADM_WLAN_PM_MAX:
3447 3451                  ps_mode.wl_ps_mode = WL_PM_MPS;
3448 3452                  break;
3449 3453          case DLADM_WLAN_PM_FAST:
3450 3454                  ps_mode.wl_ps_mode = WL_PM_FAST;
3451 3455                  break;
3452 3456          default:
3453 3457                  return (DLADM_STATUS_NOTSUP);
3454 3458          }
3455 3459          return (i_dladm_wlan_param(handle, linkid, &ps_mode,
3456 3460              MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
3457 3461  }
3458 3462  
3459 3463  /* ARGSUSED */
3460 3464  static dladm_status_t
3461 3465  get_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3462 3466      char **prop_val, uint_t *val_cnt, datalink_media_t media,
3463 3467      uint_t flags, uint_t *perm_flags)
3464 3468  {
3465 3469          wl_radio_t      radio;
3466 3470          const char      *s;
3467 3471          char            buf[WLDP_BUFSIZE];
3468 3472          dladm_status_t  status;
3469 3473  
3470 3474          if ((status = i_dladm_wlan_param(handle, linkid, buf,
3471 3475              MAC_PROP_WL_RADIO, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3472 3476                  return (status);
3473 3477  
3474 3478          (void) memcpy(&radio, buf, sizeof (radio));
3475 3479          switch (radio) {
3476 3480          case B_TRUE:
3477 3481                  s = "on";
3478 3482                  break;
3479 3483          case B_FALSE:
3480 3484                  s = "off";
3481 3485                  break;
3482 3486          default:
3483 3487                  return (DLADM_STATUS_NOTFOUND);
3484 3488          }
3485 3489          (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
3486 3490          *val_cnt = 1;
3487 3491          *perm_flags = MAC_PROP_PERM_RW;
3488 3492          return (DLADM_STATUS_OK);
3489 3493  }
3490 3494  
3491 3495  /* ARGSUSED */
3492 3496  static dladm_status_t
3493 3497  set_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3494 3498      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3495 3499  {
3496 3500          dladm_wlan_radio_t      radio = vdp->vd_val;
3497 3501          wl_radio_t              r;
3498 3502  
3499 3503          if (val_cnt != 1)
3500 3504                  return (DLADM_STATUS_BADVALCNT);
3501 3505  
3502 3506          switch (radio) {
3503 3507          case DLADM_WLAN_RADIO_ON:
3504 3508                  r = B_TRUE;
3505 3509                  break;
3506 3510          case DLADM_WLAN_RADIO_OFF:
3507 3511                  r = B_FALSE;
3508 3512                  break;
3509 3513          default:
3510 3514                  return (DLADM_STATUS_NOTSUP);
3511 3515          }
3512 3516          return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
3513 3517              sizeof (r), B_TRUE));
3514 3518  }
3515 3519  
3516 3520  /* ARGSUSED */
3517 3521  static dladm_status_t
3518 3522  check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
3519 3523      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
3520 3524      val_desc_t **vdpp, datalink_media_t media)
3521 3525  {
3522 3526          int32_t         hlim;
3523 3527          char            *ep;
3524 3528          uint_t          val_cnt = *val_cntp;
3525 3529          val_desc_t      *vdp = *vdpp;
3526 3530  
3527 3531          if (val_cnt != 1)
3528 3532                  return (DLADM_STATUS_BADVALCNT);
3529 3533  
3530 3534          errno = 0;
3531 3535          hlim = strtol(*prop_val, &ep, 10);
3532 3536          if (errno != 0 || ep == *prop_val || hlim < 1 ||
3533 3537              hlim > (int32_t)UINT8_MAX)
3534 3538                  return (DLADM_STATUS_BADVAL);
3535 3539          vdp->vd_val = hlim;
3536 3540          return (DLADM_STATUS_OK);
3537 3541  }
3538 3542  
3539 3543  /* ARGSUSED */
3540 3544  static dladm_status_t
3541 3545  check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3542 3546      char **prop_val, uint_t *val_cntp, uint_t flags, val_desc_t **vdpp,
3543 3547      datalink_media_t media)
3544 3548  {
3545 3549          int32_t         elim;
3546 3550          char            *ep;
3547 3551          uint_t          val_cnt = *val_cntp;
3548 3552          val_desc_t      *vdp = *vdpp;
3549 3553  
3550 3554          if (media != DL_IPV6)
3551 3555                  return (DLADM_STATUS_BADARG);
3552 3556  
3553 3557          if (val_cnt != 1)
3554 3558                  return (DLADM_STATUS_BADVALCNT);
3555 3559  
3556 3560          errno = 0;
3557 3561          elim = strtol(*prop_val, &ep, 10);
3558 3562          if (errno != 0 || ep == *prop_val || elim < 0 ||
3559 3563              elim > (int32_t)UINT8_MAX)
3560 3564                  return (DLADM_STATUS_BADVAL);
3561 3565          vdp->vd_val = elim;
3562 3566          return (DLADM_STATUS_OK);
3563 3567  }
3564 3568  
3565 3569  static dladm_status_t
3566 3570  i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
3567 3571      const char *prop_name, char **prop_val, uint_t val_cnt)
3568 3572  {
3569 3573          char            buf[MAXLINELEN];
3570 3574          int             i;
3571 3575          dladm_conf_t    conf;
3572 3576          dladm_status_t  status;
3573 3577  
3574 3578          status = dladm_open_conf(handle, linkid, &conf);
3575 3579          if (status != DLADM_STATUS_OK)
3576 3580                  return (status);
3577 3581  
3578 3582          /*
3579 3583           * reset case.
3580 3584           */
3581 3585          if (val_cnt == 0) {
3582 3586                  status = dladm_unset_conf_field(handle, conf, prop_name);
3583 3587                  if (status == DLADM_STATUS_OK)
3584 3588                          status = dladm_write_conf(handle, conf);
3585 3589                  goto done;
3586 3590          }
3587 3591  
3588 3592          buf[0] = '\0';
3589 3593          for (i = 0; i < val_cnt; i++) {
3590 3594                  (void) strlcat(buf, prop_val[i], MAXLINELEN);
3591 3595                  if (i != val_cnt - 1)
3592 3596                          (void) strlcat(buf, ",", MAXLINELEN);
3593 3597          }
3594 3598  
3595 3599          status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
3596 3600              buf);
3597 3601          if (status == DLADM_STATUS_OK)
3598 3602                  status = dladm_write_conf(handle, conf);
3599 3603  
3600 3604  done:
3601 3605          dladm_destroy_conf(handle, conf);
3602 3606          return (status);
3603 3607  }
3604 3608  
3605 3609  static dladm_status_t
3606 3610  i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
3607 3611      const char *prop_name, char **prop_val, uint_t *val_cntp)
3608 3612  {
3609 3613          char            buf[MAXLINELEN], *str;
3610 3614          uint_t          cnt = 0;
3611 3615          dladm_conf_t    conf;
3612 3616          dladm_status_t  status;
3613 3617  
3614 3618          status = dladm_getsnap_conf(handle, linkid, &conf);
3615 3619          if (status != DLADM_STATUS_OK)
3616 3620                  return (status);
3617 3621  
3618 3622          status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
3619 3623          if (status != DLADM_STATUS_OK)
3620 3624                  goto done;
3621 3625  
3622 3626          str = strtok(buf, ",");
3623 3627          while (str != NULL) {
3624 3628                  if (cnt == *val_cntp) {
3625 3629                          status = DLADM_STATUS_TOOSMALL;
3626 3630                          goto done;
3627 3631                  }
3628 3632                  (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
3629 3633                  str = strtok(NULL, ",");
3630 3634          }
3631 3635  
3632 3636          *val_cntp = cnt;
3633 3637  
3634 3638  done:
3635 3639          dladm_destroy_conf(handle, conf);
3636 3640          return (status);
3637 3641  }
3638 3642  
3639 3643  /*
3640 3644   * Walk persistent private link properties of a link.
3641 3645   */
3642 3646  static dladm_status_t
3643 3647  i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
3644 3648      void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
3645 3649  {
3646 3650          dladm_status_t          status;
3647 3651          dladm_conf_t            conf;
3648 3652          char                    last_attr[MAXLINKATTRLEN];
3649 3653          char                    attr[MAXLINKATTRLEN];
3650 3654          char                    attrval[MAXLINKATTRVALLEN];
3651 3655          size_t                  attrsz;
3652 3656  
3653 3657          if (linkid == DATALINK_INVALID_LINKID || func == NULL)
3654 3658                  return (DLADM_STATUS_BADARG);
3655 3659  
3656 3660          status = dladm_getsnap_conf(handle, linkid, &conf);
3657 3661          if (status != DLADM_STATUS_OK)
3658 3662                  return (status);
3659 3663  
3660 3664          last_attr[0] = '\0';
3661 3665          while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
3662 3666              attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
3663 3667                  if (attr[0] == '_') {
3664 3668                          if (func(handle, linkid, attr, arg) ==
3665 3669                              DLADM_WALK_TERMINATE)
3666 3670                                  break;
3667 3671                  }
3668 3672                  (void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
3669 3673          }
3670 3674  
3671 3675          dladm_destroy_conf(handle, conf);
3672 3676          return (DLADM_STATUS_OK);
3673 3677  }
3674 3678  
3675 3679  static link_attr_t *
3676 3680  dladm_name2prop(const char *prop_name)
3677 3681  {
3678 3682          link_attr_t *p;
3679 3683  
3680 3684          for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
3681 3685                  if (strcmp(p->pp_name, prop_name) == 0)
3682 3686                          break;
3683 3687          }
3684 3688          return (p);
3685 3689  }
3686 3690  
3687 3691  static link_attr_t *
3688 3692  dladm_id2prop(mac_prop_id_t propid)
3689 3693  {
3690 3694          link_attr_t *p;
3691 3695  
3692 3696          for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
3693 3697                  if (p->pp_id == propid)
3694 3698                          break;
3695 3699          }
3696 3700          return (p);
3697 3701  }
3698 3702  
3699 3703  static dld_ioc_macprop_t *
3700 3704  i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
3701 3705      const char *prop_name, mac_prop_id_t propid, uint_t flags,
3702 3706      dladm_status_t *status)
3703 3707  {
3704 3708          int dsize;
3705 3709          dld_ioc_macprop_t *dip;
3706 3710  
3707 3711          *status = DLADM_STATUS_OK;
3708 3712          dsize = MAC_PROP_BUFSIZE(valsize);
3709 3713          dip = malloc(dsize);
3710 3714          if (dip == NULL) {
3711 3715                  *status = DLADM_STATUS_NOMEM;
3712 3716                  return (NULL);
3713 3717          }
3714 3718          bzero(dip, dsize);
3715 3719          dip->pr_valsize = valsize;
3716 3720          (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
3717 3721          dip->pr_linkid = linkid;
3718 3722          dip->pr_num = propid;
3719 3723          dip->pr_flags = flags;
3720 3724          return (dip);
3721 3725  }
3722 3726  
3723 3727  static dld_ioc_macprop_t *
3724 3728  i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
3725 3729      const char *prop_name, uint_t flags, dladm_status_t *status)
3726 3730  {
3727 3731          link_attr_t *p;
3728 3732  
3729 3733          p = dladm_name2prop(prop_name);
3730 3734          valsize = MAX(p->pp_valsize, valsize);
3731 3735          return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
3732 3736              flags, status));
3733 3737  }
3734 3738  
3735 3739  static dld_ioc_macprop_t *
3736 3740  i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
3737 3741      mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
3738 3742  {
3739 3743          link_attr_t *p;
3740 3744  
3741 3745          p = dladm_id2prop(propid);
3742 3746          valsize = MAX(p->pp_valsize, valsize);
3743 3747          return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
3744 3748              flags, status));
3745 3749  }
3746 3750  
3747 3751  /* ARGSUSED */
3748 3752  static dladm_status_t
3749 3753  set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
3750 3754      datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
3751 3755      datalink_media_t media)
3752 3756  {
3753 3757          dld_ioc_macprop_t       *dip;
3754 3758          dladm_status_t  status = DLADM_STATUS_OK;
3755 3759          uint8_t         u8;
3756 3760          uint16_t        u16;
3757 3761          uint32_t        u32;
3758 3762          void            *val;
3759 3763  
3760 3764          dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
3761 3765          if (dip == NULL)
3762 3766                  return (status);
3763 3767  
3764 3768          if (pdp->pd_flags & PD_CHECK_ALLOC)
3765 3769                  val = (void *)vdp->vd_val;
3766 3770          else {
3767 3771                  /*
3768 3772                   * Currently all 1/2/4-byte size properties are byte/word/int.
3769 3773                   * No need (yet) to distinguish these from arrays of same size.
3770 3774                   */
3771 3775                  switch (dip->pr_valsize) {
3772 3776                  case 1:
3773 3777                          u8 = vdp->vd_val;
3774 3778                          val = &u8;
3775 3779                          break;
3776 3780                  case 2:
3777 3781                          u16 = vdp->vd_val;
3778 3782                          val = &u16;
3779 3783                          break;
3780 3784                  case 4:
3781 3785                          u32 = vdp->vd_val;
3782 3786                          val = &u32;
3783 3787                          break;
3784 3788                  default:
3785 3789                          val = &vdp->vd_val;
3786 3790                          break;
3787 3791                  }
3788 3792          }
3789 3793  
3790 3794          if (val != NULL)
3791 3795                  (void) memcpy(dip->pr_val, val, dip->pr_valsize);
3792 3796          else
3793 3797                  dip->pr_valsize = 0;
3794 3798  
3795 3799          status = i_dladm_macprop(handle, dip, B_TRUE);
3796 3800  
3797 3801  done:
3798 3802          free(dip);
3799 3803          return (status);
3800 3804  }
3801 3805  
3802 3806  dladm_status_t
3803 3807  i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
3804 3808  {
3805 3809          dladm_status_t status = DLADM_STATUS_OK;
3806 3810  
3807 3811          if (ioctl(dladm_dld_fd(handle),
3808 3812              (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
3809 3813                  status = dladm_errno2status(errno);
3810 3814  
3811 3815          return (status);
3812 3816  }
3813 3817  
3814 3818  static dladm_status_t
3815 3819  i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
3816 3820      char *prop_name, uint_t flags, uint_t *perm_flags, void *arg, size_t size)
3817 3821  {
3818 3822          dld_ioc_macprop_t       *dip;
3819 3823          dladm_status_t          status;
3820 3824  
3821 3825          dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, &status);
3822 3826          if (dip == NULL)
3823 3827                  return (DLADM_STATUS_NOMEM);
3824 3828  
3825 3829          status = i_dladm_macprop(handle, dip, B_FALSE);
3826 3830          if (status != DLADM_STATUS_OK) {
3827 3831                  free(dip);
3828 3832                  return (status);
3829 3833          }
3830 3834  
3831 3835          if (perm_flags != NULL)
3832 3836                  *perm_flags = dip->pr_perm_flags;
3833 3837  
3834 3838          if (arg != NULL)
3835 3839                  (void) memcpy(arg, dip->pr_val, size);
3836 3840          free(dip);
3837 3841          return (DLADM_STATUS_OK);
3838 3842  }
3839 3843  
3840 3844  /* ARGSUSED */
3841 3845  static dladm_status_t
3842 3846  check_uint32(dladm_handle_t handle, prop_desc_t *pdp,
3843 3847      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
3844 3848      val_desc_t **vp, datalink_media_t media)
3845 3849  {
3846 3850          uint_t          val_cnt = *val_cntp;
3847 3851          val_desc_t      *v = *vp;
3848 3852  
3849 3853          if (val_cnt != 1)
3850 3854                  return (DLADM_STATUS_BADVAL);
3851 3855          v->vd_val = strtoul(prop_val[0], NULL, 0);
3852 3856          return (DLADM_STATUS_OK);
3853 3857  }
3854 3858  
3855 3859  /* ARGSUSED */
3856 3860  static dladm_status_t
3857 3861  get_duplex(dladm_handle_t handle, prop_desc_t *pdp,
3858 3862      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3859 3863      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3860 3864  {
3861 3865          link_duplex_t   link_duplex;
3862 3866          dladm_status_t  status;
3863 3867  
3864 3868          if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
3865 3869              KSTAT_DATA_UINT32, &link_duplex)) != 0)
3866 3870                  return (status);
3867 3871  
3868 3872          switch (link_duplex) {
3869 3873          case LINK_DUPLEX_FULL:
3870 3874                  (void) strcpy(*prop_val, "full");
3871 3875                  break;
3872 3876          case LINK_DUPLEX_HALF:
3873 3877                  (void) strcpy(*prop_val, "half");
3874 3878                  break;
3875 3879          default:
3876 3880                  (void) strcpy(*prop_val, "unknown");
3877 3881                  break;
3878 3882          }
3879 3883          *val_cnt = 1;
3880 3884          return (DLADM_STATUS_OK);
3881 3885  }
3882 3886  
3883 3887  /* ARGSUSED */
3884 3888  static dladm_status_t
3885 3889  get_speed(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3886 3890      char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
3887 3891      uint_t *perm_flags)
3888 3892  {
3889 3893          uint64_t        ifspeed = 0;
3890 3894          dladm_status_t status;
3891 3895  
3892 3896          if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
3893 3897              KSTAT_DATA_UINT64, &ifspeed)) != 0)
3894 3898                  return (status);
3895 3899  
3896 3900          if ((ifspeed % 1000000) != 0) {
3897 3901                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
3898 3902                      "%llf", ifspeed / (float)1000000); /* Mbps */
3899 3903          } else {
3900 3904                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
3901 3905                      "%llu", ifspeed / 1000000); /* Mbps */
3902 3906          }
3903 3907          *val_cnt = 1;
3904 3908          *perm_flags = MAC_PROP_PERM_READ;
3905 3909          return (DLADM_STATUS_OK);
3906 3910  }
3907 3911  
3908 3912  /* ARGSUSED */
3909 3913  static dladm_status_t
3910 3914  get_link_state(dladm_handle_t handle, prop_desc_t *pdp,
3911 3915      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3912 3916      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3913 3917  {
3914 3918          link_state_t            link_state;
3915 3919          dladm_status_t          status;
3916 3920  
3917 3921          status = dladm_get_state(handle, linkid, &link_state);
3918 3922          if (status != DLADM_STATUS_OK)
3919 3923                  return (status);
3920 3924  
3921 3925          switch (link_state) {
3922 3926          case LINK_STATE_UP:
3923 3927                  (void) strcpy(*prop_val, "up");
3924 3928                  break;
3925 3929          case LINK_STATE_DOWN:
3926 3930                  (void) strcpy(*prop_val, "down");
3927 3931                  break;
3928 3932          default:
3929 3933                  (void) strcpy(*prop_val, "unknown");
3930 3934                  break;
3931 3935          }
3932 3936          *val_cnt = 1;
3933 3937          *perm_flags = MAC_PROP_PERM_READ;
3934 3938          return (DLADM_STATUS_OK);
3935 3939  }
3936 3940  
3937 3941  /* ARGSUSED */
3938 3942  static dladm_status_t
3939 3943  get_binary(dladm_handle_t handle, prop_desc_t *pdp,
3940 3944      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3941 3945      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3942 3946  {
3943 3947          dladm_status_t  status;
3944 3948          uint_t          v = 0;
3945 3949  
3946 3950          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3947 3951              perm_flags, &v, sizeof (v));
3948 3952          if (status != DLADM_STATUS_OK)
3949 3953                  return (status);
3950 3954  
3951 3955          (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%d", (uint_t)(v > 0));
3952 3956          *val_cnt = 1;
3953 3957          return (DLADM_STATUS_OK);
3954 3958  }
3955 3959  
3956 3960  /* ARGSUSED */
3957 3961  static dladm_status_t
3958 3962  get_uint32(dladm_handle_t handle, prop_desc_t *pdp,
3959 3963      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3960 3964      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3961 3965  {
3962 3966          dladm_status_t  status;
3963 3967          uint32_t        v = 0;
3964 3968  
3965 3969          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3966 3970              perm_flags, &v, sizeof (v));
3967 3971          if (status != DLADM_STATUS_OK)
3968 3972                  return (status);
3969 3973  
3970 3974          (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
3971 3975          *val_cnt = 1;
3972 3976          return (DLADM_STATUS_OK);
3973 3977  }
3974 3978  
3975 3979  /* ARGSUSED */
3976 3980  static dladm_status_t
3977 3981  get_range(dladm_handle_t handle, prop_desc_t *pdp,
3978 3982      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3979 3983      datalink_media_t media, uint_t flags, uint_t *perm_flags)
3980 3984  {
3981 3985          dld_ioc_macprop_t *dip;
3982 3986          dladm_status_t status = DLADM_STATUS_OK;
3983 3987          size_t  sz;
3984 3988          uint_t  rcount;
3985 3989          mac_propval_range_t *rangep;
3986 3990  
3987 3991          /*
3988 3992           * As caller we don't know number of value ranges, the driver
3989 3993           * supports. To begin with we assume that number to be 1. If the
3990 3994           * buffer size is insufficient, driver returns back with the
3991 3995           * actual count of value ranges. See mac.h for more details.
3992 3996           */
3993 3997          sz = sizeof (mac_propval_range_t);
3994 3998          rcount = 1;
3995 3999  retry:
3996 4000          if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
3997 4001              &status)) == NULL)
3998 4002                  return (status);
3999 4003  
4000 4004          rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
4001 4005          rangep->mpr_count = rcount;
4002 4006  
4003 4007          status = i_dladm_macprop(handle, dip, B_FALSE);
4004 4008          if (status != DLADM_STATUS_OK) {
4005 4009                  if (status == DLADM_STATUS_TOOSMALL) {
4006 4010                          int err;
4007 4011  
4008 4012                          if ((err = i_dladm_range_size(rangep, &sz, &rcount))
4009 4013                              == 0) {
4010 4014                                  free(dip);
4011 4015                                  goto retry;
4012 4016                          } else {
4013 4017                                  status = dladm_errno2status(err);
4014 4018                          }
4015 4019                  }
4016 4020                  free(dip);
4017 4021                  return (status);
4018 4022          }
4019 4023  
4020 4024          if (rangep->mpr_count == 0) {
4021 4025                  *val_cnt = 1;
4022 4026                  (void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "--");
4023 4027                  goto done;
4024 4028          }
4025 4029  
4026 4030          switch (rangep->mpr_type) {
4027 4031          case MAC_PROPVAL_UINT32: {
4028 4032                  mac_propval_uint32_range_t *ur;
4029 4033                  uint_t  count = rangep->mpr_count, i;
4030 4034  
4031 4035                  ur = &rangep->mpr_range_uint32[0];
4032 4036  
4033 4037                  for (i = 0; i < count; i++, ur++) {
4034 4038                          if (ur->mpur_min == ur->mpur_max) {
4035 4039                                  (void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
4036 4040                                      "%ld", ur->mpur_min);
4037 4041                          } else {
4038 4042                                  (void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
4039 4043                                      "%ld-%ld", ur->mpur_min, ur->mpur_max);
4040 4044                          }
4041 4045                  }
4042 4046                  *val_cnt = count;
4043 4047                  break;
4044 4048          }
4045 4049          default:
4046 4050                  status = DLADM_STATUS_BADARG;
4047 4051                  break;
4048 4052          }
4049 4053  done:
4050 4054          free(dip);
4051 4055          return (status);
4052 4056  }
4053 4057  
4054 4058  /* ARGSUSED */
4055 4059  static dladm_status_t
4056 4060  get_tagmode(dladm_handle_t handle, prop_desc_t *pdp,
4057 4061      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4058 4062      datalink_media_t media, uint_t flags, uint_t *perm_flags)
4059 4063  {
4060 4064          link_tagmode_t          mode;
4061 4065          dladm_status_t          status;
4062 4066  
4063 4067          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4064 4068              perm_flags, &mode, sizeof (mode));
4065 4069          if (status != DLADM_STATUS_OK)
4066 4070                  return (status);
4067 4071  
4068 4072          switch (mode) {
4069 4073          case LINK_TAGMODE_NORMAL:
4070 4074                  (void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
4071 4075                  break;
4072 4076          case LINK_TAGMODE_VLANONLY:
4073 4077                  (void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
4074 4078                  break;
4075 4079          default:
4076 4080                  (void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
4077 4081          }
4078 4082          *val_cnt = 1;
4079 4083          return (DLADM_STATUS_OK);
4080 4084  }
4081 4085  
4082 4086  /* ARGSUSED */
4083 4087  static dladm_status_t
4084 4088  get_flowctl(dladm_handle_t handle, prop_desc_t *pdp,
4085 4089      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4086 4090      datalink_media_t media, uint_t flags, uint_t *perm_flags)
4087 4091  {
4088 4092          link_flowctrl_t v;
4089 4093          dladm_status_t  status;
4090 4094  
4091 4095          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4092 4096              perm_flags, &v, sizeof (v));
4093 4097          if (status != DLADM_STATUS_OK)
4094 4098                  return (status);
4095 4099  
4096 4100          switch (v) {
4097 4101          case LINK_FLOWCTRL_NONE:
4098 4102                  (void) sprintf(*prop_val, "no");
4099 4103                  break;
4100 4104          case LINK_FLOWCTRL_RX:
4101 4105                  (void) sprintf(*prop_val, "rx");
4102 4106                  break;
4103 4107          case LINK_FLOWCTRL_TX:
4104 4108                  (void) sprintf(*prop_val, "tx");
4105 4109                  break;
4106 4110          case LINK_FLOWCTRL_BI:
4107 4111                  (void) sprintf(*prop_val, "bi");
4108 4112                  break;
4109 4113          }
4110 4114          *val_cnt = 1;
4111 4115          return (DLADM_STATUS_OK);
4112 4116  }
4113 4117  
4114 4118  
4115 4119  /* ARGSUSED */
4116 4120  static dladm_status_t
4117 4121  i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
4118 4122      const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
4119 4123  
4120 4124  {
4121 4125          int             i, slen;
4122 4126          int             bufsize = 0;
4123 4127          dld_ioc_macprop_t *dip = NULL;
4124 4128          uchar_t         *dp;
4125 4129          link_attr_t *p;
4126 4130          dladm_status_t  status = DLADM_STATUS_OK;
4127 4131  
4128 4132          if ((prop_name == NULL && prop_val != NULL) ||
4129 4133              (prop_val != NULL && val_cnt == 0))
4130 4134                  return (DLADM_STATUS_BADARG);
4131 4135          p = dladm_name2prop(prop_name);
4132 4136          if (p->pp_id != MAC_PROP_PRIVATE)
4133 4137                  return (DLADM_STATUS_BADARG);
4134 4138  
4135 4139          if (!(flags & DLADM_OPT_ACTIVE))
4136 4140                  return (DLADM_STATUS_OK);
4137 4141  
4138 4142          /*
4139 4143           * private properties: all parsing is done in the kernel.
4140 4144           * allocate a enough space for each property + its separator (',').
4141 4145           */
4142 4146          for (i = 0; i < val_cnt; i++) {
4143 4147                  bufsize += strlen(prop_val[i]) + 1;
4144 4148          }
4145 4149  
4146 4150          if (prop_val == NULL) {
4147 4151                  /*
4148 4152                   * getting default value. so use more buffer space.
4149 4153                   */
4150 4154                  bufsize += DLADM_PROP_BUF_CHUNK;
4151 4155          }
4152 4156  
4153 4157          dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
4154 4158              (prop_val != NULL ? 0 : DLD_PROP_DEFAULT), &status);
4155 4159          if (dip == NULL)
4156 4160                  return (status);
4157 4161  
4158 4162          dp = (uchar_t *)dip->pr_val;
4159 4163          slen = 0;
4160 4164  
4161 4165          if (prop_val == NULL) {
4162 4166                  status = i_dladm_macprop(handle, dip, B_FALSE);
4163 4167                  dip->pr_flags = 0;
4164 4168          } else {
4165 4169                  for (i = 0; i < val_cnt; i++) {
4166 4170                          int plen = 0;
4167 4171  
4168 4172                          plen = strlen(prop_val[i]);
4169 4173                          bcopy(prop_val[i], dp, plen);
4170 4174                          slen += plen;
4171 4175                          /*
4172 4176                           * add a "," separator and update dp.
4173 4177                           */
4174 4178                          if (i != (val_cnt -1))
4175 4179                                  dp[slen++] = ',';
4176 4180                          dp += (plen + 1);
4177 4181                  }
4178 4182          }
4179 4183          if (status == DLADM_STATUS_OK)
4180 4184                  status = i_dladm_macprop(handle, dip, B_TRUE);
4181 4185  
4182 4186          free(dip);
4183 4187          return (status);
4184 4188  }
4185 4189  
4186 4190  static dladm_status_t
4187 4191  i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
4188 4192      const char *prop_name, char **prop_val, uint_t *val_cnt,
4189 4193      dladm_prop_type_t type, uint_t dld_flags)
4190 4194  {
4191 4195          dladm_status_t  status = DLADM_STATUS_OK;
4192 4196          dld_ioc_macprop_t *dip = NULL;
4193 4197          link_attr_t *p;
4194 4198  
4195 4199          if ((prop_name == NULL && prop_val != NULL) ||
4196 4200              (prop_val != NULL && val_cnt == 0))
4197 4201                  return (DLADM_STATUS_BADARG);
4198 4202  
4199 4203          p = dladm_name2prop(prop_name);
4200 4204          if (p->pp_id != MAC_PROP_PRIVATE)
4201 4205                  return (DLADM_STATUS_BADARG);
4202 4206  
4203 4207          /*
4204 4208           * private properties: all parsing is done in the kernel.
4205 4209           */
4206 4210          dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
4207 4211              dld_flags, &status);
4208 4212          if (dip == NULL)
4209 4213                  return (status);
4210 4214  
4211 4215          if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
4212 4216              DLADM_STATUS_OK) {
4213 4217                  if (type == DLADM_PROP_VAL_PERM) {
4214 4218                          (void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
4215 4219                  } else if (type == DLADM_PROP_VAL_MODIFIABLE) {
4216 4220                          *prop_val[0] = '\0';
4217 4221                  } else {
4218 4222                          (void) strncpy(*prop_val, dip->pr_val,
4219 4223                              DLADM_PROP_VAL_MAX);
4220 4224                  }
4221 4225                  *val_cnt = 1;
4222 4226          } else if ((status == DLADM_STATUS_NOTSUP) &&
4223 4227              (type == DLADM_PROP_VAL_CURRENT)) {
4224 4228                  status = DLADM_STATUS_NOTFOUND;
4225 4229          }
4226 4230          free(dip);
4227 4231          return (status);
4228 4232  }
4229 4233  
4230 4234  
4231 4235  static dladm_status_t
4232 4236  i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
4233 4237      datalink_id_t linkid, datalink_media_t media, uint_t flags)
4234 4238  {
4235 4239          dladm_status_t status;
4236 4240          char **prop_vals = NULL, *buf;
4237 4241          size_t bufsize;
4238 4242          uint_t cnt;
4239 4243          int i;
4240 4244          uint_t perm_flags;
4241 4245  
4242 4246          /*
4243 4247           * Allocate buffer needed for prop_vals array. We can have at most
4244 4248           * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
4245 4249           * each entry has max size DLADM_PROP_VAL_MAX
4246 4250           */
4247 4251          bufsize =
4248 4252              (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
4249 4253          buf = malloc(bufsize);
4250 4254          prop_vals = (char **)(void *)buf;
4251 4255          for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
4252 4256                  prop_vals[i] = buf +
4253 4257                      sizeof (char *) * DLADM_MAX_PROP_VALCNT +
4254 4258                      i * DLADM_PROP_VAL_MAX;
4255 4259          }
4256 4260  
4257 4261          /*
4258 4262           * For properties which have pdp->pd_defval.vd_name as a non-empty
4259 4263           * string, the "" itself is used to reset the property (exceptions
4260 4264           * are zone and autopush, which populate vdp->vd_val). So
4261 4265           * libdladm can copy pdp->pd_defval over to the val_desc_t passed
4262 4266           * down on the setprop using the global values in the table. For
4263 4267           * other cases (vd_name is ""), doing reset-linkprop will cause
4264 4268           * libdladm to do a getprop to find the default value and then do
4265 4269           * a setprop to reset the value to default.
4266 4270           */
4267 4271          status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
4268 4272              DLD_PROP_DEFAULT, &perm_flags);
4269 4273          if (status == DLADM_STATUS_OK) {
4270 4274                  if (perm_flags == MAC_PROP_PERM_RW) {
4271 4275                          status = i_dladm_set_single_prop(handle, linkid,
4272 4276                              pdp->pd_class, media, pdp, prop_vals, cnt, flags);
4273 4277                  }
4274 4278                  else
4275 4279                          status = DLADM_STATUS_NOTSUP;
4276 4280          }
4277 4281          free(buf);
4278 4282          return (status);
4279 4283  }
4280 4284  
4281 4285  /* ARGSUSED */
4282 4286  static dladm_status_t
4283 4287  get_stp(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
4284 4288      char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
4285 4289      uint_t *perm_flags)
4286 4290  {
4287 4291          const bridge_public_prop_t *bpp;
4288 4292          dladm_status_t retv;
4289 4293          int val, i;
4290 4294  
4291 4295          if (flags != 0)
4292 4296                  return (DLADM_STATUS_NOTSUP);
4293 4297          *perm_flags = MAC_PROP_PERM_RW;
4294 4298          *val_cnt = 1;
4295 4299          for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
4296 4300                  if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
4297 4301                          break;
4298 4302          retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
4299 4303          /* If the daemon isn't running, then return the persistent value */
4300 4304          if (retv == DLADM_STATUS_NOTFOUND) {
4301 4305                  if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
4302 4306                      prop_val, val_cnt) != DLADM_STATUS_OK)
4303 4307                          (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4304 4308                              DLADM_PROP_VAL_MAX);
4305 4309                  return (DLADM_STATUS_OK);
4306 4310          }
4307 4311          if (retv != DLADM_STATUS_OK) {
4308 4312                  (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4309 4313                  return (retv);
4310 4314          }
4311 4315          if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
4312 4316                  (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4313 4317                      DLADM_PROP_VAL_MAX);
4314 4318                  return (DLADM_STATUS_OK);
4315 4319          }
4316 4320          for (i = 0; i < pd->pd_noptval; i++) {
4317 4321                  if (val == pd->pd_optval[i].vd_val) {
4318 4322                          (void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
4319 4323                              DLADM_PROP_VAL_MAX);
4320 4324                          return (DLADM_STATUS_OK);
4321 4325                  }
4322 4326          }
4323 4327          (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
4324 4328          return (DLADM_STATUS_OK);
4325 4329  }
4326 4330  
4327 4331  /* ARGSUSED1 */
4328 4332  static dladm_status_t
4329 4333  set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4330 4334      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4331 4335  {
4332 4336          /*
4333 4337           * Special case for mcheck: the daemon resets the value to zero, and we
4334 4338           * don't want the daemon to refresh itself; it leads to deadlock.
4335 4339           */
4336 4340          if (flags & DLADM_OPT_NOREFRESH)
4337 4341                  return (DLADM_STATUS_OK);
4338 4342  
4339 4343          /* Tell the running daemon, if any */
4340 4344          return (dladm_bridge_refresh(handle, linkid));
4341 4345  }
4342 4346  
4343 4347  /*
4344 4348   * This is used only for stp_priority, stp_cost, and stp_mcheck.
4345 4349   */
4346 4350  /* ARGSUSED */
4347 4351  static dladm_status_t
4348 4352  check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
4349 4353      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
4350 4354      val_desc_t **vdpp, datalink_media_t media)
4351 4355  {
4352 4356          char            *cp;
4353 4357          boolean_t       iscost;
4354 4358          uint_t          val_cnt = *val_cntp;
4355 4359          val_desc_t      *vdp = *vdpp;
4356 4360  
4357 4361          if (val_cnt != 1)
4358 4362                  return (DLADM_STATUS_BADVALCNT);
4359 4363  
4360 4364          if (prop_val == NULL) {
4361 4365                  vdp->vd_val = 0;
4362 4366          } else {
4363 4367                  /* Only stp_priority and stp_cost use this function */
4364 4368                  iscost = strcmp(pd->pd_name, "stp_cost") == 0;
4365 4369  
4366 4370                  if (iscost && strcmp(prop_val[0], "auto") == 0) {
4367 4371                          /* Illegal value 0 is allowed to mean "automatic" */
4368 4372                          vdp->vd_val = 0;
4369 4373                  } else {
4370 4374                          errno = 0;
4371 4375                          vdp->vd_val = strtoul(prop_val[0], &cp, 0);
4372 4376                          if (errno != 0 || *cp != '\0')
4373 4377                                  return (DLADM_STATUS_BADVAL);
4374 4378                  }
4375 4379          }
4376 4380  
4377 4381          if (iscost) {
4378 4382                  return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
4379 4383                      DLADM_STATUS_OK);
4380 4384          } else {
4381 4385                  if (vdp->vd_val > 255)
4382 4386                          return (DLADM_STATUS_BADVAL);
4383 4387                  /*
4384 4388                   * If the user is setting stp_mcheck non-zero, then (per the
4385 4389                   * IEEE management standards and UNH testing) we need to check
4386 4390                   * whether this link is part of a bridge that is running RSTP.
4387 4391                   * If it's not, then setting the flag is an error.  Note that
4388 4392                   * errors are intentionally discarded here; it's the value
4389 4393                   * that's the problem -- it's not a bad value, merely one that
4390 4394                   * can't be used now.
4391 4395                   */
4392 4396                  if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
4393 4397                      vdp->vd_val != 0) {
4394 4398                          char bridge[MAXLINKNAMELEN];
4395 4399                          UID_STP_CFG_T cfg;
4396 4400                          dladm_bridge_prot_t brprot;
4397 4401  
4398 4402                          if (dladm_bridge_getlink(handle, linkid, bridge,
4399 4403                              sizeof (bridge)) != DLADM_STATUS_OK ||
4400 4404                              dladm_bridge_get_properties(bridge, &cfg,
4401 4405                              &brprot) != DLADM_STATUS_OK)
4402 4406                                  return (DLADM_STATUS_FAILED);
4403 4407                          if (cfg.force_version <= 1)
4404 4408                                  return (DLADM_STATUS_FAILED);
4405 4409                  }
4406 4410                  return (DLADM_STATUS_OK);
4407 4411          }
4408 4412  }
4409 4413  
4410 4414  /* ARGSUSED */
4411 4415  static dladm_status_t
4412 4416  get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
4413 4417      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4414 4418      datalink_media_t media, uint_t flags, uint_t *perm_flags)
4415 4419  {
4416 4420          dladm_status_t retv;
4417 4421          uint_t val;
4418 4422  
4419 4423          if (flags != 0)
4420 4424                  return (DLADM_STATUS_NOTSUP);
4421 4425          *perm_flags = MAC_PROP_PERM_RW;
4422 4426          *val_cnt = 1;
4423 4427          retv = dladm_bridge_get_forwarding(handle, linkid, &val);
4424 4428          if (retv == DLADM_STATUS_NOTFOUND) {
4425 4429                  if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
4426 4430                      prop_val, val_cnt) != DLADM_STATUS_OK)
4427 4431                          (void) strlcpy(*prop_val, pd->pd_defval.vd_name,
4428 4432                              DLADM_PROP_VAL_MAX);
4429 4433                  return (DLADM_STATUS_OK);
4430 4434          }
4431 4435          if (retv == DLADM_STATUS_OK)
4432 4436                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
4433 4437          else
4434 4438                  (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4435 4439          return (retv);
4436 4440  }
4437 4441  
4438 4442  /* ARGSUSED */
4439 4443  static dladm_status_t
4440 4444  set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4441 4445      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4442 4446  {
4443 4447          /* Tell the running daemon, if any */
4444 4448          return (dladm_bridge_refresh(handle, linkid));
4445 4449  }
4446 4450  
4447 4451  /* ARGSUSED */
4448 4452  static dladm_status_t
4449 4453  get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
4450 4454      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4451 4455      datalink_media_t media, uint_t flags, uint_t *perm_flags)
4452 4456  {
4453 4457          dladm_status_t status;
4454 4458          dld_ioc_macprop_t *dip;
4455 4459          uint16_t pvid;
4456 4460  
4457 4461          if (flags != 0)
4458 4462                  return (DLADM_STATUS_NOTSUP);
4459 4463          *perm_flags = MAC_PROP_PERM_RW;
4460 4464          *val_cnt = 1;
4461 4465          dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
4462 4466              0, &status);
4463 4467          if (dip == NULL)
4464 4468                  return (status);
4465 4469          status = i_dladm_macprop(handle, dip, B_FALSE);
4466 4470          if (status == DLADM_STATUS_OK) {
4467 4471                  (void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
4468 4472                  (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
4469 4473          } else {
4470 4474                  (void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
4471 4475          }
4472 4476          free(dip);
4473 4477          return (status);
4474 4478  }
4475 4479  
4476 4480  /* ARGSUSED */
4477 4481  static dladm_status_t
4478 4482  set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
4479 4483      val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
4480 4484  {
4481 4485          dladm_status_t status;
4482 4486          dld_ioc_macprop_t *dip;
4483 4487          uint16_t pvid;
4484 4488  
4485 4489          dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
4486 4490              0, &status);
4487 4491          if (dip == NULL)
4488 4492                  return (status);
4489 4493          pvid = vdp->vd_val;
4490 4494          (void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
4491 4495          status = i_dladm_macprop(handle, dip, B_TRUE);
4492 4496          free(dip);
4493 4497          if (status != DLADM_STATUS_OK)
4494 4498                  return (status);
4495 4499  
4496 4500          /* Tell the running daemon, if any */
4497 4501          return (dladm_bridge_refresh(handle, linkid));
4498 4502  }
4499 4503  
4500 4504  /* ARGSUSED */
4501 4505  static dladm_status_t
4502 4506  check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
4503 4507      datalink_id_t linkid, char **prop_val, uint_t *val_cntp, uint_t flags,
4504 4508      val_desc_t **vdpp, datalink_media_t media)
4505 4509  {
4506 4510          char            *cp;
4507 4511          uint_t          val_cnt = *val_cntp;
4508 4512          val_desc_t      *vdp = *vdpp;
4509 4513  
4510 4514          if (val_cnt != 1)
4511 4515                  return (DLADM_STATUS_BADVALCNT);
4512 4516  
4513 4517          if (prop_val == NULL) {
4514 4518                  vdp->vd_val = 1;
4515 4519          } else {
4516 4520                  errno = 0;
4517 4521                  vdp->vd_val = strtoul(prop_val[0], &cp, 0);
4518 4522                  if (errno != 0 || *cp != '\0')
4519 4523                          return (DLADM_STATUS_BADVAL);
4520 4524          }
4521 4525  
4522 4526          return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
4523 4527              DLADM_STATUS_OK);
4524 4528  }
4525 4529  
4526 4530  dladm_status_t
4527 4531  i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
4528 4532      mac_prop_id_t cmd, size_t len, boolean_t set)
4529 4533  {
4530 4534          uint32_t                flags;
4531 4535          dladm_status_t          status;
4532 4536          uint32_t                media;
4533 4537          dld_ioc_macprop_t       *dip;
4534 4538          void                    *dp;
4535 4539  
4536 4540          if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
4537 4541              &media, NULL, 0)) != DLADM_STATUS_OK) {
4538 4542                  return (status);
4539 4543          }
4540 4544  
4541 4545          if (media != DL_WIFI)
4542 4546                  return (DLADM_STATUS_BADARG);
4543 4547  
4544 4548          if (!(flags & DLADM_OPT_ACTIVE))
4545 4549                  return (DLADM_STATUS_TEMPONLY);
4546 4550  
4547 4551          if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
4548 4552                  len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
4549 4553  
4550 4554          dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
4551 4555          if (dip == NULL)
4552 4556                  return (DLADM_STATUS_NOMEM);
4553 4557  
4554 4558          dp = (uchar_t *)dip->pr_val;
4555 4559          if (set)
4556 4560                  (void) memcpy(dp, buf, len);
4557 4561  
4558 4562          status = i_dladm_macprop(handle, dip, set);
4559 4563          if (status == DLADM_STATUS_OK) {
4560 4564                  if (!set)
4561 4565                          (void) memcpy(buf, dp, len);
4562 4566          }
4563 4567  
4564 4568          free(dip);
4565 4569          return (status);
4566 4570  }
4567 4571  
4568 4572  dladm_status_t
4569 4573  dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
4570 4574  {
4571 4575          return (dladm_parse_args(str, listp, novalues));
4572 4576  }
4573 4577  
4574 4578  /*
4575 4579   * Retrieve the one link property from the database
4576 4580   */
4577 4581  /*ARGSUSED*/
4578 4582  static int
4579 4583  i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
4580 4584      const char *prop_name, void *arg)
4581 4585  {
4582 4586          dladm_arg_list_t        *proplist = arg;
4583 4587          dladm_arg_info_t        *aip = NULL;
4584 4588  
4585 4589          aip = &proplist->al_info[proplist->al_count];
4586 4590          /*
4587 4591           * it is fine to point to prop_name since prop_name points to the
4588 4592           * prop_table[n].pd_name.
4589 4593           */
4590 4594          aip->ai_name = prop_name;
4591 4595  
4592 4596          (void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
4593 4597              prop_name, aip->ai_val, &aip->ai_count);
4594 4598  
4595 4599          if (aip->ai_count != 0)
4596 4600                  proplist->al_count++;
4597 4601  
4598 4602          return (DLADM_WALK_CONTINUE);
4599 4603  }
4600 4604  
4601 4605  
4602 4606  /*
4603 4607   * Retrieve all link properties for a link from the database and
4604 4608   * return a property list.
4605 4609   */
4606 4610  dladm_status_t
4607 4611  dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
4608 4612      dladm_arg_list_t **listp)
4609 4613  {
4610 4614          dladm_arg_list_t        *list;
4611 4615          dladm_status_t          status = DLADM_STATUS_OK;
4612 4616  
4613 4617          list = calloc(1, sizeof (dladm_arg_list_t));
4614 4618          if (list == NULL)
4615 4619                  return (dladm_errno2status(errno));
4616 4620  
4617 4621          status = dladm_walk_linkprop(handle, linkid, list,
4618 4622              i_dladm_get_one_prop);
4619 4623  
4620 4624          *listp = list;
4621 4625          return (status);
4622 4626  }
4623 4627  
4624 4628  /*
4625 4629   * Retrieve the named property from a proplist, check the value and
4626 4630   * convert to a kernel structure.
4627 4631   */
4628 4632  static dladm_status_t
4629 4633  i_dladm_link_proplist_extract_one(dladm_handle_t handle,
4630 4634      dladm_arg_list_t *proplist, const char *name, uint_t flags, void *arg)
4631 4635  {
4632 4636          dladm_status_t          status;
4633 4637          dladm_arg_info_t        *aip = NULL;
4634 4638          int                     i, j;
4635 4639  
4636 4640          /* Find named property in proplist */
4637 4641          for (i = 0; i < proplist->al_count; i++) {
4638 4642                  aip = &proplist->al_info[i];
4639 4643                  if (strcasecmp(aip->ai_name, name) == 0)
4640 4644                          break;
4641 4645          }
4642 4646  
4643 4647          /* Property not in list */
4644 4648          if (i == proplist->al_count)
4645 4649                  return (DLADM_STATUS_OK);
4646 4650  
4647 4651          for (i = 0; i < DLADM_MAX_PROPS; i++) {
4648 4652                  prop_desc_t     *pdp = &prop_table[i];
4649 4653                  val_desc_t      *vdp;
4650 4654  
4651 4655                  vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
4652 4656                  if (vdp == NULL)
4653 4657                          return (DLADM_STATUS_NOMEM);
4654 4658  
4655 4659                  if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
4656 4660                          continue;
4657 4661  
4658 4662                  if (aip->ai_val == NULL)
4659 4663                          return (DLADM_STATUS_BADARG);
4660 4664  
4661 4665                  /* Check property value */
4662 4666                  if (pdp->pd_check != NULL) {
4663 4667                          status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
4664 4668                              &(aip->ai_count), flags, &vdp, 0);
4665 4669                  } else {
4666 4670                          status = DLADM_STATUS_BADARG;
4667 4671                  }
4668 4672  
4669 4673                  if (status != DLADM_STATUS_OK)
4670 4674                          return (status);
4671 4675  
4672 4676                  for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
4673 4677                          resource_prop_t *rpp = &rsrc_prop_table[j];
4674 4678  
4675 4679                          if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
4676 4680                                  continue;
4677 4681  
4678 4682                          /* Extract kernel structure */
4679 4683                          if (rpp->rp_extract != NULL) {
4680 4684                                  status = rpp->rp_extract(vdp,
4681 4685                                      aip->ai_count, arg);
4682 4686                          } else {
4683 4687                                  status = DLADM_STATUS_BADARG;
4684 4688                          }
4685 4689                          break;
4686 4690                  }
4687 4691  
4688 4692                  if (status != DLADM_STATUS_OK)
4689 4693                          return (status);
4690 4694  
4691 4695                  break;
4692 4696          }
4693 4697          return (status);
4694 4698  }
4695 4699  
4696 4700  /*
4697 4701   * Extract properties from a proplist and convert to mac_resource_props_t.
4698 4702   */
4699 4703  dladm_status_t
4700 4704  dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
4701 4705      mac_resource_props_t *mrp, uint_t flags)
4702 4706  {
4703 4707          dladm_status_t  status;
4704 4708          int             i;
4705 4709  
4706 4710          for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
4707 4711                  status = i_dladm_link_proplist_extract_one(handle,
4708 4712                      proplist, rsrc_prop_table[i].rp_name, flags, mrp);
4709 4713                  if (status != DLADM_STATUS_OK)
4710 4714                          return (status);
4711 4715          }
4712 4716          return (status);
4713 4717  }
4714 4718  
4715 4719  static const char *
4716 4720  dladm_perm2str(uint_t perm, char *buf)
4717 4721  {
4718 4722          (void) snprintf(buf, DLADM_STRSIZE, "%c%c",
4719 4723              ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
4720 4724              ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
4721 4725          return (buf);
4722 4726  }
4723 4727  
4724 4728  dladm_status_t
4725 4729  dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
4726 4730      link_state_t *state)
4727 4731  {
4728 4732          uint_t                  perms;
4729 4733  
4730 4734          return (i_dladm_get_public_prop(handle, linkid, "state", 0,
4731 4735              &perms, state, sizeof (*state)));
4732 4736  }
4733 4737  
4734 4738  boolean_t
4735 4739  dladm_attr_is_linkprop(const char *name)
4736 4740  {
4737 4741          /* non-property attribute names */
4738 4742          const char *nonprop[] = {
4739 4743                  /* dlmgmtd core attributes */
4740 4744                  "name",
4741 4745                  "class",
4742 4746                  "media",
4743 4747                  FPHYMAJ,
4744 4748                  FPHYINST,
4745 4749                  FDEVNAME,
4746 4750  
4747 4751                  /* other attributes for vlan, aggr, etc */
4748 4752                  DLADM_ATTR_NAMES
4749 4753          };
4750 4754          boolean_t       is_nonprop = B_FALSE;
4751 4755          int             i;
4752 4756  
4753 4757          for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
4754 4758                  if (strcmp(name, nonprop[i]) == 0) {
4755 4759                          is_nonprop = B_TRUE;
4756 4760                          break;
4757 4761                  }
4758 4762          }
4759 4763  
4760 4764          return (!is_nonprop);
4761 4765  }
4762 4766  
4763 4767  dladm_status_t
4764 4768  dladm_linkprop_is_set(dladm_handle_t handle, datalink_id_t linkid,
4765 4769      dladm_prop_type_t type, const char *prop_name, boolean_t *is_set)
4766 4770  {
4767 4771          char            *buf, **propvals;
4768 4772          uint_t          valcnt = DLADM_MAX_PROP_VALCNT;
4769 4773          int             i;
4770 4774          dladm_status_t  status = DLADM_STATUS_OK;
4771 4775          size_t          bufsize;
4772 4776  
4773 4777          *is_set = B_FALSE;
4774 4778  
4775 4779          bufsize = (sizeof (char *) + DLADM_PROP_VAL_MAX) *
4776 4780              DLADM_MAX_PROP_VALCNT;
4777 4781          if ((buf = calloc(1, bufsize)) == NULL)
4778 4782                  return (DLADM_STATUS_NOMEM);
4779 4783  
4780 4784          propvals = (char **)(void *)buf;
4781 4785          for (i = 0; i < valcnt; i++) {
4782 4786                  propvals[i] = buf +
4783 4787                      sizeof (char *) * DLADM_MAX_PROP_VALCNT +
4784 4788                      i * DLADM_PROP_VAL_MAX;
4785 4789          }
4786 4790  
4787 4791          if (dladm_get_linkprop(handle, linkid, type, prop_name, propvals,
4788 4792              &valcnt) != DLADM_STATUS_OK) {
4789 4793                  goto done;
4790 4794          }
4791 4795  
4792 4796          /*
4793 4797           * valcnt is always set to 1 by get_pool(), hence we need to check
4794 4798           * for a non-null string to see if it is set. For protection,
4795 4799           * secondary-macs and allowed-ips, we can check either the *propval
4796 4800           * or the valcnt.
4797 4801           */
4798 4802          if ((strcmp(prop_name, "pool") == 0 ||
4799 4803              strcmp(prop_name, "protection") == 0 ||
4800 4804              strcmp(prop_name, "secondary-macs") == 0 ||
4801 4805              strcmp(prop_name, "allowed-ips") == 0) &&
4802 4806              (strlen(*propvals) != 0)) {
4803 4807                  *is_set = B_TRUE;
4804 4808          } else if ((strcmp(prop_name, "cpus") == 0) && (valcnt != 0)) {
4805 4809                  *is_set = B_TRUE;
4806 4810          } else if ((strcmp(prop_name, "_softmac") == 0) && (valcnt != 0) &&
4807 4811              (strcmp(propvals[0], "true") == 0)) {
4808 4812                  *is_set = B_TRUE;
4809 4813          }
4810 4814  
4811 4815  done:
4812 4816          if (buf != NULL)
4813 4817                  free(buf);
4814 4818          return (status);
4815 4819  }
4816 4820  
4817 4821  /* ARGSUSED */
4818 4822  static dladm_status_t
4819 4823  get_linkmode_prop(dladm_handle_t handle, prop_desc_t *pdp,
4820 4824      datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4821 4825      datalink_media_t media, uint_t flags, uint_t *perm_flags)
4822 4826  {
4823 4827          char                    *s;
4824 4828          uint32_t                v;
4825 4829          dladm_status_t          status;
4826 4830  
4827 4831          status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4828 4832              perm_flags, &v, sizeof (v));
4829 4833          if (status != DLADM_STATUS_OK)
4830 4834                  return (status);
4831 4835  
4832 4836          switch (v) {
4833 4837          case DLADM_PART_CM_MODE:
4834 4838                  s = "cm";
4835 4839                  break;
4836 4840          case DLADM_PART_UD_MODE:
  
    | 
      ↓ open down ↓ | 
    3220 lines elided | 
    
      ↑ open up ↑ | 
  
4837 4841                  s = "ud";
4838 4842                  break;
4839 4843          default:
4840 4844                  s = "";
4841 4845                  break;
4842 4846          }
4843 4847          (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s);
4844 4848  
4845 4849          *val_cnt = 1;
4846 4850          return (DLADM_STATUS_OK);
4847      -}
4848      -
4849      -/*ARGSUSED*/
4850      -static dladm_status_t
4851      -get_promisc_filtered(dladm_handle_t handle, prop_desc_t *pdp,
4852      -    datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
4853      -    datalink_media_t media, uint_t flags, uint_t *perm_flags)
4854      -{
4855      -        char                    *s;
4856      -        dladm_status_t          status;
4857      -        boolean_t               filt;
4858      -
4859      -        status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
4860      -            perm_flags, &filt, sizeof (filt));
4861      -        if (status != DLADM_STATUS_OK)
4862      -                return (status);
4863      -
4864      -        if (filt != 0)
4865      -                s = link_promisc_filtered_vals[1].vd_name;
4866      -        else
4867      -                s = link_promisc_filtered_vals[0].vd_name;
4868      -        (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s);
4869      -
4870      -        *val_cnt = 1;
4871      -        return (DLADM_STATUS_OK);
4872      -}
4873      -
4874      -/* ARGSUSED */
4875      -static dladm_status_t
4876      -set_promisc_filtered(dladm_handle_t handle, prop_desc_t *pdp,
4877      -    datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
4878      -    datalink_media_t media)
4879      -{
4880      -        dld_ioc_macprop_t       *dip;
4881      -        dladm_status_t          status = DLADM_STATUS_OK;
4882      -
4883      -        dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
4884      -            0, &status);
4885      -
4886      -        if (dip == NULL)
4887      -                return (status);
4888      -
4889      -        (void) memcpy(dip->pr_val, &vdp->vd_val, dip->pr_valsize);
4890      -        status = i_dladm_macprop(handle, dip, B_TRUE);
4891      -
4892      -        free(dip);
4893      -        return (status);
4894 4851  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX