13147Sxc151355 /* 23147Sxc151355 * CDDL HEADER START 33147Sxc151355 * 43147Sxc151355 * The contents of this file are subject to the terms of the 53147Sxc151355 * Common Development and Distribution License (the "License"). 63147Sxc151355 * You may not use this file except in compliance with the License. 73147Sxc151355 * 83147Sxc151355 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93147Sxc151355 * or http://www.opensolaris.org/os/licensing. 103147Sxc151355 * See the License for the specific language governing permissions 113147Sxc151355 * and limitations under the License. 123147Sxc151355 * 133147Sxc151355 * When distributing Covered Code, include this CDDL HEADER in each 143147Sxc151355 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153147Sxc151355 * If applicable, add the following below this CDDL HEADER, with the 163147Sxc151355 * fields enclosed by brackets "[]" replaced with your own identifying 173147Sxc151355 * information: Portions Copyright [yyyy] [name of copyright owner] 183147Sxc151355 * 193147Sxc151355 * CDDL HEADER END 203147Sxc151355 */ 213147Sxc151355 /* 225895Syz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233147Sxc151355 * Use is subject to license terms. 243147Sxc151355 */ 253147Sxc151355 263147Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 273147Sxc151355 283147Sxc151355 #include <stdlib.h> 293147Sxc151355 #include <strings.h> 303147Sxc151355 #include <errno.h> 313147Sxc151355 #include <ctype.h> 325895Syz147064 #include <stddef.h> 333448Sdh155122 #include <sys/types.h> 343147Sxc151355 #include <sys/stat.h> 353448Sdh155122 #include <sys/dld.h> 363448Sdh155122 #include <sys/zone.h> 373448Sdh155122 #include <fcntl.h> 383448Sdh155122 #include <unistd.h> 393448Sdh155122 #include <libdevinfo.h> 403448Sdh155122 #include <zone.h> 413871Syz147064 #include <libdllink.h> 423147Sxc151355 #include <libdladm_impl.h> 435895Syz147064 #include <libdlwlan_impl.h> 443871Syz147064 #include <libdlwlan.h> 455895Syz147064 #include <libdlvlan.h> 463448Sdh155122 #include <dlfcn.h> 473448Sdh155122 #include <link.h> 485895Syz147064 #include <inet/wifi_ioctl.h> 49*5903Ssowmini #include <libdladm.h> 50*5903Ssowmini #include <sys/param.h> 51*5903Ssowmini #include <sys/dld.h> 52*5903Ssowmini #include <inttypes.h> 53*5903Ssowmini #include <sys/ethernet.h> 543448Sdh155122 555895Syz147064 /* 565895Syz147064 * The linkprop get() callback. 57*5903Ssowmini * - pd: pointer to the struct prop_desc 585895Syz147064 * - propstrp: a property string array to keep the returned property. 595895Syz147064 * Caller allocated. 605895Syz147064 * - cntp: number of returned properties. 615895Syz147064 * Caller also uses it to indicate how many it expects. 625895Syz147064 */ 63*5903Ssowmini struct prop_desc; 64*5903Ssowmini 65*5903Ssowmini typedef dladm_status_t pd_getf_t(struct prop_desc *pd, 66*5903Ssowmini datalink_id_t, char **propstp, uint_t *cntp); 675895Syz147064 685895Syz147064 /* 695895Syz147064 * The linkprop set() callback. 705895Syz147064 * - propval: a val_desc_t array which keeps the property values to be set. 715895Syz147064 * - cnt: number of properties to be set. 72*5903Ssowmini * - flags: additional flags passed down the system call. 73*5903Ssowmini * 74*5903Ssowmini * pd_set takes val_desc_t given by pd_check(), translates it into 75*5903Ssowmini * a format suitable for kernel consumption. This may require allocation 76*5903Ssowmini * of ioctl buffers etc. pd_set() may call another common routine (used 77*5903Ssowmini * by all other pd_sets) which invokes the ioctl. 785895Syz147064 */ 79*5903Ssowmini typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t, 80*5903Ssowmini val_desc_t *propval, uint_t cnt, uint_t flags); 813448Sdh155122 823448Sdh155122 835895Syz147064 /* 845895Syz147064 * The linkprop check() callback. 855895Syz147064 * - propstrp: property string array which keeps the property to be checked. 865895Syz147064 * - cnt: number of properties. 875895Syz147064 * - propval: return value; the property values of the given property strings. 88*5903Ssowmini * 89*5903Ssowmini * pd_check checks that the input values are valid. It does so by 90*5903Ssowmini * iteraring through the pd_modval list for the property. If 91*5903Ssowmini * the modifiable values cannot be expressed as a list, a pd_check 92*5903Ssowmini * specific to this property can be used. If the input values are 93*5903Ssowmini * verified to be valid, pd_check allocates a val_desc_t and fills it 94*5903Ssowmini * with either a val_desc_t found on the pd_modval list or something 95*5903Ssowmini * generated on the fly. 965895Syz147064 */ 97*5903Ssowmini typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, 98*5903Ssowmini datalink_id_t, char **propstrp, 99*5903Ssowmini uint_t cnt, val_desc_t *propval); 1003448Sdh155122 101*5903Ssowmini typedef struct dld_public_prop_s { 102*5903Ssowmini dld_prop_id_t pp_id; 103*5903Ssowmini size_t pp_valsize; 104*5903Ssowmini char *pp_name; 105*5903Ssowmini char *pp_desc; 106*5903Ssowmini } dld_public_prop_t; 107*5903Ssowmini 108*5903Ssowmini static dld_ioc_prop_t *dld_buf_alloc(size_t, datalink_id_t, const char *, 109*5903Ssowmini dladm_status_t *); 110*5903Ssowmini static dladm_status_t dld_set_prop(datalink_id_t, const char *, char **, 111*5903Ssowmini uint_t, uint_t); 112*5903Ssowmini static dladm_status_t dld_get_prop(datalink_id_t, const char *, char **, 113*5903Ssowmini uint_t *, dladm_prop_type_t); 1145895Syz147064 static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, 1155895Syz147064 do_get_rate_prop, do_get_channel_prop, 116*5903Ssowmini do_get_powermode_prop, do_get_radio_prop, 117*5903Ssowmini dld_duplex_get, dld_speed_get, dld_status_get, 118*5903Ssowmini dld_binary_get, dld_uint64_get, dld_flowctl_get; 1195895Syz147064 static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop, 120*5903Ssowmini do_set_powermode_prop, do_set_radio_prop, 121*5903Ssowmini dld_set_public_prop; 122*5903Ssowmini static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, 123*5903Ssowmini dld_defmtu_check; 1243448Sdh155122 1253448Sdh155122 typedef struct prop_desc { 1265895Syz147064 /* 1275895Syz147064 * link property name 1285895Syz147064 */ 1295895Syz147064 char *pd_name; 1305895Syz147064 1315895Syz147064 /* 1325895Syz147064 * default property value, can be set to { "", NULL } 1335895Syz147064 */ 1345895Syz147064 val_desc_t pd_defval; 1355895Syz147064 1365895Syz147064 /* 1375895Syz147064 * list of optional property values, can be NULL. 1385895Syz147064 * 1395895Syz147064 * This is set to non-NULL if there is a list of possible property 1405895Syz147064 * values. pd_optval would point to the array of possible values. 1415895Syz147064 */ 1425895Syz147064 val_desc_t *pd_optval; 1435895Syz147064 1445895Syz147064 /* 1455895Syz147064 * count of the above optional property values. 0 if pd_optval is NULL. 1465895Syz147064 */ 1475895Syz147064 uint_t pd_noptval; 1485895Syz147064 1495895Syz147064 /* 1505895Syz147064 * callback to set link property; 1515895Syz147064 * set to NULL if this property is read-only 1525895Syz147064 */ 1535895Syz147064 pd_setf_t *pd_set; 1545895Syz147064 1555895Syz147064 /* 1565895Syz147064 * callback to get modifiable link property 1575895Syz147064 */ 1585895Syz147064 pd_getf_t *pd_getmod; 1595895Syz147064 1605895Syz147064 /* 1615895Syz147064 * callback to get current link property 1625895Syz147064 */ 1635895Syz147064 pd_getf_t *pd_get; 1645895Syz147064 1655895Syz147064 /* 1665895Syz147064 * callback to validate link property value, set to NULL if pd_optval 1675895Syz147064 * is not NULL. In that case, validate the value by comparing it with 1685895Syz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 1695895Syz147064 * valid. 1705895Syz147064 */ 1715895Syz147064 pd_checkf_t *pd_check; 1725895Syz147064 1735895Syz147064 uint_t pd_flags; 174*5903Ssowmini #define PD_TEMPONLY 0x1 /* property is temporary only */ 175*5903Ssowmini #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */ 1765895Syz147064 /* 1775895Syz147064 * indicate link classes this property applies to. 1785895Syz147064 */ 1795895Syz147064 datalink_class_t pd_class; 1805895Syz147064 1815895Syz147064 /* 1825895Syz147064 * indicate link media type this property applies to. 1835895Syz147064 */ 1845895Syz147064 datalink_media_t pd_dmedia; 1853448Sdh155122 } prop_desc_t; 1863448Sdh155122 187*5903Ssowmini #define DLD_PROPBUF_SIZE(v) sizeof (dld_ioc_prop_t) + (v) - 1 188*5903Ssowmini 189*5903Ssowmini 190*5903Ssowmini static dld_public_prop_t dld_prop[] = { 191*5903Ssowmini { DLD_PROP_DUPLEX, sizeof (uint8_t), 192*5903Ssowmini "link_duplex", "link duplex mode" }, 193*5903Ssowmini 194*5903Ssowmini {DLD_PROP_SPEED, sizeof (uint8_t), 195*5903Ssowmini "ifspeed", "link speed (Mbps)" }, 196*5903Ssowmini 197*5903Ssowmini { DLD_PROP_STATUS, sizeof (uint8_t), 198*5903Ssowmini "link_up", "link up/down" }, 199*5903Ssowmini 200*5903Ssowmini { DLD_PROP_AUTONEG, sizeof (uint8_t), 201*5903Ssowmini "adv_autoneg_cap", "Advertised auto-negotiation" }, 202*5903Ssowmini 203*5903Ssowmini { DLD_PROP_DEFMTU, sizeof (uint64_t), 204*5903Ssowmini "default_mtu", "default frame mtu" }, 205*5903Ssowmini 206*5903Ssowmini { DLD_PROP_FLOWCTRL, sizeof (link_flowctrl_t), 207*5903Ssowmini "flowctrl", "flowcontrol" }, 208*5903Ssowmini 209*5903Ssowmini { DLD_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), 210*5903Ssowmini "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, 211*5903Ssowmini 212*5903Ssowmini { DLD_PROP_EN_1000FDX_CAP, sizeof (uint8_t), 213*5903Ssowmini "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, 214*5903Ssowmini 215*5903Ssowmini { DLD_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), 216*5903Ssowmini "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, 217*5903Ssowmini 218*5903Ssowmini { DLD_PROP_EN_1000HDX_CAP, sizeof (uint8_t), 219*5903Ssowmini "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, 220*5903Ssowmini 221*5903Ssowmini { DLD_PROP_ADV_100FDX_CAP, sizeof (uint8_t), 222*5903Ssowmini "adv_100fdx_cap", "Adv 100 Mbps fdx" }, 223*5903Ssowmini 224*5903Ssowmini { DLD_PROP_EN_100FDX_CAP, sizeof (uint8_t), 225*5903Ssowmini "en_100fdx_cap", "Enable 100 Mbps fdx" }, 226*5903Ssowmini 227*5903Ssowmini { DLD_PROP_ADV_100HDX_CAP, sizeof (uint8_t), 228*5903Ssowmini "adv_100hdx_cap", "Adv 100 Mbps hdx" }, 229*5903Ssowmini 230*5903Ssowmini { DLD_PROP_EN_100HDX_CAP, sizeof (uint8_t), 231*5903Ssowmini "en_100hdx_cap", "Enable 100 Mbps hdx" }, 232*5903Ssowmini 233*5903Ssowmini { DLD_PROP_ADV_10FDX_CAP, sizeof (uint8_t), 234*5903Ssowmini "adv_10fdx_cap", "Adv 10 Mbps fdx" }, 235*5903Ssowmini 236*5903Ssowmini { DLD_PROP_EN_10FDX_CAP, sizeof (uint8_t), 237*5903Ssowmini "en_10fdx_cap", "Enable 10 Mbps fdx" }, 238*5903Ssowmini 239*5903Ssowmini { DLD_PROP_ADV_10HDX_CAP, sizeof (uint8_t), 240*5903Ssowmini "adv_10hdx_cap", "Adv 10 Mbps hdx" }, 241*5903Ssowmini 242*5903Ssowmini { DLD_PROP_EN_10HDX_CAP, sizeof (uint8_t), 243*5903Ssowmini "en_10hdx_cap", "Enable 10 Mbps hdx" }, 244*5903Ssowmini 245*5903Ssowmini { DLD_PROP_PRIVATE, 0, 246*5903Ssowmini "driver-private", "" } 247*5903Ssowmini }; 248*5903Ssowmini 249*5903Ssowmini static val_desc_t link_duplex_vals[] = { 250*5903Ssowmini { "half", LINK_DUPLEX_HALF }, 251*5903Ssowmini { "full", LINK_DUPLEX_HALF } 252*5903Ssowmini }; 253*5903Ssowmini static val_desc_t link_speed_vals[] = { 254*5903Ssowmini { "10", 10 }, 255*5903Ssowmini { "100", 100 }, 256*5903Ssowmini { "1000", 1000 } 257*5903Ssowmini }; 258*5903Ssowmini static val_desc_t link_status_vals[] = { 259*5903Ssowmini { "up", LINK_STATE_UP }, 260*5903Ssowmini { "down", LINK_STATE_DOWN } 261*5903Ssowmini }; 262*5903Ssowmini static val_desc_t link_01_vals[] = { 263*5903Ssowmini { "1", 1 }, 264*5903Ssowmini { "0", 0 } 265*5903Ssowmini }; 266*5903Ssowmini static val_desc_t link_flow_vals[] = { 267*5903Ssowmini { "no", LINK_FLOWCTRL_NONE }, 268*5903Ssowmini { "tx", LINK_FLOWCTRL_TX }, 269*5903Ssowmini { "rx", LINK_FLOWCTRL_RX }, 270*5903Ssowmini { "bi", LINK_FLOWCTRL_BI } 271*5903Ssowmini }; 272*5903Ssowmini static val_desc_t macdefaultmtu_vals[] = { 273*5903Ssowmini { "68-9000", NULL } 274*5903Ssowmini }; 275*5903Ssowmini 276*5903Ssowmini #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) 277*5903Ssowmini 2785895Syz147064 static val_desc_t dladm_wlan_radio_vals[] = { 2795895Syz147064 { "on", DLADM_WLAN_RADIO_ON }, 2805895Syz147064 { "off", DLADM_WLAN_RADIO_OFF } 2815895Syz147064 }; 2825895Syz147064 2835895Syz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 2845895Syz147064 { "off", DLADM_WLAN_PM_OFF }, 2855895Syz147064 { "fast", DLADM_WLAN_PM_FAST }, 2865895Syz147064 { "max", DLADM_WLAN_PM_MAX } 2875895Syz147064 }; 2885895Syz147064 2893448Sdh155122 static prop_desc_t prop_table[] = { 2905895Syz147064 291*5903Ssowmini { "channel", { NULL, 0 }, 292*5903Ssowmini NULL, 0, NULL, NULL, 2935895Syz147064 do_get_channel_prop, NULL, 0, 294*5903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 2955895Syz147064 2965895Syz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 2975895Syz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 2985895Syz147064 do_set_powermode_prop, NULL, 2995895Syz147064 do_get_powermode_prop, NULL, 0, 300*5903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3015895Syz147064 3025895Syz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 3035895Syz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 3045895Syz147064 do_set_radio_prop, NULL, 3055895Syz147064 do_get_radio_prop, NULL, 0, 306*5903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3075895Syz147064 3085895Syz147064 { "speed", { "", 0 }, NULL, 0, 3095895Syz147064 do_set_rate_prop, do_get_rate_mod, 3105895Syz147064 do_get_rate_prop, do_check_rate, 0, 311*5903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3125895Syz147064 3135895Syz147064 { "autopush", { "", NULL }, NULL, 0, 3145895Syz147064 do_set_autopush, NULL, 315*5903Ssowmini do_get_autopush, do_check_autopush, PD_CHECK_ALLOC, 316*5903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3175895Syz147064 3185895Syz147064 { "zone", { "", NULL }, NULL, 0, 3193448Sdh155122 do_set_zone, NULL, 3205895Syz147064 do_get_zone, do_check_zone, PD_TEMPONLY, 321*5903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 322*5903Ssowmini 323*5903Ssowmini { "link_duplex", { "full", LINK_DUPLEX_FULL }, 324*5903Ssowmini link_duplex_vals, VALCNT(link_duplex_vals), 325*5903Ssowmini NULL, NULL, dld_duplex_get, NULL, 326*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 327*5903Ssowmini 328*5903Ssowmini { "ifspeed", { "1000", 1000 }, 329*5903Ssowmini link_speed_vals, VALCNT(link_speed_vals), 330*5903Ssowmini NULL, NULL, dld_speed_get, NULL, 331*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 332*5903Ssowmini 333*5903Ssowmini { "link_up", { "up", LINK_STATE_UP }, 334*5903Ssowmini link_status_vals, VALCNT(link_status_vals), 335*5903Ssowmini NULL, NULL, dld_status_get, NULL, 336*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 337*5903Ssowmini 338*5903Ssowmini { "adv_autoneg_cap", { "1", 1 }, 339*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 340*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 341*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 342*5903Ssowmini 343*5903Ssowmini { "default_mtu", { NULL, NULL }, 344*5903Ssowmini macdefaultmtu_vals, VALCNT(macdefaultmtu_vals), 345*5903Ssowmini dld_set_public_prop, NULL, dld_uint64_get, dld_defmtu_check, 346*5903Ssowmini PD_CHECK_ALLOC, DATALINK_CLASS_PHYS, DL_ETHER }, 347*5903Ssowmini 348*5903Ssowmini { "flowctrl", { "bi", LINK_FLOWCTRL_BI }, 349*5903Ssowmini link_flow_vals, VALCNT(link_flow_vals), 350*5903Ssowmini dld_set_public_prop, NULL, dld_flowctl_get, NULL, 351*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 352*5903Ssowmini 353*5903Ssowmini { "adv_1000fdx_cap", { NULL, NULL }, 354*5903Ssowmini link_01_vals, 0, 355*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 356*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 357*5903Ssowmini 358*5903Ssowmini { "en_1000fdx_cap", { NULL, NULL }, 359*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 360*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 361*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 362*5903Ssowmini 363*5903Ssowmini { "adv_1000hdx_cap", { NULL, NULL }, 364*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 365*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 366*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 367*5903Ssowmini 368*5903Ssowmini { "en_1000hdx_cap", { NULL, NULL }, 369*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 370*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 371*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 372*5903Ssowmini 373*5903Ssowmini { "adv_100fdx_cap", { NULL, NULL }, 374*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 375*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 376*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 377*5903Ssowmini 378*5903Ssowmini { "en_100fdx_cap", { NULL, NULL }, 379*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 380*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 381*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 382*5903Ssowmini 383*5903Ssowmini { "adv_100hdx_cap", { NULL, NULL }, 384*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 385*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 386*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 387*5903Ssowmini 388*5903Ssowmini { "en_100hdx_cap", { NULL, NULL }, 389*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 390*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 391*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 392*5903Ssowmini 393*5903Ssowmini { "adv_10fdx_cap", { NULL, NULL }, 394*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 395*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 396*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 397*5903Ssowmini 398*5903Ssowmini { "en_10fdx_cap", { NULL, NULL }, 399*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 400*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 401*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 402*5903Ssowmini 403*5903Ssowmini { "adv_10hdx_cap", { NULL, NULL }, 404*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 405*5903Ssowmini NULL, NULL, dld_binary_get, NULL, 406*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 407*5903Ssowmini 408*5903Ssowmini { "en_10hdx_cap", { NULL, NULL }, 409*5903Ssowmini link_01_vals, VALCNT(link_01_vals), 410*5903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 411*5903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER } 412*5903Ssowmini 4133448Sdh155122 }; 4143448Sdh155122 4155895Syz147064 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 4165895Syz147064 4175895Syz147064 static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, 4185895Syz147064 char **, uint_t); 4195895Syz147064 static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, 4205895Syz147064 char **, uint_t *); 4215895Syz147064 static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t, 4225895Syz147064 uint32_t, prop_desc_t *, char **, uint_t, uint_t); 4235895Syz147064 static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *, 4245895Syz147064 char **, uint_t, uint_t); 4255895Syz147064 4265895Syz147064 /* 4275895Syz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 4285895Syz147064 * rates to be retrieved. However, we cannot increase it at this 4295895Syz147064 * time because it will break binary compatibility with unbundled 4305895Syz147064 * WiFi drivers and utilities. So for now we define an additional 4315895Syz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 4325895Syz147064 */ 4335895Syz147064 #define MAX_SUPPORT_RATES 64 4345895Syz147064 4355895Syz147064 #define AP_ANCHOR "[anchor]" 4365895Syz147064 #define AP_DELIMITER '.' 4375895Syz147064 4385895Syz147064 static dladm_status_t 4395895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4405895Syz147064 val_desc_t *vdp) 4415895Syz147064 { 4425895Syz147064 int i, j; 4435895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4443147Sxc151355 4455895Syz147064 for (j = 0; j < val_cnt; j++) { 4465895Syz147064 for (i = 0; i < pdp->pd_noptval; i++) { 4475895Syz147064 if (strcasecmp(*prop_val, 4485895Syz147064 pdp->pd_optval[i].vd_name) == 0) { 4495895Syz147064 break; 4505895Syz147064 } 4515895Syz147064 } 4525895Syz147064 if (i == pdp->pd_noptval) { 4535895Syz147064 status = DLADM_STATUS_BADVAL; 4545895Syz147064 goto done; 4555895Syz147064 } 4565895Syz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 4575895Syz147064 } 4585895Syz147064 4595895Syz147064 done: 4605895Syz147064 return (status); 4615895Syz147064 } 4625895Syz147064 4635895Syz147064 static dladm_status_t 4645895Syz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 4655895Syz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4665895Syz147064 uint_t flags) 4673147Sxc151355 { 4685895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4695895Syz147064 val_desc_t *vdp = NULL; 4705895Syz147064 boolean_t needfree = B_FALSE; 4715895Syz147064 uint_t cnt, i; 4723147Sxc151355 4735895Syz147064 if (!(pdp->pd_class & class)) 4745895Syz147064 return (DLADM_STATUS_BADARG); 4755895Syz147064 4765895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 4773147Sxc151355 return (DLADM_STATUS_BADARG); 4783147Sxc151355 4795895Syz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 4805895Syz147064 return (DLADM_STATUS_TEMPONLY); 4815895Syz147064 4825895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 4835895Syz147064 return (DLADM_STATUS_OK); 4845895Syz147064 4855895Syz147064 if (pdp->pd_set == NULL) 4865895Syz147064 return (DLADM_STATUS_PROPRDONLY); 4873448Sdh155122 488*5903Ssowmini if (pdp->pd_flags & PD_CHECK_ALLOC) 489*5903Ssowmini needfree = B_TRUE; 490*5903Ssowmini else 491*5903Ssowmini needfree = B_FALSE; 4925895Syz147064 if (prop_val != NULL) { 4935895Syz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 4945895Syz147064 if (vdp == NULL) 4955895Syz147064 return (DLADM_STATUS_NOMEM); 4965895Syz147064 497*5903Ssowmini 4985895Syz147064 if (pdp->pd_check != NULL) { 499*5903Ssowmini status = pdp->pd_check(pdp, linkid, prop_val, val_cnt, 500*5903Ssowmini vdp); 5015895Syz147064 } else if (pdp->pd_optval != NULL) { 5025895Syz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 5035895Syz147064 } else { 5043448Sdh155122 status = DLADM_STATUS_BADARG; 5053147Sxc151355 } 5065895Syz147064 5073147Sxc151355 if (status != DLADM_STATUS_OK) 5085895Syz147064 goto done; 5095895Syz147064 5105895Syz147064 cnt = val_cnt; 5115895Syz147064 } else { 5125895Syz147064 if (pdp->pd_defval.vd_name == NULL) 5135895Syz147064 return (DLADM_STATUS_NOTSUP); 5145895Syz147064 5155895Syz147064 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 5165895Syz147064 return (DLADM_STATUS_NOMEM); 5175895Syz147064 5185895Syz147064 (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t)); 5195895Syz147064 cnt = 1; 5205895Syz147064 } 521*5903Ssowmini status = pdp->pd_set(pdp, linkid, vdp, cnt, flags); 5225895Syz147064 if (needfree) { 5235895Syz147064 for (i = 0; i < cnt; i++) 524*5903Ssowmini free((void *)((val_desc_t *)vdp + i)->vd_val); 5253147Sxc151355 } 5265895Syz147064 done: 5275895Syz147064 free(vdp); 5285895Syz147064 return (status); 5295895Syz147064 } 5305895Syz147064 5315895Syz147064 static dladm_status_t 5325895Syz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 5335895Syz147064 char **prop_val, uint_t val_cnt, uint_t flags) 5345895Syz147064 { 5355895Syz147064 int i; 5365895Syz147064 boolean_t found = B_FALSE; 5375895Syz147064 datalink_class_t class; 5385895Syz147064 uint32_t media; 5395895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 5405895Syz147064 5415895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 5425895Syz147064 if (status != DLADM_STATUS_OK) 5435895Syz147064 return (status); 5445895Syz147064 5455895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 5465895Syz147064 prop_desc_t *pdp = &prop_table[i]; 5475895Syz147064 dladm_status_t s; 5485895Syz147064 5495895Syz147064 if (prop_name != NULL && 5505895Syz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 5515895Syz147064 continue; 5525895Syz147064 5535895Syz147064 found = B_TRUE; 5545895Syz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 5555895Syz147064 val_cnt, flags); 5563448Sdh155122 5575895Syz147064 if (prop_name != NULL) { 5585895Syz147064 status = s; 5595895Syz147064 break; 5605895Syz147064 } else { 5615895Syz147064 if (s != DLADM_STATUS_OK && 5625895Syz147064 s != DLADM_STATUS_NOTSUP) 5635895Syz147064 status = s; 5645895Syz147064 } 5655895Syz147064 } 566*5903Ssowmini if (!found) { 567*5903Ssowmini if (prop_name[0] == '_') { 568*5903Ssowmini /* other private properties */ 569*5903Ssowmini status = dld_set_prop(linkid, prop_name, prop_val, 570*5903Ssowmini val_cnt, flags); 571*5903Ssowmini } else { 572*5903Ssowmini status = DLADM_STATUS_NOTFOUND; 573*5903Ssowmini } 574*5903Ssowmini } 5755895Syz147064 5765895Syz147064 return (status); 5775895Syz147064 } 5785895Syz147064 5795895Syz147064 /* 5805895Syz147064 * Set/reset link property for specific link 5815895Syz147064 */ 5825895Syz147064 dladm_status_t 5835895Syz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 5845895Syz147064 uint_t val_cnt, uint_t flags) 5855895Syz147064 { 5865895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 5875895Syz147064 5885895Syz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 5895895Syz147064 (prop_val == NULL && val_cnt > 0) || 5905895Syz147064 (prop_val != NULL && val_cnt == 0) || 5915895Syz147064 (prop_name == NULL && prop_val != NULL)) { 5925895Syz147064 return (DLADM_STATUS_BADARG); 5935895Syz147064 } 5945895Syz147064 5955895Syz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 5965895Syz147064 val_cnt, flags); 5975895Syz147064 if (status != DLADM_STATUS_OK) 5985895Syz147064 return (status); 5995895Syz147064 6005895Syz147064 if (flags & DLADM_OPT_PERSIST) { 6015895Syz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 6023147Sxc151355 prop_val, val_cnt); 6033147Sxc151355 } 6043147Sxc151355 return (status); 6053147Sxc151355 } 6063147Sxc151355 6075895Syz147064 /* 6085895Syz147064 * Walk link properties of the given specific link. 6095895Syz147064 */ 6103147Sxc151355 dladm_status_t 6115895Syz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 6125895Syz147064 int (*func)(datalink_id_t, const char *, void *)) 6133147Sxc151355 { 6145895Syz147064 dladm_status_t status; 6155895Syz147064 datalink_class_t class; 6165895Syz147064 uint_t media; 6175895Syz147064 int i; 6185895Syz147064 6195895Syz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 6205895Syz147064 return (DLADM_STATUS_BADARG); 6215895Syz147064 6225895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6235895Syz147064 if (status != DLADM_STATUS_OK) 6245895Syz147064 return (status); 6255895Syz147064 6265895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 6275895Syz147064 if (!(prop_table[i].pd_class & class)) 6285895Syz147064 continue; 6295895Syz147064 6305895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 6315895Syz147064 continue; 6325895Syz147064 6335895Syz147064 if (func(linkid, prop_table[i].pd_name, arg) == 6345895Syz147064 DLADM_WALK_TERMINATE) { 6355895Syz147064 break; 6365895Syz147064 } 6375895Syz147064 } 6385895Syz147064 6395895Syz147064 return (DLADM_STATUS_OK); 6405895Syz147064 } 6413448Sdh155122 6425895Syz147064 /* 6435895Syz147064 * Get linkprop of the given specific link. 6445895Syz147064 */ 6455895Syz147064 dladm_status_t 6465895Syz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 6475895Syz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 6485895Syz147064 { 6495895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 6505895Syz147064 datalink_class_t class; 6515895Syz147064 uint_t media; 6525895Syz147064 prop_desc_t *pdp; 6535895Syz147064 uint_t cnt; 6545895Syz147064 int i; 6555895Syz147064 6565895Syz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 6575895Syz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 6585895Syz147064 return (DLADM_STATUS_BADARG); 6595895Syz147064 6605895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 6615895Syz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 6625895Syz147064 break; 6635895Syz147064 664*5903Ssowmini if (i == DLADM_MAX_PROPS) { 665*5903Ssowmini if (prop_name[0] == '_') { 666*5903Ssowmini /* 667*5903Ssowmini * private property. 668*5903Ssowmini */ 669*5903Ssowmini return (dld_get_prop(linkid, prop_name, 670*5903Ssowmini prop_val, val_cntp, type)); 671*5903Ssowmini } else { 672*5903Ssowmini return (DLADM_STATUS_NOTFOUND); 673*5903Ssowmini } 674*5903Ssowmini } 6755895Syz147064 6765895Syz147064 pdp = &prop_table[i]; 6775895Syz147064 6785895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6795895Syz147064 if (status != DLADM_STATUS_OK) 6805895Syz147064 return (status); 6815895Syz147064 6825895Syz147064 if (!(pdp->pd_class & class)) 6835895Syz147064 return (DLADM_STATUS_BADARG); 6845895Syz147064 6855895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 6863147Sxc151355 return (DLADM_STATUS_BADARG); 6873147Sxc151355 6885895Syz147064 switch (type) { 6895895Syz147064 case DLADM_PROP_VAL_CURRENT: 690*5903Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp); 6915895Syz147064 break; 6925895Syz147064 6935895Syz147064 case DLADM_PROP_VAL_DEFAULT: 6945895Syz147064 if (pdp->pd_defval.vd_name == NULL) { 6955895Syz147064 status = DLADM_STATUS_NOTSUP; 6965895Syz147064 break; 6975895Syz147064 } 6985895Syz147064 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 6995895Syz147064 *val_cntp = 1; 7005895Syz147064 break; 7013448Sdh155122 7025895Syz147064 case DLADM_PROP_VAL_MODIFIABLE: 7035895Syz147064 if (pdp->pd_getmod != NULL) { 704*5903Ssowmini status = pdp->pd_getmod(pdp, linkid, prop_val, 705*5903Ssowmini val_cntp); 7065895Syz147064 break; 7075895Syz147064 } 7085895Syz147064 cnt = pdp->pd_noptval; 7095895Syz147064 if (cnt == 0) { 7105895Syz147064 status = DLADM_STATUS_NOTSUP; 7115895Syz147064 } else if (cnt > *val_cntp) { 7125895Syz147064 status = DLADM_STATUS_TOOSMALL; 7135895Syz147064 } else { 7145895Syz147064 for (i = 0; i < cnt; i++) { 7155895Syz147064 (void) strcpy(prop_val[i], 7165895Syz147064 pdp->pd_optval[i].vd_name); 7175895Syz147064 } 7185895Syz147064 *val_cntp = cnt; 7195895Syz147064 } 7205895Syz147064 break; 7215895Syz147064 case DLADM_PROP_VAL_PERSISTENT: 7225895Syz147064 if (pdp->pd_flags & PD_TEMPONLY) 7235895Syz147064 return (DLADM_STATUS_TEMPONLY); 7245895Syz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 7255895Syz147064 prop_val, val_cntp); 7265895Syz147064 break; 7275895Syz147064 default: 7285895Syz147064 status = DLADM_STATUS_BADARG; 7295895Syz147064 break; 7303147Sxc151355 } 7313448Sdh155122 7325895Syz147064 return (status); 7335895Syz147064 } 7345895Syz147064 7355895Syz147064 /*ARGSUSED*/ 7365895Syz147064 static int 7375895Syz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 7385895Syz147064 { 7395895Syz147064 char *buf, **propvals; 7405895Syz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 7415895Syz147064 7425895Syz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 7435895Syz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 7445895Syz147064 return (DLADM_WALK_CONTINUE); 7455895Syz147064 } 7465895Syz147064 7475895Syz147064 propvals = (char **)(void *)buf; 7485895Syz147064 for (i = 0; i < valcnt; i++) { 7495895Syz147064 propvals[i] = buf + 7505895Syz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 7515895Syz147064 i * DLADM_PROP_VAL_MAX; 7525895Syz147064 } 7535895Syz147064 7545895Syz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 7555895Syz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 7565895Syz147064 goto done; 7575895Syz147064 } 7585895Syz147064 7595895Syz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 7605895Syz147064 DLADM_OPT_ACTIVE); 7615895Syz147064 7625895Syz147064 done: 7635895Syz147064 if (buf != NULL) 7645895Syz147064 free(buf); 7655895Syz147064 7665895Syz147064 return (DLADM_WALK_CONTINUE); 7675895Syz147064 } 7685895Syz147064 7695895Syz147064 /*ARGSUSED*/ 7705895Syz147064 static int 7715895Syz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 7725895Syz147064 { 7735895Syz147064 (void) dladm_init_linkprop(linkid); 7745895Syz147064 return (DLADM_WALK_CONTINUE); 7755895Syz147064 } 7765895Syz147064 7775895Syz147064 dladm_status_t 7785895Syz147064 dladm_init_linkprop(datalink_id_t linkid) 7795895Syz147064 { 7805895Syz147064 if (linkid == DATALINK_ALL_LINKID) { 7815895Syz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 7825895Syz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 7835895Syz147064 DLADM_OPT_PERSIST); 7845895Syz147064 } else { 7855895Syz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 7863448Sdh155122 } 7873448Sdh155122 return (DLADM_STATUS_OK); 7883147Sxc151355 } 7893147Sxc151355 790*5903Ssowmini /* ARGSUSED */ 7915895Syz147064 static dladm_status_t 792*5903Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid, 793*5903Ssowmini char **prop_val, uint_t *val_cnt) 7943147Sxc151355 { 7955895Syz147064 char zone_name[ZONENAME_MAX]; 7965895Syz147064 zoneid_t zid; 7975895Syz147064 dladm_status_t status; 7983147Sxc151355 7995895Syz147064 status = dladm_getzid(linkid, &zid); 8005895Syz147064 if (status != DLADM_STATUS_OK) 8013448Sdh155122 return (status); 8023448Sdh155122 8035895Syz147064 *val_cnt = 1; 8045895Syz147064 if (zid != GLOBAL_ZONEID) { 8055895Syz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8065895Syz147064 return (dladm_errno2status(errno)); 8073147Sxc151355 8085895Syz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 8093147Sxc151355 } else { 8105895Syz147064 *prop_val[0] = '\0'; 8113147Sxc151355 } 8123147Sxc151355 8133448Sdh155122 return (DLADM_STATUS_OK); 8143448Sdh155122 } 8153448Sdh155122 8163448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 8173448Sdh155122 8183448Sdh155122 static int 8193448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 8203448Sdh155122 { 8213448Sdh155122 char root[MAXPATHLEN]; 8223448Sdh155122 zone_get_devroot_t real_zone_get_devroot; 8233448Sdh155122 void *dlhandle; 8243448Sdh155122 void *sym; 8253448Sdh155122 int ret; 8263448Sdh155122 8273448Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 8283448Sdh155122 return (-1); 8293448Sdh155122 8303448Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 8313448Sdh155122 (void) dlclose(dlhandle); 8323448Sdh155122 return (-1); 8333448Sdh155122 } 8343448Sdh155122 8353448Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 8363448Sdh155122 8373448Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 8383448Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 8393448Sdh155122 (void) dlclose(dlhandle); 8403448Sdh155122 return (ret); 8413448Sdh155122 } 8423448Sdh155122 8433448Sdh155122 static dladm_status_t 8445895Syz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 8453448Sdh155122 { 8463448Sdh155122 char path[MAXPATHLEN]; 8475895Syz147064 char name[MAXLINKNAMELEN]; 8483448Sdh155122 di_prof_t prof = NULL; 8493448Sdh155122 char zone_name[ZONENAME_MAX]; 8503448Sdh155122 dladm_status_t status; 8515895Syz147064 int ret; 8523448Sdh155122 8533448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8543448Sdh155122 return (dladm_errno2status(errno)); 8553448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 8563448Sdh155122 return (dladm_errno2status(errno)); 8573448Sdh155122 if (di_prof_init(path, &prof) != 0) 8583448Sdh155122 return (dladm_errno2status(errno)); 8593448Sdh155122 8605895Syz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 8615895Syz147064 if (status != DLADM_STATUS_OK) 8625895Syz147064 goto cleanup; 8635895Syz147064 8645895Syz147064 if (add) 8655895Syz147064 ret = di_prof_add_dev(prof, name); 8665895Syz147064 else 8675895Syz147064 ret = di_prof_add_exclude(prof, name); 8685895Syz147064 8695895Syz147064 if (ret != 0) { 8703448Sdh155122 status = dladm_errno2status(errno); 8713448Sdh155122 goto cleanup; 8723448Sdh155122 } 8733448Sdh155122 8743448Sdh155122 if (di_prof_commit(prof) != 0) 8753448Sdh155122 status = dladm_errno2status(errno); 8763448Sdh155122 cleanup: 8773448Sdh155122 if (prof) 8783448Sdh155122 di_prof_fini(prof); 8793448Sdh155122 8803448Sdh155122 return (status); 8813448Sdh155122 } 8823448Sdh155122 883*5903Ssowmini /* ARGSUSED */ 8843448Sdh155122 static dladm_status_t 885*5903Ssowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, 886*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 8873448Sdh155122 { 8883448Sdh155122 dladm_status_t status; 8893448Sdh155122 zoneid_t zid_old, zid_new; 8905895Syz147064 char link[MAXLINKNAMELEN]; 8913448Sdh155122 8923448Sdh155122 if (val_cnt != 1) 8933448Sdh155122 return (DLADM_STATUS_BADVALCNT); 8943448Sdh155122 8955895Syz147064 status = dladm_getzid(linkid, &zid_old); 8963448Sdh155122 if (status != DLADM_STATUS_OK) 8973448Sdh155122 return (status); 8983448Sdh155122 8993448Sdh155122 /* Do nothing if setting to current value */ 9005895Syz147064 zid_new = vdp->vd_val; 9013448Sdh155122 if (zid_new == zid_old) 9023448Sdh155122 return (DLADM_STATUS_OK); 9033448Sdh155122 9045895Syz147064 if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 9055895Syz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 9065895Syz147064 return (status); 9075895Syz147064 } 9085895Syz147064 9095895Syz147064 if (zid_new != GLOBAL_ZONEID) { 9105895Syz147064 /* 9115895Syz147064 * If the new zoneid is the global zone, we could destroy 9125895Syz147064 * the link (in the case of an implicitly-created VLAN) as a 9135895Syz147064 * result of the dladm_setzid() operation. In that case, 9145895Syz147064 * we defer the operation to the end of this function to avoid 9155895Syz147064 * recreating the VLAN and getting a different linkid during 9165895Syz147064 * the rollback if other operation fails. 9175895Syz147064 * 9185895Syz147064 * Otherwise, dladm_setzid() will hold a reference to the 9195895Syz147064 * link and prevent a link renaming, so we need to do it 9205895Syz147064 * before other operations. 9215895Syz147064 */ 9225895Syz147064 status = dladm_setzid(link, zid_new); 9235895Syz147064 if (status != DLADM_STATUS_OK) 9245895Syz147064 return (status); 9255895Syz147064 } 9265895Syz147064 9273448Sdh155122 if (zid_old != GLOBAL_ZONEID) { 9285895Syz147064 if (zone_remove_datalink(zid_old, link) != 0 && 9293448Sdh155122 errno != ENXIO) { 9303448Sdh155122 status = dladm_errno2status(errno); 9313448Sdh155122 goto rollback1; 9323448Sdh155122 } 9333448Sdh155122 9345895Syz147064 /* 9355895Syz147064 * It is okay to fail to update the /dev entry (some 9365895Syz147064 * vanity-named links do not have a /dev entry). 9375895Syz147064 */ 9385895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 9395895Syz147064 } 9405895Syz147064 9415895Syz147064 if (zid_new != GLOBAL_ZONEID) { 9425895Syz147064 if (zone_add_datalink(zid_new, link) != 0) { 9435895Syz147064 status = dladm_errno2status(errno); 9445895Syz147064 goto rollback2; 9455895Syz147064 } 9465895Syz147064 9475895Syz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 9485895Syz147064 } else { 9495895Syz147064 status = dladm_setzid(link, zid_new); 9503448Sdh155122 if (status != DLADM_STATUS_OK) 9513448Sdh155122 goto rollback2; 9523448Sdh155122 } 9533448Sdh155122 9543448Sdh155122 return (DLADM_STATUS_OK); 9553448Sdh155122 9563448Sdh155122 rollback2: 9573448Sdh155122 if (zid_old != GLOBAL_ZONEID) 9585895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 9595895Syz147064 if (zid_old != GLOBAL_ZONEID) 9605895Syz147064 (void) zone_add_datalink(zid_old, link); 9613448Sdh155122 rollback1: 9625895Syz147064 if (zid_new != GLOBAL_ZONEID) 9635895Syz147064 (void) dladm_setzid(link, zid_old); 9643448Sdh155122 return (status); 9653448Sdh155122 } 9663448Sdh155122 9673448Sdh155122 /* ARGSUSED */ 9683448Sdh155122 static dladm_status_t 969*5903Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 970*5903Ssowmini uint_t val_cnt, val_desc_t *vdp) 9713448Sdh155122 { 9725895Syz147064 zoneid_t zid; 9733448Sdh155122 9743448Sdh155122 if (val_cnt != 1) 9753448Sdh155122 return (DLADM_STATUS_BADVALCNT); 9763448Sdh155122 9773448Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 9783448Sdh155122 return (DLADM_STATUS_BADVAL); 9793448Sdh155122 9803448Sdh155122 if (zid != GLOBAL_ZONEID) { 9813448Sdh155122 ushort_t flags; 9823448Sdh155122 9833448Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 9843448Sdh155122 sizeof (flags)) < 0) { 9853448Sdh155122 return (dladm_errno2status(errno)); 9863448Sdh155122 } 9873448Sdh155122 9883448Sdh155122 if (!(flags & ZF_NET_EXCL)) { 9893448Sdh155122 return (DLADM_STATUS_BADVAL); 9903448Sdh155122 } 9913448Sdh155122 } 9923448Sdh155122 9935895Syz147064 vdp->vd_val = zid; 9945895Syz147064 return (DLADM_STATUS_OK); 9955895Syz147064 } 9965895Syz147064 997*5903Ssowmini /* ARGSUSED */ 9985895Syz147064 static dladm_status_t 999*5903Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid, 1000*5903Ssowmini char **prop_val, uint_t *val_cnt) 10015895Syz147064 { 10025895Syz147064 dld_ioc_ap_t dia; 10035895Syz147064 int fd, i, len; 10045895Syz147064 10055895Syz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 10065895Syz147064 return (dladm_errno2status(errno)); 10075895Syz147064 10085895Syz147064 *val_cnt = 1; 10095895Syz147064 dia.dia_linkid = linkid; 10105895Syz147064 if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) { 10115895Syz147064 (*prop_val)[0] = '\0'; 10125895Syz147064 goto done; 10135895Syz147064 } 10145895Syz147064 10155895Syz147064 for (i = 0, len = 0; i < dia.dia_npush; i++) { 10165895Syz147064 if (i != 0) { 10175895Syz147064 (void) snprintf(*prop_val + len, 10185895Syz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 10195895Syz147064 len += 1; 10205895Syz147064 } 10215895Syz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 10225895Syz147064 "%s", dia.dia_aplist[i]); 10235895Syz147064 len += strlen(dia.dia_aplist[i]); 10245895Syz147064 if (dia.dia_anchor - 1 == i) { 10255895Syz147064 (void) snprintf(*prop_val + len, 10265895Syz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 10275895Syz147064 AP_ANCHOR); 10285895Syz147064 len += (strlen(AP_ANCHOR) + 1); 10295895Syz147064 } 10305895Syz147064 } 10315895Syz147064 10325895Syz147064 done: 10335895Syz147064 (void) close(fd); 10345895Syz147064 return (DLADM_STATUS_OK); 10355895Syz147064 } 10365895Syz147064 1037*5903Ssowmini /* ARGSUSED */ 10385895Syz147064 static dladm_status_t 1039*5903Ssowmini do_set_autopush(prop_desc_t *pd, datalink_id_t linkid, 1040*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 10415895Syz147064 { 10425895Syz147064 dld_ioc_ap_t dia; 10435895Syz147064 struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val; 10445895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 10455895Syz147064 int fd, i; 10465895Syz147064 int ic_cmd; 10475895Syz147064 10485895Syz147064 if (val_cnt != 1) 10495895Syz147064 return (DLADM_STATUS_BADVALCNT); 10505895Syz147064 10515895Syz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 10525895Syz147064 return (dladm_errno2status(errno)); 10535895Syz147064 10545895Syz147064 dia.dia_linkid = linkid; 10555895Syz147064 if (dlap != NULL) { 10565895Syz147064 dia.dia_anchor = dlap->dap_anchor; 10575895Syz147064 dia.dia_npush = dlap->dap_npush; 10585895Syz147064 for (i = 0; i < dia.dia_npush; i++) { 10595895Syz147064 (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i], 10605895Syz147064 FMNAMESZ+1); 10615895Syz147064 } 10625895Syz147064 ic_cmd = DLDIOC_SETAUTOPUSH; 10635895Syz147064 } else { 10645895Syz147064 ic_cmd = DLDIOC_CLRAUTOPUSH; 10655895Syz147064 } 10665895Syz147064 10675895Syz147064 if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0) 10685895Syz147064 status = dladm_errno2status(errno); 10695895Syz147064 10705895Syz147064 (void) close(fd); 10715895Syz147064 return (status); 10725895Syz147064 } 10735895Syz147064 10745895Syz147064 /* 10755895Syz147064 * Add the specified module to the dlautopush structure; returns a 10765895Syz147064 * DLADM_STATUS_* code. 10775895Syz147064 */ 10785895Syz147064 dladm_status_t 10795895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 10805895Syz147064 { 10815895Syz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 10825895Syz147064 return (DLADM_STATUS_BADVAL); 10835895Syz147064 10845895Syz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 10855895Syz147064 /* 10865895Syz147064 * We don't allow multiple anchors, and the anchor must 10875895Syz147064 * be after at least one module. 10885895Syz147064 */ 10895895Syz147064 if (dlap->dap_anchor != 0) 10905895Syz147064 return (DLADM_STATUS_BADVAL); 10915895Syz147064 if (dlap->dap_npush == 0) 10925895Syz147064 return (DLADM_STATUS_BADVAL); 10935895Syz147064 10945895Syz147064 dlap->dap_anchor = dlap->dap_npush; 10955895Syz147064 return (DLADM_STATUS_OK); 10965895Syz147064 } 10975895Syz147064 if (dlap->dap_npush > MAXAPUSH) 10985895Syz147064 return (DLADM_STATUS_BADVALCNT); 10995895Syz147064 11005895Syz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 11015895Syz147064 FMNAMESZ + 1); 11025895Syz147064 11035895Syz147064 return (DLADM_STATUS_OK); 11045895Syz147064 } 11055895Syz147064 11065895Syz147064 /* 11075895Syz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 11085895Syz147064 * autopush modules. The former is used in dladm set-linkprop, and the 11095895Syz147064 * latter is used in the autopush(1M) file. 11105895Syz147064 */ 11115895Syz147064 /* ARGSUSED */ 11125895Syz147064 static dladm_status_t 1113*5903Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1114*5903Ssowmini uint_t val_cnt, val_desc_t *vdp) 11155895Syz147064 { 11165895Syz147064 char *module; 11175895Syz147064 struct dlautopush *dlap; 11185895Syz147064 dladm_status_t status; 11195895Syz147064 char val[DLADM_PROP_VAL_MAX]; 11205895Syz147064 char delimiters[4]; 11215895Syz147064 11225895Syz147064 if (val_cnt != 1) 11235895Syz147064 return (DLADM_STATUS_BADVALCNT); 11245895Syz147064 11255895Syz147064 dlap = malloc(sizeof (struct dlautopush)); 11265895Syz147064 if (dlap == NULL) 11273448Sdh155122 return (DLADM_STATUS_NOMEM); 11283448Sdh155122 11295895Syz147064 (void) memset(dlap, 0, sizeof (struct dlautopush)); 11305895Syz147064 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 11315895Syz147064 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 11325895Syz147064 module = strtok(val, delimiters); 11335895Syz147064 while (module != NULL) { 11345895Syz147064 status = i_dladm_add_ap_module(module, dlap); 11355895Syz147064 if (status != DLADM_STATUS_OK) 11365895Syz147064 return (status); 11375895Syz147064 module = strtok(NULL, delimiters); 11385895Syz147064 } 11395895Syz147064 11405895Syz147064 vdp->vd_val = (uintptr_t)dlap; 11413448Sdh155122 return (DLADM_STATUS_OK); 11423448Sdh155122 } 11433448Sdh155122 1144*5903Ssowmini /* ARGSUSED */ 11453448Sdh155122 static dladm_status_t 1146*5903Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, 1147*5903Ssowmini char **prop_val, uint_t *val_cnt, uint_t id) 11483448Sdh155122 { 11495895Syz147064 wl_rates_t *wrp; 11505895Syz147064 uint_t i; 11515895Syz147064 wldp_t *gbuf = NULL; 11525895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11535895Syz147064 11545895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 11555895Syz147064 status = DLADM_STATUS_NOMEM; 11565895Syz147064 goto done; 11575895Syz147064 } 11585895Syz147064 11595895Syz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 11605895Syz147064 if (status != DLADM_STATUS_OK) 11615895Syz147064 goto done; 11625895Syz147064 11635895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 11645895Syz147064 if (wrp->wl_rates_num > *val_cnt) { 11655895Syz147064 status = DLADM_STATUS_TOOSMALL; 11665895Syz147064 goto done; 11675895Syz147064 } 11685895Syz147064 11695895Syz147064 if (wrp->wl_rates_rates[0] == 0) { 11705895Syz147064 prop_val[0][0] = '\0'; 11715895Syz147064 *val_cnt = 1; 11725895Syz147064 goto done; 11735895Syz147064 } 11745895Syz147064 11755895Syz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 11765895Syz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 11775895Syz147064 wrp->wl_rates_rates[i] % 2, 11785895Syz147064 (float)wrp->wl_rates_rates[i] / 2); 11795895Syz147064 } 11805895Syz147064 *val_cnt = wrp->wl_rates_num; 11813448Sdh155122 11825895Syz147064 done: 11835895Syz147064 free(gbuf); 11845895Syz147064 return (status); 11855895Syz147064 } 11865895Syz147064 11875895Syz147064 static dladm_status_t 1188*5903Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, 1189*5903Ssowmini char **prop_val, uint_t *val_cnt) 11905895Syz147064 { 1191*5903Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 11925895Syz147064 WL_DESIRED_RATES)); 11935895Syz147064 } 11945895Syz147064 11955895Syz147064 static dladm_status_t 1196*5903Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, 1197*5903Ssowmini char **prop_val, uint_t *val_cnt) 11985895Syz147064 { 1199*5903Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 12005895Syz147064 WL_SUPPORTED_RATES)); 12015895Syz147064 } 12025895Syz147064 12035895Syz147064 static dladm_status_t 12045895Syz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 12055895Syz147064 { 12065895Syz147064 int i; 12075895Syz147064 uint_t len; 12085895Syz147064 wldp_t *gbuf; 12095895Syz147064 wl_rates_t *wrp; 12105895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 12115895Syz147064 12125895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 12135895Syz147064 return (DLADM_STATUS_NOMEM); 12145895Syz147064 12155895Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 12163448Sdh155122 12175895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 12185895Syz147064 for (i = 0; i < rates->wr_cnt; i++) 12195895Syz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 12205895Syz147064 wrp->wl_rates_num = rates->wr_cnt; 12215895Syz147064 12225895Syz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 12235895Syz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 12245895Syz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 12255895Syz147064 WLAN_SET_PARAM, len); 12265895Syz147064 12275895Syz147064 free(gbuf); 12285895Syz147064 return (status); 12295895Syz147064 } 12303448Sdh155122 1231*5903Ssowmini /* ARGSUSED */ 12325895Syz147064 static dladm_status_t 1233*5903Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid, 1234*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 12355895Syz147064 { 12365895Syz147064 dladm_wlan_rates_t rates; 12375895Syz147064 dladm_status_t status; 12385895Syz147064 12395895Syz147064 if (val_cnt != 1) 12405895Syz147064 return (DLADM_STATUS_BADVALCNT); 12415895Syz147064 12425895Syz147064 rates.wr_cnt = 1; 12435895Syz147064 rates.wr_rates[0] = vdp[0].vd_val; 12445895Syz147064 12455895Syz147064 status = do_set_rate(linkid, &rates); 12465895Syz147064 12475895Syz147064 done: 12485895Syz147064 return (status); 12495895Syz147064 } 12503448Sdh155122 12515895Syz147064 /* ARGSUSED */ 12525895Syz147064 static dladm_status_t 1253*5903Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1254*5903Ssowmini uint_t val_cnt, val_desc_t *vdp) 12555895Syz147064 { 12565895Syz147064 int i; 12575895Syz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 12585895Syz147064 char *buf, **modval; 12595895Syz147064 dladm_status_t status; 12605895Syz147064 12615895Syz147064 if (val_cnt != 1) 12625895Syz147064 return (DLADM_STATUS_BADVALCNT); 12635895Syz147064 12645895Syz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 12655895Syz147064 MAX_SUPPORT_RATES); 12665895Syz147064 if (buf == NULL) { 12675895Syz147064 status = DLADM_STATUS_NOMEM; 12685895Syz147064 goto done; 12695895Syz147064 } 12703448Sdh155122 12715895Syz147064 modval = (char **)(void *)buf; 12725895Syz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 12735895Syz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 12745895Syz147064 i * DLADM_STRSIZE; 12755895Syz147064 } 12765895Syz147064 1277*5903Ssowmini status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt); 12785895Syz147064 if (status != DLADM_STATUS_OK) 12795895Syz147064 goto done; 12805895Syz147064 12815895Syz147064 for (i = 0; i < modval_cnt; i++) { 12825895Syz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 1283*5903Ssowmini vdp->vd_val = (uintptr_t)(uint_t) 1284*5903Ssowmini (atof(*prop_val) * 2); 12855895Syz147064 status = DLADM_STATUS_OK; 12863448Sdh155122 break; 12873448Sdh155122 } 12885895Syz147064 } 12895895Syz147064 if (i == modval_cnt) 12905895Syz147064 status = DLADM_STATUS_BADVAL; 12915895Syz147064 done: 12925895Syz147064 free(buf); 12935895Syz147064 return (status); 12945895Syz147064 } 12955895Syz147064 12965895Syz147064 static dladm_status_t 12975895Syz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 12985895Syz147064 { 12995895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 13005895Syz147064 } 13015895Syz147064 1302*5903Ssowmini /* ARGSUSED */ 13035895Syz147064 static dladm_status_t 1304*5903Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, 1305*5903Ssowmini char **prop_val, uint_t *val_cnt) 13065895Syz147064 { 13075895Syz147064 uint32_t channel; 13085895Syz147064 wldp_t *gbuf; 13095895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 13105895Syz147064 13115895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13125895Syz147064 return (DLADM_STATUS_NOMEM); 13135895Syz147064 13145895Syz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 13155895Syz147064 goto done; 13165895Syz147064 13175895Syz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 13185895Syz147064 &channel)) { 13195895Syz147064 status = DLADM_STATUS_NOTFOUND; 13205895Syz147064 goto done; 13215895Syz147064 } 13225895Syz147064 13235895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 13245895Syz147064 *val_cnt = 1; 13253448Sdh155122 13265895Syz147064 done: 13275895Syz147064 free(gbuf); 13285895Syz147064 return (status); 13295895Syz147064 } 13305895Syz147064 13315895Syz147064 static dladm_status_t 13325895Syz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 13335895Syz147064 { 13345895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 13355895Syz147064 } 13365895Syz147064 1337*5903Ssowmini /* ARGSUSED */ 13385895Syz147064 static dladm_status_t 1339*5903Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, 1340*5903Ssowmini char **prop_val, uint_t *val_cnt) 13415895Syz147064 { 13425895Syz147064 wl_ps_mode_t *mode; 13435895Syz147064 const char *s; 13445895Syz147064 wldp_t *gbuf; 13455895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 13465895Syz147064 13475895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13485895Syz147064 return (DLADM_STATUS_NOMEM); 13495895Syz147064 13505895Syz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 13515895Syz147064 goto done; 13525895Syz147064 13535895Syz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 13545895Syz147064 switch (mode->wl_ps_mode) { 13555895Syz147064 case WL_PM_AM: 13565895Syz147064 s = "off"; 13575895Syz147064 break; 13585895Syz147064 case WL_PM_MPS: 13595895Syz147064 s = "max"; 13605895Syz147064 break; 13615895Syz147064 case WL_PM_FAST: 13625895Syz147064 s = "fast"; 13633448Sdh155122 break; 13643448Sdh155122 default: 13655895Syz147064 status = DLADM_STATUS_NOTFOUND; 13665895Syz147064 goto done; 13675895Syz147064 } 13685895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 13695895Syz147064 *val_cnt = 1; 13705895Syz147064 13715895Syz147064 done: 13725895Syz147064 free(gbuf); 13735895Syz147064 return (status); 13745895Syz147064 } 13755895Syz147064 13765895Syz147064 static dladm_status_t 13775895Syz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 13785895Syz147064 { 13795895Syz147064 wl_ps_mode_t ps_mode; 13805895Syz147064 13815895Syz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 13825895Syz147064 13835895Syz147064 switch (*pm) { 13845895Syz147064 case DLADM_WLAN_PM_OFF: 13855895Syz147064 ps_mode.wl_ps_mode = WL_PM_AM; 13863448Sdh155122 break; 13875895Syz147064 case DLADM_WLAN_PM_MAX: 13885895Syz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 13895895Syz147064 break; 13905895Syz147064 case DLADM_WLAN_PM_FAST: 13915895Syz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 13925895Syz147064 break; 13935895Syz147064 default: 13945895Syz147064 return (DLADM_STATUS_NOTSUP); 13953448Sdh155122 } 13965895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 13975895Syz147064 sizeof (ps_mode))); 13985895Syz147064 } 13995895Syz147064 14005895Syz147064 /* ARGSUSED */ 14015895Syz147064 static dladm_status_t 1402*5903Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, 1403*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 14045895Syz147064 { 14055895Syz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 14065895Syz147064 dladm_status_t status; 14075895Syz147064 14085895Syz147064 if (val_cnt != 1) 14095895Syz147064 return (DLADM_STATUS_BADVALCNT); 14105895Syz147064 14115895Syz147064 status = do_set_powermode(linkid, &powermode); 14123448Sdh155122 14133448Sdh155122 return (status); 14143448Sdh155122 } 14153448Sdh155122 14163448Sdh155122 static dladm_status_t 14175895Syz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 14183448Sdh155122 { 14195895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 14205895Syz147064 } 14213448Sdh155122 1422*5903Ssowmini /* ARGSUSED */ 14235895Syz147064 static dladm_status_t 1424*5903Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, 1425*5903Ssowmini char **prop_val, uint_t *val_cnt) 14265895Syz147064 { 14275895Syz147064 wl_radio_t radio; 14285895Syz147064 const char *s; 14295895Syz147064 wldp_t *gbuf; 14305895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 14313448Sdh155122 14325895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 14335895Syz147064 return (DLADM_STATUS_NOMEM); 14343448Sdh155122 14355895Syz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 14365895Syz147064 goto done; 14373448Sdh155122 14385895Syz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 14395895Syz147064 switch (radio) { 14405895Syz147064 case B_TRUE: 14415895Syz147064 s = "on"; 14425895Syz147064 break; 14435895Syz147064 case B_FALSE: 14445895Syz147064 s = "off"; 14455895Syz147064 break; 14465895Syz147064 default: 14475895Syz147064 status = DLADM_STATUS_NOTFOUND; 14485895Syz147064 goto done; 14495895Syz147064 } 14505895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 14515895Syz147064 *val_cnt = 1; 14523448Sdh155122 14535895Syz147064 done: 14545895Syz147064 free(gbuf); 14553448Sdh155122 return (status); 14563448Sdh155122 } 14573448Sdh155122 14583448Sdh155122 static dladm_status_t 14595895Syz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 14603448Sdh155122 { 14615895Syz147064 wl_radio_t r; 14623448Sdh155122 14635895Syz147064 switch (*radio) { 14645895Syz147064 case DLADM_WLAN_RADIO_ON: 14655895Syz147064 r = B_TRUE; 14665895Syz147064 break; 14675895Syz147064 case DLADM_WLAN_RADIO_OFF: 14685895Syz147064 r = B_FALSE; 14695895Syz147064 break; 14705895Syz147064 default: 14715895Syz147064 return (DLADM_STATUS_NOTSUP); 14725895Syz147064 } 14735895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 14745895Syz147064 } 14753448Sdh155122 14765895Syz147064 /* ARGSUSED */ 14775895Syz147064 static dladm_status_t 1478*5903Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid, 1479*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t fags) 14805895Syz147064 { 14815895Syz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 14825895Syz147064 dladm_status_t status; 14833448Sdh155122 14845895Syz147064 if (val_cnt != 1) 14855895Syz147064 return (DLADM_STATUS_BADVALCNT); 14865895Syz147064 14875895Syz147064 status = do_set_radio(linkid, &radio); 14883448Sdh155122 14893448Sdh155122 return (status); 14903448Sdh155122 } 14913448Sdh155122 14925895Syz147064 static dladm_status_t 14935895Syz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 14945895Syz147064 char **prop_val, uint_t val_cnt) 14953448Sdh155122 { 14965895Syz147064 char buf[MAXLINELEN]; 14975895Syz147064 int i; 14985895Syz147064 dladm_conf_t conf; 14995895Syz147064 dladm_status_t status; 15003448Sdh155122 15015895Syz147064 status = dladm_read_conf(linkid, &conf); 15025895Syz147064 if (status != DLADM_STATUS_OK) 15035895Syz147064 return (status); 15043448Sdh155122 15055895Syz147064 /* 15065895Syz147064 * reset case. 15075895Syz147064 */ 15085895Syz147064 if (val_cnt == 0) { 15095895Syz147064 status = dladm_unset_conf_field(conf, prop_name); 15105895Syz147064 if (status == DLADM_STATUS_OK) 15115895Syz147064 status = dladm_write_conf(conf); 15125895Syz147064 goto done; 15135895Syz147064 } 15143448Sdh155122 15155895Syz147064 buf[0] = '\0'; 15165895Syz147064 for (i = 0; i < val_cnt; i++) { 15175895Syz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 15185895Syz147064 if (i != val_cnt - 1) 15195895Syz147064 (void) strlcat(buf, ",", MAXLINELEN); 15203448Sdh155122 } 15213448Sdh155122 15225895Syz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 15235895Syz147064 if (status == DLADM_STATUS_OK) 15245895Syz147064 status = dladm_write_conf(conf); 15255895Syz147064 15265895Syz147064 done: 15275895Syz147064 dladm_destroy_conf(conf); 15285895Syz147064 return (status); 15293448Sdh155122 } 15305895Syz147064 15315895Syz147064 static dladm_status_t 15325895Syz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 15335895Syz147064 char **prop_val, uint_t *val_cntp) 15345895Syz147064 { 15355895Syz147064 char buf[MAXLINELEN], *str; 15365895Syz147064 uint_t cnt = 0; 15375895Syz147064 dladm_conf_t conf; 15385895Syz147064 dladm_status_t status; 15395895Syz147064 15405895Syz147064 status = dladm_read_conf(linkid, &conf); 15415895Syz147064 if (status != DLADM_STATUS_OK) 15425895Syz147064 return (status); 15435895Syz147064 15445895Syz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 15455895Syz147064 if (status != DLADM_STATUS_OK) 15465895Syz147064 goto done; 15475895Syz147064 15485895Syz147064 str = strtok(buf, ","); 15495895Syz147064 while (str != NULL) { 15505895Syz147064 if (cnt == *val_cntp) { 15515895Syz147064 status = DLADM_STATUS_TOOSMALL; 15525895Syz147064 goto done; 15535895Syz147064 } 15545895Syz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 15555895Syz147064 str = strtok(NULL, ","); 15565895Syz147064 } 15575895Syz147064 15585895Syz147064 *val_cntp = cnt; 15595895Syz147064 15605895Syz147064 done: 15615895Syz147064 dladm_destroy_conf(conf); 15625895Syz147064 return (status); 15635895Syz147064 } 1564*5903Ssowmini 1565*5903Ssowmini static dld_public_prop_t * 1566*5903Ssowmini dladm_name2prop(const char *prop_name) 1567*5903Ssowmini { 1568*5903Ssowmini dld_public_prop_t *p; 1569*5903Ssowmini 1570*5903Ssowmini for (p = dld_prop; p->pp_id != DLD_PROP_PRIVATE; p++) { 1571*5903Ssowmini if (strcmp(p->pp_name, prop_name) == 0) 1572*5903Ssowmini break; 1573*5903Ssowmini } 1574*5903Ssowmini return (p); 1575*5903Ssowmini } 1576*5903Ssowmini 1577*5903Ssowmini 1578*5903Ssowmini static dld_ioc_prop_t * 1579*5903Ssowmini dld_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, 1580*5903Ssowmini dladm_status_t *status) 1581*5903Ssowmini { 1582*5903Ssowmini int dsize; 1583*5903Ssowmini dld_ioc_prop_t *dip; 1584*5903Ssowmini dld_public_prop_t *p; 1585*5903Ssowmini char link[DLPI_LINKNAME_MAX]; 1586*5903Ssowmini uint32_t flags; 1587*5903Ssowmini 1588*5903Ssowmini *status = DLADM_STATUS_OK; 1589*5903Ssowmini p = dladm_name2prop(prop_name); 1590*5903Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1591*5903Ssowmini valsize = p->pp_valsize; 1592*5903Ssowmini 1593*5903Ssowmini dsize = DLD_PROPBUF_SIZE(valsize); 1594*5903Ssowmini dip = malloc(dsize); 1595*5903Ssowmini if (dip == NULL) { 1596*5903Ssowmini *status = DLADM_STATUS_NOMEM; 1597*5903Ssowmini return (NULL); 1598*5903Ssowmini } 1599*5903Ssowmini bzero(dip, dsize); 1600*5903Ssowmini dip->pr_valsize = valsize; 1601*5903Ssowmini (void) strlcpy(dip->pr_name, prop_name, DLD_LINKPROP_NAME_MAX); 1602*5903Ssowmini dip->pr_version = DLD_PROP_VERSION; 1603*5903Ssowmini 1604*5903Ssowmini if ((*status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, 1605*5903Ssowmini (char *)link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK) { 1606*5903Ssowmini free(dip); 1607*5903Ssowmini return (NULL); 1608*5903Ssowmini } 1609*5903Ssowmini 1610*5903Ssowmini if (!(flags & DLADM_OPT_ACTIVE)) { 1611*5903Ssowmini free(dip); 1612*5903Ssowmini *status = DLADM_STATUS_TEMPONLY; 1613*5903Ssowmini return (NULL); 1614*5903Ssowmini } 1615*5903Ssowmini (void) strlcpy(dip->pr_linkname, link, IFNAMSIZ); 1616*5903Ssowmini dip->pr_num = p->pp_id; 1617*5903Ssowmini return (dip); 1618*5903Ssowmini } 1619*5903Ssowmini 1620*5903Ssowmini /* ARGSUSED */ 1621*5903Ssowmini static dladm_status_t 1622*5903Ssowmini dld_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, 1623*5903Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags) 1624*5903Ssowmini { 1625*5903Ssowmini dld_ioc_prop_t *dip; 1626*5903Ssowmini int fd, dsize; 1627*5903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1628*5903Ssowmini uint8_t u8; 1629*5903Ssowmini uint16_t u16; 1630*5903Ssowmini uint32_t u32; 1631*5903Ssowmini void *val; 1632*5903Ssowmini 1633*5903Ssowmini dip = dld_buf_alloc(0, linkid, pd->pd_name, &status); 1634*5903Ssowmini if (dip == NULL) 1635*5903Ssowmini return (status); 1636*5903Ssowmini 1637*5903Ssowmini if (pd->pd_flags & PD_CHECK_ALLOC) 1638*5903Ssowmini val = (void *)vdp->vd_val; 1639*5903Ssowmini else { 1640*5903Ssowmini /* 1641*5903Ssowmini * Currently all 1/2/4-byte size properties are byte/word/int. 1642*5903Ssowmini * No need (yet) to distinguish these from arrays of same size. 1643*5903Ssowmini */ 1644*5903Ssowmini switch (dip->pr_valsize) { 1645*5903Ssowmini case 1: 1646*5903Ssowmini u8 = vdp->vd_val; 1647*5903Ssowmini val = &u8; 1648*5903Ssowmini break; 1649*5903Ssowmini case 2: 1650*5903Ssowmini u16 = vdp->vd_val; 1651*5903Ssowmini val = &u16; 1652*5903Ssowmini break; 1653*5903Ssowmini case 4: 1654*5903Ssowmini u32 = vdp->vd_val; 1655*5903Ssowmini val = &u32; 1656*5903Ssowmini break; 1657*5903Ssowmini default: 1658*5903Ssowmini val = &vdp->vd_val; 1659*5903Ssowmini break; 1660*5903Ssowmini } 1661*5903Ssowmini } 1662*5903Ssowmini 1663*5903Ssowmini (void) memcpy(dip->pr_val, val, dip->pr_valsize); 1664*5903Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1665*5903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1666*5903Ssowmini status = dladm_errno2status(errno); 1667*5903Ssowmini goto done; 1668*5903Ssowmini } 1669*5903Ssowmini if (i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize) < 0) 1670*5903Ssowmini status = dladm_errno2status(errno); 1671*5903Ssowmini 1672*5903Ssowmini (void) close(fd); 1673*5903Ssowmini done: 1674*5903Ssowmini return (status); 1675*5903Ssowmini } 1676*5903Ssowmini 1677*5903Ssowmini static dladm_status_t 1678*5903Ssowmini dld_get_public_prop(dld_ioc_prop_t *dip) 1679*5903Ssowmini { 1680*5903Ssowmini int fd, dsize; 1681*5903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1682*5903Ssowmini 1683*5903Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1684*5903Ssowmini 1685*5903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1686*5903Ssowmini status = dladm_errno2status(errno); 1687*5903Ssowmini goto done; 1688*5903Ssowmini } 1689*5903Ssowmini if (i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize) < 0) { 1690*5903Ssowmini status = dladm_errno2status(errno); 1691*5903Ssowmini } 1692*5903Ssowmini done: 1693*5903Ssowmini return (status); 1694*5903Ssowmini } 1695*5903Ssowmini 1696*5903Ssowmini 1697*5903Ssowmini /* ARGSUSED */ 1698*5903Ssowmini static dladm_status_t 1699*5903Ssowmini dld_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 1700*5903Ssowmini uint_t val_cnt, val_desc_t *v) 1701*5903Ssowmini { 1702*5903Ssowmini uint64_t mtu; 1703*5903Ssowmini 1704*5903Ssowmini if (val_cnt != 1) 1705*5903Ssowmini return (DLADM_STATUS_BADVAL); 1706*5903Ssowmini mtu = atoll(prop_val[0]); 1707*5903Ssowmini v->vd_val = (uintptr_t)malloc(sizeof (uint64_t)); 1708*5903Ssowmini if ((void *)v->vd_val == NULL) 1709*5903Ssowmini return (DLADM_STATUS_NOMEM); 1710*5903Ssowmini bcopy(&mtu, (void *)v->vd_val, sizeof (mtu)); 1711*5903Ssowmini return (DLADM_STATUS_OK); 1712*5903Ssowmini } 1713*5903Ssowmini 1714*5903Ssowmini /* ARGSUSED */ 1715*5903Ssowmini static dladm_status_t 1716*5903Ssowmini dld_duplex_get(struct prop_desc *pd, datalink_id_t linkid, 1717*5903Ssowmini char **prop_val, uint_t *val_cnt) 1718*5903Ssowmini { 1719*5903Ssowmini link_duplex_t link_duplex; 1720*5903Ssowmini dladm_status_t status; 1721*5903Ssowmini 1722*5903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_duplex", 1723*5903Ssowmini KSTAT_DATA_UINT32, &link_duplex)) != 0) 1724*5903Ssowmini return (status); 1725*5903Ssowmini 1726*5903Ssowmini switch (link_duplex) { 1727*5903Ssowmini case LINK_DUPLEX_FULL: 1728*5903Ssowmini (void) strcpy(*prop_val, "full"); 1729*5903Ssowmini break; 1730*5903Ssowmini case LINK_DUPLEX_HALF: 1731*5903Ssowmini (void) strcpy(*prop_val, "half"); 1732*5903Ssowmini break; 1733*5903Ssowmini default: 1734*5903Ssowmini (void) strcpy(*prop_val, "unknown"); 1735*5903Ssowmini break; 1736*5903Ssowmini } 1737*5903Ssowmini *val_cnt = 1; 1738*5903Ssowmini return (DLADM_STATUS_OK); 1739*5903Ssowmini } 1740*5903Ssowmini 1741*5903Ssowmini /* ARGSUSED */ 1742*5903Ssowmini static dladm_status_t 1743*5903Ssowmini dld_speed_get(struct prop_desc *pd, datalink_id_t linkid, 1744*5903Ssowmini char **prop_val, uint_t *val_cnt) 1745*5903Ssowmini { 1746*5903Ssowmini uint64_t ifspeed = 0; 1747*5903Ssowmini dladm_status_t status; 1748*5903Ssowmini 1749*5903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "ifspeed", 1750*5903Ssowmini KSTAT_DATA_UINT64, &ifspeed)) != 0) 1751*5903Ssowmini return (status); 1752*5903Ssowmini 1753*5903Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 1754*5903Ssowmini "%llu", ifspeed / 1000000); /* Mbps */ 1755*5903Ssowmini *val_cnt = 1; 1756*5903Ssowmini return (DLADM_STATUS_OK); 1757*5903Ssowmini } 1758*5903Ssowmini 1759*5903Ssowmini /* ARGSUSED */ 1760*5903Ssowmini static dladm_status_t 1761*5903Ssowmini dld_status_get(struct prop_desc *pd, datalink_id_t linkid, 1762*5903Ssowmini char **prop_val, uint_t *val_cnt) 1763*5903Ssowmini { 1764*5903Ssowmini link_state_t link_state; 1765*5903Ssowmini dladm_status_t status; 1766*5903Ssowmini 1767*5903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_state", 1768*5903Ssowmini KSTAT_DATA_UINT32, &link_state)) != 0) 1769*5903Ssowmini return (status); 1770*5903Ssowmini 1771*5903Ssowmini switch (link_state) { 1772*5903Ssowmini case LINK_STATE_UP: 1773*5903Ssowmini (void) strcpy(*prop_val, "up"); 1774*5903Ssowmini break; 1775*5903Ssowmini case LINK_STATE_DOWN: 1776*5903Ssowmini (void) strcpy(*prop_val, "down"); 1777*5903Ssowmini break; 1778*5903Ssowmini default: 1779*5903Ssowmini (void) strcpy(*prop_val, "unknown"); 1780*5903Ssowmini break; 1781*5903Ssowmini } 1782*5903Ssowmini *val_cnt = 1; 1783*5903Ssowmini return (DLADM_STATUS_OK); 1784*5903Ssowmini } 1785*5903Ssowmini 1786*5903Ssowmini /* ARGSUSED */ 1787*5903Ssowmini static dladm_status_t 1788*5903Ssowmini dld_binary_get(struct prop_desc *pd, datalink_id_t linkid, 1789*5903Ssowmini char **prop_val, uint_t *val_cnt) 1790*5903Ssowmini { 1791*5903Ssowmini dld_ioc_prop_t *dip; 1792*5903Ssowmini dladm_status_t status; 1793*5903Ssowmini 1794*5903Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1795*5903Ssowmini return (status); 1796*5903Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1797*5903Ssowmini free(dip); 1798*5903Ssowmini return (status); 1799*5903Ssowmini } 1800*5903Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]); 1801*5903Ssowmini free(dip); 1802*5903Ssowmini *val_cnt = 1; 1803*5903Ssowmini return (DLADM_STATUS_OK); 1804*5903Ssowmini } 1805*5903Ssowmini 1806*5903Ssowmini static dladm_status_t 1807*5903Ssowmini dld_uint64_get(struct prop_desc *pd, datalink_id_t linkid, 1808*5903Ssowmini char **prop_val, uint_t *val_cnt) 1809*5903Ssowmini { 1810*5903Ssowmini dld_ioc_prop_t *dip; 1811*5903Ssowmini uint64_t v = 0; 1812*5903Ssowmini uchar_t *cp; 1813*5903Ssowmini dladm_status_t status; 1814*5903Ssowmini 1815*5903Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1816*5903Ssowmini return (status); 1817*5903Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1818*5903Ssowmini free(dip); 1819*5903Ssowmini return (status); 1820*5903Ssowmini } 1821*5903Ssowmini cp = (uchar_t *)dip->pr_val; 1822*5903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 1823*5903Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%" PRIu64, v); 1824*5903Ssowmini free(dip); 1825*5903Ssowmini *val_cnt = 1; 1826*5903Ssowmini return (DLADM_STATUS_OK); 1827*5903Ssowmini } 1828*5903Ssowmini 1829*5903Ssowmini static dladm_status_t 1830*5903Ssowmini dld_flowctl_get(struct prop_desc *pd, datalink_id_t linkid, 1831*5903Ssowmini char **prop_val, uint_t *val_cnt) 1832*5903Ssowmini { 1833*5903Ssowmini dld_ioc_prop_t *dip; 1834*5903Ssowmini link_flowctrl_t v; 1835*5903Ssowmini dladm_status_t status; 1836*5903Ssowmini uchar_t *cp; 1837*5903Ssowmini 1838*5903Ssowmini if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL) 1839*5903Ssowmini return (status); 1840*5903Ssowmini 1841*5903Ssowmini if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) { 1842*5903Ssowmini free(dip); 1843*5903Ssowmini return (status); 1844*5903Ssowmini } 1845*5903Ssowmini cp = (uchar_t *)dip->pr_val; 1846*5903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 1847*5903Ssowmini switch (v) { 1848*5903Ssowmini case LINK_FLOWCTRL_NONE: 1849*5903Ssowmini (void) sprintf(*prop_val, "no"); 1850*5903Ssowmini break; 1851*5903Ssowmini case LINK_FLOWCTRL_RX: 1852*5903Ssowmini (void) sprintf(*prop_val, "rx"); 1853*5903Ssowmini break; 1854*5903Ssowmini case LINK_FLOWCTRL_TX: 1855*5903Ssowmini (void) sprintf(*prop_val, "tx"); 1856*5903Ssowmini break; 1857*5903Ssowmini case LINK_FLOWCTRL_BI: 1858*5903Ssowmini (void) sprintf(*prop_val, "bi"); 1859*5903Ssowmini break; 1860*5903Ssowmini } 1861*5903Ssowmini free(dip); 1862*5903Ssowmini *val_cnt = 1; 1863*5903Ssowmini return (DLADM_STATUS_OK); 1864*5903Ssowmini } 1865*5903Ssowmini 1866*5903Ssowmini 1867*5903Ssowmini /* ARGSUSED */ 1868*5903Ssowmini static dladm_status_t 1869*5903Ssowmini dld_set_prop(datalink_id_t linkid, const char *prop_name, 1870*5903Ssowmini char **prop_val, uint_t val_cnt, uint_t flags) 1871*5903Ssowmini { 1872*5903Ssowmini int fd, i, slen; 1873*5903Ssowmini int bufsize = 0, dsize; 1874*5903Ssowmini dld_ioc_prop_t *dip = NULL; 1875*5903Ssowmini uchar_t *dp; 1876*5903Ssowmini dld_public_prop_t *p; 1877*5903Ssowmini dladm_status_t status; 1878*5903Ssowmini 1879*5903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 1880*5903Ssowmini (prop_val != NULL && val_cnt == 0)) 1881*5903Ssowmini return (DLADM_STATUS_BADARG); 1882*5903Ssowmini p = dladm_name2prop(prop_name); 1883*5903Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1884*5903Ssowmini return (DLADM_STATUS_BADARG); 1885*5903Ssowmini 1886*5903Ssowmini /* 1887*5903Ssowmini * private properties: all parsing is done in the kernel. 1888*5903Ssowmini * allocate a enough space for each property + its separator (','). 1889*5903Ssowmini */ 1890*5903Ssowmini for (i = 0; i < val_cnt; i++) { 1891*5903Ssowmini bufsize += strlen(prop_val[i]) + 1; 1892*5903Ssowmini } 1893*5903Ssowmini dip = dld_buf_alloc(bufsize + 1, linkid, prop_name, &status); 1894*5903Ssowmini if (dip == NULL) 1895*5903Ssowmini return (status); 1896*5903Ssowmini 1897*5903Ssowmini dp = (uchar_t *)dip->pr_val; 1898*5903Ssowmini dsize = sizeof (dld_ioc_prop_t) + bufsize; 1899*5903Ssowmini slen = 0; 1900*5903Ssowmini for (i = 0; i < val_cnt; i++) { 1901*5903Ssowmini int plen = 0; 1902*5903Ssowmini 1903*5903Ssowmini plen = strlen(prop_val[i]); 1904*5903Ssowmini bcopy(prop_val[i], dp, plen); 1905*5903Ssowmini slen += plen; 1906*5903Ssowmini /* 1907*5903Ssowmini * add a "," separator and update dp. 1908*5903Ssowmini */ 1909*5903Ssowmini if (i != (val_cnt -1)) 1910*5903Ssowmini dp[slen++] = ','; 1911*5903Ssowmini dp += (plen + 1); 1912*5903Ssowmini } 1913*5903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 1914*5903Ssowmini free(dip); 1915*5903Ssowmini return (dladm_errno2status(errno)); 1916*5903Ssowmini } 1917*5903Ssowmini if ((status = i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize)) < 0) { 1918*5903Ssowmini free(dip); 1919*5903Ssowmini return (status); 1920*5903Ssowmini } 1921*5903Ssowmini free(dip); 1922*5903Ssowmini (void) close(fd); 1923*5903Ssowmini return (DLADM_STATUS_OK); 1924*5903Ssowmini } 1925*5903Ssowmini 1926*5903Ssowmini static dladm_status_t 1927*5903Ssowmini dld_get_prop(datalink_id_t linkid, const char *prop_name, 1928*5903Ssowmini char **prop_val, uint_t *val_cnt, dladm_prop_type_t type) 1929*5903Ssowmini { 1930*5903Ssowmini int fd; 1931*5903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 1932*5903Ssowmini uint_t dsize; 1933*5903Ssowmini dld_ioc_prop_t *dip = NULL; 1934*5903Ssowmini dld_public_prop_t *p; 1935*5903Ssowmini char tmp = '\0'; 1936*5903Ssowmini 1937*5903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 1938*5903Ssowmini (prop_val != NULL && val_cnt == 0)) 1939*5903Ssowmini return (DLADM_STATUS_BADARG); 1940*5903Ssowmini 1941*5903Ssowmini p = dladm_name2prop(prop_name); 1942*5903Ssowmini if (p->pp_id != DLD_PROP_PRIVATE) 1943*5903Ssowmini return (DLADM_STATUS_BADARG); 1944*5903Ssowmini 1945*5903Ssowmini if (type == DLADM_PROP_VAL_DEFAULT || 1946*5903Ssowmini type == DLADM_PROP_VAL_MODIFIABLE) { 1947*5903Ssowmini *prop_val = &tmp; 1948*5903Ssowmini *val_cnt = 1; 1949*5903Ssowmini return (DLADM_STATUS_OK); 1950*5903Ssowmini } 1951*5903Ssowmini 1952*5903Ssowmini /* 1953*5903Ssowmini * private properties: all parsing is done in the kernel. 1954*5903Ssowmini */ 1955*5903Ssowmini dip = dld_buf_alloc(1024, linkid, prop_name, &status); 1956*5903Ssowmini if (dip == NULL) 1957*5903Ssowmini return (status); 1958*5903Ssowmini dsize = DLD_PROPBUF_SIZE(dip->pr_valsize); 1959*5903Ssowmini 1960*5903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 1961*5903Ssowmini return (DLADM_STATUS_BADARG); 1962*5903Ssowmini 1963*5903Ssowmini if ((status = i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize)) < 0) { 1964*5903Ssowmini status = dladm_errno2status(errno); 1965*5903Ssowmini } else { 1966*5903Ssowmini (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); 1967*5903Ssowmini *val_cnt = 1; 1968*5903Ssowmini } 1969*5903Ssowmini return (status); 1970*5903Ssowmini } 1971