10ba2cbe9Sxc151355 /* 20ba2cbe9Sxc151355 * CDDL HEADER START 30ba2cbe9Sxc151355 * 40ba2cbe9Sxc151355 * The contents of this file are subject to the terms of the 50ba2cbe9Sxc151355 * Common Development and Distribution License (the "License"). 60ba2cbe9Sxc151355 * You may not use this file except in compliance with the License. 70ba2cbe9Sxc151355 * 80ba2cbe9Sxc151355 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90ba2cbe9Sxc151355 * or http://www.opensolaris.org/os/licensing. 100ba2cbe9Sxc151355 * See the License for the specific language governing permissions 110ba2cbe9Sxc151355 * and limitations under the License. 120ba2cbe9Sxc151355 * 130ba2cbe9Sxc151355 * When distributing Covered Code, include this CDDL HEADER in each 140ba2cbe9Sxc151355 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150ba2cbe9Sxc151355 * If applicable, add the following below this CDDL HEADER, with the 160ba2cbe9Sxc151355 * fields enclosed by brackets "[]" replaced with your own identifying 170ba2cbe9Sxc151355 * information: Portions Copyright [yyyy] [name of copyright owner] 180ba2cbe9Sxc151355 * 190ba2cbe9Sxc151355 * CDDL HEADER END 200ba2cbe9Sxc151355 */ 210ba2cbe9Sxc151355 /* 22d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230ba2cbe9Sxc151355 * Use is subject to license terms. 240ba2cbe9Sxc151355 */ 250ba2cbe9Sxc151355 260ba2cbe9Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 270ba2cbe9Sxc151355 280ba2cbe9Sxc151355 #include <stdlib.h> 290ba2cbe9Sxc151355 #include <strings.h> 300ba2cbe9Sxc151355 #include <errno.h> 310ba2cbe9Sxc151355 #include <ctype.h> 32d62bc4baSyz147064 #include <stddef.h> 33f4b3ec61Sdh155122 #include <sys/types.h> 340ba2cbe9Sxc151355 #include <sys/stat.h> 35f4b3ec61Sdh155122 #include <sys/dld.h> 36f4b3ec61Sdh155122 #include <sys/zone.h> 37f4b3ec61Sdh155122 #include <fcntl.h> 38f4b3ec61Sdh155122 #include <unistd.h> 39f4b3ec61Sdh155122 #include <libdevinfo.h> 40f4b3ec61Sdh155122 #include <zone.h> 41f595a68aSyz147064 #include <libdllink.h> 420ba2cbe9Sxc151355 #include <libdladm_impl.h> 43d62bc4baSyz147064 #include <libdlwlan_impl.h> 44f595a68aSyz147064 #include <libdlwlan.h> 45d62bc4baSyz147064 #include <libdlvlan.h> 46f4b3ec61Sdh155122 #include <dlfcn.h> 47f4b3ec61Sdh155122 #include <link.h> 48d62bc4baSyz147064 #include <inet/wifi_ioctl.h> 49e7801d59Ssowmini #include <libdladm.h> 50e7801d59Ssowmini #include <sys/param.h> 51e7801d59Ssowmini #include <sys/dld.h> 52e7801d59Ssowmini #include <inttypes.h> 53e7801d59Ssowmini #include <sys/ethernet.h> 54f4b3ec61Sdh155122 55d62bc4baSyz147064 /* 56d62bc4baSyz147064 * The linkprop get() callback. 57e7801d59Ssowmini * - pd: pointer to the struct prop_desc 58d62bc4baSyz147064 * - propstrp: a property string array to keep the returned property. 59d62bc4baSyz147064 * Caller allocated. 60d62bc4baSyz147064 * - cntp: number of returned properties. 61d62bc4baSyz147064 * Caller also uses it to indicate how many it expects. 62d62bc4baSyz147064 */ 63e7801d59Ssowmini struct prop_desc; 64e7801d59Ssowmini 65e7801d59Ssowmini typedef dladm_status_t pd_getf_t(struct prop_desc *pd, 666b9e797cSsowmini datalink_id_t, char **propstp, uint_t *cntp, 674045d941Ssowmini datalink_media_t, uint_t); 68f4b3ec61Sdh155122 69d62bc4baSyz147064 /* 70d62bc4baSyz147064 * The linkprop set() callback. 71d62bc4baSyz147064 * - propval: a val_desc_t array which keeps the property values to be set. 72d62bc4baSyz147064 * - cnt: number of properties to be set. 73e7801d59Ssowmini * - flags: additional flags passed down the system call. 74e7801d59Ssowmini * 75e7801d59Ssowmini * pd_set takes val_desc_t given by pd_check(), translates it into 76e7801d59Ssowmini * a format suitable for kernel consumption. This may require allocation 77e7801d59Ssowmini * of ioctl buffers etc. pd_set() may call another common routine (used 78e7801d59Ssowmini * by all other pd_sets) which invokes the ioctl. 79d62bc4baSyz147064 */ 80e7801d59Ssowmini typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t, 816b9e797cSsowmini val_desc_t *propval, uint_t cnt, uint_t flags, 826b9e797cSsowmini datalink_media_t); 83f4b3ec61Sdh155122 84f4b3ec61Sdh155122 85d62bc4baSyz147064 /* 86d62bc4baSyz147064 * The linkprop check() callback. 87d62bc4baSyz147064 * - propstrp: property string array which keeps the property to be checked. 88d62bc4baSyz147064 * - cnt: number of properties. 89d62bc4baSyz147064 * - propval: return value; the property values of the given property strings. 90e7801d59Ssowmini * 91e7801d59Ssowmini * pd_check checks that the input values are valid. It does so by 92e7801d59Ssowmini * iteraring through the pd_modval list for the property. If 93e7801d59Ssowmini * the modifiable values cannot be expressed as a list, a pd_check 94e7801d59Ssowmini * specific to this property can be used. If the input values are 95e7801d59Ssowmini * verified to be valid, pd_check allocates a val_desc_t and fills it 96e7801d59Ssowmini * with either a val_desc_t found on the pd_modval list or something 97e7801d59Ssowmini * generated on the fly. 98d62bc4baSyz147064 */ 99e7801d59Ssowmini typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, 100e7801d59Ssowmini datalink_id_t, char **propstrp, 1016b9e797cSsowmini uint_t cnt, val_desc_t *propval, 1026b9e797cSsowmini datalink_media_t); 103f4b3ec61Sdh155122 104e7801d59Ssowmini typedef struct dld_public_prop_s { 1053fd94f8cSam223141 mac_prop_id_t pp_id; 106e7801d59Ssowmini size_t pp_valsize; 107e7801d59Ssowmini char *pp_name; 108e7801d59Ssowmini char *pp_desc; 109e7801d59Ssowmini } dld_public_prop_t; 110e7801d59Ssowmini 1113fd94f8cSam223141 static dld_ioc_macprop_t *dld_buf_alloc(size_t, datalink_id_t, const char *, 1124045d941Ssowmini uint_t, dladm_status_t *); 113e7801d59Ssowmini static dladm_status_t dld_set_prop(datalink_id_t, const char *, char **, 114e7801d59Ssowmini uint_t, uint_t); 115e7801d59Ssowmini static dladm_status_t dld_get_prop(datalink_id_t, const char *, char **, 1164045d941Ssowmini uint_t *, dladm_prop_type_t, uint_t); 117d62bc4baSyz147064 static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, 118d62bc4baSyz147064 do_get_rate_prop, do_get_channel_prop, 119e7801d59Ssowmini do_get_powermode_prop, do_get_radio_prop, 1206b9e797cSsowmini dld_duplex_get, dld_status_get, 1214045d941Ssowmini dld_binary_get, dld_uint32_get, dld_flowctl_get; 122d62bc4baSyz147064 static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop, 123e7801d59Ssowmini do_set_powermode_prop, do_set_radio_prop, 124e7801d59Ssowmini dld_set_public_prop; 125e7801d59Ssowmini static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, 126e7801d59Ssowmini dld_defmtu_check; 127f4b3ec61Sdh155122 1286b9e797cSsowmini static dladm_status_t dld_speed_get(struct prop_desc *, datalink_id_t, 1294045d941Ssowmini char **, uint_t *, uint_t); 1306b9e797cSsowmini 131f4b3ec61Sdh155122 typedef struct prop_desc { 132d62bc4baSyz147064 /* 133d62bc4baSyz147064 * link property name 134d62bc4baSyz147064 */ 135f4b3ec61Sdh155122 char *pd_name; 136d62bc4baSyz147064 137d62bc4baSyz147064 /* 138d62bc4baSyz147064 * default property value, can be set to { "", NULL } 139d62bc4baSyz147064 */ 140f4b3ec61Sdh155122 val_desc_t pd_defval; 141d62bc4baSyz147064 142d62bc4baSyz147064 /* 143d62bc4baSyz147064 * list of optional property values, can be NULL. 144d62bc4baSyz147064 * 145d62bc4baSyz147064 * This is set to non-NULL if there is a list of possible property 146d62bc4baSyz147064 * values. pd_optval would point to the array of possible values. 147d62bc4baSyz147064 */ 148d62bc4baSyz147064 val_desc_t *pd_optval; 149d62bc4baSyz147064 150d62bc4baSyz147064 /* 151d62bc4baSyz147064 * count of the above optional property values. 0 if pd_optval is NULL. 152d62bc4baSyz147064 */ 153d62bc4baSyz147064 uint_t pd_noptval; 154d62bc4baSyz147064 155d62bc4baSyz147064 /* 156d62bc4baSyz147064 * callback to set link property; 157d62bc4baSyz147064 * set to NULL if this property is read-only 158d62bc4baSyz147064 */ 159f4b3ec61Sdh155122 pd_setf_t *pd_set; 160d62bc4baSyz147064 161d62bc4baSyz147064 /* 162d62bc4baSyz147064 * callback to get modifiable link property 163d62bc4baSyz147064 */ 164f4b3ec61Sdh155122 pd_getf_t *pd_getmod; 165d62bc4baSyz147064 166d62bc4baSyz147064 /* 167d62bc4baSyz147064 * callback to get current link property 168d62bc4baSyz147064 */ 169f4b3ec61Sdh155122 pd_getf_t *pd_get; 170d62bc4baSyz147064 171d62bc4baSyz147064 /* 172d62bc4baSyz147064 * callback to validate link property value, set to NULL if pd_optval 173d62bc4baSyz147064 * is not NULL. In that case, validate the value by comparing it with 174d62bc4baSyz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 175d62bc4baSyz147064 * valid. 176d62bc4baSyz147064 */ 177f4b3ec61Sdh155122 pd_checkf_t *pd_check; 178d62bc4baSyz147064 179d62bc4baSyz147064 uint_t pd_flags; 180e7801d59Ssowmini #define PD_TEMPONLY 0x1 /* property is temporary only */ 181e7801d59Ssowmini #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */ 1824045d941Ssowmini #define PD_EMPTY_RESET 0x4 /* Use "" to reset the link property */ 183d62bc4baSyz147064 /* 184d62bc4baSyz147064 * indicate link classes this property applies to. 185d62bc4baSyz147064 */ 186d62bc4baSyz147064 datalink_class_t pd_class; 187d62bc4baSyz147064 188d62bc4baSyz147064 /* 189d62bc4baSyz147064 * indicate link media type this property applies to. 190d62bc4baSyz147064 */ 191d62bc4baSyz147064 datalink_media_t pd_dmedia; 192f4b3ec61Sdh155122 } prop_desc_t; 193f4b3ec61Sdh155122 1943fd94f8cSam223141 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1 195e7801d59Ssowmini 196e7801d59Ssowmini 197e7801d59Ssowmini static dld_public_prop_t dld_prop[] = { 1983fd94f8cSam223141 { MAC_PROP_DUPLEX, sizeof (link_duplex_t), 1996b9e797cSsowmini "duplex", "link duplex mode" }, 200e7801d59Ssowmini 2013fd94f8cSam223141 {MAC_PROP_SPEED, sizeof (uint64_t), 2026b9e797cSsowmini "speed", "link speed (bps)" }, 203e7801d59Ssowmini 2043fd94f8cSam223141 { MAC_PROP_STATUS, sizeof (link_state_t), 2056b9e797cSsowmini "state", "link up/down" }, 206e7801d59Ssowmini 2073fd94f8cSam223141 { MAC_PROP_AUTONEG, sizeof (uint8_t), 208e7801d59Ssowmini "adv_autoneg_cap", "Advertised auto-negotiation" }, 209e7801d59Ssowmini 2103fd94f8cSam223141 { MAC_PROP_MTU, sizeof (uint32_t), 2116b9e797cSsowmini "mtu", "current link mtu" }, 212e7801d59Ssowmini 2133fd94f8cSam223141 { MAC_PROP_FLOWCTRL, sizeof (link_flowctrl_t), 214e7801d59Ssowmini "flowctrl", "flowcontrol" }, 215e7801d59Ssowmini 2163fd94f8cSam223141 { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), 217e7801d59Ssowmini "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, 218e7801d59Ssowmini 2193fd94f8cSam223141 { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), 220e7801d59Ssowmini "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, 221e7801d59Ssowmini 2223fd94f8cSam223141 { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), 223e7801d59Ssowmini "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, 224e7801d59Ssowmini 2253fd94f8cSam223141 { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), 226e7801d59Ssowmini "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, 227e7801d59Ssowmini 2283fd94f8cSam223141 { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), 229e7801d59Ssowmini "adv_100fdx_cap", "Adv 100 Mbps fdx" }, 230e7801d59Ssowmini 2313fd94f8cSam223141 { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), 232e7801d59Ssowmini "en_100fdx_cap", "Enable 100 Mbps fdx" }, 233e7801d59Ssowmini 2343fd94f8cSam223141 { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), 235e7801d59Ssowmini "adv_100hdx_cap", "Adv 100 Mbps hdx" }, 236e7801d59Ssowmini 2373fd94f8cSam223141 { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), 238e7801d59Ssowmini "en_100hdx_cap", "Enable 100 Mbps hdx" }, 239e7801d59Ssowmini 2403fd94f8cSam223141 { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), 241e7801d59Ssowmini "adv_10fdx_cap", "Adv 10 Mbps fdx" }, 242e7801d59Ssowmini 2433fd94f8cSam223141 { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), 244e7801d59Ssowmini "en_10fdx_cap", "Enable 10 Mbps fdx" }, 245e7801d59Ssowmini 2463fd94f8cSam223141 { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), 247e7801d59Ssowmini "adv_10hdx_cap", "Adv 10 Mbps hdx" }, 248e7801d59Ssowmini 2493fd94f8cSam223141 { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), 250e7801d59Ssowmini "en_10hdx_cap", "Enable 10 Mbps hdx" }, 251e7801d59Ssowmini 2523fd94f8cSam223141 { MAC_PROP_PRIVATE, 0, 253e7801d59Ssowmini "driver-private", "" } 254e7801d59Ssowmini }; 255e7801d59Ssowmini 256e7801d59Ssowmini static val_desc_t link_duplex_vals[] = { 257e7801d59Ssowmini { "half", LINK_DUPLEX_HALF }, 258e7801d59Ssowmini { "full", LINK_DUPLEX_HALF } 259e7801d59Ssowmini }; 260e7801d59Ssowmini static val_desc_t link_status_vals[] = { 261e7801d59Ssowmini { "up", LINK_STATE_UP }, 262e7801d59Ssowmini { "down", LINK_STATE_DOWN } 263e7801d59Ssowmini }; 264e7801d59Ssowmini static val_desc_t link_01_vals[] = { 265e7801d59Ssowmini { "1", 1 }, 266e7801d59Ssowmini { "0", 0 } 267e7801d59Ssowmini }; 268e7801d59Ssowmini static val_desc_t link_flow_vals[] = { 269e7801d59Ssowmini { "no", LINK_FLOWCTRL_NONE }, 270e7801d59Ssowmini { "tx", LINK_FLOWCTRL_TX }, 271e7801d59Ssowmini { "rx", LINK_FLOWCTRL_RX }, 272e7801d59Ssowmini { "bi", LINK_FLOWCTRL_BI } 273e7801d59Ssowmini }; 274e7801d59Ssowmini 275e7801d59Ssowmini #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) 276e7801d59Ssowmini 277d62bc4baSyz147064 static val_desc_t dladm_wlan_radio_vals[] = { 278d62bc4baSyz147064 { "on", DLADM_WLAN_RADIO_ON }, 279d62bc4baSyz147064 { "off", DLADM_WLAN_RADIO_OFF } 280d62bc4baSyz147064 }; 281d62bc4baSyz147064 282d62bc4baSyz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 283d62bc4baSyz147064 { "off", DLADM_WLAN_PM_OFF }, 284d62bc4baSyz147064 { "fast", DLADM_WLAN_PM_FAST }, 285d62bc4baSyz147064 { "max", DLADM_WLAN_PM_MAX } 286d62bc4baSyz147064 }; 287d62bc4baSyz147064 288f4b3ec61Sdh155122 static prop_desc_t prop_table[] = { 289d62bc4baSyz147064 290e7801d59Ssowmini { "channel", { NULL, 0 }, 291e7801d59Ssowmini NULL, 0, NULL, NULL, 292d62bc4baSyz147064 do_get_channel_prop, NULL, 0, 293d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 294d62bc4baSyz147064 295d62bc4baSyz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 296d62bc4baSyz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 297d62bc4baSyz147064 do_set_powermode_prop, NULL, 298d62bc4baSyz147064 do_get_powermode_prop, NULL, 0, 299d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 300d62bc4baSyz147064 301d62bc4baSyz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 302d62bc4baSyz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 303d62bc4baSyz147064 do_set_radio_prop, NULL, 304d62bc4baSyz147064 do_get_radio_prop, NULL, 0, 305d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 306d62bc4baSyz147064 307d62bc4baSyz147064 { "speed", { "", 0 }, NULL, 0, 308d62bc4baSyz147064 do_set_rate_prop, do_get_rate_mod, 309d62bc4baSyz147064 do_get_rate_prop, do_check_rate, 0, 3106b9e797cSsowmini DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE }, 311d62bc4baSyz147064 3124045d941Ssowmini { "autopush", { "", 0 }, NULL, 0, 313d62bc4baSyz147064 do_set_autopush, NULL, 3144045d941Ssowmini do_get_autopush, do_check_autopush, PD_CHECK_ALLOC|PD_EMPTY_RESET, 315d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 316d62bc4baSyz147064 3174045d941Ssowmini { "zone", { "", 0 }, NULL, 0, 318f4b3ec61Sdh155122 do_set_zone, NULL, 3194045d941Ssowmini do_get_zone, do_check_zone, PD_TEMPONLY|PD_EMPTY_RESET, 320e7801d59Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 321e7801d59Ssowmini 3224045d941Ssowmini { "duplex", { "", 0 }, 323e7801d59Ssowmini link_duplex_vals, VALCNT(link_duplex_vals), 324e7801d59Ssowmini NULL, NULL, dld_duplex_get, NULL, 325e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 326e7801d59Ssowmini 3276b9e797cSsowmini { "state", { "up", LINK_STATE_UP }, 328e7801d59Ssowmini link_status_vals, VALCNT(link_status_vals), 329e7801d59Ssowmini NULL, NULL, dld_status_get, NULL, 3304045d941Ssowmini 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 331e7801d59Ssowmini 332e7801d59Ssowmini { "adv_autoneg_cap", { "1", 1 }, 333e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 334e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 335e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 336e7801d59Ssowmini 3374045d941Ssowmini { "mtu", { "", 0 }, NULL, 0, 3384045d941Ssowmini dld_set_public_prop, NULL, dld_uint32_get, 3394045d941Ssowmini dld_defmtu_check, 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 340e7801d59Ssowmini 3414045d941Ssowmini { "flowctrl", { "", 0 }, 342e7801d59Ssowmini link_flow_vals, VALCNT(link_flow_vals), 343e7801d59Ssowmini dld_set_public_prop, NULL, dld_flowctl_get, NULL, 344e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 345e7801d59Ssowmini 3464045d941Ssowmini { "adv_1000fdx_cap", { "", 0 }, 3474045d941Ssowmini link_01_vals, VALCNT(link_01_vals), 348e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 349e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 350e7801d59Ssowmini 3514045d941Ssowmini { "en_1000fdx_cap", { "", 0 }, 352e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 353e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 354e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 355e7801d59Ssowmini 3564045d941Ssowmini { "adv_1000hdx_cap", { "", 0 }, 357e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 358e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 359e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 360e7801d59Ssowmini 3614045d941Ssowmini { "en_1000hdx_cap", { "", 0 }, 362e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 363e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 364e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 365e7801d59Ssowmini 3664045d941Ssowmini { "adv_100fdx_cap", { "", 0 }, 367e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 368e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 369e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 370e7801d59Ssowmini 3714045d941Ssowmini { "en_100fdx_cap", { "", 0 }, 372e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 373e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 374e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 375e7801d59Ssowmini 3764045d941Ssowmini { "adv_100hdx_cap", { "", 0 }, 377e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 378e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 379e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 380e7801d59Ssowmini 3814045d941Ssowmini { "en_100hdx_cap", { "", 0 }, 382e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 383e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 384e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 385e7801d59Ssowmini 3864045d941Ssowmini { "adv_10fdx_cap", { "", 0 }, 387e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 388e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 389e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 390e7801d59Ssowmini 3914045d941Ssowmini { "en_10fdx_cap", { "", 0 }, 392e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 393e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 394e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 395e7801d59Ssowmini 3964045d941Ssowmini { "adv_10hdx_cap", { "", 0 }, 397e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 398e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 399e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 400e7801d59Ssowmini 4014045d941Ssowmini { "en_10hdx_cap", { "", 0 }, 402e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 403e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 404e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER } 405e7801d59Ssowmini 406f4b3ec61Sdh155122 }; 407f4b3ec61Sdh155122 408d62bc4baSyz147064 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 4090ba2cbe9Sxc151355 410d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, 411d62bc4baSyz147064 char **, uint_t); 412d62bc4baSyz147064 static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, 413d62bc4baSyz147064 char **, uint_t *); 414d62bc4baSyz147064 static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t, 415d62bc4baSyz147064 uint32_t, prop_desc_t *, char **, uint_t, uint_t); 416d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *, 417d62bc4baSyz147064 char **, uint_t, uint_t); 4184045d941Ssowmini static dladm_status_t i_dladm_getset_defval(prop_desc_t *, datalink_id_t, 4194045d941Ssowmini datalink_media_t, uint_t); 420d62bc4baSyz147064 /* 421d62bc4baSyz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 422d62bc4baSyz147064 * rates to be retrieved. However, we cannot increase it at this 423d62bc4baSyz147064 * time because it will break binary compatibility with unbundled 424d62bc4baSyz147064 * WiFi drivers and utilities. So for now we define an additional 425d62bc4baSyz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 426d62bc4baSyz147064 */ 427d62bc4baSyz147064 #define MAX_SUPPORT_RATES 64 428d62bc4baSyz147064 429d62bc4baSyz147064 #define AP_ANCHOR "[anchor]" 430d62bc4baSyz147064 #define AP_DELIMITER '.' 431d62bc4baSyz147064 432d62bc4baSyz147064 static dladm_status_t 433d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 434d62bc4baSyz147064 val_desc_t *vdp) 4350ba2cbe9Sxc151355 { 436d62bc4baSyz147064 int i, j; 4370ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 4380ba2cbe9Sxc151355 439d62bc4baSyz147064 for (j = 0; j < val_cnt; j++) { 440d62bc4baSyz147064 for (i = 0; i < pdp->pd_noptval; i++) { 441d62bc4baSyz147064 if (strcasecmp(*prop_val, 442d62bc4baSyz147064 pdp->pd_optval[i].vd_name) == 0) { 4430ba2cbe9Sxc151355 break; 4440ba2cbe9Sxc151355 } 4450ba2cbe9Sxc151355 } 446d62bc4baSyz147064 if (i == pdp->pd_noptval) { 447d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 448d62bc4baSyz147064 goto done; 449d62bc4baSyz147064 } 450d62bc4baSyz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 4510ba2cbe9Sxc151355 } 4520ba2cbe9Sxc151355 453d62bc4baSyz147064 done: 454d62bc4baSyz147064 return (status); 4550ba2cbe9Sxc151355 } 4560ba2cbe9Sxc151355 4570ba2cbe9Sxc151355 static dladm_status_t 458d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 459d62bc4baSyz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 460d62bc4baSyz147064 uint_t flags) 4610ba2cbe9Sxc151355 { 4620ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 463d62bc4baSyz147064 val_desc_t *vdp = NULL; 464d62bc4baSyz147064 boolean_t needfree = B_FALSE; 465d62bc4baSyz147064 uint_t cnt, i; 4660ba2cbe9Sxc151355 467d62bc4baSyz147064 if (!(pdp->pd_class & class)) 468d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 4690ba2cbe9Sxc151355 470d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 471d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 472d62bc4baSyz147064 473d62bc4baSyz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 474d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 475d62bc4baSyz147064 476d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE)) 477d62bc4baSyz147064 return (DLADM_STATUS_OK); 478d62bc4baSyz147064 479d62bc4baSyz147064 if (pdp->pd_set == NULL) 480d62bc4baSyz147064 return (DLADM_STATUS_PROPRDONLY); 481d62bc4baSyz147064 482e7801d59Ssowmini if (pdp->pd_flags & PD_CHECK_ALLOC) 483e7801d59Ssowmini needfree = B_TRUE; 484e7801d59Ssowmini else 485e7801d59Ssowmini needfree = B_FALSE; 486d62bc4baSyz147064 if (prop_val != NULL) { 487d62bc4baSyz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 488d62bc4baSyz147064 if (vdp == NULL) 489d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 490d62bc4baSyz147064 491e7801d59Ssowmini 492d62bc4baSyz147064 if (pdp->pd_check != NULL) { 493e7801d59Ssowmini status = pdp->pd_check(pdp, linkid, prop_val, val_cnt, 4946b9e797cSsowmini vdp, media); 495d62bc4baSyz147064 } else if (pdp->pd_optval != NULL) { 496d62bc4baSyz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 497d62bc4baSyz147064 } else { 498d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 4990ba2cbe9Sxc151355 } 5000ba2cbe9Sxc151355 501d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 502d62bc4baSyz147064 goto done; 503d62bc4baSyz147064 504d62bc4baSyz147064 cnt = val_cnt; 505d62bc4baSyz147064 } else { 506d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) 507d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 508d62bc4baSyz147064 5094045d941Ssowmini if ((pdp->pd_flags & PD_EMPTY_RESET) != 0 || 5104045d941Ssowmini strlen(pdp->pd_defval.vd_name) > 0) { 511d62bc4baSyz147064 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 512d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 5134045d941Ssowmini (void) memcpy(vdp, &pdp->pd_defval, 5144045d941Ssowmini sizeof (val_desc_t)); 5154045d941Ssowmini } else { 5164045d941Ssowmini status = i_dladm_getset_defval(pdp, linkid, 5174045d941Ssowmini media, flags); 5184045d941Ssowmini return (status); 5194045d941Ssowmini } 520d62bc4baSyz147064 cnt = 1; 521d62bc4baSyz147064 } 5226b9e797cSsowmini status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media); 523d62bc4baSyz147064 if (needfree) { 524d62bc4baSyz147064 for (i = 0; i < cnt; i++) 525e7801d59Ssowmini free((void *)((val_desc_t *)vdp + i)->vd_val); 526d62bc4baSyz147064 } 527d62bc4baSyz147064 done: 528d62bc4baSyz147064 free(vdp); 529d62bc4baSyz147064 return (status); 530d62bc4baSyz147064 } 531d62bc4baSyz147064 532d62bc4baSyz147064 static dladm_status_t 533d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 534d62bc4baSyz147064 char **prop_val, uint_t val_cnt, uint_t flags) 535d62bc4baSyz147064 { 536d62bc4baSyz147064 int i; 537d62bc4baSyz147064 boolean_t found = B_FALSE; 538d62bc4baSyz147064 datalink_class_t class; 539d62bc4baSyz147064 uint32_t media; 540d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 541d62bc4baSyz147064 542d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 543d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5440ba2cbe9Sxc151355 return (status); 5450ba2cbe9Sxc151355 546d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 547d62bc4baSyz147064 prop_desc_t *pdp = &prop_table[i]; 548d62bc4baSyz147064 dladm_status_t s; 5490ba2cbe9Sxc151355 550d62bc4baSyz147064 if (prop_name != NULL && 551d62bc4baSyz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 552d62bc4baSyz147064 continue; 553d62bc4baSyz147064 554d62bc4baSyz147064 found = B_TRUE; 555d62bc4baSyz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 556d62bc4baSyz147064 val_cnt, flags); 557d62bc4baSyz147064 558d62bc4baSyz147064 if (prop_name != NULL) { 559d62bc4baSyz147064 status = s; 560d62bc4baSyz147064 break; 561d62bc4baSyz147064 } else { 562d62bc4baSyz147064 if (s != DLADM_STATUS_OK && 563d62bc4baSyz147064 s != DLADM_STATUS_NOTSUP) 564d62bc4baSyz147064 status = s; 565d62bc4baSyz147064 } 566d62bc4baSyz147064 } 567e7801d59Ssowmini if (!found) { 568e7801d59Ssowmini if (prop_name[0] == '_') { 569e7801d59Ssowmini /* other private properties */ 570e7801d59Ssowmini status = dld_set_prop(linkid, prop_name, prop_val, 571e7801d59Ssowmini val_cnt, flags); 572e7801d59Ssowmini } else { 5730ba2cbe9Sxc151355 status = DLADM_STATUS_NOTFOUND; 574e7801d59Ssowmini } 575e7801d59Ssowmini } 5760ba2cbe9Sxc151355 5770ba2cbe9Sxc151355 return (status); 5780ba2cbe9Sxc151355 } 5790ba2cbe9Sxc151355 580d62bc4baSyz147064 /* 581d62bc4baSyz147064 * Set/reset link property for specific link 582d62bc4baSyz147064 */ 583d62bc4baSyz147064 dladm_status_t 584d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 585d62bc4baSyz147064 uint_t val_cnt, uint_t flags) 5860ba2cbe9Sxc151355 { 587d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 5880ba2cbe9Sxc151355 589d62bc4baSyz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 590d62bc4baSyz147064 (prop_val == NULL && val_cnt > 0) || 591d62bc4baSyz147064 (prop_val != NULL && val_cnt == 0) || 592d62bc4baSyz147064 (prop_name == NULL && prop_val != NULL)) { 593d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 5940ba2cbe9Sxc151355 } 5950ba2cbe9Sxc151355 596d62bc4baSyz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 597d62bc4baSyz147064 val_cnt, flags); 598d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 599d62bc4baSyz147064 return (status); 600d62bc4baSyz147064 601d62bc4baSyz147064 if (flags & DLADM_OPT_PERSIST) { 602d62bc4baSyz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 603d62bc4baSyz147064 prop_val, val_cnt); 604d62bc4baSyz147064 } 605d62bc4baSyz147064 return (status); 606d62bc4baSyz147064 } 607d62bc4baSyz147064 608d62bc4baSyz147064 /* 609d62bc4baSyz147064 * Walk link properties of the given specific link. 610d62bc4baSyz147064 */ 611d62bc4baSyz147064 dladm_status_t 612d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 613d62bc4baSyz147064 int (*func)(datalink_id_t, const char *, void *)) 6140ba2cbe9Sxc151355 { 615d62bc4baSyz147064 dladm_status_t status; 616d62bc4baSyz147064 datalink_class_t class; 617d62bc4baSyz147064 uint_t media; 618d62bc4baSyz147064 int i; 6190ba2cbe9Sxc151355 620d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 621d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 6220ba2cbe9Sxc151355 623d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 624d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 625d62bc4baSyz147064 return (status); 626d62bc4baSyz147064 627d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 628d62bc4baSyz147064 if (!(prop_table[i].pd_class & class)) 629d62bc4baSyz147064 continue; 630d62bc4baSyz147064 631d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 632d62bc4baSyz147064 continue; 633d62bc4baSyz147064 634d62bc4baSyz147064 if (func(linkid, prop_table[i].pd_name, arg) == 635d62bc4baSyz147064 DLADM_WALK_TERMINATE) { 636d62bc4baSyz147064 break; 637d62bc4baSyz147064 } 638d62bc4baSyz147064 } 639d62bc4baSyz147064 640d62bc4baSyz147064 return (DLADM_STATUS_OK); 641d62bc4baSyz147064 } 642d62bc4baSyz147064 643d62bc4baSyz147064 /* 644d62bc4baSyz147064 * Get linkprop of the given specific link. 645d62bc4baSyz147064 */ 646d62bc4baSyz147064 dladm_status_t 647d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 648d62bc4baSyz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 649d62bc4baSyz147064 { 650d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 651d62bc4baSyz147064 datalink_class_t class; 652d62bc4baSyz147064 uint_t media; 653d62bc4baSyz147064 prop_desc_t *pdp; 6544045d941Ssowmini uint_t cnt, dld_flags = 0; 655d62bc4baSyz147064 int i; 656d62bc4baSyz147064 6574045d941Ssowmini if (type == DLADM_PROP_VAL_DEFAULT) 6583fd94f8cSam223141 dld_flags = MAC_PROP_DEFAULT; 6594045d941Ssowmini 660d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 661d62bc4baSyz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 662d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 663d62bc4baSyz147064 664d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 665d62bc4baSyz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 666d62bc4baSyz147064 break; 667d62bc4baSyz147064 668e7801d59Ssowmini if (i == DLADM_MAX_PROPS) { 669e7801d59Ssowmini if (prop_name[0] == '_') { 670e7801d59Ssowmini /* 671e7801d59Ssowmini * private property. 672e7801d59Ssowmini */ 673e7801d59Ssowmini return (dld_get_prop(linkid, prop_name, 6744045d941Ssowmini prop_val, val_cntp, type, dld_flags)); 675e7801d59Ssowmini } else { 676d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 677e7801d59Ssowmini } 678e7801d59Ssowmini } 679d62bc4baSyz147064 680d62bc4baSyz147064 pdp = &prop_table[i]; 681d62bc4baSyz147064 682d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 683d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 684d62bc4baSyz147064 return (status); 685d62bc4baSyz147064 686d62bc4baSyz147064 if (!(pdp->pd_class & class)) 687d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 688d62bc4baSyz147064 689d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 690d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 691d62bc4baSyz147064 692d62bc4baSyz147064 switch (type) { 693d62bc4baSyz147064 case DLADM_PROP_VAL_CURRENT: 6944045d941Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media, 6954045d941Ssowmini dld_flags); 696d62bc4baSyz147064 break; 697d62bc4baSyz147064 698d62bc4baSyz147064 case DLADM_PROP_VAL_DEFAULT: 69913a55820Sar224390 /* 70013a55820Sar224390 * If defaults are not defined for the property, 70113a55820Sar224390 * pd_defval.vd_name should be null. If the driver 70213a55820Sar224390 * has to be contacted for the value, vd_name should 70313a55820Sar224390 * be the empty string (""). Otherwise, dladm will 70413a55820Sar224390 * just print whatever is in the table. 70513a55820Sar224390 */ 706d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) { 707d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 708d62bc4baSyz147064 break; 709d62bc4baSyz147064 } 7104045d941Ssowmini 7114045d941Ssowmini if (strlen(pdp->pd_defval.vd_name) == 0) { 7124045d941Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, 7134045d941Ssowmini media, dld_flags); 7144045d941Ssowmini } else { 715d62bc4baSyz147064 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 7164045d941Ssowmini } 717d62bc4baSyz147064 *val_cntp = 1; 718d62bc4baSyz147064 break; 719d62bc4baSyz147064 720d62bc4baSyz147064 case DLADM_PROP_VAL_MODIFIABLE: 721d62bc4baSyz147064 if (pdp->pd_getmod != NULL) { 722e7801d59Ssowmini status = pdp->pd_getmod(pdp, linkid, prop_val, 7234045d941Ssowmini val_cntp, media, dld_flags); 724d62bc4baSyz147064 break; 725d62bc4baSyz147064 } 726d62bc4baSyz147064 cnt = pdp->pd_noptval; 727d62bc4baSyz147064 if (cnt == 0) { 728d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 729d62bc4baSyz147064 } else if (cnt > *val_cntp) { 730d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 731d62bc4baSyz147064 } else { 732d62bc4baSyz147064 for (i = 0; i < cnt; i++) { 733d62bc4baSyz147064 (void) strcpy(prop_val[i], 734d62bc4baSyz147064 pdp->pd_optval[i].vd_name); 735d62bc4baSyz147064 } 736d62bc4baSyz147064 *val_cntp = cnt; 737d62bc4baSyz147064 } 738d62bc4baSyz147064 break; 739d62bc4baSyz147064 case DLADM_PROP_VAL_PERSISTENT: 740d62bc4baSyz147064 if (pdp->pd_flags & PD_TEMPONLY) 741d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 742d62bc4baSyz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 743d62bc4baSyz147064 prop_val, val_cntp); 744d62bc4baSyz147064 break; 745d62bc4baSyz147064 default: 746d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 747d62bc4baSyz147064 break; 748d62bc4baSyz147064 } 749d62bc4baSyz147064 750d62bc4baSyz147064 return (status); 751d62bc4baSyz147064 } 752d62bc4baSyz147064 753d62bc4baSyz147064 /*ARGSUSED*/ 754d62bc4baSyz147064 static int 755d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 756d62bc4baSyz147064 { 757d62bc4baSyz147064 char *buf, **propvals; 758d62bc4baSyz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 759d62bc4baSyz147064 760d62bc4baSyz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 761d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 762d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 763d62bc4baSyz147064 } 764d62bc4baSyz147064 765d62bc4baSyz147064 propvals = (char **)(void *)buf; 766d62bc4baSyz147064 for (i = 0; i < valcnt; i++) { 767d62bc4baSyz147064 propvals[i] = buf + 768d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 769d62bc4baSyz147064 i * DLADM_PROP_VAL_MAX; 770d62bc4baSyz147064 } 771d62bc4baSyz147064 772d62bc4baSyz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 773d62bc4baSyz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 774d62bc4baSyz147064 goto done; 775d62bc4baSyz147064 } 776d62bc4baSyz147064 777d62bc4baSyz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 778d62bc4baSyz147064 DLADM_OPT_ACTIVE); 779d62bc4baSyz147064 780d62bc4baSyz147064 done: 781d62bc4baSyz147064 if (buf != NULL) 782d62bc4baSyz147064 free(buf); 783d62bc4baSyz147064 784d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 785d62bc4baSyz147064 } 786d62bc4baSyz147064 787d62bc4baSyz147064 /*ARGSUSED*/ 788d62bc4baSyz147064 static int 789d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 790d62bc4baSyz147064 { 791*30890389Sartem (void) dladm_init_linkprop(linkid, B_TRUE); 792d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 7930ba2cbe9Sxc151355 } 7940ba2cbe9Sxc151355 7950ba2cbe9Sxc151355 dladm_status_t 796*30890389Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media) 7970ba2cbe9Sxc151355 { 798*30890389Sartem datalink_media_t dmedia; 799*30890389Sartem uint32_t media; 800*30890389Sartem 801*30890389Sartem dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI; 802*30890389Sartem 803d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 804d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 805*30890389Sartem DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST); 806*30890389Sartem } else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL, 807*30890389Sartem &media, NULL, 0) == DLADM_STATUS_OK) && 808*30890389Sartem DATALINK_MEDIA_ACCEPTED(dmedia, media))) { 809d62bc4baSyz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 810d62bc4baSyz147064 } 811d62bc4baSyz147064 return (DLADM_STATUS_OK); 8120ba2cbe9Sxc151355 } 813f4b3ec61Sdh155122 814e7801d59Ssowmini /* ARGSUSED */ 815f4b3ec61Sdh155122 static dladm_status_t 816e7801d59Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid, 8174045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 818f4b3ec61Sdh155122 { 819d62bc4baSyz147064 char zone_name[ZONENAME_MAX]; 820d62bc4baSyz147064 zoneid_t zid; 821d62bc4baSyz147064 dladm_status_t status; 822f4b3ec61Sdh155122 8234045d941Ssowmini if (flags != 0) 8244045d941Ssowmini return (DLADM_STATUS_NOTSUP); 8254045d941Ssowmini 826d62bc4baSyz147064 status = dladm_getzid(linkid, &zid); 827d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 828d62bc4baSyz147064 return (status); 829d62bc4baSyz147064 830d62bc4baSyz147064 *val_cnt = 1; 831d62bc4baSyz147064 if (zid != GLOBAL_ZONEID) { 832d62bc4baSyz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 833f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 834f4b3ec61Sdh155122 835d62bc4baSyz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 83647a01978Sbw } else { 837d62bc4baSyz147064 *prop_val[0] = '\0'; 83847a01978Sbw } 839f4b3ec61Sdh155122 840f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 841f4b3ec61Sdh155122 } 842f4b3ec61Sdh155122 843f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 844f4b3ec61Sdh155122 845f4b3ec61Sdh155122 static int 846f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 847f4b3ec61Sdh155122 { 848f4b3ec61Sdh155122 char root[MAXPATHLEN]; 849f4b3ec61Sdh155122 zone_get_devroot_t real_zone_get_devroot; 850f4b3ec61Sdh155122 void *dlhandle; 851f4b3ec61Sdh155122 void *sym; 852f4b3ec61Sdh155122 int ret; 853f4b3ec61Sdh155122 854f4b3ec61Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 855f4b3ec61Sdh155122 return (-1); 856f4b3ec61Sdh155122 857f4b3ec61Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 858f4b3ec61Sdh155122 (void) dlclose(dlhandle); 859f4b3ec61Sdh155122 return (-1); 860f4b3ec61Sdh155122 } 861f4b3ec61Sdh155122 862f4b3ec61Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 863f4b3ec61Sdh155122 864f4b3ec61Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 865f4b3ec61Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 866f4b3ec61Sdh155122 (void) dlclose(dlhandle); 867f4b3ec61Sdh155122 return (ret); 868f4b3ec61Sdh155122 } 869f4b3ec61Sdh155122 870f4b3ec61Sdh155122 static dladm_status_t 871d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 872f4b3ec61Sdh155122 { 873f4b3ec61Sdh155122 char path[MAXPATHLEN]; 874d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 875f4b3ec61Sdh155122 di_prof_t prof = NULL; 876f4b3ec61Sdh155122 char zone_name[ZONENAME_MAX]; 877f4b3ec61Sdh155122 dladm_status_t status; 878d62bc4baSyz147064 int ret; 879f4b3ec61Sdh155122 880f4b3ec61Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 881f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 882f4b3ec61Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 883f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 884f4b3ec61Sdh155122 if (di_prof_init(path, &prof) != 0) 885f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 886f4b3ec61Sdh155122 887d62bc4baSyz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 888f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 889d62bc4baSyz147064 goto cleanup; 890f4b3ec61Sdh155122 891d62bc4baSyz147064 if (add) 892d62bc4baSyz147064 ret = di_prof_add_dev(prof, name); 893d62bc4baSyz147064 else 894d62bc4baSyz147064 ret = di_prof_add_exclude(prof, name); 895f4b3ec61Sdh155122 896d62bc4baSyz147064 if (ret != 0) { 897d62bc4baSyz147064 status = dladm_errno2status(errno); 898d62bc4baSyz147064 goto cleanup; 899f4b3ec61Sdh155122 } 900f4b3ec61Sdh155122 901d62bc4baSyz147064 if (di_prof_commit(prof) != 0) 902d62bc4baSyz147064 status = dladm_errno2status(errno); 903d62bc4baSyz147064 cleanup: 904d62bc4baSyz147064 if (prof) 905d62bc4baSyz147064 di_prof_fini(prof); 906d62bc4baSyz147064 907d62bc4baSyz147064 return (status); 908f4b3ec61Sdh155122 } 909f4b3ec61Sdh155122 910e7801d59Ssowmini /* ARGSUSED */ 911f4b3ec61Sdh155122 static dladm_status_t 9126b9e797cSsowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, 9136b9e797cSsowmini uint_t val_cnt, uint_t flags, datalink_media_t media) 914f4b3ec61Sdh155122 { 915f4b3ec61Sdh155122 dladm_status_t status; 916f4b3ec61Sdh155122 zoneid_t zid_old, zid_new; 917d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 918f4b3ec61Sdh155122 919f4b3ec61Sdh155122 if (val_cnt != 1) 920f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 921f4b3ec61Sdh155122 922d62bc4baSyz147064 status = dladm_getzid(linkid, &zid_old); 923f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 924f4b3ec61Sdh155122 return (status); 925f4b3ec61Sdh155122 926f4b3ec61Sdh155122 /* Do nothing if setting to current value */ 927d62bc4baSyz147064 zid_new = vdp->vd_val; 928f4b3ec61Sdh155122 if (zid_new == zid_old) 929f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 930f4b3ec61Sdh155122 931d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 932d62bc4baSyz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 933d62bc4baSyz147064 return (status); 934d62bc4baSyz147064 } 935f4b3ec61Sdh155122 936d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 937d62bc4baSyz147064 /* 938d62bc4baSyz147064 * If the new zoneid is the global zone, we could destroy 939d62bc4baSyz147064 * the link (in the case of an implicitly-created VLAN) as a 940d62bc4baSyz147064 * result of the dladm_setzid() operation. In that case, 941d62bc4baSyz147064 * we defer the operation to the end of this function to avoid 942d62bc4baSyz147064 * recreating the VLAN and getting a different linkid during 943d62bc4baSyz147064 * the rollback if other operation fails. 944d62bc4baSyz147064 * 945d62bc4baSyz147064 * Otherwise, dladm_setzid() will hold a reference to the 946d62bc4baSyz147064 * link and prevent a link renaming, so we need to do it 947d62bc4baSyz147064 * before other operations. 948d62bc4baSyz147064 */ 949d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 950d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 951d62bc4baSyz147064 return (status); 952d62bc4baSyz147064 } 953d62bc4baSyz147064 954d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) { 955d62bc4baSyz147064 if (zone_remove_datalink(zid_old, link) != 0 && 956f4b3ec61Sdh155122 errno != ENXIO) { 957f4b3ec61Sdh155122 status = dladm_errno2status(errno); 958f4b3ec61Sdh155122 goto rollback1; 959f4b3ec61Sdh155122 } 960f4b3ec61Sdh155122 961d62bc4baSyz147064 /* 962d62bc4baSyz147064 * It is okay to fail to update the /dev entry (some 963d62bc4baSyz147064 * vanity-named links do not have a /dev entry). 964d62bc4baSyz147064 */ 965d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 966d62bc4baSyz147064 } 967d62bc4baSyz147064 968d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 969d62bc4baSyz147064 if (zone_add_datalink(zid_new, link) != 0) { 970d62bc4baSyz147064 status = dladm_errno2status(errno); 971d62bc4baSyz147064 goto rollback2; 972d62bc4baSyz147064 } 973d62bc4baSyz147064 974d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 975d62bc4baSyz147064 } else { 976d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 977f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 978f4b3ec61Sdh155122 goto rollback2; 979f4b3ec61Sdh155122 } 980f4b3ec61Sdh155122 981f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 982f4b3ec61Sdh155122 983f4b3ec61Sdh155122 rollback2: 984f4b3ec61Sdh155122 if (zid_old != GLOBAL_ZONEID) 985d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 986d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) 987d62bc4baSyz147064 (void) zone_add_datalink(zid_old, link); 988f4b3ec61Sdh155122 rollback1: 989d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) 990d62bc4baSyz147064 (void) dladm_setzid(link, zid_old); 991f4b3ec61Sdh155122 return (status); 992f4b3ec61Sdh155122 } 993f4b3ec61Sdh155122 994f4b3ec61Sdh155122 /* ARGSUSED */ 995f4b3ec61Sdh155122 static dladm_status_t 996e7801d59Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 9976b9e797cSsowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 998f4b3ec61Sdh155122 { 999f4b3ec61Sdh155122 zoneid_t zid; 1000f4b3ec61Sdh155122 1001f4b3ec61Sdh155122 if (val_cnt != 1) 1002f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 1003f4b3ec61Sdh155122 1004f4b3ec61Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 1005f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 1006f4b3ec61Sdh155122 1007f4b3ec61Sdh155122 if (zid != GLOBAL_ZONEID) { 1008f4b3ec61Sdh155122 ushort_t flags; 1009f4b3ec61Sdh155122 1010f4b3ec61Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 1011f4b3ec61Sdh155122 sizeof (flags)) < 0) { 1012f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 1013f4b3ec61Sdh155122 } 1014f4b3ec61Sdh155122 1015f4b3ec61Sdh155122 if (!(flags & ZF_NET_EXCL)) { 1016f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 1017f4b3ec61Sdh155122 } 1018f4b3ec61Sdh155122 } 1019f4b3ec61Sdh155122 1020d62bc4baSyz147064 vdp->vd_val = zid; 1021f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 1022f4b3ec61Sdh155122 } 1023f4b3ec61Sdh155122 1024e7801d59Ssowmini /* ARGSUSED */ 1025f4b3ec61Sdh155122 static dladm_status_t 1026e7801d59Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid, 10274045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1028d62bc4baSyz147064 { 1029d62bc4baSyz147064 dld_ioc_ap_t dia; 1030d62bc4baSyz147064 int fd, i, len; 1031d62bc4baSyz147064 10323fd94f8cSam223141 if (flags & MAC_PROP_DEFAULT) 10334045d941Ssowmini return (DLADM_STATUS_NOTSUP); 10344045d941Ssowmini 1035d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1036d62bc4baSyz147064 return (dladm_errno2status(errno)); 1037d62bc4baSyz147064 1038d62bc4baSyz147064 *val_cnt = 1; 1039d62bc4baSyz147064 dia.dia_linkid = linkid; 1040d62bc4baSyz147064 if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) { 1041d62bc4baSyz147064 (*prop_val)[0] = '\0'; 1042d62bc4baSyz147064 goto done; 1043d62bc4baSyz147064 } 1044d62bc4baSyz147064 1045d62bc4baSyz147064 for (i = 0, len = 0; i < dia.dia_npush; i++) { 1046d62bc4baSyz147064 if (i != 0) { 1047d62bc4baSyz147064 (void) snprintf(*prop_val + len, 1048d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 1049d62bc4baSyz147064 len += 1; 1050d62bc4baSyz147064 } 1051d62bc4baSyz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 1052d62bc4baSyz147064 "%s", dia.dia_aplist[i]); 1053d62bc4baSyz147064 len += strlen(dia.dia_aplist[i]); 1054d62bc4baSyz147064 if (dia.dia_anchor - 1 == i) { 1055d62bc4baSyz147064 (void) snprintf(*prop_val + len, 1056d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 1057d62bc4baSyz147064 AP_ANCHOR); 1058d62bc4baSyz147064 len += (strlen(AP_ANCHOR) + 1); 1059d62bc4baSyz147064 } 1060d62bc4baSyz147064 } 1061d62bc4baSyz147064 1062d62bc4baSyz147064 done: 1063d62bc4baSyz147064 (void) close(fd); 1064d62bc4baSyz147064 return (DLADM_STATUS_OK); 1065d62bc4baSyz147064 } 1066d62bc4baSyz147064 1067e7801d59Ssowmini /* ARGSUSED */ 1068d62bc4baSyz147064 static dladm_status_t 10696b9e797cSsowmini do_set_autopush(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, 10706b9e797cSsowmini uint_t val_cnt, uint_t flags, datalink_media_t media) 1071d62bc4baSyz147064 { 1072d62bc4baSyz147064 dld_ioc_ap_t dia; 1073d62bc4baSyz147064 struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val; 1074d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1075d62bc4baSyz147064 int fd, i; 1076d62bc4baSyz147064 int ic_cmd; 1077d62bc4baSyz147064 1078d62bc4baSyz147064 if (val_cnt != 1) 1079d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1080d62bc4baSyz147064 1081d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1082d62bc4baSyz147064 return (dladm_errno2status(errno)); 1083d62bc4baSyz147064 1084d62bc4baSyz147064 dia.dia_linkid = linkid; 1085d62bc4baSyz147064 if (dlap != NULL) { 1086d62bc4baSyz147064 dia.dia_anchor = dlap->dap_anchor; 1087d62bc4baSyz147064 dia.dia_npush = dlap->dap_npush; 1088d62bc4baSyz147064 for (i = 0; i < dia.dia_npush; i++) { 1089d62bc4baSyz147064 (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i], 1090d62bc4baSyz147064 FMNAMESZ+1); 1091d62bc4baSyz147064 } 1092d62bc4baSyz147064 ic_cmd = DLDIOC_SETAUTOPUSH; 1093d62bc4baSyz147064 } else { 1094d62bc4baSyz147064 ic_cmd = DLDIOC_CLRAUTOPUSH; 1095d62bc4baSyz147064 } 1096d62bc4baSyz147064 1097d62bc4baSyz147064 if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0) 1098d62bc4baSyz147064 status = dladm_errno2status(errno); 1099d62bc4baSyz147064 1100d62bc4baSyz147064 (void) close(fd); 1101d62bc4baSyz147064 return (status); 1102d62bc4baSyz147064 } 1103d62bc4baSyz147064 1104d62bc4baSyz147064 /* 1105d62bc4baSyz147064 * Add the specified module to the dlautopush structure; returns a 1106d62bc4baSyz147064 * DLADM_STATUS_* code. 1107d62bc4baSyz147064 */ 1108d62bc4baSyz147064 dladm_status_t 1109d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 1110d62bc4baSyz147064 { 1111d62bc4baSyz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 1112d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1113d62bc4baSyz147064 1114d62bc4baSyz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 1115d62bc4baSyz147064 /* 1116d62bc4baSyz147064 * We don't allow multiple anchors, and the anchor must 1117d62bc4baSyz147064 * be after at least one module. 1118d62bc4baSyz147064 */ 1119d62bc4baSyz147064 if (dlap->dap_anchor != 0) 1120d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1121d62bc4baSyz147064 if (dlap->dap_npush == 0) 1122d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1123d62bc4baSyz147064 1124d62bc4baSyz147064 dlap->dap_anchor = dlap->dap_npush; 1125d62bc4baSyz147064 return (DLADM_STATUS_OK); 1126d62bc4baSyz147064 } 1127d62bc4baSyz147064 if (dlap->dap_npush > MAXAPUSH) 1128d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1129d62bc4baSyz147064 1130d62bc4baSyz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 1131d62bc4baSyz147064 FMNAMESZ + 1); 1132d62bc4baSyz147064 1133d62bc4baSyz147064 return (DLADM_STATUS_OK); 1134d62bc4baSyz147064 } 1135d62bc4baSyz147064 1136d62bc4baSyz147064 /* 1137d62bc4baSyz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 1138d62bc4baSyz147064 * autopush modules. The former is used in dladm set-linkprop, and the 1139d62bc4baSyz147064 * latter is used in the autopush(1M) file. 1140d62bc4baSyz147064 */ 1141d62bc4baSyz147064 /* ARGSUSED */ 1142d62bc4baSyz147064 static dladm_status_t 1143e7801d59Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 11446b9e797cSsowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 1145d62bc4baSyz147064 { 1146d62bc4baSyz147064 char *module; 1147d62bc4baSyz147064 struct dlautopush *dlap; 1148d62bc4baSyz147064 dladm_status_t status; 1149d62bc4baSyz147064 char val[DLADM_PROP_VAL_MAX]; 1150d62bc4baSyz147064 char delimiters[4]; 1151d62bc4baSyz147064 1152d62bc4baSyz147064 if (val_cnt != 1) 1153d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1154d62bc4baSyz147064 1155d62bc4baSyz147064 dlap = malloc(sizeof (struct dlautopush)); 1156d62bc4baSyz147064 if (dlap == NULL) 1157d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1158d62bc4baSyz147064 1159d62bc4baSyz147064 (void) memset(dlap, 0, sizeof (struct dlautopush)); 1160d62bc4baSyz147064 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 1161d62bc4baSyz147064 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 1162d62bc4baSyz147064 module = strtok(val, delimiters); 1163d62bc4baSyz147064 while (module != NULL) { 1164d62bc4baSyz147064 status = i_dladm_add_ap_module(module, dlap); 1165d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1166d62bc4baSyz147064 return (status); 1167d62bc4baSyz147064 module = strtok(NULL, delimiters); 1168d62bc4baSyz147064 } 1169d62bc4baSyz147064 1170d62bc4baSyz147064 vdp->vd_val = (uintptr_t)dlap; 1171d62bc4baSyz147064 return (DLADM_STATUS_OK); 1172d62bc4baSyz147064 } 1173d62bc4baSyz147064 1174e7801d59Ssowmini /* ARGSUSED */ 1175d62bc4baSyz147064 static dladm_status_t 1176e7801d59Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, 1177e7801d59Ssowmini char **prop_val, uint_t *val_cnt, uint_t id) 1178d62bc4baSyz147064 { 1179d62bc4baSyz147064 wl_rates_t *wrp; 1180d62bc4baSyz147064 uint_t i; 1181d62bc4baSyz147064 wldp_t *gbuf = NULL; 1182d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1183d62bc4baSyz147064 1184d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 1185d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1186d62bc4baSyz147064 goto done; 1187d62bc4baSyz147064 } 1188d62bc4baSyz147064 1189d62bc4baSyz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 1190d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1191d62bc4baSyz147064 goto done; 1192d62bc4baSyz147064 1193d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 1194d62bc4baSyz147064 if (wrp->wl_rates_num > *val_cnt) { 1195d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 1196d62bc4baSyz147064 goto done; 1197d62bc4baSyz147064 } 1198d62bc4baSyz147064 1199d62bc4baSyz147064 if (wrp->wl_rates_rates[0] == 0) { 1200d62bc4baSyz147064 prop_val[0][0] = '\0'; 1201d62bc4baSyz147064 *val_cnt = 1; 1202d62bc4baSyz147064 goto done; 1203d62bc4baSyz147064 } 1204d62bc4baSyz147064 1205d62bc4baSyz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 1206d62bc4baSyz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 1207d62bc4baSyz147064 wrp->wl_rates_rates[i] % 2, 1208d62bc4baSyz147064 (float)wrp->wl_rates_rates[i] / 2); 1209d62bc4baSyz147064 } 1210d62bc4baSyz147064 *val_cnt = wrp->wl_rates_num; 1211d62bc4baSyz147064 1212d62bc4baSyz147064 done: 1213d62bc4baSyz147064 free(gbuf); 1214d62bc4baSyz147064 return (status); 1215d62bc4baSyz147064 } 1216d62bc4baSyz147064 1217d62bc4baSyz147064 static dladm_status_t 1218e7801d59Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, 12194045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1220d62bc4baSyz147064 { 12216b9e797cSsowmini if (media != DL_WIFI) 12224045d941Ssowmini return (dld_speed_get(pd, linkid, prop_val, val_cnt, flags)); 12236b9e797cSsowmini 1224e7801d59Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 1225d62bc4baSyz147064 WL_DESIRED_RATES)); 1226d62bc4baSyz147064 } 1227d62bc4baSyz147064 12284045d941Ssowmini /* ARGSUSED */ 1229d62bc4baSyz147064 static dladm_status_t 1230e7801d59Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, 12314045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1232d62bc4baSyz147064 { 12336b9e797cSsowmini switch (media) { 12346b9e797cSsowmini case DL_ETHER: 12354045d941Ssowmini /* 12364045d941Ssowmini * Speed for ethernet links is unbounded. E.g., 802.11b 12374045d941Ssowmini * links can have a speed of 5.5 Gbps. 12384045d941Ssowmini */ 12394045d941Ssowmini return (DLADM_STATUS_NOTSUP); 12406b9e797cSsowmini 12416b9e797cSsowmini case DL_WIFI: 1242e7801d59Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 1243d62bc4baSyz147064 WL_SUPPORTED_RATES)); 12446b9e797cSsowmini default: 12456b9e797cSsowmini return (DLADM_STATUS_BADARG); 12466b9e797cSsowmini } 1247d62bc4baSyz147064 } 1248d62bc4baSyz147064 1249d62bc4baSyz147064 static dladm_status_t 1250d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 1251f4b3ec61Sdh155122 { 1252f4b3ec61Sdh155122 int i; 1253d62bc4baSyz147064 uint_t len; 1254d62bc4baSyz147064 wldp_t *gbuf; 1255d62bc4baSyz147064 wl_rates_t *wrp; 1256d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1257d62bc4baSyz147064 1258d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1259d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1260d62bc4baSyz147064 1261d62bc4baSyz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 1262d62bc4baSyz147064 1263d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 1264d62bc4baSyz147064 for (i = 0; i < rates->wr_cnt; i++) 1265d62bc4baSyz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 1266d62bc4baSyz147064 wrp->wl_rates_num = rates->wr_cnt; 1267d62bc4baSyz147064 1268d62bc4baSyz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 1269d62bc4baSyz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 1270d62bc4baSyz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 1271d62bc4baSyz147064 WLAN_SET_PARAM, len); 1272d62bc4baSyz147064 1273d62bc4baSyz147064 free(gbuf); 1274d62bc4baSyz147064 return (status); 1275d62bc4baSyz147064 } 1276d62bc4baSyz147064 1277e7801d59Ssowmini /* ARGSUSED */ 1278d62bc4baSyz147064 static dladm_status_t 1279e7801d59Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid, 12806b9e797cSsowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 1281d62bc4baSyz147064 { 1282d62bc4baSyz147064 dladm_wlan_rates_t rates; 1283f4b3ec61Sdh155122 dladm_status_t status; 1284f4b3ec61Sdh155122 12856b9e797cSsowmini /* 12866b9e797cSsowmini * can currently set rate on WIFI links only. 12876b9e797cSsowmini */ 12886b9e797cSsowmini if (media != DL_WIFI) 12896b9e797cSsowmini return (DLADM_STATUS_PROPRDONLY); 12906b9e797cSsowmini 1291d62bc4baSyz147064 if (val_cnt != 1) 1292d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1293f4b3ec61Sdh155122 1294d62bc4baSyz147064 rates.wr_cnt = 1; 1295d62bc4baSyz147064 rates.wr_rates[0] = vdp[0].vd_val; 1296f4b3ec61Sdh155122 1297d62bc4baSyz147064 status = do_set_rate(linkid, &rates); 1298f4b3ec61Sdh155122 1299d62bc4baSyz147064 done: 1300d62bc4baSyz147064 return (status); 1301d62bc4baSyz147064 } 1302d62bc4baSyz147064 1303d62bc4baSyz147064 /* ARGSUSED */ 1304d62bc4baSyz147064 static dladm_status_t 1305e7801d59Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 13066b9e797cSsowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 1307d62bc4baSyz147064 { 1308d62bc4baSyz147064 int i; 1309d62bc4baSyz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 1310d62bc4baSyz147064 char *buf, **modval; 1311d62bc4baSyz147064 dladm_status_t status; 1312d62bc4baSyz147064 1313d62bc4baSyz147064 if (val_cnt != 1) 1314d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1315d62bc4baSyz147064 1316d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 1317d62bc4baSyz147064 MAX_SUPPORT_RATES); 1318d62bc4baSyz147064 if (buf == NULL) { 1319d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1320d62bc4baSyz147064 goto done; 1321d62bc4baSyz147064 } 1322d62bc4baSyz147064 1323d62bc4baSyz147064 modval = (char **)(void *)buf; 1324d62bc4baSyz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 1325d62bc4baSyz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 1326d62bc4baSyz147064 i * DLADM_STRSIZE; 1327d62bc4baSyz147064 } 1328d62bc4baSyz147064 13294045d941Ssowmini status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media, 0); 1330d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1331d62bc4baSyz147064 goto done; 1332d62bc4baSyz147064 1333d62bc4baSyz147064 for (i = 0; i < modval_cnt; i++) { 1334d62bc4baSyz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 1335e7801d59Ssowmini vdp->vd_val = (uintptr_t)(uint_t) 1336e7801d59Ssowmini (atof(*prop_val) * 2); 1337f4b3ec61Sdh155122 status = DLADM_STATUS_OK; 1338f4b3ec61Sdh155122 break; 1339f4b3ec61Sdh155122 } 1340d62bc4baSyz147064 } 1341d62bc4baSyz147064 if (i == modval_cnt) 1342d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 1343d62bc4baSyz147064 done: 1344d62bc4baSyz147064 free(buf); 1345d62bc4baSyz147064 return (status); 1346d62bc4baSyz147064 } 1347f4b3ec61Sdh155122 1348d62bc4baSyz147064 static dladm_status_t 1349d62bc4baSyz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 1350d62bc4baSyz147064 { 1351d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 1352d62bc4baSyz147064 } 1353d62bc4baSyz147064 1354e7801d59Ssowmini /* ARGSUSED */ 1355d62bc4baSyz147064 static dladm_status_t 1356e7801d59Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, 13574045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1358d62bc4baSyz147064 { 1359d62bc4baSyz147064 uint32_t channel; 1360d62bc4baSyz147064 wldp_t *gbuf; 1361d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1362d62bc4baSyz147064 1363d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1364d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1365d62bc4baSyz147064 1366d62bc4baSyz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 1367d62bc4baSyz147064 goto done; 1368d62bc4baSyz147064 1369d62bc4baSyz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 1370d62bc4baSyz147064 &channel)) { 1371d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1372d62bc4baSyz147064 goto done; 1373d62bc4baSyz147064 } 1374d62bc4baSyz147064 1375d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 1376d62bc4baSyz147064 *val_cnt = 1; 1377d62bc4baSyz147064 1378d62bc4baSyz147064 done: 1379d62bc4baSyz147064 free(gbuf); 1380d62bc4baSyz147064 return (status); 1381d62bc4baSyz147064 } 1382d62bc4baSyz147064 1383d62bc4baSyz147064 static dladm_status_t 1384d62bc4baSyz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 1385d62bc4baSyz147064 { 1386d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 1387d62bc4baSyz147064 } 1388d62bc4baSyz147064 1389e7801d59Ssowmini /* ARGSUSED */ 1390d62bc4baSyz147064 static dladm_status_t 1391e7801d59Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, 13924045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1393d62bc4baSyz147064 { 1394d62bc4baSyz147064 wl_ps_mode_t *mode; 1395d62bc4baSyz147064 const char *s; 1396d62bc4baSyz147064 wldp_t *gbuf; 1397d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1398d62bc4baSyz147064 1399d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1400d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1401d62bc4baSyz147064 1402d62bc4baSyz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 1403d62bc4baSyz147064 goto done; 1404d62bc4baSyz147064 1405d62bc4baSyz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 1406d62bc4baSyz147064 switch (mode->wl_ps_mode) { 1407d62bc4baSyz147064 case WL_PM_AM: 1408d62bc4baSyz147064 s = "off"; 1409f4b3ec61Sdh155122 break; 1410d62bc4baSyz147064 case WL_PM_MPS: 1411d62bc4baSyz147064 s = "max"; 1412d62bc4baSyz147064 break; 1413d62bc4baSyz147064 case WL_PM_FAST: 1414d62bc4baSyz147064 s = "fast"; 1415f4b3ec61Sdh155122 break; 1416f4b3ec61Sdh155122 default: 1417d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1418d62bc4baSyz147064 goto done; 1419f4b3ec61Sdh155122 } 1420d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1421d62bc4baSyz147064 *val_cnt = 1; 1422d62bc4baSyz147064 1423d62bc4baSyz147064 done: 1424d62bc4baSyz147064 free(gbuf); 1425d62bc4baSyz147064 return (status); 1426d62bc4baSyz147064 } 1427d62bc4baSyz147064 1428d62bc4baSyz147064 static dladm_status_t 1429d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 1430d62bc4baSyz147064 { 1431d62bc4baSyz147064 wl_ps_mode_t ps_mode; 1432d62bc4baSyz147064 1433d62bc4baSyz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 1434d62bc4baSyz147064 1435d62bc4baSyz147064 switch (*pm) { 1436d62bc4baSyz147064 case DLADM_WLAN_PM_OFF: 1437d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_AM; 1438d62bc4baSyz147064 break; 1439d62bc4baSyz147064 case DLADM_WLAN_PM_MAX: 1440d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 1441d62bc4baSyz147064 break; 1442d62bc4baSyz147064 case DLADM_WLAN_PM_FAST: 1443d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 1444d62bc4baSyz147064 break; 1445d62bc4baSyz147064 default: 1446d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1447d62bc4baSyz147064 } 1448d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 1449d62bc4baSyz147064 sizeof (ps_mode))); 1450d62bc4baSyz147064 } 1451d62bc4baSyz147064 1452d62bc4baSyz147064 /* ARGSUSED */ 1453d62bc4baSyz147064 static dladm_status_t 1454e7801d59Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, 14556b9e797cSsowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 1456d62bc4baSyz147064 { 1457d62bc4baSyz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 1458d62bc4baSyz147064 dladm_status_t status; 1459d62bc4baSyz147064 1460d62bc4baSyz147064 if (val_cnt != 1) 1461d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1462d62bc4baSyz147064 1463d62bc4baSyz147064 status = do_set_powermode(linkid, &powermode); 1464f4b3ec61Sdh155122 1465f4b3ec61Sdh155122 return (status); 1466f4b3ec61Sdh155122 } 1467f4b3ec61Sdh155122 1468f4b3ec61Sdh155122 static dladm_status_t 1469d62bc4baSyz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 1470f4b3ec61Sdh155122 { 1471d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 1472d62bc4baSyz147064 } 1473d62bc4baSyz147064 1474e7801d59Ssowmini /* ARGSUSED */ 1475d62bc4baSyz147064 static dladm_status_t 1476e7801d59Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, 14774045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1478d62bc4baSyz147064 { 1479d62bc4baSyz147064 wl_radio_t radio; 1480d62bc4baSyz147064 const char *s; 1481d62bc4baSyz147064 wldp_t *gbuf; 1482d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1483d62bc4baSyz147064 1484d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1485d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1486d62bc4baSyz147064 1487d62bc4baSyz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 1488d62bc4baSyz147064 goto done; 1489d62bc4baSyz147064 1490d62bc4baSyz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 1491d62bc4baSyz147064 switch (radio) { 1492d62bc4baSyz147064 case B_TRUE: 1493d62bc4baSyz147064 s = "on"; 1494d62bc4baSyz147064 break; 1495d62bc4baSyz147064 case B_FALSE: 1496d62bc4baSyz147064 s = "off"; 1497d62bc4baSyz147064 break; 1498d62bc4baSyz147064 default: 1499d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1500d62bc4baSyz147064 goto done; 1501d62bc4baSyz147064 } 1502d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1503d62bc4baSyz147064 *val_cnt = 1; 1504d62bc4baSyz147064 1505d62bc4baSyz147064 done: 1506d62bc4baSyz147064 free(gbuf); 1507d62bc4baSyz147064 return (status); 1508d62bc4baSyz147064 } 1509d62bc4baSyz147064 1510d62bc4baSyz147064 static dladm_status_t 1511d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 1512d62bc4baSyz147064 { 1513d62bc4baSyz147064 wl_radio_t r; 1514d62bc4baSyz147064 1515d62bc4baSyz147064 switch (*radio) { 1516d62bc4baSyz147064 case DLADM_WLAN_RADIO_ON: 1517d62bc4baSyz147064 r = B_TRUE; 1518d62bc4baSyz147064 break; 1519d62bc4baSyz147064 case DLADM_WLAN_RADIO_OFF: 1520d62bc4baSyz147064 r = B_FALSE; 1521d62bc4baSyz147064 break; 1522d62bc4baSyz147064 default: 1523d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1524d62bc4baSyz147064 } 1525d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 1526d62bc4baSyz147064 } 1527d62bc4baSyz147064 1528d62bc4baSyz147064 /* ARGSUSED */ 1529d62bc4baSyz147064 static dladm_status_t 1530e7801d59Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid, 15316b9e797cSsowmini val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media) 1532d62bc4baSyz147064 { 1533d62bc4baSyz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 1534f4b3ec61Sdh155122 dladm_status_t status; 1535f4b3ec61Sdh155122 1536d62bc4baSyz147064 if (val_cnt != 1) 1537d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1538f4b3ec61Sdh155122 1539d62bc4baSyz147064 status = do_set_radio(linkid, &radio); 1540f4b3ec61Sdh155122 1541d62bc4baSyz147064 return (status); 1542d62bc4baSyz147064 } 1543f4b3ec61Sdh155122 1544d62bc4baSyz147064 static dladm_status_t 1545d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 1546d62bc4baSyz147064 char **prop_val, uint_t val_cnt) 1547d62bc4baSyz147064 { 1548d62bc4baSyz147064 char buf[MAXLINELEN]; 1549d62bc4baSyz147064 int i; 1550d62bc4baSyz147064 dladm_conf_t conf; 1551d62bc4baSyz147064 dladm_status_t status; 1552d62bc4baSyz147064 1553d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1554f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 1555f4b3ec61Sdh155122 return (status); 1556f4b3ec61Sdh155122 1557d62bc4baSyz147064 /* 1558d62bc4baSyz147064 * reset case. 1559d62bc4baSyz147064 */ 1560d62bc4baSyz147064 if (val_cnt == 0) { 1561d62bc4baSyz147064 status = dladm_unset_conf_field(conf, prop_name); 1562d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1563d62bc4baSyz147064 status = dladm_write_conf(conf); 1564d62bc4baSyz147064 goto done; 1565f4b3ec61Sdh155122 } 1566f4b3ec61Sdh155122 1567d62bc4baSyz147064 buf[0] = '\0'; 1568d62bc4baSyz147064 for (i = 0; i < val_cnt; i++) { 1569d62bc4baSyz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 1570d62bc4baSyz147064 if (i != val_cnt - 1) 1571d62bc4baSyz147064 (void) strlcat(buf, ",", MAXLINELEN); 1572d62bc4baSyz147064 } 1573f4b3ec61Sdh155122 1574d62bc4baSyz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 1575d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1576d62bc4baSyz147064 status = dladm_write_conf(conf); 1577d62bc4baSyz147064 1578d62bc4baSyz147064 done: 1579d62bc4baSyz147064 dladm_destroy_conf(conf); 1580f4b3ec61Sdh155122 return (status); 1581f4b3ec61Sdh155122 } 1582f4b3ec61Sdh155122 1583f4b3ec61Sdh155122 static dladm_status_t 1584d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 1585d62bc4baSyz147064 char **prop_val, uint_t *val_cntp) 1586f4b3ec61Sdh155122 { 1587d62bc4baSyz147064 char buf[MAXLINELEN], *str; 1588d62bc4baSyz147064 uint_t cnt = 0; 1589d62bc4baSyz147064 dladm_conf_t conf; 1590d62bc4baSyz147064 dladm_status_t status; 1591f4b3ec61Sdh155122 1592d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1593d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1594f4b3ec61Sdh155122 return (status); 1595d62bc4baSyz147064 1596d62bc4baSyz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 1597d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1598d62bc4baSyz147064 goto done; 1599d62bc4baSyz147064 1600d62bc4baSyz147064 str = strtok(buf, ","); 1601d62bc4baSyz147064 while (str != NULL) { 1602d62bc4baSyz147064 if (cnt == *val_cntp) { 1603d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 1604d62bc4baSyz147064 goto done; 1605d62bc4baSyz147064 } 1606d62bc4baSyz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 1607d62bc4baSyz147064 str = strtok(NULL, ","); 1608f4b3ec61Sdh155122 } 1609f4b3ec61Sdh155122 1610d62bc4baSyz147064 *val_cntp = cnt; 1611f4b3ec61Sdh155122 1612d62bc4baSyz147064 done: 1613d62bc4baSyz147064 dladm_destroy_conf(conf); 1614d62bc4baSyz147064 return (status); 1615f4b3ec61Sdh155122 } 1616e7801d59Ssowmini 1617e7801d59Ssowmini static dld_public_prop_t * 1618e7801d59Ssowmini dladm_name2prop(const char *prop_name) 1619e7801d59Ssowmini { 1620e7801d59Ssowmini dld_public_prop_t *p; 1621e7801d59Ssowmini 16223fd94f8cSam223141 for (p = dld_prop; p->pp_id != MAC_PROP_PRIVATE; p++) { 1623e7801d59Ssowmini if (strcmp(p->pp_name, prop_name) == 0) 1624e7801d59Ssowmini break; 1625e7801d59Ssowmini } 1626e7801d59Ssowmini return (p); 1627e7801d59Ssowmini } 1628e7801d59Ssowmini 1629e7801d59Ssowmini 16303fd94f8cSam223141 static dld_ioc_macprop_t * 1631e7801d59Ssowmini dld_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, 16324045d941Ssowmini uint_t flags, dladm_status_t *status) 1633e7801d59Ssowmini { 1634e7801d59Ssowmini int dsize; 16353fd94f8cSam223141 dld_ioc_macprop_t *dip; 1636e7801d59Ssowmini dld_public_prop_t *p; 1637e7801d59Ssowmini 1638e7801d59Ssowmini *status = DLADM_STATUS_OK; 1639e7801d59Ssowmini p = dladm_name2prop(prop_name); 16403fd94f8cSam223141 if (p->pp_id != MAC_PROP_PRIVATE) 1641e7801d59Ssowmini valsize = p->pp_valsize; 1642e7801d59Ssowmini 16433fd94f8cSam223141 dsize = MAC_PROP_BUFSIZE(valsize); 1644e7801d59Ssowmini dip = malloc(dsize); 1645e7801d59Ssowmini if (dip == NULL) { 1646e7801d59Ssowmini *status = DLADM_STATUS_NOMEM; 1647e7801d59Ssowmini return (NULL); 1648e7801d59Ssowmini } 1649e7801d59Ssowmini bzero(dip, dsize); 1650e7801d59Ssowmini dip->pr_valsize = valsize; 16514045d941Ssowmini (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name)); 16523fd94f8cSam223141 dip->pr_version = MAC_PROP_VERSION; 16536b9e797cSsowmini dip->pr_linkid = linkid; 1654e7801d59Ssowmini dip->pr_num = p->pp_id; 16554045d941Ssowmini dip->pr_flags = flags; 1656e7801d59Ssowmini return (dip); 1657e7801d59Ssowmini } 1658e7801d59Ssowmini 1659e7801d59Ssowmini /* ARGSUSED */ 1660e7801d59Ssowmini static dladm_status_t 1661e7801d59Ssowmini dld_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, 16626b9e797cSsowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 1663e7801d59Ssowmini { 16643fd94f8cSam223141 dld_ioc_macprop_t *dip; 1665e7801d59Ssowmini int fd, dsize; 1666e7801d59Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1667e7801d59Ssowmini uint8_t u8; 1668e7801d59Ssowmini uint16_t u16; 1669e7801d59Ssowmini uint32_t u32; 1670e7801d59Ssowmini void *val; 1671e7801d59Ssowmini 16724045d941Ssowmini dip = dld_buf_alloc(0, linkid, pd->pd_name, 0, &status); 1673e7801d59Ssowmini if (dip == NULL) 1674e7801d59Ssowmini return (status); 1675e7801d59Ssowmini 1676e7801d59Ssowmini if (pd->pd_flags & PD_CHECK_ALLOC) 1677e7801d59Ssowmini val = (void *)vdp->vd_val; 1678e7801d59Ssowmini else { 1679e7801d59Ssowmini /* 1680e7801d59Ssowmini * Currently all 1/2/4-byte size properties are byte/word/int. 1681e7801d59Ssowmini * No need (yet) to distinguish these from arrays of same size. 1682e7801d59Ssowmini */ 1683e7801d59Ssowmini switch (dip->pr_valsize) { 1684e7801d59Ssowmini case 1: 1685e7801d59Ssowmini u8 = vdp->vd_val; 1686e7801d59Ssowmini val = &u8; 1687e7801d59Ssowmini break; 1688e7801d59Ssowmini case 2: 1689e7801d59Ssowmini u16 = vdp->vd_val; 1690e7801d59Ssowmini val = &u16; 1691e7801d59Ssowmini break; 1692e7801d59Ssowmini case 4: 1693e7801d59Ssowmini u32 = vdp->vd_val; 1694e7801d59Ssowmini val = &u32; 1695e7801d59Ssowmini break; 1696e7801d59Ssowmini default: 1697e7801d59Ssowmini val = &vdp->vd_val; 1698e7801d59Ssowmini break; 1699e7801d59Ssowmini } 1700e7801d59Ssowmini } 1701e7801d59Ssowmini 1702e7801d59Ssowmini (void) memcpy(dip->pr_val, val, dip->pr_valsize); 17033fd94f8cSam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 1704e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1705e7801d59Ssowmini status = dladm_errno2status(errno); 1706e7801d59Ssowmini goto done; 1707e7801d59Ssowmini } 17083fd94f8cSam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) 1709e7801d59Ssowmini status = dladm_errno2status(errno); 1710e7801d59Ssowmini 1711e7801d59Ssowmini (void) close(fd); 1712e7801d59Ssowmini done: 17134045d941Ssowmini free(dip); 1714e7801d59Ssowmini return (status); 1715e7801d59Ssowmini } 1716e7801d59Ssowmini 17173fd94f8cSam223141 static dld_ioc_macprop_t * 17184045d941Ssowmini dld_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags, 17194045d941Ssowmini dladm_status_t *status) 1720e7801d59Ssowmini { 1721e7801d59Ssowmini int fd, dsize; 17223fd94f8cSam223141 dld_ioc_macprop_t *dip = NULL; 17234045d941Ssowmini 17244045d941Ssowmini *status = DLADM_STATUS_OK; 17254045d941Ssowmini 17264045d941Ssowmini dip = dld_buf_alloc(0, linkid, prop_name, flags, status); 17274045d941Ssowmini if (dip == NULL) 17284045d941Ssowmini return (NULL); 1729e7801d59Ssowmini 17303fd94f8cSam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 1731e7801d59Ssowmini 1732e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 17334045d941Ssowmini *status = dladm_errno2status(errno); 1734e7801d59Ssowmini goto done; 1735e7801d59Ssowmini } 17363fd94f8cSam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 17374045d941Ssowmini *status = dladm_errno2status(errno); 1738e7801d59Ssowmini } 17394045d941Ssowmini 17404045d941Ssowmini (void) close(fd); 1741e7801d59Ssowmini done: 17424045d941Ssowmini if (*status != DLADM_STATUS_OK) { 17434045d941Ssowmini free(dip); 17444045d941Ssowmini return (NULL); 17454045d941Ssowmini } 17464045d941Ssowmini return (dip); 1747e7801d59Ssowmini } 1748e7801d59Ssowmini 1749e7801d59Ssowmini /* ARGSUSED */ 1750e7801d59Ssowmini static dladm_status_t 1751e7801d59Ssowmini dld_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 17526b9e797cSsowmini uint_t val_cnt, val_desc_t *v, datalink_media_t media) 1753e7801d59Ssowmini { 1754e7801d59Ssowmini if (val_cnt != 1) 1755e7801d59Ssowmini return (DLADM_STATUS_BADVAL); 17564045d941Ssowmini v->vd_val = atoi(prop_val[0]); 1757e7801d59Ssowmini return (DLADM_STATUS_OK); 1758e7801d59Ssowmini } 1759e7801d59Ssowmini 1760e7801d59Ssowmini /* ARGSUSED */ 1761e7801d59Ssowmini static dladm_status_t 1762e7801d59Ssowmini dld_duplex_get(struct prop_desc *pd, datalink_id_t linkid, 17634045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1764e7801d59Ssowmini { 1765e7801d59Ssowmini link_duplex_t link_duplex; 1766e7801d59Ssowmini dladm_status_t status; 1767e7801d59Ssowmini 17683fd94f8cSam223141 if (flags & MAC_PROP_DEFAULT) 17694045d941Ssowmini return (DLADM_STATUS_NOTSUP); 17704045d941Ssowmini 1771e7801d59Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_duplex", 1772e7801d59Ssowmini KSTAT_DATA_UINT32, &link_duplex)) != 0) 1773e7801d59Ssowmini return (status); 1774e7801d59Ssowmini 1775e7801d59Ssowmini switch (link_duplex) { 1776e7801d59Ssowmini case LINK_DUPLEX_FULL: 1777e7801d59Ssowmini (void) strcpy(*prop_val, "full"); 1778e7801d59Ssowmini break; 1779e7801d59Ssowmini case LINK_DUPLEX_HALF: 1780e7801d59Ssowmini (void) strcpy(*prop_val, "half"); 1781e7801d59Ssowmini break; 1782e7801d59Ssowmini default: 1783e7801d59Ssowmini (void) strcpy(*prop_val, "unknown"); 1784e7801d59Ssowmini break; 1785e7801d59Ssowmini } 1786e7801d59Ssowmini *val_cnt = 1; 1787e7801d59Ssowmini return (DLADM_STATUS_OK); 1788e7801d59Ssowmini } 1789e7801d59Ssowmini 1790e7801d59Ssowmini /* ARGSUSED */ 1791e7801d59Ssowmini static dladm_status_t 1792e7801d59Ssowmini dld_speed_get(struct prop_desc *pd, datalink_id_t linkid, 17934045d941Ssowmini char **prop_val, uint_t *val_cnt, uint_t flags) 1794e7801d59Ssowmini { 1795e7801d59Ssowmini uint64_t ifspeed = 0; 1796e7801d59Ssowmini dladm_status_t status; 1797e7801d59Ssowmini 17983fd94f8cSam223141 if (flags & MAC_PROP_DEFAULT) 17994045d941Ssowmini return (DLADM_STATUS_NOTSUP); 18004045d941Ssowmini 1801e7801d59Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "ifspeed", 1802e7801d59Ssowmini KSTAT_DATA_UINT64, &ifspeed)) != 0) 1803e7801d59Ssowmini return (status); 18044045d941Ssowmini 18056b9e797cSsowmini if ((ifspeed % 1000000) != 0) { 18066b9e797cSsowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 18076b9e797cSsowmini "%llf", ifspeed / (float)1000000); /* Mbps */ 18086b9e797cSsowmini } else { 1809e7801d59Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 1810e7801d59Ssowmini "%llu", ifspeed / 1000000); /* Mbps */ 18116b9e797cSsowmini } 1812e7801d59Ssowmini *val_cnt = 1; 1813e7801d59Ssowmini return (DLADM_STATUS_OK); 1814e7801d59Ssowmini } 1815e7801d59Ssowmini 1816e7801d59Ssowmini /* ARGSUSED */ 1817e7801d59Ssowmini static dladm_status_t 1818e7801d59Ssowmini dld_status_get(struct prop_desc *pd, datalink_id_t linkid, 18194045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1820e7801d59Ssowmini { 1821e7801d59Ssowmini link_state_t link_state; 1822e7801d59Ssowmini dladm_status_t status; 18234045d941Ssowmini uchar_t *cp; 18243fd94f8cSam223141 dld_ioc_macprop_t *dip; 1825e7801d59Ssowmini 18263fd94f8cSam223141 if (flags & MAC_PROP_DEFAULT) 18274045d941Ssowmini return (DLADM_STATUS_NOTSUP); 18284045d941Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18294045d941Ssowmini if (status != DLADM_STATUS_OK) 1830e7801d59Ssowmini return (status); 18314045d941Ssowmini cp = (uchar_t *)dip->pr_val; 18324045d941Ssowmini (void) memcpy(&link_state, cp, sizeof (link_state)); 1833e7801d59Ssowmini 1834e7801d59Ssowmini switch (link_state) { 1835e7801d59Ssowmini case LINK_STATE_UP: 1836e7801d59Ssowmini (void) strcpy(*prop_val, "up"); 1837e7801d59Ssowmini break; 1838e7801d59Ssowmini case LINK_STATE_DOWN: 1839e7801d59Ssowmini (void) strcpy(*prop_val, "down"); 1840e7801d59Ssowmini break; 1841e7801d59Ssowmini default: 1842e7801d59Ssowmini (void) strcpy(*prop_val, "unknown"); 1843e7801d59Ssowmini break; 1844e7801d59Ssowmini } 1845e7801d59Ssowmini *val_cnt = 1; 18464045d941Ssowmini free(dip); 1847e7801d59Ssowmini return (DLADM_STATUS_OK); 1848e7801d59Ssowmini } 1849e7801d59Ssowmini 1850e7801d59Ssowmini /* ARGSUSED */ 1851e7801d59Ssowmini static dladm_status_t 1852e7801d59Ssowmini dld_binary_get(struct prop_desc *pd, datalink_id_t linkid, 18534045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1854e7801d59Ssowmini { 18553fd94f8cSam223141 dld_ioc_macprop_t *dip; 1856e7801d59Ssowmini dladm_status_t status; 1857e7801d59Ssowmini 18584045d941Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18594045d941Ssowmini if (dip == NULL) 1860e7801d59Ssowmini return (status); 1861e7801d59Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]); 1862e7801d59Ssowmini free(dip); 1863e7801d59Ssowmini *val_cnt = 1; 1864e7801d59Ssowmini return (DLADM_STATUS_OK); 1865e7801d59Ssowmini } 1866e7801d59Ssowmini 18676b9e797cSsowmini /* ARGSUSED */ 1868e7801d59Ssowmini static dladm_status_t 18694045d941Ssowmini dld_uint32_get(struct prop_desc *pd, datalink_id_t linkid, 18704045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1871e7801d59Ssowmini { 18723fd94f8cSam223141 dld_ioc_macprop_t *dip; 18734045d941Ssowmini uint32_t v = 0; 1874e7801d59Ssowmini uchar_t *cp; 1875e7801d59Ssowmini dladm_status_t status; 1876e7801d59Ssowmini 18774045d941Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18784045d941Ssowmini if (dip == NULL) 1879e7801d59Ssowmini return (status); 1880e7801d59Ssowmini cp = (uchar_t *)dip->pr_val; 1881e7801d59Ssowmini (void) memcpy(&v, cp, sizeof (v)); 18824045d941Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v); 1883e7801d59Ssowmini free(dip); 1884e7801d59Ssowmini *val_cnt = 1; 1885e7801d59Ssowmini return (DLADM_STATUS_OK); 1886e7801d59Ssowmini } 1887e7801d59Ssowmini 18886b9e797cSsowmini /* ARGSUSED */ 1889e7801d59Ssowmini static dladm_status_t 1890e7801d59Ssowmini dld_flowctl_get(struct prop_desc *pd, datalink_id_t linkid, 18914045d941Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 1892e7801d59Ssowmini { 18933fd94f8cSam223141 dld_ioc_macprop_t *dip; 1894e7801d59Ssowmini link_flowctrl_t v; 1895e7801d59Ssowmini dladm_status_t status; 1896e7801d59Ssowmini uchar_t *cp; 1897e7801d59Ssowmini 18984045d941Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18994045d941Ssowmini if (dip == NULL) 1900e7801d59Ssowmini return (status); 1901e7801d59Ssowmini cp = (uchar_t *)dip->pr_val; 1902e7801d59Ssowmini (void) memcpy(&v, cp, sizeof (v)); 1903e7801d59Ssowmini switch (v) { 1904e7801d59Ssowmini case LINK_FLOWCTRL_NONE: 1905e7801d59Ssowmini (void) sprintf(*prop_val, "no"); 1906e7801d59Ssowmini break; 1907e7801d59Ssowmini case LINK_FLOWCTRL_RX: 1908e7801d59Ssowmini (void) sprintf(*prop_val, "rx"); 1909e7801d59Ssowmini break; 1910e7801d59Ssowmini case LINK_FLOWCTRL_TX: 1911e7801d59Ssowmini (void) sprintf(*prop_val, "tx"); 1912e7801d59Ssowmini break; 1913e7801d59Ssowmini case LINK_FLOWCTRL_BI: 1914e7801d59Ssowmini (void) sprintf(*prop_val, "bi"); 1915e7801d59Ssowmini break; 1916e7801d59Ssowmini } 1917e7801d59Ssowmini free(dip); 1918e7801d59Ssowmini *val_cnt = 1; 1919e7801d59Ssowmini return (DLADM_STATUS_OK); 1920e7801d59Ssowmini } 1921e7801d59Ssowmini 1922e7801d59Ssowmini 1923e7801d59Ssowmini /* ARGSUSED */ 1924e7801d59Ssowmini static dladm_status_t 1925e7801d59Ssowmini dld_set_prop(datalink_id_t linkid, const char *prop_name, 1926e7801d59Ssowmini char **prop_val, uint_t val_cnt, uint_t flags) 1927e7801d59Ssowmini { 1928e7801d59Ssowmini int fd, i, slen; 1929e7801d59Ssowmini int bufsize = 0, dsize; 19303fd94f8cSam223141 dld_ioc_macprop_t *dip = NULL; 1931e7801d59Ssowmini uchar_t *dp; 1932e7801d59Ssowmini dld_public_prop_t *p; 19334045d941Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1934e7801d59Ssowmini 1935e7801d59Ssowmini if ((prop_name == NULL && prop_val != NULL) || 1936e7801d59Ssowmini (prop_val != NULL && val_cnt == 0)) 1937e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1938e7801d59Ssowmini p = dladm_name2prop(prop_name); 19393fd94f8cSam223141 if (p->pp_id != MAC_PROP_PRIVATE) 1940e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1941e7801d59Ssowmini 1942e7801d59Ssowmini /* 1943e7801d59Ssowmini * private properties: all parsing is done in the kernel. 1944e7801d59Ssowmini * allocate a enough space for each property + its separator (','). 1945e7801d59Ssowmini */ 1946e7801d59Ssowmini for (i = 0; i < val_cnt; i++) { 1947e7801d59Ssowmini bufsize += strlen(prop_val[i]) + 1; 1948e7801d59Ssowmini } 19494045d941Ssowmini 19504045d941Ssowmini if (prop_val == NULL) { 19514045d941Ssowmini /* 19524045d941Ssowmini * getting default value. so use more buffer space. 19534045d941Ssowmini */ 19544045d941Ssowmini bufsize += 1024; 19554045d941Ssowmini } 19564045d941Ssowmini 19574045d941Ssowmini dip = dld_buf_alloc(bufsize + 1, linkid, prop_name, 19583fd94f8cSam223141 (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status); 1959e7801d59Ssowmini if (dip == NULL) 1960e7801d59Ssowmini return (status); 1961e7801d59Ssowmini 1962e7801d59Ssowmini dp = (uchar_t *)dip->pr_val; 19633fd94f8cSam223141 dsize = sizeof (dld_ioc_macprop_t) + bufsize; 1964e7801d59Ssowmini slen = 0; 19654045d941Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 19664045d941Ssowmini status = dladm_errno2status(errno); 19674045d941Ssowmini goto done; 19684045d941Ssowmini } 19694045d941Ssowmini if (prop_val == NULL) { 19703fd94f8cSam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 19714045d941Ssowmini status = dladm_errno2status(errno); 19724045d941Ssowmini goto done; 19734045d941Ssowmini } 19744045d941Ssowmini } else { 1975e7801d59Ssowmini for (i = 0; i < val_cnt; i++) { 1976e7801d59Ssowmini int plen = 0; 1977e7801d59Ssowmini 1978e7801d59Ssowmini plen = strlen(prop_val[i]); 1979e7801d59Ssowmini bcopy(prop_val[i], dp, plen); 1980e7801d59Ssowmini slen += plen; 1981e7801d59Ssowmini /* 1982e7801d59Ssowmini * add a "," separator and update dp. 1983e7801d59Ssowmini */ 1984e7801d59Ssowmini if (i != (val_cnt -1)) 1985e7801d59Ssowmini dp[slen++] = ','; 1986e7801d59Ssowmini dp += (plen + 1); 1987e7801d59Ssowmini } 1988e7801d59Ssowmini } 19893fd94f8cSam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) { 19904045d941Ssowmini status = dladm_errno2status(errno); 19914045d941Ssowmini } 19924045d941Ssowmini 19934045d941Ssowmini done: 19944045d941Ssowmini if (fd > 0) 19954045d941Ssowmini (void) close(fd); 1996e7801d59Ssowmini free(dip); 1997e7801d59Ssowmini return (status); 1998e7801d59Ssowmini } 1999e7801d59Ssowmini 2000e7801d59Ssowmini static dladm_status_t 2001e7801d59Ssowmini dld_get_prop(datalink_id_t linkid, const char *prop_name, 20024045d941Ssowmini char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags) 2003e7801d59Ssowmini { 2004e7801d59Ssowmini int fd; 2005e7801d59Ssowmini dladm_status_t status = DLADM_STATUS_OK; 2006e7801d59Ssowmini uint_t dsize; 20073fd94f8cSam223141 dld_ioc_macprop_t *dip = NULL; 2008e7801d59Ssowmini dld_public_prop_t *p; 2009e7801d59Ssowmini char tmp = '\0'; 2010e7801d59Ssowmini 2011e7801d59Ssowmini if ((prop_name == NULL && prop_val != NULL) || 2012e7801d59Ssowmini (prop_val != NULL && val_cnt == 0)) 2013e7801d59Ssowmini return (DLADM_STATUS_BADARG); 2014e7801d59Ssowmini 2015e7801d59Ssowmini p = dladm_name2prop(prop_name); 20163fd94f8cSam223141 if (p->pp_id != MAC_PROP_PRIVATE) 2017e7801d59Ssowmini return (DLADM_STATUS_BADARG); 2018e7801d59Ssowmini 20194045d941Ssowmini if (type == DLADM_PROP_VAL_MODIFIABLE) { 2020e7801d59Ssowmini *prop_val = &tmp; 2021e7801d59Ssowmini *val_cnt = 1; 2022e7801d59Ssowmini return (DLADM_STATUS_OK); 2023e7801d59Ssowmini } 2024e7801d59Ssowmini 2025e7801d59Ssowmini /* 2026e7801d59Ssowmini * private properties: all parsing is done in the kernel. 2027e7801d59Ssowmini */ 20284045d941Ssowmini dip = dld_buf_alloc(1024, linkid, prop_name, dld_flags, &status); 2029e7801d59Ssowmini if (dip == NULL) 2030e7801d59Ssowmini return (status); 20313fd94f8cSam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 2032e7801d59Ssowmini 20334045d941Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 20344045d941Ssowmini free(dip); 2035e7801d59Ssowmini return (DLADM_STATUS_BADARG); 20364045d941Ssowmini } 2037e7801d59Ssowmini 20383fd94f8cSam223141 if ((status = i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize)) < 0) { 2039e7801d59Ssowmini status = dladm_errno2status(errno); 2040e7801d59Ssowmini } else { 2041e7801d59Ssowmini (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); 2042e7801d59Ssowmini *val_cnt = 1; 2043e7801d59Ssowmini } 20444045d941Ssowmini 20454045d941Ssowmini (void) close(fd); 20464045d941Ssowmini free(dip); 20474045d941Ssowmini return (status); 20484045d941Ssowmini } 20494045d941Ssowmini 20504045d941Ssowmini 20514045d941Ssowmini static dladm_status_t 20524045d941Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid, 20534045d941Ssowmini datalink_media_t media, uint_t flags) 20544045d941Ssowmini { 20554045d941Ssowmini dladm_status_t status; 20564045d941Ssowmini char **prop_vals = NULL, *buf; 20574045d941Ssowmini size_t bufsize; 20584045d941Ssowmini uint_t cnt; 20594045d941Ssowmini int i; 20604045d941Ssowmini 20614045d941Ssowmini /* 20624045d941Ssowmini * Allocate buffer needed for prop_vals array. We can have at most 20634045d941Ssowmini * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where 20644045d941Ssowmini * each entry has max size DLADM_PROP_VAL_MAX 20654045d941Ssowmini */ 20664045d941Ssowmini bufsize = 20674045d941Ssowmini (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 20684045d941Ssowmini buf = malloc(bufsize); 20694045d941Ssowmini prop_vals = (char **)(void *)buf; 20704045d941Ssowmini for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 20714045d941Ssowmini prop_vals[i] = buf + 20724045d941Ssowmini sizeof (char *) * DLADM_MAX_PROP_VALCNT + 20734045d941Ssowmini i * DLADM_PROP_VAL_MAX; 20744045d941Ssowmini } 207513a55820Sar224390 207613a55820Sar224390 /* 207713a55820Sar224390 * PD_EMPTY_RESET is used for properties like zone where the 207813a55820Sar224390 * "" itself is used to reset the property. So libdladm can 207913a55820Sar224390 * copy pdp->pd_defval over to the val_desc_t passed down on 208013a55820Sar224390 * the setprop using the global values in the table. For other 208113a55820Sar224390 * cases (PD_EMPTY_RESET is not set, vd_name is ""), doing 208213a55820Sar224390 * reset-linkprop will cause libdladm to do a getprop to find 208313a55820Sar224390 * the default value and then do a setprop to reset the value 208413a55820Sar224390 * to default. 208513a55820Sar224390 */ 20863fd94f8cSam223141 status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media, 20873fd94f8cSam223141 MAC_PROP_DEFAULT); 20884045d941Ssowmini if (status == DLADM_STATUS_OK) { 20894045d941Ssowmini status = i_dladm_set_single_prop(linkid, pdp->pd_class, 20904045d941Ssowmini media, pdp, prop_vals, cnt, flags); 20914045d941Ssowmini } 20924045d941Ssowmini free(buf); 2093e7801d59Ssowmini return (status); 2094e7801d59Ssowmini } 2095