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> 495903Ssowmini #include <libdladm.h> 505903Ssowmini #include <sys/param.h> 515903Ssowmini #include <sys/dld.h> 525903Ssowmini #include <inttypes.h> 535903Ssowmini #include <sys/ethernet.h> 543448Sdh155122 555895Syz147064 /* 565895Syz147064 * The linkprop get() callback. 575903Ssowmini * - 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 */ 635903Ssowmini struct prop_desc; 645903Ssowmini 655903Ssowmini typedef dladm_status_t pd_getf_t(struct prop_desc *pd, 665960Ssowmini datalink_id_t, char **propstp, uint_t *cntp, 676512Ssowmini datalink_media_t, uint_t); 685895Syz147064 695895Syz147064 /* 705895Syz147064 * The linkprop set() callback. 715895Syz147064 * - propval: a val_desc_t array which keeps the property values to be set. 725895Syz147064 * - cnt: number of properties to be set. 735903Ssowmini * - flags: additional flags passed down the system call. 745903Ssowmini * 755903Ssowmini * pd_set takes val_desc_t given by pd_check(), translates it into 765903Ssowmini * a format suitable for kernel consumption. This may require allocation 775903Ssowmini * of ioctl buffers etc. pd_set() may call another common routine (used 785903Ssowmini * by all other pd_sets) which invokes the ioctl. 795895Syz147064 */ 805903Ssowmini typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t, 815960Ssowmini val_desc_t *propval, uint_t cnt, uint_t flags, 825960Ssowmini datalink_media_t); 833448Sdh155122 843448Sdh155122 855895Syz147064 /* 865895Syz147064 * The linkprop check() callback. 875895Syz147064 * - propstrp: property string array which keeps the property to be checked. 885895Syz147064 * - cnt: number of properties. 895895Syz147064 * - propval: return value; the property values of the given property strings. 905903Ssowmini * 915903Ssowmini * pd_check checks that the input values are valid. It does so by 925903Ssowmini * iteraring through the pd_modval list for the property. If 935903Ssowmini * the modifiable values cannot be expressed as a list, a pd_check 945903Ssowmini * specific to this property can be used. If the input values are 955903Ssowmini * verified to be valid, pd_check allocates a val_desc_t and fills it 965903Ssowmini * with either a val_desc_t found on the pd_modval list or something 975903Ssowmini * generated on the fly. 985895Syz147064 */ 995903Ssowmini typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, 1005903Ssowmini datalink_id_t, char **propstrp, 1015960Ssowmini uint_t cnt, val_desc_t *propval, 1025960Ssowmini datalink_media_t); 1033448Sdh155122 1045903Ssowmini typedef struct dld_public_prop_s { 1056789Sam223141 mac_prop_id_t pp_id; 1065903Ssowmini size_t pp_valsize; 1075903Ssowmini char *pp_name; 1085903Ssowmini char *pp_desc; 1095903Ssowmini } dld_public_prop_t; 1105903Ssowmini 1116789Sam223141 static dld_ioc_macprop_t *dld_buf_alloc(size_t, datalink_id_t, const char *, 1126512Ssowmini uint_t, dladm_status_t *); 1135903Ssowmini static dladm_status_t dld_set_prop(datalink_id_t, const char *, char **, 1145903Ssowmini uint_t, uint_t); 1155903Ssowmini static dladm_status_t dld_get_prop(datalink_id_t, const char *, char **, 1166512Ssowmini uint_t *, dladm_prop_type_t, uint_t); 1175895Syz147064 static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, 1185895Syz147064 do_get_rate_prop, do_get_channel_prop, 1195903Ssowmini do_get_powermode_prop, do_get_radio_prop, 1205960Ssowmini dld_duplex_get, dld_status_get, 1216512Ssowmini dld_binary_get, dld_uint32_get, dld_flowctl_get; 1225895Syz147064 static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop, 1235903Ssowmini do_set_powermode_prop, do_set_radio_prop, 1245903Ssowmini dld_set_public_prop; 1255903Ssowmini static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, 1265903Ssowmini dld_defmtu_check; 1273448Sdh155122 1285960Ssowmini static dladm_status_t dld_speed_get(struct prop_desc *, datalink_id_t, 1296512Ssowmini char **, uint_t *, uint_t); 1305960Ssowmini 1313448Sdh155122 typedef struct prop_desc { 1325895Syz147064 /* 1335895Syz147064 * link property name 1345895Syz147064 */ 1355895Syz147064 char *pd_name; 1365895Syz147064 1375895Syz147064 /* 1385895Syz147064 * default property value, can be set to { "", NULL } 1395895Syz147064 */ 1405895Syz147064 val_desc_t pd_defval; 1415895Syz147064 1425895Syz147064 /* 1435895Syz147064 * list of optional property values, can be NULL. 1445895Syz147064 * 1455895Syz147064 * This is set to non-NULL if there is a list of possible property 1465895Syz147064 * values. pd_optval would point to the array of possible values. 1475895Syz147064 */ 1485895Syz147064 val_desc_t *pd_optval; 1495895Syz147064 1505895Syz147064 /* 1515895Syz147064 * count of the above optional property values. 0 if pd_optval is NULL. 1525895Syz147064 */ 1535895Syz147064 uint_t pd_noptval; 1545895Syz147064 1555895Syz147064 /* 1565895Syz147064 * callback to set link property; 1575895Syz147064 * set to NULL if this property is read-only 1585895Syz147064 */ 1595895Syz147064 pd_setf_t *pd_set; 1605895Syz147064 1615895Syz147064 /* 1625895Syz147064 * callback to get modifiable link property 1635895Syz147064 */ 1645895Syz147064 pd_getf_t *pd_getmod; 1655895Syz147064 1665895Syz147064 /* 1675895Syz147064 * callback to get current link property 1685895Syz147064 */ 1695895Syz147064 pd_getf_t *pd_get; 1705895Syz147064 1715895Syz147064 /* 1725895Syz147064 * callback to validate link property value, set to NULL if pd_optval 1735895Syz147064 * is not NULL. In that case, validate the value by comparing it with 1745895Syz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 1755895Syz147064 * valid. 1765895Syz147064 */ 1775895Syz147064 pd_checkf_t *pd_check; 1785895Syz147064 1795895Syz147064 uint_t pd_flags; 1805903Ssowmini #define PD_TEMPONLY 0x1 /* property is temporary only */ 1815903Ssowmini #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */ 1826512Ssowmini #define PD_EMPTY_RESET 0x4 /* Use "" to reset the link property */ 1835895Syz147064 /* 1845895Syz147064 * indicate link classes this property applies to. 1855895Syz147064 */ 1865895Syz147064 datalink_class_t pd_class; 1875895Syz147064 1885895Syz147064 /* 1895895Syz147064 * indicate link media type this property applies to. 1905895Syz147064 */ 1915895Syz147064 datalink_media_t pd_dmedia; 1923448Sdh155122 } prop_desc_t; 1933448Sdh155122 1946789Sam223141 #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1 1955903Ssowmini 1965903Ssowmini 1975903Ssowmini static dld_public_prop_t dld_prop[] = { 1986789Sam223141 { MAC_PROP_DUPLEX, sizeof (link_duplex_t), 1995960Ssowmini "duplex", "link duplex mode" }, 2005903Ssowmini 2016789Sam223141 {MAC_PROP_SPEED, sizeof (uint64_t), 2025960Ssowmini "speed", "link speed (bps)" }, 2035903Ssowmini 2046789Sam223141 { MAC_PROP_STATUS, sizeof (link_state_t), 2055960Ssowmini "state", "link up/down" }, 2065903Ssowmini 2076789Sam223141 { MAC_PROP_AUTONEG, sizeof (uint8_t), 2085903Ssowmini "adv_autoneg_cap", "Advertised auto-negotiation" }, 2095903Ssowmini 2106789Sam223141 { MAC_PROP_MTU, sizeof (uint32_t), 2115960Ssowmini "mtu", "current link mtu" }, 2125903Ssowmini 2136789Sam223141 { MAC_PROP_FLOWCTRL, sizeof (link_flowctrl_t), 2145903Ssowmini "flowctrl", "flowcontrol" }, 2155903Ssowmini 2166789Sam223141 { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), 2175903Ssowmini "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, 2185903Ssowmini 2196789Sam223141 { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), 2205903Ssowmini "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, 2215903Ssowmini 2226789Sam223141 { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), 2235903Ssowmini "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, 2245903Ssowmini 2256789Sam223141 { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), 2265903Ssowmini "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, 2275903Ssowmini 2286789Sam223141 { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), 2295903Ssowmini "adv_100fdx_cap", "Adv 100 Mbps fdx" }, 2305903Ssowmini 2316789Sam223141 { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), 2325903Ssowmini "en_100fdx_cap", "Enable 100 Mbps fdx" }, 2335903Ssowmini 2346789Sam223141 { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), 2355903Ssowmini "adv_100hdx_cap", "Adv 100 Mbps hdx" }, 2365903Ssowmini 2376789Sam223141 { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), 2385903Ssowmini "en_100hdx_cap", "Enable 100 Mbps hdx" }, 2395903Ssowmini 2406789Sam223141 { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), 2415903Ssowmini "adv_10fdx_cap", "Adv 10 Mbps fdx" }, 2425903Ssowmini 2436789Sam223141 { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), 2445903Ssowmini "en_10fdx_cap", "Enable 10 Mbps fdx" }, 2455903Ssowmini 2466789Sam223141 { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), 2475903Ssowmini "adv_10hdx_cap", "Adv 10 Mbps hdx" }, 2485903Ssowmini 2496789Sam223141 { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), 2505903Ssowmini "en_10hdx_cap", "Enable 10 Mbps hdx" }, 2515903Ssowmini 2526789Sam223141 { MAC_PROP_PRIVATE, 0, 2535903Ssowmini "driver-private", "" } 2545903Ssowmini }; 2555903Ssowmini 2565903Ssowmini static val_desc_t link_duplex_vals[] = { 2575903Ssowmini { "half", LINK_DUPLEX_HALF }, 2585903Ssowmini { "full", LINK_DUPLEX_HALF } 2595903Ssowmini }; 2605903Ssowmini static val_desc_t link_status_vals[] = { 2615903Ssowmini { "up", LINK_STATE_UP }, 2625903Ssowmini { "down", LINK_STATE_DOWN } 2635903Ssowmini }; 2645903Ssowmini static val_desc_t link_01_vals[] = { 2655903Ssowmini { "1", 1 }, 2665903Ssowmini { "0", 0 } 2675903Ssowmini }; 2685903Ssowmini static val_desc_t link_flow_vals[] = { 2695903Ssowmini { "no", LINK_FLOWCTRL_NONE }, 2705903Ssowmini { "tx", LINK_FLOWCTRL_TX }, 2715903Ssowmini { "rx", LINK_FLOWCTRL_RX }, 2725903Ssowmini { "bi", LINK_FLOWCTRL_BI } 2735903Ssowmini }; 2745903Ssowmini 2755903Ssowmini #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) 2765903Ssowmini 2775895Syz147064 static val_desc_t dladm_wlan_radio_vals[] = { 2785895Syz147064 { "on", DLADM_WLAN_RADIO_ON }, 2795895Syz147064 { "off", DLADM_WLAN_RADIO_OFF } 2805895Syz147064 }; 2815895Syz147064 2825895Syz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 2835895Syz147064 { "off", DLADM_WLAN_PM_OFF }, 2845895Syz147064 { "fast", DLADM_WLAN_PM_FAST }, 2855895Syz147064 { "max", DLADM_WLAN_PM_MAX } 2865895Syz147064 }; 2875895Syz147064 2883448Sdh155122 static prop_desc_t prop_table[] = { 2895895Syz147064 2905903Ssowmini { "channel", { NULL, 0 }, 2915903Ssowmini NULL, 0, NULL, NULL, 2925895Syz147064 do_get_channel_prop, NULL, 0, 2935903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 2945895Syz147064 2955895Syz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 2965895Syz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 2975895Syz147064 do_set_powermode_prop, NULL, 2985895Syz147064 do_get_powermode_prop, NULL, 0, 2995903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3005895Syz147064 3015895Syz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 3025895Syz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 3035895Syz147064 do_set_radio_prop, NULL, 3045895Syz147064 do_get_radio_prop, NULL, 0, 3055903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3065895Syz147064 3075895Syz147064 { "speed", { "", 0 }, NULL, 0, 3085895Syz147064 do_set_rate_prop, do_get_rate_mod, 3095895Syz147064 do_get_rate_prop, do_check_rate, 0, 3105960Ssowmini DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE }, 3115895Syz147064 3126512Ssowmini { "autopush", { "", 0 }, NULL, 0, 3135895Syz147064 do_set_autopush, NULL, 3146512Ssowmini do_get_autopush, do_check_autopush, PD_CHECK_ALLOC|PD_EMPTY_RESET, 3155903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3165895Syz147064 3176512Ssowmini { "zone", { "", 0 }, NULL, 0, 3183448Sdh155122 do_set_zone, NULL, 3196512Ssowmini do_get_zone, do_check_zone, PD_TEMPONLY|PD_EMPTY_RESET, 3205903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3215903Ssowmini 3226512Ssowmini { "duplex", { "", 0 }, 3235903Ssowmini link_duplex_vals, VALCNT(link_duplex_vals), 3245903Ssowmini NULL, NULL, dld_duplex_get, NULL, 3255903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3265903Ssowmini 3275960Ssowmini { "state", { "up", LINK_STATE_UP }, 3285903Ssowmini link_status_vals, VALCNT(link_status_vals), 3295903Ssowmini NULL, NULL, dld_status_get, NULL, 3306512Ssowmini 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3315903Ssowmini 3325903Ssowmini { "adv_autoneg_cap", { "1", 1 }, 3335903Ssowmini link_01_vals, VALCNT(link_01_vals), 3345903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3355903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3365903Ssowmini 3376512Ssowmini { "mtu", { "", 0 }, NULL, 0, 3386512Ssowmini dld_set_public_prop, NULL, dld_uint32_get, 3396512Ssowmini dld_defmtu_check, 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3405903Ssowmini 3416512Ssowmini { "flowctrl", { "", 0 }, 3425903Ssowmini link_flow_vals, VALCNT(link_flow_vals), 3435903Ssowmini dld_set_public_prop, NULL, dld_flowctl_get, NULL, 3445903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3455903Ssowmini 3466512Ssowmini { "adv_1000fdx_cap", { "", 0 }, 3476512Ssowmini link_01_vals, VALCNT(link_01_vals), 3485903Ssowmini NULL, NULL, dld_binary_get, NULL, 3495903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3505903Ssowmini 3516512Ssowmini { "en_1000fdx_cap", { "", 0 }, 3525903Ssowmini link_01_vals, VALCNT(link_01_vals), 3535903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3545903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3555903Ssowmini 3566512Ssowmini { "adv_1000hdx_cap", { "", 0 }, 3575903Ssowmini link_01_vals, VALCNT(link_01_vals), 3585903Ssowmini NULL, NULL, dld_binary_get, NULL, 3595903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3605903Ssowmini 3616512Ssowmini { "en_1000hdx_cap", { "", 0 }, 3625903Ssowmini link_01_vals, VALCNT(link_01_vals), 3635903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3645903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3655903Ssowmini 3666512Ssowmini { "adv_100fdx_cap", { "", 0 }, 3675903Ssowmini link_01_vals, VALCNT(link_01_vals), 3685903Ssowmini NULL, NULL, dld_binary_get, NULL, 3695903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3705903Ssowmini 3716512Ssowmini { "en_100fdx_cap", { "", 0 }, 3725903Ssowmini link_01_vals, VALCNT(link_01_vals), 3735903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3745903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3755903Ssowmini 3766512Ssowmini { "adv_100hdx_cap", { "", 0 }, 3775903Ssowmini link_01_vals, VALCNT(link_01_vals), 3785903Ssowmini NULL, NULL, dld_binary_get, NULL, 3795903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3805903Ssowmini 3816512Ssowmini { "en_100hdx_cap", { "", 0 }, 3825903Ssowmini link_01_vals, VALCNT(link_01_vals), 3835903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3845903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3855903Ssowmini 3866512Ssowmini { "adv_10fdx_cap", { "", 0 }, 3875903Ssowmini link_01_vals, VALCNT(link_01_vals), 3885903Ssowmini NULL, NULL, dld_binary_get, NULL, 3895903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3905903Ssowmini 3916512Ssowmini { "en_10fdx_cap", { "", 0 }, 3925903Ssowmini link_01_vals, VALCNT(link_01_vals), 3935903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 3945903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3955903Ssowmini 3966512Ssowmini { "adv_10hdx_cap", { "", 0 }, 3975903Ssowmini link_01_vals, VALCNT(link_01_vals), 3985903Ssowmini NULL, NULL, dld_binary_get, NULL, 3995903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 4005903Ssowmini 4016512Ssowmini { "en_10hdx_cap", { "", 0 }, 4025903Ssowmini link_01_vals, VALCNT(link_01_vals), 4035903Ssowmini dld_set_public_prop, NULL, dld_binary_get, NULL, 4045903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER } 4055903Ssowmini 4063448Sdh155122 }; 4073448Sdh155122 4085895Syz147064 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 4095895Syz147064 4105895Syz147064 static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, 4115895Syz147064 char **, uint_t); 4125895Syz147064 static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, 4135895Syz147064 char **, uint_t *); 4145895Syz147064 static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t, 4155895Syz147064 uint32_t, prop_desc_t *, char **, uint_t, uint_t); 4165895Syz147064 static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *, 4175895Syz147064 char **, uint_t, uint_t); 4186512Ssowmini static dladm_status_t i_dladm_getset_defval(prop_desc_t *, datalink_id_t, 4196512Ssowmini datalink_media_t, uint_t); 4205895Syz147064 /* 4215895Syz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 4225895Syz147064 * rates to be retrieved. However, we cannot increase it at this 4235895Syz147064 * time because it will break binary compatibility with unbundled 4245895Syz147064 * WiFi drivers and utilities. So for now we define an additional 4255895Syz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 4265895Syz147064 */ 4275895Syz147064 #define MAX_SUPPORT_RATES 64 4285895Syz147064 4295895Syz147064 #define AP_ANCHOR "[anchor]" 4305895Syz147064 #define AP_DELIMITER '.' 4315895Syz147064 4325895Syz147064 static dladm_status_t 4335895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4345895Syz147064 val_desc_t *vdp) 4355895Syz147064 { 4365895Syz147064 int i, j; 4375895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4383147Sxc151355 4395895Syz147064 for (j = 0; j < val_cnt; j++) { 4405895Syz147064 for (i = 0; i < pdp->pd_noptval; i++) { 4415895Syz147064 if (strcasecmp(*prop_val, 4425895Syz147064 pdp->pd_optval[i].vd_name) == 0) { 4435895Syz147064 break; 4445895Syz147064 } 4455895Syz147064 } 4465895Syz147064 if (i == pdp->pd_noptval) { 4475895Syz147064 status = DLADM_STATUS_BADVAL; 4485895Syz147064 goto done; 4495895Syz147064 } 4505895Syz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 4515895Syz147064 } 4525895Syz147064 4535895Syz147064 done: 4545895Syz147064 return (status); 4555895Syz147064 } 4565895Syz147064 4575895Syz147064 static dladm_status_t 4585895Syz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 4595895Syz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4605895Syz147064 uint_t flags) 4613147Sxc151355 { 4625895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4635895Syz147064 val_desc_t *vdp = NULL; 4645895Syz147064 boolean_t needfree = B_FALSE; 4655895Syz147064 uint_t cnt, i; 4663147Sxc151355 4675895Syz147064 if (!(pdp->pd_class & class)) 4685895Syz147064 return (DLADM_STATUS_BADARG); 4695895Syz147064 4705895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 4713147Sxc151355 return (DLADM_STATUS_BADARG); 4723147Sxc151355 4735895Syz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 4745895Syz147064 return (DLADM_STATUS_TEMPONLY); 4755895Syz147064 4765895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 4775895Syz147064 return (DLADM_STATUS_OK); 4785895Syz147064 4795895Syz147064 if (pdp->pd_set == NULL) 4805895Syz147064 return (DLADM_STATUS_PROPRDONLY); 4813448Sdh155122 4825903Ssowmini if (pdp->pd_flags & PD_CHECK_ALLOC) 4835903Ssowmini needfree = B_TRUE; 4845903Ssowmini else 4855903Ssowmini needfree = B_FALSE; 4865895Syz147064 if (prop_val != NULL) { 4875895Syz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 4885895Syz147064 if (vdp == NULL) 4895895Syz147064 return (DLADM_STATUS_NOMEM); 4905895Syz147064 4915903Ssowmini 4925895Syz147064 if (pdp->pd_check != NULL) { 4935903Ssowmini status = pdp->pd_check(pdp, linkid, prop_val, val_cnt, 4945960Ssowmini vdp, media); 4955895Syz147064 } else if (pdp->pd_optval != NULL) { 4965895Syz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 4975895Syz147064 } else { 4983448Sdh155122 status = DLADM_STATUS_BADARG; 4993147Sxc151355 } 5005895Syz147064 5013147Sxc151355 if (status != DLADM_STATUS_OK) 5025895Syz147064 goto done; 5035895Syz147064 5045895Syz147064 cnt = val_cnt; 5055895Syz147064 } else { 5065895Syz147064 if (pdp->pd_defval.vd_name == NULL) 5075895Syz147064 return (DLADM_STATUS_NOTSUP); 5085895Syz147064 5096512Ssowmini if ((pdp->pd_flags & PD_EMPTY_RESET) != 0 || 5106512Ssowmini strlen(pdp->pd_defval.vd_name) > 0) { 5116512Ssowmini if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 5126512Ssowmini return (DLADM_STATUS_NOMEM); 5136512Ssowmini (void) memcpy(vdp, &pdp->pd_defval, 5146512Ssowmini sizeof (val_desc_t)); 5156512Ssowmini } else { 5166512Ssowmini status = i_dladm_getset_defval(pdp, linkid, 5176512Ssowmini media, flags); 5186512Ssowmini return (status); 5196512Ssowmini } 5205895Syz147064 cnt = 1; 5215895Syz147064 } 5225960Ssowmini status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media); 5235895Syz147064 if (needfree) { 5245895Syz147064 for (i = 0; i < cnt; i++) 5255903Ssowmini free((void *)((val_desc_t *)vdp + i)->vd_val); 5263147Sxc151355 } 5275895Syz147064 done: 5285895Syz147064 free(vdp); 5295895Syz147064 return (status); 5305895Syz147064 } 5315895Syz147064 5325895Syz147064 static dladm_status_t 5335895Syz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 5345895Syz147064 char **prop_val, uint_t val_cnt, uint_t flags) 5355895Syz147064 { 5365895Syz147064 int i; 5375895Syz147064 boolean_t found = B_FALSE; 5385895Syz147064 datalink_class_t class; 5395895Syz147064 uint32_t media; 5405895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 5415895Syz147064 5425895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 5435895Syz147064 if (status != DLADM_STATUS_OK) 5445895Syz147064 return (status); 5455895Syz147064 5465895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 5475895Syz147064 prop_desc_t *pdp = &prop_table[i]; 5485895Syz147064 dladm_status_t s; 5495895Syz147064 5505895Syz147064 if (prop_name != NULL && 5515895Syz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 5525895Syz147064 continue; 5535895Syz147064 5545895Syz147064 found = B_TRUE; 5555895Syz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 5565895Syz147064 val_cnt, flags); 5573448Sdh155122 5585895Syz147064 if (prop_name != NULL) { 5595895Syz147064 status = s; 5605895Syz147064 break; 5615895Syz147064 } else { 5625895Syz147064 if (s != DLADM_STATUS_OK && 5635895Syz147064 s != DLADM_STATUS_NOTSUP) 5645895Syz147064 status = s; 5655895Syz147064 } 5665895Syz147064 } 5675903Ssowmini if (!found) { 5685903Ssowmini if (prop_name[0] == '_') { 5695903Ssowmini /* other private properties */ 5705903Ssowmini status = dld_set_prop(linkid, prop_name, prop_val, 5715903Ssowmini val_cnt, flags); 5725903Ssowmini } else { 5735903Ssowmini status = DLADM_STATUS_NOTFOUND; 5745903Ssowmini } 5755903Ssowmini } 5765895Syz147064 5775895Syz147064 return (status); 5785895Syz147064 } 5795895Syz147064 5805895Syz147064 /* 5815895Syz147064 * Set/reset link property for specific link 5825895Syz147064 */ 5835895Syz147064 dladm_status_t 5845895Syz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 5855895Syz147064 uint_t val_cnt, uint_t flags) 5865895Syz147064 { 5875895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 5885895Syz147064 5895895Syz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 5905895Syz147064 (prop_val == NULL && val_cnt > 0) || 5915895Syz147064 (prop_val != NULL && val_cnt == 0) || 5925895Syz147064 (prop_name == NULL && prop_val != NULL)) { 5935895Syz147064 return (DLADM_STATUS_BADARG); 5945895Syz147064 } 5955895Syz147064 5965895Syz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 5975895Syz147064 val_cnt, flags); 5985895Syz147064 if (status != DLADM_STATUS_OK) 5995895Syz147064 return (status); 6005895Syz147064 6015895Syz147064 if (flags & DLADM_OPT_PERSIST) { 6025895Syz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 6033147Sxc151355 prop_val, val_cnt); 6043147Sxc151355 } 6053147Sxc151355 return (status); 6063147Sxc151355 } 6073147Sxc151355 6085895Syz147064 /* 6095895Syz147064 * Walk link properties of the given specific link. 6105895Syz147064 */ 6113147Sxc151355 dladm_status_t 6125895Syz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 6135895Syz147064 int (*func)(datalink_id_t, const char *, void *)) 6143147Sxc151355 { 6155895Syz147064 dladm_status_t status; 6165895Syz147064 datalink_class_t class; 6175895Syz147064 uint_t media; 6185895Syz147064 int i; 6195895Syz147064 6205895Syz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 6215895Syz147064 return (DLADM_STATUS_BADARG); 6225895Syz147064 6235895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6245895Syz147064 if (status != DLADM_STATUS_OK) 6255895Syz147064 return (status); 6265895Syz147064 6275895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 6285895Syz147064 if (!(prop_table[i].pd_class & class)) 6295895Syz147064 continue; 6305895Syz147064 6315895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 6325895Syz147064 continue; 6335895Syz147064 6345895Syz147064 if (func(linkid, prop_table[i].pd_name, arg) == 6355895Syz147064 DLADM_WALK_TERMINATE) { 6365895Syz147064 break; 6375895Syz147064 } 6385895Syz147064 } 6395895Syz147064 6405895Syz147064 return (DLADM_STATUS_OK); 6415895Syz147064 } 6423448Sdh155122 6435895Syz147064 /* 6445895Syz147064 * Get linkprop of the given specific link. 6455895Syz147064 */ 6465895Syz147064 dladm_status_t 6475895Syz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 6485895Syz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 6495895Syz147064 { 6505895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 6515895Syz147064 datalink_class_t class; 6525895Syz147064 uint_t media; 6535895Syz147064 prop_desc_t *pdp; 6546512Ssowmini uint_t cnt, dld_flags = 0; 6555895Syz147064 int i; 6565895Syz147064 6576512Ssowmini if (type == DLADM_PROP_VAL_DEFAULT) 6586789Sam223141 dld_flags = MAC_PROP_DEFAULT; 6596512Ssowmini 6605895Syz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 6615895Syz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 6625895Syz147064 return (DLADM_STATUS_BADARG); 6635895Syz147064 6645895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 6655895Syz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 6665895Syz147064 break; 6675895Syz147064 6685903Ssowmini if (i == DLADM_MAX_PROPS) { 6695903Ssowmini if (prop_name[0] == '_') { 6705903Ssowmini /* 6715903Ssowmini * private property. 6725903Ssowmini */ 6735903Ssowmini return (dld_get_prop(linkid, prop_name, 6746512Ssowmini prop_val, val_cntp, type, dld_flags)); 6755903Ssowmini } else { 6765903Ssowmini return (DLADM_STATUS_NOTFOUND); 6775903Ssowmini } 6785903Ssowmini } 6795895Syz147064 6805895Syz147064 pdp = &prop_table[i]; 6815895Syz147064 6825895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6835895Syz147064 if (status != DLADM_STATUS_OK) 6845895Syz147064 return (status); 6855895Syz147064 6865895Syz147064 if (!(pdp->pd_class & class)) 6875895Syz147064 return (DLADM_STATUS_BADARG); 6885895Syz147064 6895895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 6903147Sxc151355 return (DLADM_STATUS_BADARG); 6913147Sxc151355 6925895Syz147064 switch (type) { 6935895Syz147064 case DLADM_PROP_VAL_CURRENT: 6946512Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media, 6956512Ssowmini dld_flags); 6965895Syz147064 break; 6975895Syz147064 6985895Syz147064 case DLADM_PROP_VAL_DEFAULT: 6996768Sar224390 /* 7006768Sar224390 * If defaults are not defined for the property, 7016768Sar224390 * pd_defval.vd_name should be null. If the driver 7026768Sar224390 * has to be contacted for the value, vd_name should 7036768Sar224390 * be the empty string (""). Otherwise, dladm will 7046768Sar224390 * just print whatever is in the table. 7056768Sar224390 */ 7065895Syz147064 if (pdp->pd_defval.vd_name == NULL) { 7075895Syz147064 status = DLADM_STATUS_NOTSUP; 7085895Syz147064 break; 7095895Syz147064 } 7106512Ssowmini 7116512Ssowmini if (strlen(pdp->pd_defval.vd_name) == 0) { 7126512Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, 7136512Ssowmini media, dld_flags); 7146512Ssowmini } else { 7156512Ssowmini (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 7166512Ssowmini } 7175895Syz147064 *val_cntp = 1; 7185895Syz147064 break; 7193448Sdh155122 7205895Syz147064 case DLADM_PROP_VAL_MODIFIABLE: 7215895Syz147064 if (pdp->pd_getmod != NULL) { 7225903Ssowmini status = pdp->pd_getmod(pdp, linkid, prop_val, 7236512Ssowmini val_cntp, media, dld_flags); 7245895Syz147064 break; 7255895Syz147064 } 7265895Syz147064 cnt = pdp->pd_noptval; 7275895Syz147064 if (cnt == 0) { 7285895Syz147064 status = DLADM_STATUS_NOTSUP; 7295895Syz147064 } else if (cnt > *val_cntp) { 7305895Syz147064 status = DLADM_STATUS_TOOSMALL; 7315895Syz147064 } else { 7325895Syz147064 for (i = 0; i < cnt; i++) { 7335895Syz147064 (void) strcpy(prop_val[i], 7345895Syz147064 pdp->pd_optval[i].vd_name); 7355895Syz147064 } 7365895Syz147064 *val_cntp = cnt; 7375895Syz147064 } 7385895Syz147064 break; 7395895Syz147064 case DLADM_PROP_VAL_PERSISTENT: 7405895Syz147064 if (pdp->pd_flags & PD_TEMPONLY) 7415895Syz147064 return (DLADM_STATUS_TEMPONLY); 7425895Syz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 7435895Syz147064 prop_val, val_cntp); 7445895Syz147064 break; 7455895Syz147064 default: 7465895Syz147064 status = DLADM_STATUS_BADARG; 7475895Syz147064 break; 7483147Sxc151355 } 7493448Sdh155122 7505895Syz147064 return (status); 7515895Syz147064 } 7525895Syz147064 7535895Syz147064 /*ARGSUSED*/ 7545895Syz147064 static int 7555895Syz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 7565895Syz147064 { 7575895Syz147064 char *buf, **propvals; 7585895Syz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 7595895Syz147064 7605895Syz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 7615895Syz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 7625895Syz147064 return (DLADM_WALK_CONTINUE); 7635895Syz147064 } 7645895Syz147064 7655895Syz147064 propvals = (char **)(void *)buf; 7665895Syz147064 for (i = 0; i < valcnt; i++) { 7675895Syz147064 propvals[i] = buf + 7685895Syz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 7695895Syz147064 i * DLADM_PROP_VAL_MAX; 7705895Syz147064 } 7715895Syz147064 7725895Syz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 7735895Syz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 7745895Syz147064 goto done; 7755895Syz147064 } 7765895Syz147064 7775895Syz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 7785895Syz147064 DLADM_OPT_ACTIVE); 7795895Syz147064 7805895Syz147064 done: 7815895Syz147064 if (buf != NULL) 7825895Syz147064 free(buf); 7835895Syz147064 7845895Syz147064 return (DLADM_WALK_CONTINUE); 7855895Syz147064 } 7865895Syz147064 7875895Syz147064 /*ARGSUSED*/ 7885895Syz147064 static int 7895895Syz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 7905895Syz147064 { 791*6916Sartem (void) dladm_init_linkprop(linkid, B_TRUE); 7925895Syz147064 return (DLADM_WALK_CONTINUE); 7935895Syz147064 } 7945895Syz147064 7955895Syz147064 dladm_status_t 796*6916Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media) 7975895Syz147064 { 798*6916Sartem datalink_media_t dmedia; 799*6916Sartem uint32_t media; 800*6916Sartem 801*6916Sartem dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI; 802*6916Sartem 8035895Syz147064 if (linkid == DATALINK_ALL_LINKID) { 8045895Syz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 805*6916Sartem DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST); 806*6916Sartem } else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL, 807*6916Sartem &media, NULL, 0) == DLADM_STATUS_OK) && 808*6916Sartem DATALINK_MEDIA_ACCEPTED(dmedia, media))) { 8095895Syz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 8103448Sdh155122 } 8113448Sdh155122 return (DLADM_STATUS_OK); 8123147Sxc151355 } 8133147Sxc151355 8145903Ssowmini /* ARGSUSED */ 8155895Syz147064 static dladm_status_t 8165903Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid, 8176512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 8183147Sxc151355 { 8195895Syz147064 char zone_name[ZONENAME_MAX]; 8205895Syz147064 zoneid_t zid; 8215895Syz147064 dladm_status_t status; 8223147Sxc151355 8236512Ssowmini if (flags != 0) 8246512Ssowmini return (DLADM_STATUS_NOTSUP); 8256512Ssowmini 8265895Syz147064 status = dladm_getzid(linkid, &zid); 8275895Syz147064 if (status != DLADM_STATUS_OK) 8283448Sdh155122 return (status); 8293448Sdh155122 8305895Syz147064 *val_cnt = 1; 8315895Syz147064 if (zid != GLOBAL_ZONEID) { 8325895Syz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8335895Syz147064 return (dladm_errno2status(errno)); 8343147Sxc151355 8355895Syz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 8363147Sxc151355 } else { 8375895Syz147064 *prop_val[0] = '\0'; 8383147Sxc151355 } 8393147Sxc151355 8403448Sdh155122 return (DLADM_STATUS_OK); 8413448Sdh155122 } 8423448Sdh155122 8433448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 8443448Sdh155122 8453448Sdh155122 static int 8463448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 8473448Sdh155122 { 8483448Sdh155122 char root[MAXPATHLEN]; 8493448Sdh155122 zone_get_devroot_t real_zone_get_devroot; 8503448Sdh155122 void *dlhandle; 8513448Sdh155122 void *sym; 8523448Sdh155122 int ret; 8533448Sdh155122 8543448Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 8553448Sdh155122 return (-1); 8563448Sdh155122 8573448Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 8583448Sdh155122 (void) dlclose(dlhandle); 8593448Sdh155122 return (-1); 8603448Sdh155122 } 8613448Sdh155122 8623448Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 8633448Sdh155122 8643448Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 8653448Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 8663448Sdh155122 (void) dlclose(dlhandle); 8673448Sdh155122 return (ret); 8683448Sdh155122 } 8693448Sdh155122 8703448Sdh155122 static dladm_status_t 8715895Syz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 8723448Sdh155122 { 8733448Sdh155122 char path[MAXPATHLEN]; 8745895Syz147064 char name[MAXLINKNAMELEN]; 8753448Sdh155122 di_prof_t prof = NULL; 8763448Sdh155122 char zone_name[ZONENAME_MAX]; 8773448Sdh155122 dladm_status_t status; 8785895Syz147064 int ret; 8793448Sdh155122 8803448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8813448Sdh155122 return (dladm_errno2status(errno)); 8823448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 8833448Sdh155122 return (dladm_errno2status(errno)); 8843448Sdh155122 if (di_prof_init(path, &prof) != 0) 8853448Sdh155122 return (dladm_errno2status(errno)); 8863448Sdh155122 8875895Syz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 8885895Syz147064 if (status != DLADM_STATUS_OK) 8895895Syz147064 goto cleanup; 8905895Syz147064 8915895Syz147064 if (add) 8925895Syz147064 ret = di_prof_add_dev(prof, name); 8935895Syz147064 else 8945895Syz147064 ret = di_prof_add_exclude(prof, name); 8955895Syz147064 8965895Syz147064 if (ret != 0) { 8973448Sdh155122 status = dladm_errno2status(errno); 8983448Sdh155122 goto cleanup; 8993448Sdh155122 } 9003448Sdh155122 9013448Sdh155122 if (di_prof_commit(prof) != 0) 9023448Sdh155122 status = dladm_errno2status(errno); 9033448Sdh155122 cleanup: 9043448Sdh155122 if (prof) 9053448Sdh155122 di_prof_fini(prof); 9063448Sdh155122 9073448Sdh155122 return (status); 9083448Sdh155122 } 9093448Sdh155122 9105903Ssowmini /* ARGSUSED */ 9113448Sdh155122 static dladm_status_t 9125960Ssowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, 9135960Ssowmini uint_t val_cnt, uint_t flags, datalink_media_t media) 9143448Sdh155122 { 9153448Sdh155122 dladm_status_t status; 9163448Sdh155122 zoneid_t zid_old, zid_new; 9175895Syz147064 char link[MAXLINKNAMELEN]; 9183448Sdh155122 9193448Sdh155122 if (val_cnt != 1) 9203448Sdh155122 return (DLADM_STATUS_BADVALCNT); 9213448Sdh155122 9225895Syz147064 status = dladm_getzid(linkid, &zid_old); 9233448Sdh155122 if (status != DLADM_STATUS_OK) 9243448Sdh155122 return (status); 9253448Sdh155122 9263448Sdh155122 /* Do nothing if setting to current value */ 9275895Syz147064 zid_new = vdp->vd_val; 9283448Sdh155122 if (zid_new == zid_old) 9293448Sdh155122 return (DLADM_STATUS_OK); 9303448Sdh155122 9315895Syz147064 if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 9325895Syz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 9335895Syz147064 return (status); 9345895Syz147064 } 9355895Syz147064 9365895Syz147064 if (zid_new != GLOBAL_ZONEID) { 9375895Syz147064 /* 9385895Syz147064 * If the new zoneid is the global zone, we could destroy 9395895Syz147064 * the link (in the case of an implicitly-created VLAN) as a 9405895Syz147064 * result of the dladm_setzid() operation. In that case, 9415895Syz147064 * we defer the operation to the end of this function to avoid 9425895Syz147064 * recreating the VLAN and getting a different linkid during 9435895Syz147064 * the rollback if other operation fails. 9445895Syz147064 * 9455895Syz147064 * Otherwise, dladm_setzid() will hold a reference to the 9465895Syz147064 * link and prevent a link renaming, so we need to do it 9475895Syz147064 * before other operations. 9485895Syz147064 */ 9495895Syz147064 status = dladm_setzid(link, zid_new); 9505895Syz147064 if (status != DLADM_STATUS_OK) 9515895Syz147064 return (status); 9525895Syz147064 } 9535895Syz147064 9543448Sdh155122 if (zid_old != GLOBAL_ZONEID) { 9555895Syz147064 if (zone_remove_datalink(zid_old, link) != 0 && 9563448Sdh155122 errno != ENXIO) { 9573448Sdh155122 status = dladm_errno2status(errno); 9583448Sdh155122 goto rollback1; 9593448Sdh155122 } 9603448Sdh155122 9615895Syz147064 /* 9625895Syz147064 * It is okay to fail to update the /dev entry (some 9635895Syz147064 * vanity-named links do not have a /dev entry). 9645895Syz147064 */ 9655895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 9665895Syz147064 } 9675895Syz147064 9685895Syz147064 if (zid_new != GLOBAL_ZONEID) { 9695895Syz147064 if (zone_add_datalink(zid_new, link) != 0) { 9705895Syz147064 status = dladm_errno2status(errno); 9715895Syz147064 goto rollback2; 9725895Syz147064 } 9735895Syz147064 9745895Syz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 9755895Syz147064 } else { 9765895Syz147064 status = dladm_setzid(link, zid_new); 9773448Sdh155122 if (status != DLADM_STATUS_OK) 9783448Sdh155122 goto rollback2; 9793448Sdh155122 } 9803448Sdh155122 9813448Sdh155122 return (DLADM_STATUS_OK); 9823448Sdh155122 9833448Sdh155122 rollback2: 9843448Sdh155122 if (zid_old != GLOBAL_ZONEID) 9855895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 9865895Syz147064 if (zid_old != GLOBAL_ZONEID) 9875895Syz147064 (void) zone_add_datalink(zid_old, link); 9883448Sdh155122 rollback1: 9895895Syz147064 if (zid_new != GLOBAL_ZONEID) 9905895Syz147064 (void) dladm_setzid(link, zid_old); 9913448Sdh155122 return (status); 9923448Sdh155122 } 9933448Sdh155122 9943448Sdh155122 /* ARGSUSED */ 9953448Sdh155122 static dladm_status_t 9965903Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 9975960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 9983448Sdh155122 { 9995895Syz147064 zoneid_t zid; 10003448Sdh155122 10013448Sdh155122 if (val_cnt != 1) 10023448Sdh155122 return (DLADM_STATUS_BADVALCNT); 10033448Sdh155122 10043448Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 10053448Sdh155122 return (DLADM_STATUS_BADVAL); 10063448Sdh155122 10073448Sdh155122 if (zid != GLOBAL_ZONEID) { 10083448Sdh155122 ushort_t flags; 10093448Sdh155122 10103448Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 10113448Sdh155122 sizeof (flags)) < 0) { 10123448Sdh155122 return (dladm_errno2status(errno)); 10133448Sdh155122 } 10143448Sdh155122 10153448Sdh155122 if (!(flags & ZF_NET_EXCL)) { 10163448Sdh155122 return (DLADM_STATUS_BADVAL); 10173448Sdh155122 } 10183448Sdh155122 } 10193448Sdh155122 10205895Syz147064 vdp->vd_val = zid; 10215895Syz147064 return (DLADM_STATUS_OK); 10225895Syz147064 } 10235895Syz147064 10245903Ssowmini /* ARGSUSED */ 10255895Syz147064 static dladm_status_t 10265903Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid, 10276512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 10285895Syz147064 { 10295895Syz147064 dld_ioc_ap_t dia; 10305895Syz147064 int fd, i, len; 10315895Syz147064 10326789Sam223141 if (flags & MAC_PROP_DEFAULT) 10336512Ssowmini return (DLADM_STATUS_NOTSUP); 10346512Ssowmini 10355895Syz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 10365895Syz147064 return (dladm_errno2status(errno)); 10375895Syz147064 10385895Syz147064 *val_cnt = 1; 10395895Syz147064 dia.dia_linkid = linkid; 10405895Syz147064 if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) { 10415895Syz147064 (*prop_val)[0] = '\0'; 10425895Syz147064 goto done; 10435895Syz147064 } 10445895Syz147064 10455895Syz147064 for (i = 0, len = 0; i < dia.dia_npush; i++) { 10465895Syz147064 if (i != 0) { 10475895Syz147064 (void) snprintf(*prop_val + len, 10485895Syz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 10495895Syz147064 len += 1; 10505895Syz147064 } 10515895Syz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 10525895Syz147064 "%s", dia.dia_aplist[i]); 10535895Syz147064 len += strlen(dia.dia_aplist[i]); 10545895Syz147064 if (dia.dia_anchor - 1 == i) { 10555895Syz147064 (void) snprintf(*prop_val + len, 10565895Syz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 10575895Syz147064 AP_ANCHOR); 10585895Syz147064 len += (strlen(AP_ANCHOR) + 1); 10595895Syz147064 } 10605895Syz147064 } 10615895Syz147064 10625895Syz147064 done: 10635895Syz147064 (void) close(fd); 10645895Syz147064 return (DLADM_STATUS_OK); 10655895Syz147064 } 10665895Syz147064 10675903Ssowmini /* ARGSUSED */ 10685895Syz147064 static dladm_status_t 10695960Ssowmini do_set_autopush(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, 10705960Ssowmini uint_t val_cnt, uint_t flags, datalink_media_t media) 10715895Syz147064 { 10725895Syz147064 dld_ioc_ap_t dia; 10735895Syz147064 struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val; 10745895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 10755895Syz147064 int fd, i; 10765895Syz147064 int ic_cmd; 10775895Syz147064 10785895Syz147064 if (val_cnt != 1) 10795895Syz147064 return (DLADM_STATUS_BADVALCNT); 10805895Syz147064 10815895Syz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 10825895Syz147064 return (dladm_errno2status(errno)); 10835895Syz147064 10845895Syz147064 dia.dia_linkid = linkid; 10855895Syz147064 if (dlap != NULL) { 10865895Syz147064 dia.dia_anchor = dlap->dap_anchor; 10875895Syz147064 dia.dia_npush = dlap->dap_npush; 10885895Syz147064 for (i = 0; i < dia.dia_npush; i++) { 10895895Syz147064 (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i], 10905895Syz147064 FMNAMESZ+1); 10915895Syz147064 } 10925895Syz147064 ic_cmd = DLDIOC_SETAUTOPUSH; 10935895Syz147064 } else { 10945895Syz147064 ic_cmd = DLDIOC_CLRAUTOPUSH; 10955895Syz147064 } 10965895Syz147064 10975895Syz147064 if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0) 10985895Syz147064 status = dladm_errno2status(errno); 10995895Syz147064 11005895Syz147064 (void) close(fd); 11015895Syz147064 return (status); 11025895Syz147064 } 11035895Syz147064 11045895Syz147064 /* 11055895Syz147064 * Add the specified module to the dlautopush structure; returns a 11065895Syz147064 * DLADM_STATUS_* code. 11075895Syz147064 */ 11085895Syz147064 dladm_status_t 11095895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 11105895Syz147064 { 11115895Syz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 11125895Syz147064 return (DLADM_STATUS_BADVAL); 11135895Syz147064 11145895Syz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 11155895Syz147064 /* 11165895Syz147064 * We don't allow multiple anchors, and the anchor must 11175895Syz147064 * be after at least one module. 11185895Syz147064 */ 11195895Syz147064 if (dlap->dap_anchor != 0) 11205895Syz147064 return (DLADM_STATUS_BADVAL); 11215895Syz147064 if (dlap->dap_npush == 0) 11225895Syz147064 return (DLADM_STATUS_BADVAL); 11235895Syz147064 11245895Syz147064 dlap->dap_anchor = dlap->dap_npush; 11255895Syz147064 return (DLADM_STATUS_OK); 11265895Syz147064 } 11275895Syz147064 if (dlap->dap_npush > MAXAPUSH) 11285895Syz147064 return (DLADM_STATUS_BADVALCNT); 11295895Syz147064 11305895Syz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 11315895Syz147064 FMNAMESZ + 1); 11325895Syz147064 11335895Syz147064 return (DLADM_STATUS_OK); 11345895Syz147064 } 11355895Syz147064 11365895Syz147064 /* 11375895Syz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 11385895Syz147064 * autopush modules. The former is used in dladm set-linkprop, and the 11395895Syz147064 * latter is used in the autopush(1M) file. 11405895Syz147064 */ 11415895Syz147064 /* ARGSUSED */ 11425895Syz147064 static dladm_status_t 11435903Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 11445960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 11455895Syz147064 { 11465895Syz147064 char *module; 11475895Syz147064 struct dlautopush *dlap; 11485895Syz147064 dladm_status_t status; 11495895Syz147064 char val[DLADM_PROP_VAL_MAX]; 11505895Syz147064 char delimiters[4]; 11515895Syz147064 11525895Syz147064 if (val_cnt != 1) 11535895Syz147064 return (DLADM_STATUS_BADVALCNT); 11545895Syz147064 11555895Syz147064 dlap = malloc(sizeof (struct dlautopush)); 11565895Syz147064 if (dlap == NULL) 11573448Sdh155122 return (DLADM_STATUS_NOMEM); 11583448Sdh155122 11595895Syz147064 (void) memset(dlap, 0, sizeof (struct dlautopush)); 11605895Syz147064 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 11615895Syz147064 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 11625895Syz147064 module = strtok(val, delimiters); 11635895Syz147064 while (module != NULL) { 11645895Syz147064 status = i_dladm_add_ap_module(module, dlap); 11655895Syz147064 if (status != DLADM_STATUS_OK) 11665895Syz147064 return (status); 11675895Syz147064 module = strtok(NULL, delimiters); 11685895Syz147064 } 11695895Syz147064 11705895Syz147064 vdp->vd_val = (uintptr_t)dlap; 11713448Sdh155122 return (DLADM_STATUS_OK); 11723448Sdh155122 } 11733448Sdh155122 11745903Ssowmini /* ARGSUSED */ 11753448Sdh155122 static dladm_status_t 11765903Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, 11775903Ssowmini char **prop_val, uint_t *val_cnt, uint_t id) 11783448Sdh155122 { 11795895Syz147064 wl_rates_t *wrp; 11805895Syz147064 uint_t i; 11815895Syz147064 wldp_t *gbuf = NULL; 11825895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11835895Syz147064 11845895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 11855895Syz147064 status = DLADM_STATUS_NOMEM; 11865895Syz147064 goto done; 11875895Syz147064 } 11885895Syz147064 11895895Syz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 11905895Syz147064 if (status != DLADM_STATUS_OK) 11915895Syz147064 goto done; 11925895Syz147064 11935895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 11945895Syz147064 if (wrp->wl_rates_num > *val_cnt) { 11955895Syz147064 status = DLADM_STATUS_TOOSMALL; 11965895Syz147064 goto done; 11975895Syz147064 } 11985895Syz147064 11995895Syz147064 if (wrp->wl_rates_rates[0] == 0) { 12005895Syz147064 prop_val[0][0] = '\0'; 12015895Syz147064 *val_cnt = 1; 12025895Syz147064 goto done; 12035895Syz147064 } 12045895Syz147064 12055895Syz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 12065895Syz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 12075895Syz147064 wrp->wl_rates_rates[i] % 2, 12085895Syz147064 (float)wrp->wl_rates_rates[i] / 2); 12095895Syz147064 } 12105895Syz147064 *val_cnt = wrp->wl_rates_num; 12113448Sdh155122 12125895Syz147064 done: 12135895Syz147064 free(gbuf); 12145895Syz147064 return (status); 12155895Syz147064 } 12165895Syz147064 12175895Syz147064 static dladm_status_t 12185903Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, 12196512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 12205895Syz147064 { 12215960Ssowmini if (media != DL_WIFI) 12226512Ssowmini return (dld_speed_get(pd, linkid, prop_val, val_cnt, flags)); 12235960Ssowmini 12245903Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 12255895Syz147064 WL_DESIRED_RATES)); 12265895Syz147064 } 12275895Syz147064 12286512Ssowmini /* ARGSUSED */ 12295895Syz147064 static dladm_status_t 12305903Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, 12316512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 12325895Syz147064 { 12335960Ssowmini switch (media) { 12345960Ssowmini case DL_ETHER: 12356512Ssowmini /* 12366512Ssowmini * Speed for ethernet links is unbounded. E.g., 802.11b 12376512Ssowmini * links can have a speed of 5.5 Gbps. 12386512Ssowmini */ 12396512Ssowmini return (DLADM_STATUS_NOTSUP); 12405960Ssowmini 12415960Ssowmini case DL_WIFI: 12425960Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 12435960Ssowmini WL_SUPPORTED_RATES)); 12445960Ssowmini default: 12455960Ssowmini return (DLADM_STATUS_BADARG); 12465960Ssowmini } 12475895Syz147064 } 12485895Syz147064 12495895Syz147064 static dladm_status_t 12505895Syz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 12515895Syz147064 { 12525895Syz147064 int i; 12535895Syz147064 uint_t len; 12545895Syz147064 wldp_t *gbuf; 12555895Syz147064 wl_rates_t *wrp; 12565895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 12575895Syz147064 12585895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 12595895Syz147064 return (DLADM_STATUS_NOMEM); 12605895Syz147064 12615895Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 12623448Sdh155122 12635895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 12645895Syz147064 for (i = 0; i < rates->wr_cnt; i++) 12655895Syz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 12665895Syz147064 wrp->wl_rates_num = rates->wr_cnt; 12675895Syz147064 12685895Syz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 12695895Syz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 12705895Syz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 12715895Syz147064 WLAN_SET_PARAM, len); 12725895Syz147064 12735895Syz147064 free(gbuf); 12745895Syz147064 return (status); 12755895Syz147064 } 12763448Sdh155122 12775903Ssowmini /* ARGSUSED */ 12785895Syz147064 static dladm_status_t 12795903Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid, 12805960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 12815895Syz147064 { 12825895Syz147064 dladm_wlan_rates_t rates; 12835895Syz147064 dladm_status_t status; 12845895Syz147064 12855960Ssowmini /* 12865960Ssowmini * can currently set rate on WIFI links only. 12875960Ssowmini */ 12885960Ssowmini if (media != DL_WIFI) 12895960Ssowmini return (DLADM_STATUS_PROPRDONLY); 12905960Ssowmini 12915895Syz147064 if (val_cnt != 1) 12925895Syz147064 return (DLADM_STATUS_BADVALCNT); 12935895Syz147064 12945895Syz147064 rates.wr_cnt = 1; 12955895Syz147064 rates.wr_rates[0] = vdp[0].vd_val; 12965895Syz147064 12975895Syz147064 status = do_set_rate(linkid, &rates); 12985895Syz147064 12995895Syz147064 done: 13005895Syz147064 return (status); 13015895Syz147064 } 13023448Sdh155122 13035895Syz147064 /* ARGSUSED */ 13045895Syz147064 static dladm_status_t 13055903Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 13065960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 13075895Syz147064 { 13085895Syz147064 int i; 13095895Syz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 13105895Syz147064 char *buf, **modval; 13115895Syz147064 dladm_status_t status; 13125895Syz147064 13135895Syz147064 if (val_cnt != 1) 13145895Syz147064 return (DLADM_STATUS_BADVALCNT); 13155895Syz147064 13165895Syz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 13175895Syz147064 MAX_SUPPORT_RATES); 13185895Syz147064 if (buf == NULL) { 13195895Syz147064 status = DLADM_STATUS_NOMEM; 13205895Syz147064 goto done; 13215895Syz147064 } 13223448Sdh155122 13235895Syz147064 modval = (char **)(void *)buf; 13245895Syz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 13255895Syz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 13265895Syz147064 i * DLADM_STRSIZE; 13275895Syz147064 } 13285895Syz147064 13296512Ssowmini status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media, 0); 13305895Syz147064 if (status != DLADM_STATUS_OK) 13315895Syz147064 goto done; 13325895Syz147064 13335895Syz147064 for (i = 0; i < modval_cnt; i++) { 13345895Syz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 13355903Ssowmini vdp->vd_val = (uintptr_t)(uint_t) 13365903Ssowmini (atof(*prop_val) * 2); 13375895Syz147064 status = DLADM_STATUS_OK; 13383448Sdh155122 break; 13393448Sdh155122 } 13405895Syz147064 } 13415895Syz147064 if (i == modval_cnt) 13425895Syz147064 status = DLADM_STATUS_BADVAL; 13435895Syz147064 done: 13445895Syz147064 free(buf); 13455895Syz147064 return (status); 13465895Syz147064 } 13475895Syz147064 13485895Syz147064 static dladm_status_t 13495895Syz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 13505895Syz147064 { 13515895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 13525895Syz147064 } 13535895Syz147064 13545903Ssowmini /* ARGSUSED */ 13555895Syz147064 static dladm_status_t 13565903Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, 13576512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 13585895Syz147064 { 13595895Syz147064 uint32_t channel; 13605895Syz147064 wldp_t *gbuf; 13615895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 13625895Syz147064 13635895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13645895Syz147064 return (DLADM_STATUS_NOMEM); 13655895Syz147064 13665895Syz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 13675895Syz147064 goto done; 13685895Syz147064 13695895Syz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 13705895Syz147064 &channel)) { 13715895Syz147064 status = DLADM_STATUS_NOTFOUND; 13725895Syz147064 goto done; 13735895Syz147064 } 13745895Syz147064 13755895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 13765895Syz147064 *val_cnt = 1; 13773448Sdh155122 13785895Syz147064 done: 13795895Syz147064 free(gbuf); 13805895Syz147064 return (status); 13815895Syz147064 } 13825895Syz147064 13835895Syz147064 static dladm_status_t 13845895Syz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 13855895Syz147064 { 13865895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 13875895Syz147064 } 13885895Syz147064 13895903Ssowmini /* ARGSUSED */ 13905895Syz147064 static dladm_status_t 13915903Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, 13926512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 13935895Syz147064 { 13945895Syz147064 wl_ps_mode_t *mode; 13955895Syz147064 const char *s; 13965895Syz147064 wldp_t *gbuf; 13975895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 13985895Syz147064 13995895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 14005895Syz147064 return (DLADM_STATUS_NOMEM); 14015895Syz147064 14025895Syz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 14035895Syz147064 goto done; 14045895Syz147064 14055895Syz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 14065895Syz147064 switch (mode->wl_ps_mode) { 14075895Syz147064 case WL_PM_AM: 14085895Syz147064 s = "off"; 14095895Syz147064 break; 14105895Syz147064 case WL_PM_MPS: 14115895Syz147064 s = "max"; 14125895Syz147064 break; 14135895Syz147064 case WL_PM_FAST: 14145895Syz147064 s = "fast"; 14153448Sdh155122 break; 14163448Sdh155122 default: 14175895Syz147064 status = DLADM_STATUS_NOTFOUND; 14185895Syz147064 goto done; 14195895Syz147064 } 14205895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 14215895Syz147064 *val_cnt = 1; 14225895Syz147064 14235895Syz147064 done: 14245895Syz147064 free(gbuf); 14255895Syz147064 return (status); 14265895Syz147064 } 14275895Syz147064 14285895Syz147064 static dladm_status_t 14295895Syz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 14305895Syz147064 { 14315895Syz147064 wl_ps_mode_t ps_mode; 14325895Syz147064 14335895Syz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 14345895Syz147064 14355895Syz147064 switch (*pm) { 14365895Syz147064 case DLADM_WLAN_PM_OFF: 14375895Syz147064 ps_mode.wl_ps_mode = WL_PM_AM; 14383448Sdh155122 break; 14395895Syz147064 case DLADM_WLAN_PM_MAX: 14405895Syz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 14415895Syz147064 break; 14425895Syz147064 case DLADM_WLAN_PM_FAST: 14435895Syz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 14445895Syz147064 break; 14455895Syz147064 default: 14465895Syz147064 return (DLADM_STATUS_NOTSUP); 14473448Sdh155122 } 14485895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 14495895Syz147064 sizeof (ps_mode))); 14505895Syz147064 } 14515895Syz147064 14525895Syz147064 /* ARGSUSED */ 14535895Syz147064 static dladm_status_t 14545903Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, 14555960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 14565895Syz147064 { 14575895Syz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 14585895Syz147064 dladm_status_t status; 14595895Syz147064 14605895Syz147064 if (val_cnt != 1) 14615895Syz147064 return (DLADM_STATUS_BADVALCNT); 14625895Syz147064 14635895Syz147064 status = do_set_powermode(linkid, &powermode); 14643448Sdh155122 14653448Sdh155122 return (status); 14663448Sdh155122 } 14673448Sdh155122 14683448Sdh155122 static dladm_status_t 14695895Syz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 14703448Sdh155122 { 14715895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 14725895Syz147064 } 14733448Sdh155122 14745903Ssowmini /* ARGSUSED */ 14755895Syz147064 static dladm_status_t 14765903Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, 14776512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 14785895Syz147064 { 14795895Syz147064 wl_radio_t radio; 14805895Syz147064 const char *s; 14815895Syz147064 wldp_t *gbuf; 14825895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 14833448Sdh155122 14845895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 14855895Syz147064 return (DLADM_STATUS_NOMEM); 14863448Sdh155122 14875895Syz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 14885895Syz147064 goto done; 14893448Sdh155122 14905895Syz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 14915895Syz147064 switch (radio) { 14925895Syz147064 case B_TRUE: 14935895Syz147064 s = "on"; 14945895Syz147064 break; 14955895Syz147064 case B_FALSE: 14965895Syz147064 s = "off"; 14975895Syz147064 break; 14985895Syz147064 default: 14995895Syz147064 status = DLADM_STATUS_NOTFOUND; 15005895Syz147064 goto done; 15015895Syz147064 } 15025895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 15035895Syz147064 *val_cnt = 1; 15043448Sdh155122 15055895Syz147064 done: 15065895Syz147064 free(gbuf); 15073448Sdh155122 return (status); 15083448Sdh155122 } 15093448Sdh155122 15103448Sdh155122 static dladm_status_t 15115895Syz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 15123448Sdh155122 { 15135895Syz147064 wl_radio_t r; 15143448Sdh155122 15155895Syz147064 switch (*radio) { 15165895Syz147064 case DLADM_WLAN_RADIO_ON: 15175895Syz147064 r = B_TRUE; 15185895Syz147064 break; 15195895Syz147064 case DLADM_WLAN_RADIO_OFF: 15205895Syz147064 r = B_FALSE; 15215895Syz147064 break; 15225895Syz147064 default: 15235895Syz147064 return (DLADM_STATUS_NOTSUP); 15245895Syz147064 } 15255895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 15265895Syz147064 } 15273448Sdh155122 15285895Syz147064 /* ARGSUSED */ 15295895Syz147064 static dladm_status_t 15305903Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid, 15315960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media) 15325895Syz147064 { 15335895Syz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 15345895Syz147064 dladm_status_t status; 15353448Sdh155122 15365895Syz147064 if (val_cnt != 1) 15375895Syz147064 return (DLADM_STATUS_BADVALCNT); 15385895Syz147064 15395895Syz147064 status = do_set_radio(linkid, &radio); 15403448Sdh155122 15413448Sdh155122 return (status); 15423448Sdh155122 } 15433448Sdh155122 15445895Syz147064 static dladm_status_t 15455895Syz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 15465895Syz147064 char **prop_val, uint_t val_cnt) 15473448Sdh155122 { 15485895Syz147064 char buf[MAXLINELEN]; 15495895Syz147064 int i; 15505895Syz147064 dladm_conf_t conf; 15515895Syz147064 dladm_status_t status; 15523448Sdh155122 15535895Syz147064 status = dladm_read_conf(linkid, &conf); 15545895Syz147064 if (status != DLADM_STATUS_OK) 15555895Syz147064 return (status); 15563448Sdh155122 15575895Syz147064 /* 15585895Syz147064 * reset case. 15595895Syz147064 */ 15605895Syz147064 if (val_cnt == 0) { 15615895Syz147064 status = dladm_unset_conf_field(conf, prop_name); 15625895Syz147064 if (status == DLADM_STATUS_OK) 15635895Syz147064 status = dladm_write_conf(conf); 15645895Syz147064 goto done; 15655895Syz147064 } 15663448Sdh155122 15675895Syz147064 buf[0] = '\0'; 15685895Syz147064 for (i = 0; i < val_cnt; i++) { 15695895Syz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 15705895Syz147064 if (i != val_cnt - 1) 15715895Syz147064 (void) strlcat(buf, ",", MAXLINELEN); 15723448Sdh155122 } 15733448Sdh155122 15745895Syz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 15755895Syz147064 if (status == DLADM_STATUS_OK) 15765895Syz147064 status = dladm_write_conf(conf); 15775895Syz147064 15785895Syz147064 done: 15795895Syz147064 dladm_destroy_conf(conf); 15805895Syz147064 return (status); 15813448Sdh155122 } 15825895Syz147064 15835895Syz147064 static dladm_status_t 15845895Syz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 15855895Syz147064 char **prop_val, uint_t *val_cntp) 15865895Syz147064 { 15875895Syz147064 char buf[MAXLINELEN], *str; 15885895Syz147064 uint_t cnt = 0; 15895895Syz147064 dladm_conf_t conf; 15905895Syz147064 dladm_status_t status; 15915895Syz147064 15925895Syz147064 status = dladm_read_conf(linkid, &conf); 15935895Syz147064 if (status != DLADM_STATUS_OK) 15945895Syz147064 return (status); 15955895Syz147064 15965895Syz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 15975895Syz147064 if (status != DLADM_STATUS_OK) 15985895Syz147064 goto done; 15995895Syz147064 16005895Syz147064 str = strtok(buf, ","); 16015895Syz147064 while (str != NULL) { 16025895Syz147064 if (cnt == *val_cntp) { 16035895Syz147064 status = DLADM_STATUS_TOOSMALL; 16045895Syz147064 goto done; 16055895Syz147064 } 16065895Syz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 16075895Syz147064 str = strtok(NULL, ","); 16085895Syz147064 } 16095895Syz147064 16105895Syz147064 *val_cntp = cnt; 16115895Syz147064 16125895Syz147064 done: 16135895Syz147064 dladm_destroy_conf(conf); 16145895Syz147064 return (status); 16155895Syz147064 } 16165903Ssowmini 16175903Ssowmini static dld_public_prop_t * 16185903Ssowmini dladm_name2prop(const char *prop_name) 16195903Ssowmini { 16205903Ssowmini dld_public_prop_t *p; 16215903Ssowmini 16226789Sam223141 for (p = dld_prop; p->pp_id != MAC_PROP_PRIVATE; p++) { 16235903Ssowmini if (strcmp(p->pp_name, prop_name) == 0) 16245903Ssowmini break; 16255903Ssowmini } 16265903Ssowmini return (p); 16275903Ssowmini } 16285903Ssowmini 16295903Ssowmini 16306789Sam223141 static dld_ioc_macprop_t * 16315903Ssowmini dld_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, 16326512Ssowmini uint_t flags, dladm_status_t *status) 16335903Ssowmini { 16345903Ssowmini int dsize; 16356789Sam223141 dld_ioc_macprop_t *dip; 16365903Ssowmini dld_public_prop_t *p; 16375903Ssowmini 16385903Ssowmini *status = DLADM_STATUS_OK; 16395903Ssowmini p = dladm_name2prop(prop_name); 16406789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 16415903Ssowmini valsize = p->pp_valsize; 16425903Ssowmini 16436789Sam223141 dsize = MAC_PROP_BUFSIZE(valsize); 16445903Ssowmini dip = malloc(dsize); 16455903Ssowmini if (dip == NULL) { 16465903Ssowmini *status = DLADM_STATUS_NOMEM; 16475903Ssowmini return (NULL); 16485903Ssowmini } 16495903Ssowmini bzero(dip, dsize); 16505903Ssowmini dip->pr_valsize = valsize; 16516512Ssowmini (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name)); 16526789Sam223141 dip->pr_version = MAC_PROP_VERSION; 16535960Ssowmini dip->pr_linkid = linkid; 16545903Ssowmini dip->pr_num = p->pp_id; 16556512Ssowmini dip->pr_flags = flags; 16565903Ssowmini return (dip); 16575903Ssowmini } 16585903Ssowmini 16595903Ssowmini /* ARGSUSED */ 16605903Ssowmini static dladm_status_t 16615903Ssowmini dld_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, 16625960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 16635903Ssowmini { 16646789Sam223141 dld_ioc_macprop_t *dip; 16655903Ssowmini int fd, dsize; 16665903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 16675903Ssowmini uint8_t u8; 16685903Ssowmini uint16_t u16; 16695903Ssowmini uint32_t u32; 16705903Ssowmini void *val; 16715903Ssowmini 16726512Ssowmini dip = dld_buf_alloc(0, linkid, pd->pd_name, 0, &status); 16735903Ssowmini if (dip == NULL) 16745903Ssowmini return (status); 16755903Ssowmini 16765903Ssowmini if (pd->pd_flags & PD_CHECK_ALLOC) 16775903Ssowmini val = (void *)vdp->vd_val; 16785903Ssowmini else { 16795903Ssowmini /* 16805903Ssowmini * Currently all 1/2/4-byte size properties are byte/word/int. 16815903Ssowmini * No need (yet) to distinguish these from arrays of same size. 16825903Ssowmini */ 16835903Ssowmini switch (dip->pr_valsize) { 16845903Ssowmini case 1: 16855903Ssowmini u8 = vdp->vd_val; 16865903Ssowmini val = &u8; 16875903Ssowmini break; 16885903Ssowmini case 2: 16895903Ssowmini u16 = vdp->vd_val; 16905903Ssowmini val = &u16; 16915903Ssowmini break; 16925903Ssowmini case 4: 16935903Ssowmini u32 = vdp->vd_val; 16945903Ssowmini val = &u32; 16955903Ssowmini break; 16965903Ssowmini default: 16975903Ssowmini val = &vdp->vd_val; 16985903Ssowmini break; 16995903Ssowmini } 17005903Ssowmini } 17015903Ssowmini 17025903Ssowmini (void) memcpy(dip->pr_val, val, dip->pr_valsize); 17036789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 17045903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 17055903Ssowmini status = dladm_errno2status(errno); 17065903Ssowmini goto done; 17075903Ssowmini } 17086789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) 17095903Ssowmini status = dladm_errno2status(errno); 17105903Ssowmini 17115903Ssowmini (void) close(fd); 17125903Ssowmini done: 17136512Ssowmini free(dip); 17145903Ssowmini return (status); 17155903Ssowmini } 17165903Ssowmini 17176789Sam223141 static dld_ioc_macprop_t * 17186512Ssowmini dld_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags, 17196512Ssowmini dladm_status_t *status) 17205903Ssowmini { 17215903Ssowmini int fd, dsize; 17226789Sam223141 dld_ioc_macprop_t *dip = NULL; 17236512Ssowmini 17246512Ssowmini *status = DLADM_STATUS_OK; 17256512Ssowmini 17266512Ssowmini dip = dld_buf_alloc(0, linkid, prop_name, flags, status); 17276512Ssowmini if (dip == NULL) 17286512Ssowmini return (NULL); 17295903Ssowmini 17306789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 17315903Ssowmini 17325903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 17336512Ssowmini *status = dladm_errno2status(errno); 17345903Ssowmini goto done; 17355903Ssowmini } 17366789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 17376512Ssowmini *status = dladm_errno2status(errno); 17385903Ssowmini } 17396512Ssowmini 17406512Ssowmini (void) close(fd); 17415903Ssowmini done: 17426512Ssowmini if (*status != DLADM_STATUS_OK) { 17436512Ssowmini free(dip); 17446512Ssowmini return (NULL); 17456512Ssowmini } 17466512Ssowmini return (dip); 17475903Ssowmini } 17485903Ssowmini 17495903Ssowmini /* ARGSUSED */ 17505903Ssowmini static dladm_status_t 17515903Ssowmini dld_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 17525960Ssowmini uint_t val_cnt, val_desc_t *v, datalink_media_t media) 17535903Ssowmini { 17545903Ssowmini if (val_cnt != 1) 17555903Ssowmini return (DLADM_STATUS_BADVAL); 17566512Ssowmini v->vd_val = atoi(prop_val[0]); 17575903Ssowmini return (DLADM_STATUS_OK); 17585903Ssowmini } 17595903Ssowmini 17605903Ssowmini /* ARGSUSED */ 17615903Ssowmini static dladm_status_t 17625903Ssowmini dld_duplex_get(struct prop_desc *pd, datalink_id_t linkid, 17636512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 17645903Ssowmini { 17655903Ssowmini link_duplex_t link_duplex; 17665903Ssowmini dladm_status_t status; 17675903Ssowmini 17686789Sam223141 if (flags & MAC_PROP_DEFAULT) 17696512Ssowmini return (DLADM_STATUS_NOTSUP); 17706512Ssowmini 17715903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_duplex", 17725903Ssowmini KSTAT_DATA_UINT32, &link_duplex)) != 0) 17735903Ssowmini return (status); 17745903Ssowmini 17755903Ssowmini switch (link_duplex) { 17765903Ssowmini case LINK_DUPLEX_FULL: 17775903Ssowmini (void) strcpy(*prop_val, "full"); 17785903Ssowmini break; 17795903Ssowmini case LINK_DUPLEX_HALF: 17805903Ssowmini (void) strcpy(*prop_val, "half"); 17815903Ssowmini break; 17825903Ssowmini default: 17835903Ssowmini (void) strcpy(*prop_val, "unknown"); 17845903Ssowmini break; 17855903Ssowmini } 17865903Ssowmini *val_cnt = 1; 17875903Ssowmini return (DLADM_STATUS_OK); 17885903Ssowmini } 17895903Ssowmini 17905903Ssowmini /* ARGSUSED */ 17915903Ssowmini static dladm_status_t 17925903Ssowmini dld_speed_get(struct prop_desc *pd, datalink_id_t linkid, 17936512Ssowmini char **prop_val, uint_t *val_cnt, uint_t flags) 17945903Ssowmini { 17955903Ssowmini uint64_t ifspeed = 0; 17965903Ssowmini dladm_status_t status; 17975903Ssowmini 17986789Sam223141 if (flags & MAC_PROP_DEFAULT) 17996512Ssowmini return (DLADM_STATUS_NOTSUP); 18006512Ssowmini 18015903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "ifspeed", 18025903Ssowmini KSTAT_DATA_UINT64, &ifspeed)) != 0) 18035903Ssowmini return (status); 18046512Ssowmini 18055960Ssowmini if ((ifspeed % 1000000) != 0) { 18065960Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 18075960Ssowmini "%llf", ifspeed / (float)1000000); /* Mbps */ 18085960Ssowmini } else { 18095960Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 18105960Ssowmini "%llu", ifspeed / 1000000); /* Mbps */ 18115960Ssowmini } 18125903Ssowmini *val_cnt = 1; 18135903Ssowmini return (DLADM_STATUS_OK); 18145903Ssowmini } 18155903Ssowmini 18165903Ssowmini /* ARGSUSED */ 18175903Ssowmini static dladm_status_t 18185903Ssowmini dld_status_get(struct prop_desc *pd, datalink_id_t linkid, 18196512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18205903Ssowmini { 18216512Ssowmini link_state_t link_state; 18226512Ssowmini dladm_status_t status; 18236512Ssowmini uchar_t *cp; 18246789Sam223141 dld_ioc_macprop_t *dip; 18255903Ssowmini 18266789Sam223141 if (flags & MAC_PROP_DEFAULT) 18276512Ssowmini return (DLADM_STATUS_NOTSUP); 18286512Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18296512Ssowmini if (status != DLADM_STATUS_OK) 18305903Ssowmini return (status); 18316512Ssowmini cp = (uchar_t *)dip->pr_val; 18326512Ssowmini (void) memcpy(&link_state, cp, sizeof (link_state)); 18335903Ssowmini 18345903Ssowmini switch (link_state) { 18355903Ssowmini case LINK_STATE_UP: 18365903Ssowmini (void) strcpy(*prop_val, "up"); 18375903Ssowmini break; 18385903Ssowmini case LINK_STATE_DOWN: 18395903Ssowmini (void) strcpy(*prop_val, "down"); 18405903Ssowmini break; 18415903Ssowmini default: 18425903Ssowmini (void) strcpy(*prop_val, "unknown"); 18435903Ssowmini break; 18445903Ssowmini } 18455903Ssowmini *val_cnt = 1; 18466512Ssowmini free(dip); 18475903Ssowmini return (DLADM_STATUS_OK); 18485903Ssowmini } 18495903Ssowmini 18505903Ssowmini /* ARGSUSED */ 18515903Ssowmini static dladm_status_t 18525903Ssowmini dld_binary_get(struct prop_desc *pd, datalink_id_t linkid, 18536512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18545903Ssowmini { 18556789Sam223141 dld_ioc_macprop_t *dip; 18565903Ssowmini dladm_status_t status; 18575903Ssowmini 18586512Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18596512Ssowmini if (dip == NULL) 18605903Ssowmini return (status); 18615903Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]); 18625903Ssowmini free(dip); 18635903Ssowmini *val_cnt = 1; 18645903Ssowmini return (DLADM_STATUS_OK); 18655903Ssowmini } 18665903Ssowmini 18675960Ssowmini /* ARGSUSED */ 18685903Ssowmini static dladm_status_t 18696512Ssowmini dld_uint32_get(struct prop_desc *pd, datalink_id_t linkid, 18706512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18715903Ssowmini { 18726789Sam223141 dld_ioc_macprop_t *dip; 18736512Ssowmini uint32_t v = 0; 18745903Ssowmini uchar_t *cp; 18755903Ssowmini dladm_status_t status; 18765903Ssowmini 18776512Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18786512Ssowmini if (dip == NULL) 18795903Ssowmini return (status); 18805903Ssowmini cp = (uchar_t *)dip->pr_val; 18815903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 18826512Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v); 18835903Ssowmini free(dip); 18845903Ssowmini *val_cnt = 1; 18855903Ssowmini return (DLADM_STATUS_OK); 18865903Ssowmini } 18875903Ssowmini 18885960Ssowmini /* ARGSUSED */ 18895903Ssowmini static dladm_status_t 18905903Ssowmini dld_flowctl_get(struct prop_desc *pd, datalink_id_t linkid, 18916512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18925903Ssowmini { 18936789Sam223141 dld_ioc_macprop_t *dip; 18945903Ssowmini link_flowctrl_t v; 18955903Ssowmini dladm_status_t status; 18965903Ssowmini uchar_t *cp; 18975903Ssowmini 18986512Ssowmini dip = dld_get_public_prop(linkid, pd->pd_name, flags, &status); 18996512Ssowmini if (dip == NULL) 19005903Ssowmini return (status); 19015903Ssowmini cp = (uchar_t *)dip->pr_val; 19025903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 19035903Ssowmini switch (v) { 19045903Ssowmini case LINK_FLOWCTRL_NONE: 19055903Ssowmini (void) sprintf(*prop_val, "no"); 19065903Ssowmini break; 19075903Ssowmini case LINK_FLOWCTRL_RX: 19085903Ssowmini (void) sprintf(*prop_val, "rx"); 19095903Ssowmini break; 19105903Ssowmini case LINK_FLOWCTRL_TX: 19115903Ssowmini (void) sprintf(*prop_val, "tx"); 19125903Ssowmini break; 19135903Ssowmini case LINK_FLOWCTRL_BI: 19145903Ssowmini (void) sprintf(*prop_val, "bi"); 19155903Ssowmini break; 19165903Ssowmini } 19175903Ssowmini free(dip); 19185903Ssowmini *val_cnt = 1; 19195903Ssowmini return (DLADM_STATUS_OK); 19205903Ssowmini } 19215903Ssowmini 19225903Ssowmini 19235903Ssowmini /* ARGSUSED */ 19245903Ssowmini static dladm_status_t 19255903Ssowmini dld_set_prop(datalink_id_t linkid, const char *prop_name, 19265903Ssowmini char **prop_val, uint_t val_cnt, uint_t flags) 19275903Ssowmini { 19285903Ssowmini int fd, i, slen; 19295903Ssowmini int bufsize = 0, dsize; 19306789Sam223141 dld_ioc_macprop_t *dip = NULL; 19315903Ssowmini uchar_t *dp; 19325903Ssowmini dld_public_prop_t *p; 19336512Ssowmini dladm_status_t status = DLADM_STATUS_OK; 19345903Ssowmini 19355903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 19365903Ssowmini (prop_val != NULL && val_cnt == 0)) 19375903Ssowmini return (DLADM_STATUS_BADARG); 19385903Ssowmini p = dladm_name2prop(prop_name); 19396789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 19405903Ssowmini return (DLADM_STATUS_BADARG); 19415903Ssowmini 19425903Ssowmini /* 19435903Ssowmini * private properties: all parsing is done in the kernel. 19445903Ssowmini * allocate a enough space for each property + its separator (','). 19455903Ssowmini */ 19465903Ssowmini for (i = 0; i < val_cnt; i++) { 19475903Ssowmini bufsize += strlen(prop_val[i]) + 1; 19485903Ssowmini } 19496512Ssowmini 19506512Ssowmini if (prop_val == NULL) { 19516512Ssowmini /* 19526512Ssowmini * getting default value. so use more buffer space. 19536512Ssowmini */ 19546512Ssowmini bufsize += 1024; 19556512Ssowmini } 19566512Ssowmini 19576512Ssowmini dip = dld_buf_alloc(bufsize + 1, linkid, prop_name, 19586789Sam223141 (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status); 19595903Ssowmini if (dip == NULL) 19605903Ssowmini return (status); 19615903Ssowmini 19625903Ssowmini dp = (uchar_t *)dip->pr_val; 19636789Sam223141 dsize = sizeof (dld_ioc_macprop_t) + bufsize; 19645903Ssowmini slen = 0; 19656512Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 19666512Ssowmini status = dladm_errno2status(errno); 19676512Ssowmini goto done; 19686512Ssowmini } 19696512Ssowmini if (prop_val == NULL) { 19706789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 19716512Ssowmini status = dladm_errno2status(errno); 19726512Ssowmini goto done; 19736512Ssowmini } 19746512Ssowmini } else { 19756512Ssowmini for (i = 0; i < val_cnt; i++) { 19766512Ssowmini int plen = 0; 19775903Ssowmini 19786512Ssowmini plen = strlen(prop_val[i]); 19796512Ssowmini bcopy(prop_val[i], dp, plen); 19806512Ssowmini slen += plen; 19816512Ssowmini /* 19826512Ssowmini * add a "," separator and update dp. 19836512Ssowmini */ 19846512Ssowmini if (i != (val_cnt -1)) 19856512Ssowmini dp[slen++] = ','; 19866512Ssowmini dp += (plen + 1); 19876512Ssowmini } 19885903Ssowmini } 19896789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) { 19906512Ssowmini status = dladm_errno2status(errno); 19915903Ssowmini } 19926512Ssowmini 19936512Ssowmini done: 19946512Ssowmini if (fd > 0) 19956512Ssowmini (void) close(fd); 19965903Ssowmini free(dip); 19976512Ssowmini return (status); 19985903Ssowmini } 19995903Ssowmini 20005903Ssowmini static dladm_status_t 20015903Ssowmini dld_get_prop(datalink_id_t linkid, const char *prop_name, 20026512Ssowmini char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags) 20035903Ssowmini { 20045903Ssowmini int fd; 20055903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 20065903Ssowmini uint_t dsize; 20076789Sam223141 dld_ioc_macprop_t *dip = NULL; 20085903Ssowmini dld_public_prop_t *p; 20095903Ssowmini char tmp = '\0'; 20105903Ssowmini 20115903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 20125903Ssowmini (prop_val != NULL && val_cnt == 0)) 20135903Ssowmini return (DLADM_STATUS_BADARG); 20145903Ssowmini 20155903Ssowmini p = dladm_name2prop(prop_name); 20166789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 20175903Ssowmini return (DLADM_STATUS_BADARG); 20185903Ssowmini 20196512Ssowmini if (type == DLADM_PROP_VAL_MODIFIABLE) { 20205903Ssowmini *prop_val = &tmp; 20215903Ssowmini *val_cnt = 1; 20225903Ssowmini return (DLADM_STATUS_OK); 20235903Ssowmini } 20245903Ssowmini 20255903Ssowmini /* 20265903Ssowmini * private properties: all parsing is done in the kernel. 20275903Ssowmini */ 20286512Ssowmini dip = dld_buf_alloc(1024, linkid, prop_name, dld_flags, &status); 20295903Ssowmini if (dip == NULL) 20305903Ssowmini return (status); 20316789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 20325903Ssowmini 20336512Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 20346512Ssowmini free(dip); 20355903Ssowmini return (DLADM_STATUS_BADARG); 20366512Ssowmini } 20375903Ssowmini 20386789Sam223141 if ((status = i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize)) < 0) { 20395903Ssowmini status = dladm_errno2status(errno); 20405903Ssowmini } else { 20415903Ssowmini (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); 20425903Ssowmini *val_cnt = 1; 20435903Ssowmini } 20446512Ssowmini 20456512Ssowmini (void) close(fd); 20466512Ssowmini free(dip); 20475903Ssowmini return (status); 20485903Ssowmini } 20496512Ssowmini 20506512Ssowmini 20516512Ssowmini static dladm_status_t 20526512Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid, 20536512Ssowmini datalink_media_t media, uint_t flags) 20546512Ssowmini { 20556512Ssowmini dladm_status_t status; 20566512Ssowmini char **prop_vals = NULL, *buf; 20576512Ssowmini size_t bufsize; 20586512Ssowmini uint_t cnt; 20596512Ssowmini int i; 20606512Ssowmini 20616512Ssowmini /* 20626512Ssowmini * Allocate buffer needed for prop_vals array. We can have at most 20636512Ssowmini * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where 20646512Ssowmini * each entry has max size DLADM_PROP_VAL_MAX 20656512Ssowmini */ 20666512Ssowmini bufsize = 20676512Ssowmini (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 20686512Ssowmini buf = malloc(bufsize); 20696512Ssowmini prop_vals = (char **)(void *)buf; 20706512Ssowmini for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 20716512Ssowmini prop_vals[i] = buf + 20726512Ssowmini sizeof (char *) * DLADM_MAX_PROP_VALCNT + 20736512Ssowmini i * DLADM_PROP_VAL_MAX; 20746512Ssowmini } 20756768Sar224390 20766768Sar224390 /* 20776768Sar224390 * PD_EMPTY_RESET is used for properties like zone where the 20786768Sar224390 * "" itself is used to reset the property. So libdladm can 20796768Sar224390 * copy pdp->pd_defval over to the val_desc_t passed down on 20806768Sar224390 * the setprop using the global values in the table. For other 20816768Sar224390 * cases (PD_EMPTY_RESET is not set, vd_name is ""), doing 20826768Sar224390 * reset-linkprop will cause libdladm to do a getprop to find 20836768Sar224390 * the default value and then do a setprop to reset the value 20846768Sar224390 * to default. 20856768Sar224390 */ 20866789Sam223141 status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media, 20876789Sam223141 MAC_PROP_DEFAULT); 20886512Ssowmini if (status == DLADM_STATUS_OK) { 20896512Ssowmini status = i_dladm_set_single_prop(linkid, pdp->pd_class, 20906512Ssowmini media, pdp, prop_vals, cnt, flags); 20916512Ssowmini } 20926512Ssowmini free(buf); 20936512Ssowmini return (status); 20946512Ssowmini } 2095