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> 49*e7801d59Ssowmini #include <libdladm.h> 50*e7801d59Ssowmini #include <sys/param.h> 51*e7801d59Ssowmini #include <sys/dld.h> 52*e7801d59Ssowmini #include <inttypes.h> 53*e7801d59Ssowmini #include <sys/ethernet.h> 54f4b3ec61Sdh155122 55d62bc4baSyz147064 /* 56d62bc4baSyz147064 * The linkprop get() callback. 57*e7801d59Ssowmini * - 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 */ 63*e7801d59Ssowmini struct prop_desc; 64*e7801d59Ssowmini 65*e7801d59Ssowmini typedef dladm_status_t pd_getf_t(struct prop_desc *pd, 66*e7801d59Ssowmini datalink_id_t, char **propstp, uint_t *cntp); 67f4b3ec61Sdh155122 68d62bc4baSyz147064 /* 69d62bc4baSyz147064 * The linkprop set() callback. 70d62bc4baSyz147064 * - propval: a val_desc_t array which keeps the property values to be set. 71d62bc4baSyz147064 * - cnt: number of properties to be set. 72*e7801d59Ssowmini * - flags: additional flags passed down the system call. 73*e7801d59Ssowmini * 74*e7801d59Ssowmini * pd_set takes val_desc_t given by pd_check(), translates it into 75*e7801d59Ssowmini * a format suitable for kernel consumption. This may require allocation 76*e7801d59Ssowmini * of ioctl buffers etc. pd_set() may call another common routine (used 77*e7801d59Ssowmini * by all other pd_sets) which invokes the ioctl. 78d62bc4baSyz147064 */ 79*e7801d59Ssowmini typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t, 80*e7801d59Ssowmini val_desc_t *propval, uint_t cnt, uint_t flags); 81f4b3ec61Sdh155122 82f4b3ec61Sdh155122 83d62bc4baSyz147064 /* 84d62bc4baSyz147064 * The linkprop check() callback. 85d62bc4baSyz147064 * - propstrp: property string array which keeps the property to be checked. 86d62bc4baSyz147064 * - cnt: number of properties. 87d62bc4baSyz147064 * - propval: return value; the property values of the given property strings. 88*e7801d59Ssowmini * 89*e7801d59Ssowmini * pd_check checks that the input values are valid. It does so by 90*e7801d59Ssowmini * iteraring through the pd_modval list for the property. If 91*e7801d59Ssowmini * the modifiable values cannot be expressed as a list, a pd_check 92*e7801d59Ssowmini * specific to this property can be used. If the input values are 93*e7801d59Ssowmini * verified to be valid, pd_check allocates a val_desc_t and fills it 94*e7801d59Ssowmini * with either a val_desc_t found on the pd_modval list or something 95*e7801d59Ssowmini * generated on the fly. 96d62bc4baSyz147064 */ 97*e7801d59Ssowmini typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, 98*e7801d59Ssowmini datalink_id_t, char **propstrp, 99*e7801d59Ssowmini uint_t cnt, val_desc_t *propval); 100f4b3ec61Sdh155122 101*e7801d59Ssowmini typedef struct dld_public_prop_s { 102*e7801d59Ssowmini dld_prop_id_t pp_id; 103*e7801d59Ssowmini size_t pp_valsize; 104*e7801d59Ssowmini char *pp_name; 105*e7801d59Ssowmini char *pp_desc; 106*e7801d59Ssowmini } dld_public_prop_t; 107*e7801d59Ssowmini 108*e7801d59Ssowmini static dld_ioc_prop_t *dld_buf_alloc(size_t, datalink_id_t, const char *, 109*e7801d59Ssowmini dladm_status_t *); 110*e7801d59Ssowmini static dladm_status_t dld_set_prop(datalink_id_t, const char *, char **, 111*e7801d59Ssowmini uint_t, uint_t); 112*e7801d59Ssowmini static dladm_status_t dld_get_prop(datalink_id_t, const char *, char **, 113*e7801d59Ssowmini uint_t *, dladm_prop_type_t); 114d62bc4baSyz147064 static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, 115d62bc4baSyz147064 do_get_rate_prop, do_get_channel_prop, 116*e7801d59Ssowmini do_get_powermode_prop, do_get_radio_prop, 117*e7801d59Ssowmini dld_duplex_get, dld_speed_get, dld_status_get, 118*e7801d59Ssowmini dld_binary_get, dld_uint64_get, dld_flowctl_get; 119d62bc4baSyz147064 static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop, 120*e7801d59Ssowmini do_set_powermode_prop, do_set_radio_prop, 121*e7801d59Ssowmini dld_set_public_prop; 122*e7801d59Ssowmini static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, 123*e7801d59Ssowmini dld_defmtu_check; 124f4b3ec61Sdh155122 125f4b3ec61Sdh155122 typedef struct prop_desc { 126d62bc4baSyz147064 /* 127d62bc4baSyz147064 * link property name 128d62bc4baSyz147064 */ 129f4b3ec61Sdh155122 char *pd_name; 130d62bc4baSyz147064 131d62bc4baSyz147064 /* 132d62bc4baSyz147064 * default property value, can be set to { "", NULL } 133d62bc4baSyz147064 */ 134f4b3ec61Sdh155122 val_desc_t pd_defval; 135d62bc4baSyz147064 136d62bc4baSyz147064 /* 137d62bc4baSyz147064 * list of optional property values, can be NULL. 138d62bc4baSyz147064 * 139d62bc4baSyz147064 * This is set to non-NULL if there is a list of possible property 140d62bc4baSyz147064 * values. pd_optval would point to the array of possible values. 141d62bc4baSyz147064 */ 142d62bc4baSyz147064 val_desc_t *pd_optval; 143d62bc4baSyz147064 144d62bc4baSyz147064 /* 145d62bc4baSyz147064 * count of the above optional property values. 0 if pd_optval is NULL. 146d62bc4baSyz147064 */ 147d62bc4baSyz147064 uint_t pd_noptval; 148d62bc4baSyz147064 149d62bc4baSyz147064 /* 150d62bc4baSyz147064 * callback to set link property; 151d62bc4baSyz147064 * set to NULL if this property is read-only 152d62bc4baSyz147064 */ 153f4b3ec61Sdh155122 pd_setf_t *pd_set; 154d62bc4baSyz147064 155d62bc4baSyz147064 /* 156d62bc4baSyz147064 * callback to get modifiable link property 157d62bc4baSyz147064 */ 158f4b3ec61Sdh155122 pd_getf_t *pd_getmod; 159d62bc4baSyz147064 160d62bc4baSyz147064 /* 161d62bc4baSyz147064 * callback to get current link property 162d62bc4baSyz147064 */ 163f4b3ec61Sdh155122 pd_getf_t *pd_get; 164d62bc4baSyz147064 165d62bc4baSyz147064 /* 166d62bc4baSyz147064 * callback to validate link property value, set to NULL if pd_optval 167d62bc4baSyz147064 * is not NULL. In that case, validate the value by comparing it with 168d62bc4baSyz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 169d62bc4baSyz147064 * valid. 170d62bc4baSyz147064 */ 171f4b3ec61Sdh155122 pd_checkf_t *pd_check; 172d62bc4baSyz147064 173d62bc4baSyz147064 uint_t pd_flags; 174*e7801d59Ssowmini #define PD_TEMPONLY 0x1 /* property is temporary only */ 175*e7801d59Ssowmini #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */ 176d62bc4baSyz147064 /* 177d62bc4baSyz147064 * indicate link classes this property applies to. 178d62bc4baSyz147064 */ 179d62bc4baSyz147064 datalink_class_t pd_class; 180d62bc4baSyz147064 181d62bc4baSyz147064 /* 182d62bc4baSyz147064 * indicate link media type this property applies to. 183d62bc4baSyz147064 */ 184d62bc4baSyz147064 datalink_media_t pd_dmedia; 185f4b3ec61Sdh155122 } prop_desc_t; 186f4b3ec61Sdh155122 187*e7801d59Ssowmini #define DLD_PROPBUF_SIZE(v) sizeof (dld_ioc_prop_t) + (v) - 1 188*e7801d59Ssowmini 189*e7801d59Ssowmini 190*e7801d59Ssowmini static dld_public_prop_t dld_prop[] = { 191*e7801d59Ssowmini { DLD_PROP_DUPLEX, sizeof (uint8_t), 192*e7801d59Ssowmini "link_duplex", "link duplex mode" }, 193*e7801d59Ssowmini 194*e7801d59Ssowmini {DLD_PROP_SPEED, sizeof (uint8_t), 195*e7801d59Ssowmini "ifspeed", "link speed (Mbps)" }, 196*e7801d59Ssowmini 197*e7801d59Ssowmini { DLD_PROP_STATUS, sizeof (uint8_t), 198*e7801d59Ssowmini "link_up", "link up/down" }, 199*e7801d59Ssowmini 200*e7801d59Ssowmini { DLD_PROP_AUTONEG, sizeof (uint8_t), 201*e7801d59Ssowmini "adv_autoneg_cap", "Advertised auto-negotiation" }, 202*e7801d59Ssowmini 203*e7801d59Ssowmini { DLD_PROP_DEFMTU, sizeof (uint64_t), 204*e7801d59Ssowmini "default_mtu", "default frame mtu" }, 205*e7801d59Ssowmini 206*e7801d59Ssowmini { DLD_PROP_FLOWCTRL, sizeof (link_flowctrl_t), 207*e7801d59Ssowmini "flowctrl", "flowcontrol" }, 208*e7801d59Ssowmini 209*e7801d59Ssowmini { DLD_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), 210*e7801d59Ssowmini "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, 211*e7801d59Ssowmini 212*e7801d59Ssowmini { DLD_PROP_EN_1000FDX_CAP, sizeof (uint8_t), 213*e7801d59Ssowmini "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, 214*e7801d59Ssowmini 215*e7801d59Ssowmini { DLD_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), 216*e7801d59Ssowmini "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, 217*e7801d59Ssowmini 218*e7801d59Ssowmini { DLD_PROP_EN_1000HDX_CAP, sizeof (uint8_t), 219*e7801d59Ssowmini "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, 220*e7801d59Ssowmini 221*e7801d59Ssowmini { DLD_PROP_ADV_100FDX_CAP, sizeof (uint8_t), 222*e7801d59Ssowmini "adv_100fdx_cap", "Adv 100 Mbps fdx" }, 223*e7801d59Ssowmini 224*e7801d59Ssowmini { DLD_PROP_EN_100FDX_CAP, sizeof (uint8_t), 225*e7801d59Ssowmini "en_100fdx_cap", "Enable 100 Mbps fdx" }, 226*e7801d59Ssowmini 227*e7801d59Ssowmini { DLD_PROP_ADV_100HDX_CAP, sizeof (uint8_t), 228*e7801d59Ssowmini "adv_100hdx_cap", "Adv 100 Mbps hdx" }, 229*e7801d59Ssowmini 230*e7801d59Ssowmini { DLD_PROP_EN_100HDX_CAP, sizeof (uint8_t), 231*e7801d59Ssowmini "en_100hdx_cap", "Enable 100 Mbps hdx" }, 232*e7801d59Ssowmini 233*e7801d59Ssowmini { DLD_PROP_ADV_10FDX_CAP, sizeof (uint8_t), 234*e7801d59Ssowmini "adv_10fdx_cap", "Adv 10 Mbps fdx" }, 235*e7801d59Ssowmini 236*e7801d59Ssowmini { DLD_PROP_EN_10FDX_CAP, sizeof (uint8_t), 237*e7801d59Ssowmini "en_10fdx_cap", "Enable 10 Mbps fdx" }, 238*e7801d59Ssowmini 239*e7801d59Ssowmini { DLD_PROP_ADV_10HDX_CAP, sizeof (uint8_t), 240*e7801d59Ssowmini "adv_10hdx_cap", "Adv 10 Mbps hdx" }, 241*e7801d59Ssowmini 242*e7801d59Ssowmini { DLD_PROP_EN_10HDX_CAP, sizeof (uint8_t), 243*e7801d59Ssowmini "en_10hdx_cap", "Enable 10 Mbps hdx" }, 244*e7801d59Ssowmini 245*e7801d59Ssowmini { DLD_PROP_PRIVATE, 0, 246*e7801d59Ssowmini "driver-private", "" } 247*e7801d59Ssowmini }; 248*e7801d59Ssowmini 249*e7801d59Ssowmini static val_desc_t link_duplex_vals[] = { 250*e7801d59Ssowmini { "half", LINK_DUPLEX_HALF }, 251*e7801d59Ssowmini { "full", LINK_DUPLEX_HALF } 252*e7801d59Ssowmini }; 253*e7801d59Ssowmini static val_desc_t link_speed_vals[] = { 254*e7801d59Ssowmini { "10", 10 }, 255*e7801d59Ssowmini { "100", 100 }, 256*e7801d59Ssowmini { "1000", 1000 } 257*e7801d59Ssowmini }; 258*e7801d59Ssowmini static val_desc_t link_status_vals[] = { 259*e7801d59Ssowmini { "up", LINK_STATE_UP }, 260*e7801d59Ssowmini { "down", LINK_STATE_DOWN } 261*e7801d59Ssowmini }; 262*e7801d59Ssowmini static val_desc_t link_01_vals[] = { 263*e7801d59Ssowmini { "1", 1 }, 264*e7801d59Ssowmini { "0", 0 } 265*e7801d59Ssowmini }; 266*e7801d59Ssowmini static val_desc_t link_flow_vals[] = { 267*e7801d59Ssowmini { "no", LINK_FLOWCTRL_NONE }, 268*e7801d59Ssowmini { "tx", LINK_FLOWCTRL_TX }, 269*e7801d59Ssowmini { "rx", LINK_FLOWCTRL_RX }, 270*e7801d59Ssowmini { "bi", LINK_FLOWCTRL_BI } 271*e7801d59Ssowmini }; 272*e7801d59Ssowmini static val_desc_t macdefaultmtu_vals[] = { 273*e7801d59Ssowmini { "68-9000", NULL } 274*e7801d59Ssowmini }; 275*e7801d59Ssowmini 276*e7801d59Ssowmini #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) 277*e7801d59Ssowmini 278d62bc4baSyz147064 static val_desc_t dladm_wlan_radio_vals[] = { 279d62bc4baSyz147064 { "on", DLADM_WLAN_RADIO_ON }, 280d62bc4baSyz147064 { "off", DLADM_WLAN_RADIO_OFF } 281d62bc4baSyz147064 }; 282d62bc4baSyz147064 283d62bc4baSyz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 284d62bc4baSyz147064 { "off", DLADM_WLAN_PM_OFF }, 285d62bc4baSyz147064 { "fast", DLADM_WLAN_PM_FAST }, 286d62bc4baSyz147064 { "max", DLADM_WLAN_PM_MAX } 287d62bc4baSyz147064 }; 288d62bc4baSyz147064 289f4b3ec61Sdh155122 static prop_desc_t prop_table[] = { 290d62bc4baSyz147064 291*e7801d59Ssowmini { "channel", { NULL, 0 }, 292*e7801d59Ssowmini NULL, 0, NULL, NULL, 293d62bc4baSyz147064 do_get_channel_prop, NULL, 0, 294d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 295d62bc4baSyz147064 296d62bc4baSyz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 297d62bc4baSyz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 298d62bc4baSyz147064 do_set_powermode_prop, NULL, 299d62bc4baSyz147064 do_get_powermode_prop, NULL, 0, 300d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 301d62bc4baSyz147064 302d62bc4baSyz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 303d62bc4baSyz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 304d62bc4baSyz147064 do_set_radio_prop, NULL, 305d62bc4baSyz147064 do_get_radio_prop, NULL, 0, 306d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 307d62bc4baSyz147064 308d62bc4baSyz147064 { "speed", { "", 0 }, NULL, 0, 309d62bc4baSyz147064 do_set_rate_prop, do_get_rate_mod, 310d62bc4baSyz147064 do_get_rate_prop, do_check_rate, 0, 311d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI }, 312d62bc4baSyz147064 313d62bc4baSyz147064 { "autopush", { "", NULL }, NULL, 0, 314d62bc4baSyz147064 do_set_autopush, NULL, 315*e7801d59Ssowmini do_get_autopush, do_check_autopush, PD_CHECK_ALLOC, 316d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 317d62bc4baSyz147064 318d62bc4baSyz147064 { "zone", { "", NULL }, NULL, 0, 319f4b3ec61Sdh155122 do_set_zone, NULL, 320d62bc4baSyz147064 do_get_zone, do_check_zone, PD_TEMPONLY, 321*e7801d59Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 322*e7801d59Ssowmini 323*e7801d59Ssowmini { "link_duplex", { "full", LINK_DUPLEX_FULL }, 324*e7801d59Ssowmini link_duplex_vals, VALCNT(link_duplex_vals), 325*e7801d59Ssowmini NULL, NULL, dld_duplex_get, NULL, 326*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 327*e7801d59Ssowmini 328*e7801d59Ssowmini { "ifspeed", { "1000", 1000 }, 329*e7801d59Ssowmini link_speed_vals, VALCNT(link_speed_vals), 330*e7801d59Ssowmini NULL, NULL, dld_speed_get, NULL, 331*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 332*e7801d59Ssowmini 333*e7801d59Ssowmini { "link_up", { "up", LINK_STATE_UP }, 334*e7801d59Ssowmini link_status_vals, VALCNT(link_status_vals), 335*e7801d59Ssowmini NULL, NULL, dld_status_get, NULL, 336*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 337*e7801d59Ssowmini 338*e7801d59Ssowmini { "adv_autoneg_cap", { "1", 1 }, 339*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 340*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 341*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 342*e7801d59Ssowmini 343*e7801d59Ssowmini { "default_mtu", { NULL, NULL }, 344*e7801d59Ssowmini macdefaultmtu_vals, VALCNT(macdefaultmtu_vals), 345*e7801d59Ssowmini dld_set_public_prop, NULL, dld_uint64_get, dld_defmtu_check, 346*e7801d59Ssowmini PD_CHECK_ALLOC, DATALINK_CLASS_PHYS, DL_ETHER }, 347*e7801d59Ssowmini 348*e7801d59Ssowmini { "flowctrl", { "bi", LINK_FLOWCTRL_BI }, 349*e7801d59Ssowmini link_flow_vals, VALCNT(link_flow_vals), 350*e7801d59Ssowmini dld_set_public_prop, NULL, dld_flowctl_get, NULL, 351*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 352*e7801d59Ssowmini 353*e7801d59Ssowmini { "adv_1000fdx_cap", { NULL, NULL }, 354*e7801d59Ssowmini link_01_vals, 0, 355*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 356*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 357*e7801d59Ssowmini 358*e7801d59Ssowmini { "en_1000fdx_cap", { NULL, NULL }, 359*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 360*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 361*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 362*e7801d59Ssowmini 363*e7801d59Ssowmini { "adv_1000hdx_cap", { NULL, NULL }, 364*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 365*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 366*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 367*e7801d59Ssowmini 368*e7801d59Ssowmini { "en_1000hdx_cap", { NULL, NULL }, 369*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 370*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 371*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 372*e7801d59Ssowmini 373*e7801d59Ssowmini { "adv_100fdx_cap", { NULL, NULL }, 374*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 375*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 376*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 377*e7801d59Ssowmini 378*e7801d59Ssowmini { "en_100fdx_cap", { NULL, NULL }, 379*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 380*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 381*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 382*e7801d59Ssowmini 383*e7801d59Ssowmini { "adv_100hdx_cap", { NULL, NULL }, 384*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 385*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 386*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 387*e7801d59Ssowmini 388*e7801d59Ssowmini { "en_100hdx_cap", { NULL, NULL }, 389*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 390*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 391*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 392*e7801d59Ssowmini 393*e7801d59Ssowmini { "adv_10fdx_cap", { NULL, NULL }, 394*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 395*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 396*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 397*e7801d59Ssowmini 398*e7801d59Ssowmini { "en_10fdx_cap", { NULL, NULL }, 399*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 400*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 401*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 402*e7801d59Ssowmini 403*e7801d59Ssowmini { "adv_10hdx_cap", { NULL, NULL }, 404*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 405*e7801d59Ssowmini NULL, NULL, dld_binary_get, NULL, 406*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 407*e7801d59Ssowmini 408*e7801d59Ssowmini { "en_10hdx_cap", { NULL, NULL }, 409*e7801d59Ssowmini link_01_vals, VALCNT(link_01_vals), 410*e7801d59Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 411*e7801d59Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER } 412*e7801d59Ssowmini 413f4b3ec61Sdh155122 }; 414f4b3ec61Sdh155122 415d62bc4baSyz147064 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 4160ba2cbe9Sxc151355 417d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, 418d62bc4baSyz147064 char **, uint_t); 419d62bc4baSyz147064 static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, 420d62bc4baSyz147064 char **, uint_t *); 421d62bc4baSyz147064 static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t, 422d62bc4baSyz147064 uint32_t, prop_desc_t *, char **, uint_t, uint_t); 423d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *, 424d62bc4baSyz147064 char **, uint_t, uint_t); 425d62bc4baSyz147064 426d62bc4baSyz147064 /* 427d62bc4baSyz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 428d62bc4baSyz147064 * rates to be retrieved. However, we cannot increase it at this 429d62bc4baSyz147064 * time because it will break binary compatibility with unbundled 430d62bc4baSyz147064 * WiFi drivers and utilities. So for now we define an additional 431d62bc4baSyz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 432d62bc4baSyz147064 */ 433d62bc4baSyz147064 #define MAX_SUPPORT_RATES 64 434d62bc4baSyz147064 435d62bc4baSyz147064 #define AP_ANCHOR "[anchor]" 436d62bc4baSyz147064 #define AP_DELIMITER '.' 437d62bc4baSyz147064 438d62bc4baSyz147064 static dladm_status_t 439d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 440d62bc4baSyz147064 val_desc_t *vdp) 4410ba2cbe9Sxc151355 { 442d62bc4baSyz147064 int i, j; 4430ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 4440ba2cbe9Sxc151355 445d62bc4baSyz147064 for (j = 0; j < val_cnt; j++) { 446d62bc4baSyz147064 for (i = 0; i < pdp->pd_noptval; i++) { 447d62bc4baSyz147064 if (strcasecmp(*prop_val, 448d62bc4baSyz147064 pdp->pd_optval[i].vd_name) == 0) { 4490ba2cbe9Sxc151355 break; 4500ba2cbe9Sxc151355 } 4510ba2cbe9Sxc151355 } 452d62bc4baSyz147064 if (i == pdp->pd_noptval) { 453d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 454d62bc4baSyz147064 goto done; 455d62bc4baSyz147064 } 456d62bc4baSyz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 4570ba2cbe9Sxc151355 } 4580ba2cbe9Sxc151355 459d62bc4baSyz147064 done: 460d62bc4baSyz147064 return (status); 4610ba2cbe9Sxc151355 } 4620ba2cbe9Sxc151355 4630ba2cbe9Sxc151355 static dladm_status_t 464d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 465d62bc4baSyz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 466d62bc4baSyz147064 uint_t flags) 4670ba2cbe9Sxc151355 { 4680ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 469d62bc4baSyz147064 val_desc_t *vdp = NULL; 470d62bc4baSyz147064 boolean_t needfree = B_FALSE; 471d62bc4baSyz147064 uint_t cnt, i; 4720ba2cbe9Sxc151355 473d62bc4baSyz147064 if (!(pdp->pd_class & class)) 474d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 4750ba2cbe9Sxc151355 476d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 477d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 478d62bc4baSyz147064 479d62bc4baSyz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 480d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 481d62bc4baSyz147064 482d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE)) 483d62bc4baSyz147064 return (DLADM_STATUS_OK); 484d62bc4baSyz147064 485d62bc4baSyz147064 if (pdp->pd_set == NULL) 486d62bc4baSyz147064 return (DLADM_STATUS_PROPRDONLY); 487d62bc4baSyz147064 488*e7801d59Ssowmini if (pdp->pd_flags & PD_CHECK_ALLOC) 489*e7801d59Ssowmini needfree = B_TRUE; 490*e7801d59Ssowmini else 491*e7801d59Ssowmini needfree = B_FALSE; 492d62bc4baSyz147064 if (prop_val != NULL) { 493d62bc4baSyz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 494d62bc4baSyz147064 if (vdp == NULL) 495d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 496d62bc4baSyz147064 497*e7801d59Ssowmini 498d62bc4baSyz147064 if (pdp->pd_check != NULL) { 499*e7801d59Ssowmini status = pdp->pd_check(pdp, linkid, prop_val, val_cnt, 500*e7801d59Ssowmini vdp); 501d62bc4baSyz147064 } else if (pdp->pd_optval != NULL) { 502d62bc4baSyz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 503d62bc4baSyz147064 } else { 504d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 5050ba2cbe9Sxc151355 } 5060ba2cbe9Sxc151355 507d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 508d62bc4baSyz147064 goto done; 509d62bc4baSyz147064 510d62bc4baSyz147064 cnt = val_cnt; 511d62bc4baSyz147064 } else { 512d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) 513d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 514d62bc4baSyz147064 515d62bc4baSyz147064 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 516d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 517d62bc4baSyz147064 518d62bc4baSyz147064 (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t)); 519d62bc4baSyz147064 cnt = 1; 520d62bc4baSyz147064 } 521*e7801d59Ssowmini status = pdp->pd_set(pdp, linkid, vdp, cnt, flags); 522d62bc4baSyz147064 if (needfree) { 523d62bc4baSyz147064 for (i = 0; i < cnt; i++) 524*e7801d59Ssowmini free((void *)((val_desc_t *)vdp + i)->vd_val); 525d62bc4baSyz147064 } 526d62bc4baSyz147064 done: 527d62bc4baSyz147064 free(vdp); 528d62bc4baSyz147064 return (status); 529d62bc4baSyz147064 } 530d62bc4baSyz147064 531d62bc4baSyz147064 static dladm_status_t 532d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 533d62bc4baSyz147064 char **prop_val, uint_t val_cnt, uint_t flags) 534d62bc4baSyz147064 { 535d62bc4baSyz147064 int i; 536d62bc4baSyz147064 boolean_t found = B_FALSE; 537d62bc4baSyz147064 datalink_class_t class; 538d62bc4baSyz147064 uint32_t media; 539d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 540d62bc4baSyz147064 541d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 542d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5430ba2cbe9Sxc151355 return (status); 5440ba2cbe9Sxc151355 545d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 546d62bc4baSyz147064 prop_desc_t *pdp = &prop_table[i]; 547d62bc4baSyz147064 dladm_status_t s; 5480ba2cbe9Sxc151355 549d62bc4baSyz147064 if (prop_name != NULL && 550d62bc4baSyz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 551d62bc4baSyz147064 continue; 552d62bc4baSyz147064 553d62bc4baSyz147064 found = B_TRUE; 554d62bc4baSyz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 555d62bc4baSyz147064 val_cnt, flags); 556d62bc4baSyz147064 557d62bc4baSyz147064 if (prop_name != NULL) { 558d62bc4baSyz147064 status = s; 559d62bc4baSyz147064 break; 560d62bc4baSyz147064 } else { 561d62bc4baSyz147064 if (s != DLADM_STATUS_OK && 562d62bc4baSyz147064 s != DLADM_STATUS_NOTSUP) 563d62bc4baSyz147064 status = s; 564d62bc4baSyz147064 } 565d62bc4baSyz147064 } 566*e7801d59Ssowmini if (!found) { 567*e7801d59Ssowmini if (prop_name[0] == '_') { 568*e7801d59Ssowmini /* other private properties */ 569*e7801d59Ssowmini status = dld_set_prop(linkid, prop_name, prop_val, 570*e7801d59Ssowmini val_cnt, flags); 571*e7801d59Ssowmini } else { 5720ba2cbe9Sxc151355 status = DLADM_STATUS_NOTFOUND; 573*e7801d59Ssowmini } 574*e7801d59Ssowmini } 5750ba2cbe9Sxc151355 5760ba2cbe9Sxc151355 return (status); 5770ba2cbe9Sxc151355 } 5780ba2cbe9Sxc151355 579d62bc4baSyz147064 /* 580d62bc4baSyz147064 * Set/reset link property for specific link 581d62bc4baSyz147064 */ 582d62bc4baSyz147064 dladm_status_t 583d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 584d62bc4baSyz147064 uint_t val_cnt, uint_t flags) 5850ba2cbe9Sxc151355 { 586d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 5870ba2cbe9Sxc151355 588d62bc4baSyz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 589d62bc4baSyz147064 (prop_val == NULL && val_cnt > 0) || 590d62bc4baSyz147064 (prop_val != NULL && val_cnt == 0) || 591d62bc4baSyz147064 (prop_name == NULL && prop_val != NULL)) { 592d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 5930ba2cbe9Sxc151355 } 5940ba2cbe9Sxc151355 595d62bc4baSyz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 596d62bc4baSyz147064 val_cnt, flags); 597d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 598d62bc4baSyz147064 return (status); 599d62bc4baSyz147064 600d62bc4baSyz147064 if (flags & DLADM_OPT_PERSIST) { 601d62bc4baSyz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 602d62bc4baSyz147064 prop_val, val_cnt); 603d62bc4baSyz147064 } 604d62bc4baSyz147064 return (status); 605d62bc4baSyz147064 } 606d62bc4baSyz147064 607d62bc4baSyz147064 /* 608d62bc4baSyz147064 * Walk link properties of the given specific link. 609d62bc4baSyz147064 */ 610d62bc4baSyz147064 dladm_status_t 611d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 612d62bc4baSyz147064 int (*func)(datalink_id_t, const char *, void *)) 6130ba2cbe9Sxc151355 { 614d62bc4baSyz147064 dladm_status_t status; 615d62bc4baSyz147064 datalink_class_t class; 616d62bc4baSyz147064 uint_t media; 617d62bc4baSyz147064 int i; 6180ba2cbe9Sxc151355 619d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 620d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 6210ba2cbe9Sxc151355 622d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 623d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 624d62bc4baSyz147064 return (status); 625d62bc4baSyz147064 626d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 627d62bc4baSyz147064 if (!(prop_table[i].pd_class & class)) 628d62bc4baSyz147064 continue; 629d62bc4baSyz147064 630d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 631d62bc4baSyz147064 continue; 632d62bc4baSyz147064 633d62bc4baSyz147064 if (func(linkid, prop_table[i].pd_name, arg) == 634d62bc4baSyz147064 DLADM_WALK_TERMINATE) { 635d62bc4baSyz147064 break; 636d62bc4baSyz147064 } 637d62bc4baSyz147064 } 638d62bc4baSyz147064 639d62bc4baSyz147064 return (DLADM_STATUS_OK); 640d62bc4baSyz147064 } 641d62bc4baSyz147064 642d62bc4baSyz147064 /* 643d62bc4baSyz147064 * Get linkprop of the given specific link. 644d62bc4baSyz147064 */ 645d62bc4baSyz147064 dladm_status_t 646d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 647d62bc4baSyz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 648d62bc4baSyz147064 { 649d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 650d62bc4baSyz147064 datalink_class_t class; 651d62bc4baSyz147064 uint_t media; 652d62bc4baSyz147064 prop_desc_t *pdp; 653d62bc4baSyz147064 uint_t cnt; 654d62bc4baSyz147064 int i; 655d62bc4baSyz147064 656d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 657d62bc4baSyz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 658d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 659d62bc4baSyz147064 660d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 661d62bc4baSyz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 662d62bc4baSyz147064 break; 663d62bc4baSyz147064 664*e7801d59Ssowmini if (i == DLADM_MAX_PROPS) { 665*e7801d59Ssowmini if (prop_name[0] == '_') { 666*e7801d59Ssowmini /* 667*e7801d59Ssowmini * private property. 668*e7801d59Ssowmini */ 669*e7801d59Ssowmini return (dld_get_prop(linkid, prop_name, 670*e7801d59Ssowmini prop_val, val_cntp, type)); 671*e7801d59Ssowmini } else { 672d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 673*e7801d59Ssowmini } 674*e7801d59Ssowmini } 675d62bc4baSyz147064 676d62bc4baSyz147064 pdp = &prop_table[i]; 677d62bc4baSyz147064 678d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 679d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 680d62bc4baSyz147064 return (status); 681d62bc4baSyz147064 682d62bc4baSyz147064 if (!(pdp->pd_class & class)) 683d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 684d62bc4baSyz147064 685d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 686d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 687d62bc4baSyz147064 688d62bc4baSyz147064 switch (type) { 689d62bc4baSyz147064 case DLADM_PROP_VAL_CURRENT: 690*e7801d59Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp); 691d62bc4baSyz147064 break; 692d62bc4baSyz147064 693d62bc4baSyz147064 case DLADM_PROP_VAL_DEFAULT: 694d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) { 695d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 696d62bc4baSyz147064 break; 697d62bc4baSyz147064 } 698d62bc4baSyz147064 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 699d62bc4baSyz147064 *val_cntp = 1; 700d62bc4baSyz147064 break; 701d62bc4baSyz147064 702d62bc4baSyz147064 case DLADM_PROP_VAL_MODIFIABLE: 703d62bc4baSyz147064 if (pdp->pd_getmod != NULL) { 704*e7801d59Ssowmini status = pdp->pd_getmod(pdp, linkid, prop_val, 705*e7801d59Ssowmini val_cntp); 706d62bc4baSyz147064 break; 707d62bc4baSyz147064 } 708d62bc4baSyz147064 cnt = pdp->pd_noptval; 709d62bc4baSyz147064 if (cnt == 0) { 710d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 711d62bc4baSyz147064 } else if (cnt > *val_cntp) { 712d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 713d62bc4baSyz147064 } else { 714d62bc4baSyz147064 for (i = 0; i < cnt; i++) { 715d62bc4baSyz147064 (void) strcpy(prop_val[i], 716d62bc4baSyz147064 pdp->pd_optval[i].vd_name); 717d62bc4baSyz147064 } 718d62bc4baSyz147064 *val_cntp = cnt; 719d62bc4baSyz147064 } 720d62bc4baSyz147064 break; 721d62bc4baSyz147064 case DLADM_PROP_VAL_PERSISTENT: 722d62bc4baSyz147064 if (pdp->pd_flags & PD_TEMPONLY) 723d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 724d62bc4baSyz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 725d62bc4baSyz147064 prop_val, val_cntp); 726d62bc4baSyz147064 break; 727d62bc4baSyz147064 default: 728d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 729d62bc4baSyz147064 break; 730d62bc4baSyz147064 } 731d62bc4baSyz147064 732d62bc4baSyz147064 return (status); 733d62bc4baSyz147064 } 734d62bc4baSyz147064 735d62bc4baSyz147064 /*ARGSUSED*/ 736d62bc4baSyz147064 static int 737d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 738d62bc4baSyz147064 { 739d62bc4baSyz147064 char *buf, **propvals; 740d62bc4baSyz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 741d62bc4baSyz147064 742d62bc4baSyz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 743d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 744d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 745d62bc4baSyz147064 } 746d62bc4baSyz147064 747d62bc4baSyz147064 propvals = (char **)(void *)buf; 748d62bc4baSyz147064 for (i = 0; i < valcnt; i++) { 749d62bc4baSyz147064 propvals[i] = buf + 750d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 751d62bc4baSyz147064 i * DLADM_PROP_VAL_MAX; 752d62bc4baSyz147064 } 753d62bc4baSyz147064 754d62bc4baSyz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 755d62bc4baSyz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 756d62bc4baSyz147064 goto done; 757d62bc4baSyz147064 } 758d62bc4baSyz147064 759d62bc4baSyz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 760d62bc4baSyz147064 DLADM_OPT_ACTIVE); 761d62bc4baSyz147064 762d62bc4baSyz147064 done: 763d62bc4baSyz147064 if (buf != NULL) 764d62bc4baSyz147064 free(buf); 765d62bc4baSyz147064 766d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 767d62bc4baSyz147064 } 768d62bc4baSyz147064 769d62bc4baSyz147064 /*ARGSUSED*/ 770d62bc4baSyz147064 static int 771d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 772d62bc4baSyz147064 { 773d62bc4baSyz147064 (void) dladm_init_linkprop(linkid); 774d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 7750ba2cbe9Sxc151355 } 7760ba2cbe9Sxc151355 7770ba2cbe9Sxc151355 dladm_status_t 778d62bc4baSyz147064 dladm_init_linkprop(datalink_id_t linkid) 7790ba2cbe9Sxc151355 { 780d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 781d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 782d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 783d62bc4baSyz147064 DLADM_OPT_PERSIST); 784d62bc4baSyz147064 } else { 785d62bc4baSyz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 786d62bc4baSyz147064 } 787d62bc4baSyz147064 return (DLADM_STATUS_OK); 7880ba2cbe9Sxc151355 } 789f4b3ec61Sdh155122 790*e7801d59Ssowmini /* ARGSUSED */ 791f4b3ec61Sdh155122 static dladm_status_t 792*e7801d59Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid, 793*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 794f4b3ec61Sdh155122 { 795d62bc4baSyz147064 char zone_name[ZONENAME_MAX]; 796d62bc4baSyz147064 zoneid_t zid; 797d62bc4baSyz147064 dladm_status_t status; 798f4b3ec61Sdh155122 799d62bc4baSyz147064 status = dladm_getzid(linkid, &zid); 800d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 801d62bc4baSyz147064 return (status); 802d62bc4baSyz147064 803d62bc4baSyz147064 *val_cnt = 1; 804d62bc4baSyz147064 if (zid != GLOBAL_ZONEID) { 805d62bc4baSyz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 806f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 807f4b3ec61Sdh155122 808d62bc4baSyz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 80947a01978Sbw } else { 810d62bc4baSyz147064 *prop_val[0] = '\0'; 81147a01978Sbw } 812f4b3ec61Sdh155122 813f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 814f4b3ec61Sdh155122 } 815f4b3ec61Sdh155122 816f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 817f4b3ec61Sdh155122 818f4b3ec61Sdh155122 static int 819f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 820f4b3ec61Sdh155122 { 821f4b3ec61Sdh155122 char root[MAXPATHLEN]; 822f4b3ec61Sdh155122 zone_get_devroot_t real_zone_get_devroot; 823f4b3ec61Sdh155122 void *dlhandle; 824f4b3ec61Sdh155122 void *sym; 825f4b3ec61Sdh155122 int ret; 826f4b3ec61Sdh155122 827f4b3ec61Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 828f4b3ec61Sdh155122 return (-1); 829f4b3ec61Sdh155122 830f4b3ec61Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 831f4b3ec61Sdh155122 (void) dlclose(dlhandle); 832f4b3ec61Sdh155122 return (-1); 833f4b3ec61Sdh155122 } 834f4b3ec61Sdh155122 835f4b3ec61Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 836f4b3ec61Sdh155122 837f4b3ec61Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 838f4b3ec61Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 839f4b3ec61Sdh155122 (void) dlclose(dlhandle); 840f4b3ec61Sdh155122 return (ret); 841f4b3ec61Sdh155122 } 842f4b3ec61Sdh155122 843f4b3ec61Sdh155122 static dladm_status_t 844d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 845f4b3ec61Sdh155122 { 846f4b3ec61Sdh155122 char path[MAXPATHLEN]; 847d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 848f4b3ec61Sdh155122 di_prof_t prof = NULL; 849f4b3ec61Sdh155122 char zone_name[ZONENAME_MAX]; 850f4b3ec61Sdh155122 dladm_status_t status; 851d62bc4baSyz147064 int ret; 852f4b3ec61Sdh155122 853f4b3ec61Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 854f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 855f4b3ec61Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 856f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 857f4b3ec61Sdh155122 if (di_prof_init(path, &prof) != 0) 858f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 859f4b3ec61Sdh155122 860d62bc4baSyz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 861f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 862d62bc4baSyz147064 goto cleanup; 863f4b3ec61Sdh155122 864d62bc4baSyz147064 if (add) 865d62bc4baSyz147064 ret = di_prof_add_dev(prof, name); 866d62bc4baSyz147064 else 867d62bc4baSyz147064 ret = di_prof_add_exclude(prof, name); 868f4b3ec61Sdh155122 869d62bc4baSyz147064 if (ret != 0) { 870d62bc4baSyz147064 status = dladm_errno2status(errno); 871d62bc4baSyz147064 goto cleanup; 872f4b3ec61Sdh155122 } 873f4b3ec61Sdh155122 874d62bc4baSyz147064 if (di_prof_commit(prof) != 0) 875d62bc4baSyz147064 status = dladm_errno2status(errno); 876d62bc4baSyz147064 cleanup: 877d62bc4baSyz147064 if (prof) 878d62bc4baSyz147064 di_prof_fini(prof); 879d62bc4baSyz147064 880d62bc4baSyz147064 return (status); 881f4b3ec61Sdh155122 } 882f4b3ec61Sdh155122 883*e7801d59Ssowmini /* ARGSUSED */ 884f4b3ec61Sdh155122 static dladm_status_t 885*e7801d59Ssowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, 886*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 887f4b3ec61Sdh155122 { 888f4b3ec61Sdh155122 dladm_status_t status; 889f4b3ec61Sdh155122 zoneid_t zid_old, zid_new; 890d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 891f4b3ec61Sdh155122 892f4b3ec61Sdh155122 if (val_cnt != 1) 893f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 894f4b3ec61Sdh155122 895d62bc4baSyz147064 status = dladm_getzid(linkid, &zid_old); 896f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 897f4b3ec61Sdh155122 return (status); 898f4b3ec61Sdh155122 899f4b3ec61Sdh155122 /* Do nothing if setting to current value */ 900d62bc4baSyz147064 zid_new = vdp->vd_val; 901f4b3ec61Sdh155122 if (zid_new == zid_old) 902f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 903f4b3ec61Sdh155122 904d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 905d62bc4baSyz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 906d62bc4baSyz147064 return (status); 907d62bc4baSyz147064 } 908f4b3ec61Sdh155122 909d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 910d62bc4baSyz147064 /* 911d62bc4baSyz147064 * If the new zoneid is the global zone, we could destroy 912d62bc4baSyz147064 * the link (in the case of an implicitly-created VLAN) as a 913d62bc4baSyz147064 * result of the dladm_setzid() operation. In that case, 914d62bc4baSyz147064 * we defer the operation to the end of this function to avoid 915d62bc4baSyz147064 * recreating the VLAN and getting a different linkid during 916d62bc4baSyz147064 * the rollback if other operation fails. 917d62bc4baSyz147064 * 918d62bc4baSyz147064 * Otherwise, dladm_setzid() will hold a reference to the 919d62bc4baSyz147064 * link and prevent a link renaming, so we need to do it 920d62bc4baSyz147064 * before other operations. 921d62bc4baSyz147064 */ 922d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 923d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 924d62bc4baSyz147064 return (status); 925d62bc4baSyz147064 } 926d62bc4baSyz147064 927d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) { 928d62bc4baSyz147064 if (zone_remove_datalink(zid_old, link) != 0 && 929f4b3ec61Sdh155122 errno != ENXIO) { 930f4b3ec61Sdh155122 status = dladm_errno2status(errno); 931f4b3ec61Sdh155122 goto rollback1; 932f4b3ec61Sdh155122 } 933f4b3ec61Sdh155122 934d62bc4baSyz147064 /* 935d62bc4baSyz147064 * It is okay to fail to update the /dev entry (some 936d62bc4baSyz147064 * vanity-named links do not have a /dev entry). 937d62bc4baSyz147064 */ 938d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 939d62bc4baSyz147064 } 940d62bc4baSyz147064 941d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 942d62bc4baSyz147064 if (zone_add_datalink(zid_new, link) != 0) { 943d62bc4baSyz147064 status = dladm_errno2status(errno); 944d62bc4baSyz147064 goto rollback2; 945d62bc4baSyz147064 } 946d62bc4baSyz147064 947d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 948d62bc4baSyz147064 } else { 949d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 950f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 951f4b3ec61Sdh155122 goto rollback2; 952f4b3ec61Sdh155122 } 953f4b3ec61Sdh155122 954f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 955f4b3ec61Sdh155122 956f4b3ec61Sdh155122 rollback2: 957f4b3ec61Sdh155122 if (zid_old != GLOBAL_ZONEID) 958d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 959d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) 960d62bc4baSyz147064 (void) zone_add_datalink(zid_old, link); 961f4b3ec61Sdh155122 rollback1: 962d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) 963d62bc4baSyz147064 (void) dladm_setzid(link, zid_old); 964f4b3ec61Sdh155122 return (status); 965f4b3ec61Sdh155122 } 966f4b3ec61Sdh155122 967f4b3ec61Sdh155122 /* ARGSUSED */ 968f4b3ec61Sdh155122 static dladm_status_t 969*e7801d59Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 970*e7801d59Ssowmini uint_t val_cnt, val_desc_t *vdp) 971f4b3ec61Sdh155122 { 972f4b3ec61Sdh155122 zoneid_t zid; 973f4b3ec61Sdh155122 974f4b3ec61Sdh155122 if (val_cnt != 1) 975f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 976f4b3ec61Sdh155122 977f4b3ec61Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 978f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 979f4b3ec61Sdh155122 980f4b3ec61Sdh155122 if (zid != GLOBAL_ZONEID) { 981f4b3ec61Sdh155122 ushort_t flags; 982f4b3ec61Sdh155122 983f4b3ec61Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 984f4b3ec61Sdh155122 sizeof (flags)) < 0) { 985f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 986f4b3ec61Sdh155122 } 987f4b3ec61Sdh155122 988f4b3ec61Sdh155122 if (!(flags & ZF_NET_EXCL)) { 989f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 990f4b3ec61Sdh155122 } 991f4b3ec61Sdh155122 } 992f4b3ec61Sdh155122 993d62bc4baSyz147064 vdp->vd_val = zid; 994f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 995f4b3ec61Sdh155122 } 996f4b3ec61Sdh155122 997*e7801d59Ssowmini /* ARGSUSED */ 998f4b3ec61Sdh155122 static dladm_status_t 999*e7801d59Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid, 1000*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1001d62bc4baSyz147064 { 1002d62bc4baSyz147064 dld_ioc_ap_t dia; 1003d62bc4baSyz147064 int fd, i, len; 1004d62bc4baSyz147064 1005d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1006d62bc4baSyz147064 return (dladm_errno2status(errno)); 1007d62bc4baSyz147064 1008d62bc4baSyz147064 *val_cnt = 1; 1009d62bc4baSyz147064 dia.dia_linkid = linkid; 1010d62bc4baSyz147064 if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) { 1011d62bc4baSyz147064 (*prop_val)[0] = '\0'; 1012d62bc4baSyz147064 goto done; 1013d62bc4baSyz147064 } 1014d62bc4baSyz147064 1015d62bc4baSyz147064 for (i = 0, len = 0; i < dia.dia_npush; i++) { 1016d62bc4baSyz147064 if (i != 0) { 1017d62bc4baSyz147064 (void) snprintf(*prop_val + len, 1018d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 1019d62bc4baSyz147064 len += 1; 1020d62bc4baSyz147064 } 1021d62bc4baSyz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 1022d62bc4baSyz147064 "%s", dia.dia_aplist[i]); 1023d62bc4baSyz147064 len += strlen(dia.dia_aplist[i]); 1024d62bc4baSyz147064 if (dia.dia_anchor - 1 == i) { 1025d62bc4baSyz147064 (void) snprintf(*prop_val + len, 1026d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 1027d62bc4baSyz147064 AP_ANCHOR); 1028d62bc4baSyz147064 len += (strlen(AP_ANCHOR) + 1); 1029d62bc4baSyz147064 } 1030d62bc4baSyz147064 } 1031d62bc4baSyz147064 1032d62bc4baSyz147064 done: 1033d62bc4baSyz147064 (void) close(fd); 1034d62bc4baSyz147064 return (DLADM_STATUS_OK); 1035d62bc4baSyz147064 } 1036d62bc4baSyz147064 1037*e7801d59Ssowmini /* ARGSUSED */ 1038d62bc4baSyz147064 static dladm_status_t 1039*e7801d59Ssowmini do_set_autopush(prop_desc_t *pd, datalink_id_t linkid, 1040*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 1041d62bc4baSyz147064 { 1042d62bc4baSyz147064 dld_ioc_ap_t dia; 1043d62bc4baSyz147064 struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val; 1044d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1045d62bc4baSyz147064 int fd, i; 1046d62bc4baSyz147064 int ic_cmd; 1047d62bc4baSyz147064 1048d62bc4baSyz147064 if (val_cnt != 1) 1049d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1050d62bc4baSyz147064 1051d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1052d62bc4baSyz147064 return (dladm_errno2status(errno)); 1053d62bc4baSyz147064 1054d62bc4baSyz147064 dia.dia_linkid = linkid; 1055d62bc4baSyz147064 if (dlap != NULL) { 1056d62bc4baSyz147064 dia.dia_anchor = dlap->dap_anchor; 1057d62bc4baSyz147064 dia.dia_npush = dlap->dap_npush; 1058d62bc4baSyz147064 for (i = 0; i < dia.dia_npush; i++) { 1059d62bc4baSyz147064 (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i], 1060d62bc4baSyz147064 FMNAMESZ+1); 1061d62bc4baSyz147064 } 1062d62bc4baSyz147064 ic_cmd = DLDIOC_SETAUTOPUSH; 1063d62bc4baSyz147064 } else { 1064d62bc4baSyz147064 ic_cmd = DLDIOC_CLRAUTOPUSH; 1065d62bc4baSyz147064 } 1066d62bc4baSyz147064 1067d62bc4baSyz147064 if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0) 1068d62bc4baSyz147064 status = dladm_errno2status(errno); 1069d62bc4baSyz147064 1070d62bc4baSyz147064 (void) close(fd); 1071d62bc4baSyz147064 return (status); 1072d62bc4baSyz147064 } 1073d62bc4baSyz147064 1074d62bc4baSyz147064 /* 1075d62bc4baSyz147064 * Add the specified module to the dlautopush structure; returns a 1076d62bc4baSyz147064 * DLADM_STATUS_* code. 1077d62bc4baSyz147064 */ 1078d62bc4baSyz147064 dladm_status_t 1079d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 1080d62bc4baSyz147064 { 1081d62bc4baSyz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 1082d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1083d62bc4baSyz147064 1084d62bc4baSyz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 1085d62bc4baSyz147064 /* 1086d62bc4baSyz147064 * We don't allow multiple anchors, and the anchor must 1087d62bc4baSyz147064 * be after at least one module. 1088d62bc4baSyz147064 */ 1089d62bc4baSyz147064 if (dlap->dap_anchor != 0) 1090d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1091d62bc4baSyz147064 if (dlap->dap_npush == 0) 1092d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1093d62bc4baSyz147064 1094d62bc4baSyz147064 dlap->dap_anchor = dlap->dap_npush; 1095d62bc4baSyz147064 return (DLADM_STATUS_OK); 1096d62bc4baSyz147064 } 1097d62bc4baSyz147064 if (dlap->dap_npush > MAXAPUSH) 1098d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1099d62bc4baSyz147064 1100d62bc4baSyz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 1101d62bc4baSyz147064 FMNAMESZ + 1); 1102d62bc4baSyz147064 1103d62bc4baSyz147064 return (DLADM_STATUS_OK); 1104d62bc4baSyz147064 } 1105d62bc4baSyz147064 1106d62bc4baSyz147064 /* 1107d62bc4baSyz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 1108d62bc4baSyz147064 * autopush modules. The former is used in dladm set-linkprop, and the 1109d62bc4baSyz147064 * latter is used in the autopush(1M) file. 1110d62bc4baSyz147064 */ 1111d62bc4baSyz147064 /* ARGSUSED */ 1112d62bc4baSyz147064 static dladm_status_t 1113*e7801d59Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1114*e7801d59Ssowmini uint_t val_cnt, val_desc_t *vdp) 1115d62bc4baSyz147064 { 1116d62bc4baSyz147064 char *module; 1117d62bc4baSyz147064 struct dlautopush *dlap; 1118d62bc4baSyz147064 dladm_status_t status; 1119d62bc4baSyz147064 char val[DLADM_PROP_VAL_MAX]; 1120d62bc4baSyz147064 char delimiters[4]; 1121d62bc4baSyz147064 1122d62bc4baSyz147064 if (val_cnt != 1) 1123d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1124d62bc4baSyz147064 1125d62bc4baSyz147064 dlap = malloc(sizeof (struct dlautopush)); 1126d62bc4baSyz147064 if (dlap == NULL) 1127d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1128d62bc4baSyz147064 1129d62bc4baSyz147064 (void) memset(dlap, 0, sizeof (struct dlautopush)); 1130d62bc4baSyz147064 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 1131d62bc4baSyz147064 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 1132d62bc4baSyz147064 module = strtok(val, delimiters); 1133d62bc4baSyz147064 while (module != NULL) { 1134d62bc4baSyz147064 status = i_dladm_add_ap_module(module, dlap); 1135d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1136d62bc4baSyz147064 return (status); 1137d62bc4baSyz147064 module = strtok(NULL, delimiters); 1138d62bc4baSyz147064 } 1139d62bc4baSyz147064 1140d62bc4baSyz147064 vdp->vd_val = (uintptr_t)dlap; 1141d62bc4baSyz147064 return (DLADM_STATUS_OK); 1142d62bc4baSyz147064 } 1143d62bc4baSyz147064 1144*e7801d59Ssowmini /* ARGSUSED */ 1145d62bc4baSyz147064 static dladm_status_t 1146*e7801d59Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, 1147*e7801d59Ssowmini char **prop_val, uint_t *val_cnt, uint_t id) 1148d62bc4baSyz147064 { 1149d62bc4baSyz147064 wl_rates_t *wrp; 1150d62bc4baSyz147064 uint_t i; 1151d62bc4baSyz147064 wldp_t *gbuf = NULL; 1152d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1153d62bc4baSyz147064 1154d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 1155d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1156d62bc4baSyz147064 goto done; 1157d62bc4baSyz147064 } 1158d62bc4baSyz147064 1159d62bc4baSyz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 1160d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1161d62bc4baSyz147064 goto done; 1162d62bc4baSyz147064 1163d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 1164d62bc4baSyz147064 if (wrp->wl_rates_num > *val_cnt) { 1165d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 1166d62bc4baSyz147064 goto done; 1167d62bc4baSyz147064 } 1168d62bc4baSyz147064 1169d62bc4baSyz147064 if (wrp->wl_rates_rates[0] == 0) { 1170d62bc4baSyz147064 prop_val[0][0] = '\0'; 1171d62bc4baSyz147064 *val_cnt = 1; 1172d62bc4baSyz147064 goto done; 1173d62bc4baSyz147064 } 1174d62bc4baSyz147064 1175d62bc4baSyz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 1176d62bc4baSyz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 1177d62bc4baSyz147064 wrp->wl_rates_rates[i] % 2, 1178d62bc4baSyz147064 (float)wrp->wl_rates_rates[i] / 2); 1179d62bc4baSyz147064 } 1180d62bc4baSyz147064 *val_cnt = wrp->wl_rates_num; 1181d62bc4baSyz147064 1182d62bc4baSyz147064 done: 1183d62bc4baSyz147064 free(gbuf); 1184d62bc4baSyz147064 return (status); 1185d62bc4baSyz147064 } 1186d62bc4baSyz147064 1187d62bc4baSyz147064 static dladm_status_t 1188*e7801d59Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, 1189*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1190d62bc4baSyz147064 { 1191*e7801d59Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 1192d62bc4baSyz147064 WL_DESIRED_RATES)); 1193d62bc4baSyz147064 } 1194d62bc4baSyz147064 1195d62bc4baSyz147064 static dladm_status_t 1196*e7801d59Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, 1197*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1198d62bc4baSyz147064 { 1199*e7801d59Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 1200d62bc4baSyz147064 WL_SUPPORTED_RATES)); 1201d62bc4baSyz147064 } 1202d62bc4baSyz147064 1203d62bc4baSyz147064 static dladm_status_t 1204d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 1205f4b3ec61Sdh155122 { 1206f4b3ec61Sdh155122 int i; 1207d62bc4baSyz147064 uint_t len; 1208d62bc4baSyz147064 wldp_t *gbuf; 1209d62bc4baSyz147064 wl_rates_t *wrp; 1210d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1211d62bc4baSyz147064 1212d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1213d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1214d62bc4baSyz147064 1215d62bc4baSyz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 1216d62bc4baSyz147064 1217d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 1218d62bc4baSyz147064 for (i = 0; i < rates->wr_cnt; i++) 1219d62bc4baSyz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 1220d62bc4baSyz147064 wrp->wl_rates_num = rates->wr_cnt; 1221d62bc4baSyz147064 1222d62bc4baSyz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 1223d62bc4baSyz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 1224d62bc4baSyz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 1225d62bc4baSyz147064 WLAN_SET_PARAM, len); 1226d62bc4baSyz147064 1227d62bc4baSyz147064 free(gbuf); 1228d62bc4baSyz147064 return (status); 1229d62bc4baSyz147064 } 1230d62bc4baSyz147064 1231*e7801d59Ssowmini /* ARGSUSED */ 1232d62bc4baSyz147064 static dladm_status_t 1233*e7801d59Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid, 1234*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 1235d62bc4baSyz147064 { 1236d62bc4baSyz147064 dladm_wlan_rates_t rates; 1237f4b3ec61Sdh155122 dladm_status_t status; 1238f4b3ec61Sdh155122 1239d62bc4baSyz147064 if (val_cnt != 1) 1240d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1241f4b3ec61Sdh155122 1242d62bc4baSyz147064 rates.wr_cnt = 1; 1243d62bc4baSyz147064 rates.wr_rates[0] = vdp[0].vd_val; 1244f4b3ec61Sdh155122 1245d62bc4baSyz147064 status = do_set_rate(linkid, &rates); 1246f4b3ec61Sdh155122 1247d62bc4baSyz147064 done: 1248d62bc4baSyz147064 return (status); 1249d62bc4baSyz147064 } 1250d62bc4baSyz147064 1251d62bc4baSyz147064 /* ARGSUSED */ 1252d62bc4baSyz147064 static dladm_status_t 1253*e7801d59Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1254*e7801d59Ssowmini uint_t val_cnt, val_desc_t *vdp) 1255d62bc4baSyz147064 { 1256d62bc4baSyz147064 int i; 1257d62bc4baSyz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 1258d62bc4baSyz147064 char *buf, **modval; 1259d62bc4baSyz147064 dladm_status_t status; 1260d62bc4baSyz147064 1261d62bc4baSyz147064 if (val_cnt != 1) 1262d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1263d62bc4baSyz147064 1264d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 1265d62bc4baSyz147064 MAX_SUPPORT_RATES); 1266d62bc4baSyz147064 if (buf == NULL) { 1267d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1268d62bc4baSyz147064 goto done; 1269d62bc4baSyz147064 } 1270d62bc4baSyz147064 1271d62bc4baSyz147064 modval = (char **)(void *)buf; 1272d62bc4baSyz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 1273d62bc4baSyz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 1274d62bc4baSyz147064 i * DLADM_STRSIZE; 1275d62bc4baSyz147064 } 1276d62bc4baSyz147064 1277*e7801d59Ssowmini status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt); 1278d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1279d62bc4baSyz147064 goto done; 1280d62bc4baSyz147064 1281d62bc4baSyz147064 for (i = 0; i < modval_cnt; i++) { 1282d62bc4baSyz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 1283*e7801d59Ssowmini vdp->vd_val = (uintptr_t)(uint_t) 1284*e7801d59Ssowmini (atof(*prop_val) * 2); 1285f4b3ec61Sdh155122 status = DLADM_STATUS_OK; 1286f4b3ec61Sdh155122 break; 1287f4b3ec61Sdh155122 } 1288d62bc4baSyz147064 } 1289d62bc4baSyz147064 if (i == modval_cnt) 1290d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 1291d62bc4baSyz147064 done: 1292d62bc4baSyz147064 free(buf); 1293d62bc4baSyz147064 return (status); 1294d62bc4baSyz147064 } 1295f4b3ec61Sdh155122 1296d62bc4baSyz147064 static dladm_status_t 1297d62bc4baSyz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 1298d62bc4baSyz147064 { 1299d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 1300d62bc4baSyz147064 } 1301d62bc4baSyz147064 1302*e7801d59Ssowmini /* ARGSUSED */ 1303d62bc4baSyz147064 static dladm_status_t 1304*e7801d59Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, 1305*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1306d62bc4baSyz147064 { 1307d62bc4baSyz147064 uint32_t channel; 1308d62bc4baSyz147064 wldp_t *gbuf; 1309d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1310d62bc4baSyz147064 1311d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1312d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1313d62bc4baSyz147064 1314d62bc4baSyz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 1315d62bc4baSyz147064 goto done; 1316d62bc4baSyz147064 1317d62bc4baSyz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 1318d62bc4baSyz147064 &channel)) { 1319d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1320d62bc4baSyz147064 goto done; 1321d62bc4baSyz147064 } 1322d62bc4baSyz147064 1323d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 1324d62bc4baSyz147064 *val_cnt = 1; 1325d62bc4baSyz147064 1326d62bc4baSyz147064 done: 1327d62bc4baSyz147064 free(gbuf); 1328d62bc4baSyz147064 return (status); 1329d62bc4baSyz147064 } 1330d62bc4baSyz147064 1331d62bc4baSyz147064 static dladm_status_t 1332d62bc4baSyz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 1333d62bc4baSyz147064 { 1334d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 1335d62bc4baSyz147064 } 1336d62bc4baSyz147064 1337*e7801d59Ssowmini /* ARGSUSED */ 1338d62bc4baSyz147064 static dladm_status_t 1339*e7801d59Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, 1340*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1341d62bc4baSyz147064 { 1342d62bc4baSyz147064 wl_ps_mode_t *mode; 1343d62bc4baSyz147064 const char *s; 1344d62bc4baSyz147064 wldp_t *gbuf; 1345d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1346d62bc4baSyz147064 1347d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1348d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1349d62bc4baSyz147064 1350d62bc4baSyz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 1351d62bc4baSyz147064 goto done; 1352d62bc4baSyz147064 1353d62bc4baSyz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 1354d62bc4baSyz147064 switch (mode->wl_ps_mode) { 1355d62bc4baSyz147064 case WL_PM_AM: 1356d62bc4baSyz147064 s = "off"; 1357f4b3ec61Sdh155122 break; 1358d62bc4baSyz147064 case WL_PM_MPS: 1359d62bc4baSyz147064 s = "max"; 1360d62bc4baSyz147064 break; 1361d62bc4baSyz147064 case WL_PM_FAST: 1362d62bc4baSyz147064 s = "fast"; 1363f4b3ec61Sdh155122 break; 1364f4b3ec61Sdh155122 default: 1365d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1366d62bc4baSyz147064 goto done; 1367f4b3ec61Sdh155122 } 1368d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1369d62bc4baSyz147064 *val_cnt = 1; 1370d62bc4baSyz147064 1371d62bc4baSyz147064 done: 1372d62bc4baSyz147064 free(gbuf); 1373d62bc4baSyz147064 return (status); 1374d62bc4baSyz147064 } 1375d62bc4baSyz147064 1376d62bc4baSyz147064 static dladm_status_t 1377d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 1378d62bc4baSyz147064 { 1379d62bc4baSyz147064 wl_ps_mode_t ps_mode; 1380d62bc4baSyz147064 1381d62bc4baSyz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 1382d62bc4baSyz147064 1383d62bc4baSyz147064 switch (*pm) { 1384d62bc4baSyz147064 case DLADM_WLAN_PM_OFF: 1385d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_AM; 1386d62bc4baSyz147064 break; 1387d62bc4baSyz147064 case DLADM_WLAN_PM_MAX: 1388d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 1389d62bc4baSyz147064 break; 1390d62bc4baSyz147064 case DLADM_WLAN_PM_FAST: 1391d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 1392d62bc4baSyz147064 break; 1393d62bc4baSyz147064 default: 1394d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1395d62bc4baSyz147064 } 1396d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 1397d62bc4baSyz147064 sizeof (ps_mode))); 1398d62bc4baSyz147064 } 1399d62bc4baSyz147064 1400d62bc4baSyz147064 /* ARGSUSED */ 1401d62bc4baSyz147064 static dladm_status_t 1402*e7801d59Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, 1403*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 1404d62bc4baSyz147064 { 1405d62bc4baSyz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 1406d62bc4baSyz147064 dladm_status_t status; 1407d62bc4baSyz147064 1408d62bc4baSyz147064 if (val_cnt != 1) 1409d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1410d62bc4baSyz147064 1411d62bc4baSyz147064 status = do_set_powermode(linkid, &powermode); 1412f4b3ec61Sdh155122 1413f4b3ec61Sdh155122 return (status); 1414f4b3ec61Sdh155122 } 1415f4b3ec61Sdh155122 1416f4b3ec61Sdh155122 static dladm_status_t 1417d62bc4baSyz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 1418f4b3ec61Sdh155122 { 1419d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 1420d62bc4baSyz147064 } 1421d62bc4baSyz147064 1422*e7801d59Ssowmini /* ARGSUSED */ 1423d62bc4baSyz147064 static dladm_status_t 1424*e7801d59Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, 1425*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1426d62bc4baSyz147064 { 1427d62bc4baSyz147064 wl_radio_t radio; 1428d62bc4baSyz147064 const char *s; 1429d62bc4baSyz147064 wldp_t *gbuf; 1430d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1431d62bc4baSyz147064 1432d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1433d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1434d62bc4baSyz147064 1435d62bc4baSyz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 1436d62bc4baSyz147064 goto done; 1437d62bc4baSyz147064 1438d62bc4baSyz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 1439d62bc4baSyz147064 switch (radio) { 1440d62bc4baSyz147064 case B_TRUE: 1441d62bc4baSyz147064 s = "on"; 1442d62bc4baSyz147064 break; 1443d62bc4baSyz147064 case B_FALSE: 1444d62bc4baSyz147064 s = "off"; 1445d62bc4baSyz147064 break; 1446d62bc4baSyz147064 default: 1447d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1448d62bc4baSyz147064 goto done; 1449d62bc4baSyz147064 } 1450d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1451d62bc4baSyz147064 *val_cnt = 1; 1452d62bc4baSyz147064 1453d62bc4baSyz147064 done: 1454d62bc4baSyz147064 free(gbuf); 1455d62bc4baSyz147064 return (status); 1456d62bc4baSyz147064 } 1457d62bc4baSyz147064 1458d62bc4baSyz147064 static dladm_status_t 1459d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 1460d62bc4baSyz147064 { 1461d62bc4baSyz147064 wl_radio_t r; 1462d62bc4baSyz147064 1463d62bc4baSyz147064 switch (*radio) { 1464d62bc4baSyz147064 case DLADM_WLAN_RADIO_ON: 1465d62bc4baSyz147064 r = B_TRUE; 1466d62bc4baSyz147064 break; 1467d62bc4baSyz147064 case DLADM_WLAN_RADIO_OFF: 1468d62bc4baSyz147064 r = B_FALSE; 1469d62bc4baSyz147064 break; 1470d62bc4baSyz147064 default: 1471d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1472d62bc4baSyz147064 } 1473d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 1474d62bc4baSyz147064 } 1475d62bc4baSyz147064 1476d62bc4baSyz147064 /* ARGSUSED */ 1477d62bc4baSyz147064 static dladm_status_t 1478*e7801d59Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid, 1479*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t fags) 1480d62bc4baSyz147064 { 1481d62bc4baSyz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 1482f4b3ec61Sdh155122 dladm_status_t status; 1483f4b3ec61Sdh155122 1484d62bc4baSyz147064 if (val_cnt != 1) 1485d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1486f4b3ec61Sdh155122 1487d62bc4baSyz147064 status = do_set_radio(linkid, &radio); 1488f4b3ec61Sdh155122 1489d62bc4baSyz147064 return (status); 1490d62bc4baSyz147064 } 1491f4b3ec61Sdh155122 1492d62bc4baSyz147064 static dladm_status_t 1493d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 1494d62bc4baSyz147064 char **prop_val, uint_t val_cnt) 1495d62bc4baSyz147064 { 1496d62bc4baSyz147064 char buf[MAXLINELEN]; 1497d62bc4baSyz147064 int i; 1498d62bc4baSyz147064 dladm_conf_t conf; 1499d62bc4baSyz147064 dladm_status_t status; 1500d62bc4baSyz147064 1501d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1502f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 1503f4b3ec61Sdh155122 return (status); 1504f4b3ec61Sdh155122 1505d62bc4baSyz147064 /* 1506d62bc4baSyz147064 * reset case. 1507d62bc4baSyz147064 */ 1508d62bc4baSyz147064 if (val_cnt == 0) { 1509d62bc4baSyz147064 status = dladm_unset_conf_field(conf, prop_name); 1510d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1511d62bc4baSyz147064 status = dladm_write_conf(conf); 1512d62bc4baSyz147064 goto done; 1513f4b3ec61Sdh155122 } 1514f4b3ec61Sdh155122 1515d62bc4baSyz147064 buf[0] = '\0'; 1516d62bc4baSyz147064 for (i = 0; i < val_cnt; i++) { 1517d62bc4baSyz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 1518d62bc4baSyz147064 if (i != val_cnt - 1) 1519d62bc4baSyz147064 (void) strlcat(buf, ",", MAXLINELEN); 1520d62bc4baSyz147064 } 1521f4b3ec61Sdh155122 1522d62bc4baSyz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 1523d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1524d62bc4baSyz147064 status = dladm_write_conf(conf); 1525d62bc4baSyz147064 1526d62bc4baSyz147064 done: 1527d62bc4baSyz147064 dladm_destroy_conf(conf); 1528f4b3ec61Sdh155122 return (status); 1529f4b3ec61Sdh155122 } 1530f4b3ec61Sdh155122 1531f4b3ec61Sdh155122 static dladm_status_t 1532d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 1533d62bc4baSyz147064 char **prop_val, uint_t *val_cntp) 1534f4b3ec61Sdh155122 { 1535d62bc4baSyz147064 char buf[MAXLINELEN], *str; 1536d62bc4baSyz147064 uint_t cnt = 0; 1537d62bc4baSyz147064 dladm_conf_t conf; 1538d62bc4baSyz147064 dladm_status_t status; 1539f4b3ec61Sdh155122 1540d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1541d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1542f4b3ec61Sdh155122 return (status); 1543d62bc4baSyz147064 1544d62bc4baSyz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 1545d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1546d62bc4baSyz147064 goto done; 1547d62bc4baSyz147064 1548d62bc4baSyz147064 str = strtok(buf, ","); 1549d62bc4baSyz147064 while (str != NULL) { 1550d62bc4baSyz147064 if (cnt == *val_cntp) { 1551d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 1552d62bc4baSyz147064 goto done; 1553d62bc4baSyz147064 } 1554d62bc4baSyz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 1555d62bc4baSyz147064 str = strtok(NULL, ","); 1556f4b3ec61Sdh155122 } 1557f4b3ec61Sdh155122 1558d62bc4baSyz147064 *val_cntp = cnt; 1559f4b3ec61Sdh155122 1560d62bc4baSyz147064 done: 1561d62bc4baSyz147064 dladm_destroy_conf(conf); 1562d62bc4baSyz147064 return (status); 1563f4b3ec61Sdh155122 } 1564*e7801d59Ssowmini 1565*e7801d59Ssowmini static dld_public_prop_t * 1566*e7801d59Ssowmini dladm_name2prop(const char *prop_name) 1567*e7801d59Ssowmini { 1568*e7801d59Ssowmini dld_public_prop_t *p; 1569*e7801d59Ssowmini 1570*e7801d59Ssowmini for (p = dld_prop; p->pp_id != DLD_PROP_PRIVATE; p++) { 1571*e7801d59Ssowmini if (strcmp(p->pp_name, prop_name) == 0) 1572*e7801d59Ssowmini break; 1573*e7801d59Ssowmini } 1574*e7801d59Ssowmini return (p); 1575*e7801d59Ssowmini } 1576*e7801d59Ssowmini 1577*e7801d59Ssowmini 1578*e7801d59Ssowmini static dld_ioc_prop_t * 1579*e7801d59Ssowmini dld_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, 1580*e7801d59Ssowmini dladm_status_t *status) 1581*e7801d59Ssowmini { 1582*e7801d59Ssowmini int dsize; 1583*e7801d59Ssowmini dld_ioc_prop_t *dip; 1584*e7801d59Ssowmini dld_public_prop_t *p; 1585*e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 1586*e7801d59Ssowmini uint32_t flags; 1587*e7801d59Ssowmini 1588*e7801d59Ssowmini *status = DLADM_STATUS_OK; 1589*e7801d59Ssowmini p = dladm_name2prop(prop_name); 1590*e7801d59Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1591*e7801d59Ssowmini valsize = p->pp_valsize; 1592*e7801d59Ssowmini 1593*e7801d59Ssowmini dsize = DLD_PROPBUF_SIZE(valsize); 1594*e7801d59Ssowmini dip = malloc(dsize); 1595*e7801d59Ssowmini if (dip == NULL) { 1596*e7801d59Ssowmini *status = DLADM_STATUS_NOMEM; 1597*e7801d59Ssowmini return (NULL); 1598*e7801d59Ssowmini } 1599*e7801d59Ssowmini bzero(dip, dsize); 1600*e7801d59Ssowmini dip->pr_valsize = valsize; 1601*e7801d59Ssowmini (void) strlcpy(dip->pr_name, prop_name, DLD_LINKPROP_NAME_MAX); 1602*e7801d59Ssowmini dip->pr_version = DLD_PROP_VERSION; 1603*e7801d59Ssowmini 1604*e7801d59Ssowmini if ((*status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, 1605*e7801d59Ssowmini (char *)link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK) { 1606*e7801d59Ssowmini free(dip); 1607*e7801d59Ssowmini return (NULL); 1608*e7801d59Ssowmini } 1609*e7801d59Ssowmini 1610*e7801d59Ssowmini if (!(flags & DLADM_OPT_ACTIVE)) { 1611*e7801d59Ssowmini free(dip); 1612*e7801d59Ssowmini *status = DLADM_STATUS_TEMPONLY; 1613*e7801d59Ssowmini return (NULL); 1614*e7801d59Ssowmini } 1615*e7801d59Ssowmini (void) strlcpy(dip->pr_linkname, link, IFNAMSIZ); 1616*e7801d59Ssowmini dip->pr_num = p->pp_id; 1617*e7801d59Ssowmini return (dip); 1618*e7801d59Ssowmini } 1619*e7801d59Ssowmini 1620*e7801d59Ssowmini /* ARGSUSED */ 1621*e7801d59Ssowmini static dladm_status_t 1622*e7801d59Ssowmini dld_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, 1623*e7801d59Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 1624*e7801d59Ssowmini { 1625*e7801d59Ssowmini dld_ioc_prop_t *dip; 1626*e7801d59Ssowmini int fd, dsize; 1627*e7801d59Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1628*e7801d59Ssowmini uint8_t u8; 1629*e7801d59Ssowmini uint16_t u16; 1630*e7801d59Ssowmini uint32_t u32; 1631*e7801d59Ssowmini void *val; 1632*e7801d59Ssowmini 1633*e7801d59Ssowmini dip = dld_buf_alloc(0, linkid, pd->pd_name, &status); 1634*e7801d59Ssowmini if (dip == NULL) 1635*e7801d59Ssowmini return (status); 1636*e7801d59Ssowmini 1637*e7801d59Ssowmini if (pd->pd_flags & PD_CHECK_ALLOC) 1638*e7801d59Ssowmini val = (void *)vdp->vd_val; 1639*e7801d59Ssowmini else { 1640*e7801d59Ssowmini /* 1641*e7801d59Ssowmini * Currently all 1/2/4-byte size properties are byte/word/int. 1642*e7801d59Ssowmini * No need (yet) to distinguish these from arrays of same size. 1643*e7801d59Ssowmini */ 1644*e7801d59Ssowmini switch (dip->pr_valsize) { 1645*e7801d59Ssowmini case 1: 1646*e7801d59Ssowmini u8 = vdp->vd_val; 1647*e7801d59Ssowmini val = &u8; 1648*e7801d59Ssowmini break; 1649*e7801d59Ssowmini case 2: 1650*e7801d59Ssowmini u16 = vdp->vd_val; 1651*e7801d59Ssowmini val = &u16; 1652*e7801d59Ssowmini break; 1653*e7801d59Ssowmini case 4: 1654*e7801d59Ssowmini u32 = vdp->vd_val; 1655*e7801d59Ssowmini val = &u32; 1656*e7801d59Ssowmini break; 1657*e7801d59Ssowmini default: 1658*e7801d59Ssowmini val = &vdp->vd_val; 1659*e7801d59Ssowmini break; 1660*e7801d59Ssowmini } 1661*e7801d59Ssowmini } 1662*e7801d59Ssowmini 1663*e7801d59Ssowmini (void) memcpy(dip->pr_val, val, dip->pr_valsize); 1664*e7801d59Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1665*e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1666*e7801d59Ssowmini status = dladm_errno2status(errno); 1667*e7801d59Ssowmini goto done; 1668*e7801d59Ssowmini } 1669*e7801d59Ssowmini if (i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize) < 0) 1670*e7801d59Ssowmini status = dladm_errno2status(errno); 1671*e7801d59Ssowmini 1672*e7801d59Ssowmini (void) close(fd); 1673*e7801d59Ssowmini done: 1674*e7801d59Ssowmini return (status); 1675*e7801d59Ssowmini } 1676*e7801d59Ssowmini 1677*e7801d59Ssowmini static dladm_status_t 1678*e7801d59Ssowmini dld_get_public_prop(dld_ioc_prop_t *dip) 1679*e7801d59Ssowmini { 1680*e7801d59Ssowmini int fd, dsize; 1681*e7801d59Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1682*e7801d59Ssowmini 1683*e7801d59Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1684*e7801d59Ssowmini 1685*e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1686*e7801d59Ssowmini status = dladm_errno2status(errno); 1687*e7801d59Ssowmini goto done; 1688*e7801d59Ssowmini } 1689*e7801d59Ssowmini if (i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize) < 0) { 1690*e7801d59Ssowmini status = dladm_errno2status(errno); 1691*e7801d59Ssowmini } 1692*e7801d59Ssowmini done: 1693*e7801d59Ssowmini return (status); 1694*e7801d59Ssowmini } 1695*e7801d59Ssowmini 1696*e7801d59Ssowmini 1697*e7801d59Ssowmini /* ARGSUSED */ 1698*e7801d59Ssowmini static dladm_status_t 1699*e7801d59Ssowmini dld_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1700*e7801d59Ssowmini uint_t val_cnt, val_desc_t *v) 1701*e7801d59Ssowmini { 1702*e7801d59Ssowmini uint64_t mtu; 1703*e7801d59Ssowmini 1704*e7801d59Ssowmini if (val_cnt != 1) 1705*e7801d59Ssowmini return (DLADM_STATUS_BADVAL); 1706*e7801d59Ssowmini mtu = atoll(prop_val[0]); 1707*e7801d59Ssowmini v->vd_val = (uintptr_t)malloc(sizeof (uint64_t)); 1708*e7801d59Ssowmini if ((void *)v->vd_val == NULL) 1709*e7801d59Ssowmini return (DLADM_STATUS_NOMEM); 1710*e7801d59Ssowmini bcopy(&mtu, (void *)v->vd_val, sizeof (mtu)); 1711*e7801d59Ssowmini return (DLADM_STATUS_OK); 1712*e7801d59Ssowmini } 1713*e7801d59Ssowmini 1714*e7801d59Ssowmini /* ARGSUSED */ 1715*e7801d59Ssowmini static dladm_status_t 1716*e7801d59Ssowmini dld_duplex_get(struct prop_desc *pd, datalink_id_t linkid, 1717*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1718*e7801d59Ssowmini { 1719*e7801d59Ssowmini link_duplex_t link_duplex; 1720*e7801d59Ssowmini dladm_status_t status; 1721*e7801d59Ssowmini 1722*e7801d59Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_duplex", 1723*e7801d59Ssowmini KSTAT_DATA_UINT32, &link_duplex)) != 0) 1724*e7801d59Ssowmini return (status); 1725*e7801d59Ssowmini 1726*e7801d59Ssowmini switch (link_duplex) { 1727*e7801d59Ssowmini case LINK_DUPLEX_FULL: 1728*e7801d59Ssowmini (void) strcpy(*prop_val, "full"); 1729*e7801d59Ssowmini break; 1730*e7801d59Ssowmini case LINK_DUPLEX_HALF: 1731*e7801d59Ssowmini (void) strcpy(*prop_val, "half"); 1732*e7801d59Ssowmini break; 1733*e7801d59Ssowmini default: 1734*e7801d59Ssowmini (void) strcpy(*prop_val, "unknown"); 1735*e7801d59Ssowmini break; 1736*e7801d59Ssowmini } 1737*e7801d59Ssowmini *val_cnt = 1; 1738*e7801d59Ssowmini return (DLADM_STATUS_OK); 1739*e7801d59Ssowmini } 1740*e7801d59Ssowmini 1741*e7801d59Ssowmini /* ARGSUSED */ 1742*e7801d59Ssowmini static dladm_status_t 1743*e7801d59Ssowmini dld_speed_get(struct prop_desc *pd, datalink_id_t linkid, 1744*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1745*e7801d59Ssowmini { 1746*e7801d59Ssowmini uint64_t ifspeed = 0; 1747*e7801d59Ssowmini dladm_status_t status; 1748*e7801d59Ssowmini 1749*e7801d59Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "ifspeed", 1750*e7801d59Ssowmini KSTAT_DATA_UINT64, &ifspeed)) != 0) 1751*e7801d59Ssowmini return (status); 1752*e7801d59Ssowmini 1753*e7801d59Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 1754*e7801d59Ssowmini "%llu", ifspeed / 1000000); /* Mbps */ 1755*e7801d59Ssowmini *val_cnt = 1; 1756*e7801d59Ssowmini return (DLADM_STATUS_OK); 1757*e7801d59Ssowmini } 1758*e7801d59Ssowmini 1759*e7801d59Ssowmini /* ARGSUSED */ 1760*e7801d59Ssowmini static dladm_status_t 1761*e7801d59Ssowmini dld_status_get(struct prop_desc *pd, datalink_id_t linkid, 1762*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1763*e7801d59Ssowmini { 1764*e7801d59Ssowmini link_state_t link_state; 1765*e7801d59Ssowmini dladm_status_t status; 1766*e7801d59Ssowmini 1767*e7801d59Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_state", 1768*e7801d59Ssowmini KSTAT_DATA_UINT32, &link_state)) != 0) 1769*e7801d59Ssowmini return (status); 1770*e7801d59Ssowmini 1771*e7801d59Ssowmini switch (link_state) { 1772*e7801d59Ssowmini case LINK_STATE_UP: 1773*e7801d59Ssowmini (void) strcpy(*prop_val, "up"); 1774*e7801d59Ssowmini break; 1775*e7801d59Ssowmini case LINK_STATE_DOWN: 1776*e7801d59Ssowmini (void) strcpy(*prop_val, "down"); 1777*e7801d59Ssowmini break; 1778*e7801d59Ssowmini default: 1779*e7801d59Ssowmini (void) strcpy(*prop_val, "unknown"); 1780*e7801d59Ssowmini break; 1781*e7801d59Ssowmini } 1782*e7801d59Ssowmini *val_cnt = 1; 1783*e7801d59Ssowmini return (DLADM_STATUS_OK); 1784*e7801d59Ssowmini } 1785*e7801d59Ssowmini 1786*e7801d59Ssowmini /* ARGSUSED */ 1787*e7801d59Ssowmini static dladm_status_t 1788*e7801d59Ssowmini dld_binary_get(struct prop_desc *pd, datalink_id_t linkid, 1789*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1790*e7801d59Ssowmini { 1791*e7801d59Ssowmini dld_ioc_prop_t *dip; 1792*e7801d59Ssowmini dladm_status_t status; 1793*e7801d59Ssowmini 1794*e7801d59Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1795*e7801d59Ssowmini return (status); 1796*e7801d59Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1797*e7801d59Ssowmini free(dip); 1798*e7801d59Ssowmini return (status); 1799*e7801d59Ssowmini } 1800*e7801d59Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]); 1801*e7801d59Ssowmini free(dip); 1802*e7801d59Ssowmini *val_cnt = 1; 1803*e7801d59Ssowmini return (DLADM_STATUS_OK); 1804*e7801d59Ssowmini } 1805*e7801d59Ssowmini 1806*e7801d59Ssowmini static dladm_status_t 1807*e7801d59Ssowmini dld_uint64_get(struct prop_desc *pd, datalink_id_t linkid, 1808*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1809*e7801d59Ssowmini { 1810*e7801d59Ssowmini dld_ioc_prop_t *dip; 1811*e7801d59Ssowmini uint64_t v = 0; 1812*e7801d59Ssowmini uchar_t *cp; 1813*e7801d59Ssowmini dladm_status_t status; 1814*e7801d59Ssowmini 1815*e7801d59Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1816*e7801d59Ssowmini return (status); 1817*e7801d59Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1818*e7801d59Ssowmini free(dip); 1819*e7801d59Ssowmini return (status); 1820*e7801d59Ssowmini } 1821*e7801d59Ssowmini cp = (uchar_t *)dip->pr_val; 1822*e7801d59Ssowmini (void) memcpy(&v, cp, sizeof (v)); 1823*e7801d59Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%" PRIu64, v); 1824*e7801d59Ssowmini free(dip); 1825*e7801d59Ssowmini *val_cnt = 1; 1826*e7801d59Ssowmini return (DLADM_STATUS_OK); 1827*e7801d59Ssowmini } 1828*e7801d59Ssowmini 1829*e7801d59Ssowmini static dladm_status_t 1830*e7801d59Ssowmini dld_flowctl_get(struct prop_desc *pd, datalink_id_t linkid, 1831*e7801d59Ssowmini char **prop_val, uint_t *val_cnt) 1832*e7801d59Ssowmini { 1833*e7801d59Ssowmini dld_ioc_prop_t *dip; 1834*e7801d59Ssowmini link_flowctrl_t v; 1835*e7801d59Ssowmini dladm_status_t status; 1836*e7801d59Ssowmini uchar_t *cp; 1837*e7801d59Ssowmini 1838*e7801d59Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1839*e7801d59Ssowmini return (status); 1840*e7801d59Ssowmini 1841*e7801d59Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1842*e7801d59Ssowmini free(dip); 1843*e7801d59Ssowmini return (status); 1844*e7801d59Ssowmini } 1845*e7801d59Ssowmini cp = (uchar_t *)dip->pr_val; 1846*e7801d59Ssowmini (void) memcpy(&v, cp, sizeof (v)); 1847*e7801d59Ssowmini switch (v) { 1848*e7801d59Ssowmini case LINK_FLOWCTRL_NONE: 1849*e7801d59Ssowmini (void) sprintf(*prop_val, "no"); 1850*e7801d59Ssowmini break; 1851*e7801d59Ssowmini case LINK_FLOWCTRL_RX: 1852*e7801d59Ssowmini (void) sprintf(*prop_val, "rx"); 1853*e7801d59Ssowmini break; 1854*e7801d59Ssowmini case LINK_FLOWCTRL_TX: 1855*e7801d59Ssowmini (void) sprintf(*prop_val, "tx"); 1856*e7801d59Ssowmini break; 1857*e7801d59Ssowmini case LINK_FLOWCTRL_BI: 1858*e7801d59Ssowmini (void) sprintf(*prop_val, "bi"); 1859*e7801d59Ssowmini break; 1860*e7801d59Ssowmini } 1861*e7801d59Ssowmini free(dip); 1862*e7801d59Ssowmini *val_cnt = 1; 1863*e7801d59Ssowmini return (DLADM_STATUS_OK); 1864*e7801d59Ssowmini } 1865*e7801d59Ssowmini 1866*e7801d59Ssowmini 1867*e7801d59Ssowmini /* ARGSUSED */ 1868*e7801d59Ssowmini static dladm_status_t 1869*e7801d59Ssowmini dld_set_prop(datalink_id_t linkid, const char *prop_name, 1870*e7801d59Ssowmini char **prop_val, uint_t val_cnt, uint_t flags) 1871*e7801d59Ssowmini { 1872*e7801d59Ssowmini int fd, i, slen; 1873*e7801d59Ssowmini int bufsize = 0, dsize; 1874*e7801d59Ssowmini dld_ioc_prop_t *dip = NULL; 1875*e7801d59Ssowmini uchar_t *dp; 1876*e7801d59Ssowmini dld_public_prop_t *p; 1877*e7801d59Ssowmini dladm_status_t status; 1878*e7801d59Ssowmini 1879*e7801d59Ssowmini if ((prop_name == NULL && prop_val != NULL) || 1880*e7801d59Ssowmini (prop_val != NULL && val_cnt == 0)) 1881*e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1882*e7801d59Ssowmini p = dladm_name2prop(prop_name); 1883*e7801d59Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1884*e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1885*e7801d59Ssowmini 1886*e7801d59Ssowmini /* 1887*e7801d59Ssowmini * private properties: all parsing is done in the kernel. 1888*e7801d59Ssowmini * allocate a enough space for each property + its separator (','). 1889*e7801d59Ssowmini */ 1890*e7801d59Ssowmini for (i = 0; i < val_cnt; i++) { 1891*e7801d59Ssowmini bufsize += strlen(prop_val[i]) + 1; 1892*e7801d59Ssowmini } 1893*e7801d59Ssowmini dip = dld_buf_alloc(bufsize + 1, linkid, prop_name, &status); 1894*e7801d59Ssowmini if (dip == NULL) 1895*e7801d59Ssowmini return (status); 1896*e7801d59Ssowmini 1897*e7801d59Ssowmini dp = (uchar_t *)dip->pr_val; 1898*e7801d59Ssowmini dsize = sizeof (dld_ioc_prop_t) + bufsize; 1899*e7801d59Ssowmini slen = 0; 1900*e7801d59Ssowmini for (i = 0; i < val_cnt; i++) { 1901*e7801d59Ssowmini int plen = 0; 1902*e7801d59Ssowmini 1903*e7801d59Ssowmini plen = strlen(prop_val[i]); 1904*e7801d59Ssowmini bcopy(prop_val[i], dp, plen); 1905*e7801d59Ssowmini slen += plen; 1906*e7801d59Ssowmini /* 1907*e7801d59Ssowmini * add a "," separator and update dp. 1908*e7801d59Ssowmini */ 1909*e7801d59Ssowmini if (i != (val_cnt -1)) 1910*e7801d59Ssowmini dp[slen++] = ','; 1911*e7801d59Ssowmini dp += (plen + 1); 1912*e7801d59Ssowmini } 1913*e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1914*e7801d59Ssowmini free(dip); 1915*e7801d59Ssowmini return (dladm_errno2status(errno)); 1916*e7801d59Ssowmini } 1917*e7801d59Ssowmini if ((status = i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize)) < 0) { 1918*e7801d59Ssowmini free(dip); 1919*e7801d59Ssowmini return (status); 1920*e7801d59Ssowmini } 1921*e7801d59Ssowmini free(dip); 1922*e7801d59Ssowmini (void) close(fd); 1923*e7801d59Ssowmini return (DLADM_STATUS_OK); 1924*e7801d59Ssowmini } 1925*e7801d59Ssowmini 1926*e7801d59Ssowmini static dladm_status_t 1927*e7801d59Ssowmini dld_get_prop(datalink_id_t linkid, const char *prop_name, 1928*e7801d59Ssowmini char **prop_val, uint_t *val_cnt, dladm_prop_type_t type) 1929*e7801d59Ssowmini { 1930*e7801d59Ssowmini int fd; 1931*e7801d59Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1932*e7801d59Ssowmini uint_t dsize; 1933*e7801d59Ssowmini dld_ioc_prop_t *dip = NULL; 1934*e7801d59Ssowmini dld_public_prop_t *p; 1935*e7801d59Ssowmini char tmp = '\0'; 1936*e7801d59Ssowmini 1937*e7801d59Ssowmini if ((prop_name == NULL && prop_val != NULL) || 1938*e7801d59Ssowmini (prop_val != NULL && val_cnt == 0)) 1939*e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1940*e7801d59Ssowmini 1941*e7801d59Ssowmini p = dladm_name2prop(prop_name); 1942*e7801d59Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1943*e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1944*e7801d59Ssowmini 1945*e7801d59Ssowmini if (type == DLADM_PROP_VAL_DEFAULT || 1946*e7801d59Ssowmini type == DLADM_PROP_VAL_MODIFIABLE) { 1947*e7801d59Ssowmini *prop_val = &tmp; 1948*e7801d59Ssowmini *val_cnt = 1; 1949*e7801d59Ssowmini return (DLADM_STATUS_OK); 1950*e7801d59Ssowmini } 1951*e7801d59Ssowmini 1952*e7801d59Ssowmini /* 1953*e7801d59Ssowmini * private properties: all parsing is done in the kernel. 1954*e7801d59Ssowmini */ 1955*e7801d59Ssowmini dip = dld_buf_alloc(1024, linkid, prop_name, &status); 1956*e7801d59Ssowmini if (dip == NULL) 1957*e7801d59Ssowmini return (status); 1958*e7801d59Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1959*e7801d59Ssowmini 1960*e7801d59Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1961*e7801d59Ssowmini return (DLADM_STATUS_BADARG); 1962*e7801d59Ssowmini 1963*e7801d59Ssowmini if ((status = i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize)) < 0) { 1964*e7801d59Ssowmini status = dladm_errno2status(errno); 1965*e7801d59Ssowmini } else { 1966*e7801d59Ssowmini (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); 1967*e7801d59Ssowmini *val_cnt = 1; 1968*e7801d59Ssowmini } 1969*e7801d59Ssowmini return (status); 1970*e7801d59Ssowmini } 1971