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 #include <stdlib.h> 273147Sxc151355 #include <strings.h> 283147Sxc151355 #include <errno.h> 293147Sxc151355 #include <ctype.h> 305895Syz147064 #include <stddef.h> 313448Sdh155122 #include <sys/types.h> 323147Sxc151355 #include <sys/stat.h> 333448Sdh155122 #include <sys/dld.h> 343448Sdh155122 #include <sys/zone.h> 353448Sdh155122 #include <fcntl.h> 363448Sdh155122 #include <unistd.h> 373448Sdh155122 #include <libdevinfo.h> 383448Sdh155122 #include <zone.h> 393871Syz147064 #include <libdllink.h> 403147Sxc151355 #include <libdladm_impl.h> 415895Syz147064 #include <libdlwlan_impl.h> 423871Syz147064 #include <libdlwlan.h> 435895Syz147064 #include <libdlvlan.h> 443448Sdh155122 #include <dlfcn.h> 453448Sdh155122 #include <link.h> 465895Syz147064 #include <inet/wifi_ioctl.h> 475903Ssowmini #include <libdladm.h> 485903Ssowmini #include <sys/param.h> 495903Ssowmini #include <inttypes.h> 505903Ssowmini #include <sys/ethernet.h> 513448Sdh155122 525895Syz147064 /* 535895Syz147064 * The linkprop get() callback. 545903Ssowmini * - pd: pointer to the struct prop_desc 555895Syz147064 * - propstrp: a property string array to keep the returned property. 565895Syz147064 * Caller allocated. 575895Syz147064 * - cntp: number of returned properties. 585895Syz147064 * Caller also uses it to indicate how many it expects. 595895Syz147064 */ 605903Ssowmini struct prop_desc; 615903Ssowmini 625903Ssowmini typedef dladm_status_t pd_getf_t(struct prop_desc *pd, 635960Ssowmini datalink_id_t, char **propstp, uint_t *cntp, 646512Ssowmini datalink_media_t, uint_t); 655895Syz147064 665895Syz147064 /* 675895Syz147064 * The linkprop set() callback. 685895Syz147064 * - propval: a val_desc_t array which keeps the property values to be set. 695895Syz147064 * - cnt: number of properties to be set. 705903Ssowmini * - flags: additional flags passed down the system call. 715903Ssowmini * 725903Ssowmini * pd_set takes val_desc_t given by pd_check(), translates it into 735903Ssowmini * a format suitable for kernel consumption. This may require allocation 745903Ssowmini * of ioctl buffers etc. pd_set() may call another common routine (used 755903Ssowmini * by all other pd_sets) which invokes the ioctl. 765895Syz147064 */ 775903Ssowmini typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t, 785960Ssowmini val_desc_t *propval, uint_t cnt, uint_t flags, 795960Ssowmini datalink_media_t); 803448Sdh155122 813448Sdh155122 825895Syz147064 /* 835895Syz147064 * The linkprop check() callback. 845895Syz147064 * - propstrp: property string array which keeps the property to be checked. 855895Syz147064 * - cnt: number of properties. 865895Syz147064 * - propval: return value; the property values of the given property strings. 875903Ssowmini * 885903Ssowmini * pd_check checks that the input values are valid. It does so by 895903Ssowmini * iteraring through the pd_modval list for the property. If 905903Ssowmini * the modifiable values cannot be expressed as a list, a pd_check 915903Ssowmini * specific to this property can be used. If the input values are 925903Ssowmini * verified to be valid, pd_check allocates a val_desc_t and fills it 935903Ssowmini * with either a val_desc_t found on the pd_modval list or something 945903Ssowmini * generated on the fly. 955895Syz147064 */ 965903Ssowmini typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, 975903Ssowmini datalink_id_t, char **propstrp, 985960Ssowmini uint_t cnt, val_desc_t *propval, 995960Ssowmini datalink_media_t); 1003448Sdh155122 101*7342SAruna.Ramakrishna@Sun.COM typedef struct dladm_public_prop_s { 1026789Sam223141 mac_prop_id_t pp_id; 1035903Ssowmini size_t pp_valsize; 1045903Ssowmini char *pp_name; 1055903Ssowmini char *pp_desc; 106*7342SAruna.Ramakrishna@Sun.COM } dladm_public_prop_t; 1075903Ssowmini 108*7342SAruna.Ramakrishna@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc(size_t, datalink_id_t, const char *, 1096512Ssowmini uint_t, dladm_status_t *); 110*7342SAruna.Ramakrishna@Sun.COM static dladm_status_t i_dladm_set_prop(datalink_id_t, const char *, char **, 1115903Ssowmini uint_t, uint_t); 112*7342SAruna.Ramakrishna@Sun.COM static dladm_status_t i_dladm_get_prop(datalink_id_t, const char *, char **, 1136512Ssowmini uint_t *, dladm_prop_type_t, uint_t); 114*7342SAruna.Ramakrishna@Sun.COM static dladm_public_prop_t *dladm_name2prop(const char *); 115*7342SAruna.Ramakrishna@Sun.COM static dld_ioc_macprop_t *i_dladm_get_public_prop(datalink_id_t, char *, uint_t, 116*7342SAruna.Ramakrishna@Sun.COM dladm_status_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, 120*7342SAruna.Ramakrishna@Sun.COM i_dladm_duplex_get, i_dladm_status_get, 121*7342SAruna.Ramakrishna@Sun.COM i_dladm_binary_get, i_dladm_uint32_get, 122*7342SAruna.Ramakrishna@Sun.COM i_dladm_flowctl_get; 123*7342SAruna.Ramakrishna@Sun.COM static pd_setf_t do_set_zone, do_set_rate_prop, 1245903Ssowmini do_set_powermode_prop, do_set_radio_prop, 125*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop; 1265903Ssowmini static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, 127*7342SAruna.Ramakrishna@Sun.COM i_dladm_defmtu_check; 1283448Sdh155122 129*7342SAruna.Ramakrishna@Sun.COM static dladm_status_t i_dladm_speed_get(struct prop_desc *, datalink_id_t, 1306512Ssowmini char **, uint_t *, uint_t); 1315960Ssowmini 1323448Sdh155122 typedef struct prop_desc { 1335895Syz147064 /* 1345895Syz147064 * link property name 1355895Syz147064 */ 1365895Syz147064 char *pd_name; 1375895Syz147064 1385895Syz147064 /* 1395895Syz147064 * default property value, can be set to { "", NULL } 1405895Syz147064 */ 1415895Syz147064 val_desc_t pd_defval; 1425895Syz147064 1435895Syz147064 /* 1445895Syz147064 * list of optional property values, can be NULL. 1455895Syz147064 * 1465895Syz147064 * This is set to non-NULL if there is a list of possible property 1475895Syz147064 * values. pd_optval would point to the array of possible values. 1485895Syz147064 */ 1495895Syz147064 val_desc_t *pd_optval; 1505895Syz147064 1515895Syz147064 /* 1525895Syz147064 * count of the above optional property values. 0 if pd_optval is NULL. 1535895Syz147064 */ 1545895Syz147064 uint_t pd_noptval; 1555895Syz147064 1565895Syz147064 /* 1575895Syz147064 * callback to set link property; 1585895Syz147064 * set to NULL if this property is read-only 1595895Syz147064 */ 1605895Syz147064 pd_setf_t *pd_set; 1615895Syz147064 1625895Syz147064 /* 1635895Syz147064 * callback to get modifiable link property 1645895Syz147064 */ 1655895Syz147064 pd_getf_t *pd_getmod; 1665895Syz147064 1675895Syz147064 /* 1685895Syz147064 * callback to get current link property 1695895Syz147064 */ 1705895Syz147064 pd_getf_t *pd_get; 1715895Syz147064 1725895Syz147064 /* 1735895Syz147064 * callback to validate link property value, set to NULL if pd_optval 1745895Syz147064 * is not NULL. In that case, validate the value by comparing it with 1755895Syz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 1765895Syz147064 * valid. 1775895Syz147064 */ 1785895Syz147064 pd_checkf_t *pd_check; 1795895Syz147064 1805895Syz147064 uint_t pd_flags; 1815903Ssowmini #define PD_TEMPONLY 0x1 /* property is temporary only */ 1825903Ssowmini #define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */ 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 197*7342SAruna.Ramakrishna@Sun.COM static dladm_public_prop_t dladm_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 216*7342SAruna.Ramakrishna@Sun.COM { MAC_PROP_ZONE, sizeof (dld_ioc_zid_t), 217*7342SAruna.Ramakrishna@Sun.COM "zone", "non-global zones" }, 218*7342SAruna.Ramakrishna@Sun.COM 219*7342SAruna.Ramakrishna@Sun.COM { MAC_PROP_AUTOPUSH, sizeof (struct dlautopush), 220*7342SAruna.Ramakrishna@Sun.COM "autopush", "autopush modules" }, 221*7342SAruna.Ramakrishna@Sun.COM 2226789Sam223141 { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), 2235903Ssowmini "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, 2245903Ssowmini 2256789Sam223141 { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), 2265903Ssowmini "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, 2275903Ssowmini 2286789Sam223141 { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), 2295903Ssowmini "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, 2305903Ssowmini 2316789Sam223141 { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), 2325903Ssowmini "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, 2335903Ssowmini 2346789Sam223141 { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), 2355903Ssowmini "adv_100fdx_cap", "Adv 100 Mbps fdx" }, 2365903Ssowmini 2376789Sam223141 { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), 2385903Ssowmini "en_100fdx_cap", "Enable 100 Mbps fdx" }, 2395903Ssowmini 2406789Sam223141 { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), 2415903Ssowmini "adv_100hdx_cap", "Adv 100 Mbps hdx" }, 2425903Ssowmini 2436789Sam223141 { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), 2445903Ssowmini "en_100hdx_cap", "Enable 100 Mbps hdx" }, 2455903Ssowmini 2466789Sam223141 { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), 2475903Ssowmini "adv_10fdx_cap", "Adv 10 Mbps fdx" }, 2485903Ssowmini 2496789Sam223141 { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), 2505903Ssowmini "en_10fdx_cap", "Enable 10 Mbps fdx" }, 2515903Ssowmini 2526789Sam223141 { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), 2535903Ssowmini "adv_10hdx_cap", "Adv 10 Mbps hdx" }, 2545903Ssowmini 2556789Sam223141 { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), 2565903Ssowmini "en_10hdx_cap", "Enable 10 Mbps hdx" }, 2575903Ssowmini 2586789Sam223141 { MAC_PROP_PRIVATE, 0, 2595903Ssowmini "driver-private", "" } 2605903Ssowmini }; 2615903Ssowmini 2625903Ssowmini static val_desc_t link_duplex_vals[] = { 2635903Ssowmini { "half", LINK_DUPLEX_HALF }, 2645903Ssowmini { "full", LINK_DUPLEX_HALF } 2655903Ssowmini }; 2665903Ssowmini static val_desc_t link_status_vals[] = { 2675903Ssowmini { "up", LINK_STATE_UP }, 2685903Ssowmini { "down", LINK_STATE_DOWN } 2695903Ssowmini }; 2705903Ssowmini static val_desc_t link_01_vals[] = { 2715903Ssowmini { "1", 1 }, 2725903Ssowmini { "0", 0 } 2735903Ssowmini }; 2745903Ssowmini static val_desc_t link_flow_vals[] = { 2755903Ssowmini { "no", LINK_FLOWCTRL_NONE }, 2765903Ssowmini { "tx", LINK_FLOWCTRL_TX }, 2775903Ssowmini { "rx", LINK_FLOWCTRL_RX }, 2785903Ssowmini { "bi", LINK_FLOWCTRL_BI } 2795903Ssowmini }; 2805903Ssowmini 2815903Ssowmini #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) 2825903Ssowmini 2835895Syz147064 static val_desc_t dladm_wlan_radio_vals[] = { 2845895Syz147064 { "on", DLADM_WLAN_RADIO_ON }, 2855895Syz147064 { "off", DLADM_WLAN_RADIO_OFF } 2865895Syz147064 }; 2875895Syz147064 2885895Syz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 2895895Syz147064 { "off", DLADM_WLAN_PM_OFF }, 2905895Syz147064 { "fast", DLADM_WLAN_PM_FAST }, 2915895Syz147064 { "max", DLADM_WLAN_PM_MAX } 2925895Syz147064 }; 2935895Syz147064 2943448Sdh155122 static prop_desc_t prop_table[] = { 2955895Syz147064 2965903Ssowmini { "channel", { NULL, 0 }, 2975903Ssowmini NULL, 0, NULL, NULL, 2985895Syz147064 do_get_channel_prop, NULL, 0, 2995903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3005895Syz147064 3015895Syz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 3025895Syz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 3035895Syz147064 do_set_powermode_prop, NULL, 3045895Syz147064 do_get_powermode_prop, NULL, 0, 3055903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3065895Syz147064 3075895Syz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 3085895Syz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 3095895Syz147064 do_set_radio_prop, NULL, 3105895Syz147064 do_get_radio_prop, NULL, 0, 3115903Ssowmini DATALINK_CLASS_PHYS, DL_WIFI }, 3125895Syz147064 3135895Syz147064 { "speed", { "", 0 }, NULL, 0, 3145895Syz147064 do_set_rate_prop, do_get_rate_mod, 3155895Syz147064 do_get_rate_prop, do_check_rate, 0, 3165960Ssowmini DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE }, 3175895Syz147064 3186512Ssowmini { "autopush", { "", 0 }, NULL, 0, 319*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, 320*7342SAruna.Ramakrishna@Sun.COM do_get_autopush, do_check_autopush, PD_CHECK_ALLOC, 3215903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3225895Syz147064 3236512Ssowmini { "zone", { "", 0 }, NULL, 0, 3243448Sdh155122 do_set_zone, NULL, 325*7342SAruna.Ramakrishna@Sun.COM do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC, 3265903Ssowmini DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3275903Ssowmini 3286512Ssowmini { "duplex", { "", 0 }, 3295903Ssowmini link_duplex_vals, VALCNT(link_duplex_vals), 330*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_duplex_get, NULL, 3315903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3325903Ssowmini 3335960Ssowmini { "state", { "up", LINK_STATE_UP }, 3345903Ssowmini link_status_vals, VALCNT(link_status_vals), 335*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_status_get, NULL, 3366512Ssowmini 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, 3375903Ssowmini 3385903Ssowmini { "adv_autoneg_cap", { "1", 1 }, 3395903Ssowmini link_01_vals, VALCNT(link_01_vals), 340*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 3415903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3425903Ssowmini 3436512Ssowmini { "mtu", { "", 0 }, NULL, 0, 344*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_uint32_get, 345*7342SAruna.Ramakrishna@Sun.COM i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL, 346*7342SAruna.Ramakrishna@Sun.COM DATALINK_ANY_MEDIATYPE }, 3475903Ssowmini 3486512Ssowmini { "flowctrl", { "", 0 }, 3495903Ssowmini link_flow_vals, VALCNT(link_flow_vals), 350*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL, 3515903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3525903Ssowmini 3536512Ssowmini { "adv_1000fdx_cap", { "", 0 }, 3546512Ssowmini link_01_vals, VALCNT(link_01_vals), 355*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 3565903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3575903Ssowmini 3586512Ssowmini { "en_1000fdx_cap", { "", 0 }, 3595903Ssowmini link_01_vals, VALCNT(link_01_vals), 360*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 3615903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3625903Ssowmini 3636512Ssowmini { "adv_1000hdx_cap", { "", 0 }, 3645903Ssowmini link_01_vals, VALCNT(link_01_vals), 365*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 3665903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3675903Ssowmini 3686512Ssowmini { "en_1000hdx_cap", { "", 0 }, 3695903Ssowmini link_01_vals, VALCNT(link_01_vals), 370*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 3715903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3725903Ssowmini 3736512Ssowmini { "adv_100fdx_cap", { "", 0 }, 3745903Ssowmini link_01_vals, VALCNT(link_01_vals), 375*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 3765903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3775903Ssowmini 3786512Ssowmini { "en_100fdx_cap", { "", 0 }, 3795903Ssowmini link_01_vals, VALCNT(link_01_vals), 380*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 3815903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3825903Ssowmini 3836512Ssowmini { "adv_100hdx_cap", { "", 0 }, 3845903Ssowmini link_01_vals, VALCNT(link_01_vals), 385*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 3865903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3875903Ssowmini 3886512Ssowmini { "en_100hdx_cap", { "", 0 }, 3895903Ssowmini link_01_vals, VALCNT(link_01_vals), 390*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 3915903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3925903Ssowmini 3936512Ssowmini { "adv_10fdx_cap", { "", 0 }, 3945903Ssowmini link_01_vals, VALCNT(link_01_vals), 395*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 3965903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 3975903Ssowmini 3986512Ssowmini { "en_10fdx_cap", { "", 0 }, 3995903Ssowmini link_01_vals, VALCNT(link_01_vals), 400*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 4015903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 4025903Ssowmini 4036512Ssowmini { "adv_10hdx_cap", { "", 0 }, 4045903Ssowmini link_01_vals, VALCNT(link_01_vals), 405*7342SAruna.Ramakrishna@Sun.COM NULL, NULL, i_dladm_binary_get, NULL, 4065903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER }, 4075903Ssowmini 4086512Ssowmini { "en_10hdx_cap", { "", 0 }, 4095903Ssowmini link_01_vals, VALCNT(link_01_vals), 410*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL, 4115903Ssowmini 0, DATALINK_CLASS_PHYS, DL_ETHER } 4125903Ssowmini 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); 4256512Ssowmini static dladm_status_t i_dladm_getset_defval(prop_desc_t *, datalink_id_t, 4266512Ssowmini datalink_media_t, uint_t); 4275895Syz147064 /* 4285895Syz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 4295895Syz147064 * rates to be retrieved. However, we cannot increase it at this 4305895Syz147064 * time because it will break binary compatibility with unbundled 4315895Syz147064 * WiFi drivers and utilities. So for now we define an additional 4325895Syz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 4335895Syz147064 */ 4345895Syz147064 #define MAX_SUPPORT_RATES 64 4355895Syz147064 4365895Syz147064 #define AP_ANCHOR "[anchor]" 4375895Syz147064 #define AP_DELIMITER '.' 4385895Syz147064 4395895Syz147064 static dladm_status_t 4405895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4415895Syz147064 val_desc_t *vdp) 4425895Syz147064 { 4435895Syz147064 int i, j; 4445895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4453147Sxc151355 4465895Syz147064 for (j = 0; j < val_cnt; j++) { 4475895Syz147064 for (i = 0; i < pdp->pd_noptval; i++) { 4485895Syz147064 if (strcasecmp(*prop_val, 4495895Syz147064 pdp->pd_optval[i].vd_name) == 0) { 4505895Syz147064 break; 4515895Syz147064 } 4525895Syz147064 } 4535895Syz147064 if (i == pdp->pd_noptval) { 4545895Syz147064 status = DLADM_STATUS_BADVAL; 4555895Syz147064 goto done; 4565895Syz147064 } 4575895Syz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 4585895Syz147064 } 4595895Syz147064 4605895Syz147064 done: 4615895Syz147064 return (status); 4625895Syz147064 } 4635895Syz147064 4645895Syz147064 static dladm_status_t 4655895Syz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 4665895Syz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4675895Syz147064 uint_t flags) 4683147Sxc151355 { 4695895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 4705895Syz147064 val_desc_t *vdp = NULL; 4715895Syz147064 boolean_t needfree = B_FALSE; 4725895Syz147064 uint_t cnt, i; 4733147Sxc151355 4745895Syz147064 if (!(pdp->pd_class & class)) 4755895Syz147064 return (DLADM_STATUS_BADARG); 4765895Syz147064 4775895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 4783147Sxc151355 return (DLADM_STATUS_BADARG); 4793147Sxc151355 4805895Syz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 4815895Syz147064 return (DLADM_STATUS_TEMPONLY); 4825895Syz147064 4835895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 4845895Syz147064 return (DLADM_STATUS_OK); 4855895Syz147064 4865895Syz147064 if (pdp->pd_set == NULL) 4875895Syz147064 return (DLADM_STATUS_PROPRDONLY); 4883448Sdh155122 4895903Ssowmini if (pdp->pd_flags & PD_CHECK_ALLOC) 4905903Ssowmini needfree = B_TRUE; 4915903Ssowmini else 4925903Ssowmini needfree = B_FALSE; 4935895Syz147064 if (prop_val != NULL) { 4945895Syz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 4955895Syz147064 if (vdp == NULL) 4965895Syz147064 return (DLADM_STATUS_NOMEM); 4975895Syz147064 4985903Ssowmini 4995895Syz147064 if (pdp->pd_check != NULL) { 5005903Ssowmini status = pdp->pd_check(pdp, linkid, prop_val, val_cnt, 5015960Ssowmini vdp, media); 5025895Syz147064 } else if (pdp->pd_optval != NULL) { 5035895Syz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 5045895Syz147064 } else { 5053448Sdh155122 status = DLADM_STATUS_BADARG; 5063147Sxc151355 } 5075895Syz147064 5083147Sxc151355 if (status != DLADM_STATUS_OK) 5095895Syz147064 goto done; 5105895Syz147064 5115895Syz147064 cnt = val_cnt; 5125895Syz147064 } else { 5135895Syz147064 if (pdp->pd_defval.vd_name == NULL) 5145895Syz147064 return (DLADM_STATUS_NOTSUP); 5155895Syz147064 516*7342SAruna.Ramakrishna@Sun.COM cnt = 1; 517*7342SAruna.Ramakrishna@Sun.COM if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || 5186512Ssowmini strlen(pdp->pd_defval.vd_name) > 0) { 5196512Ssowmini if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 5206512Ssowmini return (DLADM_STATUS_NOMEM); 521*7342SAruna.Ramakrishna@Sun.COM 522*7342SAruna.Ramakrishna@Sun.COM if (pdp->pd_check != NULL) { 523*7342SAruna.Ramakrishna@Sun.COM status = pdp->pd_check(pdp, linkid, prop_val, 524*7342SAruna.Ramakrishna@Sun.COM cnt, vdp, media); 525*7342SAruna.Ramakrishna@Sun.COM if (status != DLADM_STATUS_OK) 526*7342SAruna.Ramakrishna@Sun.COM goto done; 527*7342SAruna.Ramakrishna@Sun.COM } else { 528*7342SAruna.Ramakrishna@Sun.COM (void) memcpy(vdp, &pdp->pd_defval, 529*7342SAruna.Ramakrishna@Sun.COM sizeof (val_desc_t)); 530*7342SAruna.Ramakrishna@Sun.COM } 5316512Ssowmini } else { 5326512Ssowmini status = i_dladm_getset_defval(pdp, linkid, 5336512Ssowmini media, flags); 5346512Ssowmini return (status); 5356512Ssowmini } 5365895Syz147064 } 5375960Ssowmini status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media); 5385895Syz147064 if (needfree) { 5395895Syz147064 for (i = 0; i < cnt; i++) 5405903Ssowmini free((void *)((val_desc_t *)vdp + i)->vd_val); 5413147Sxc151355 } 5425895Syz147064 done: 5435895Syz147064 free(vdp); 5445895Syz147064 return (status); 5455895Syz147064 } 5465895Syz147064 5475895Syz147064 static dladm_status_t 5485895Syz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 5495895Syz147064 char **prop_val, uint_t val_cnt, uint_t flags) 5505895Syz147064 { 5515895Syz147064 int i; 5525895Syz147064 boolean_t found = B_FALSE; 5535895Syz147064 datalink_class_t class; 5545895Syz147064 uint32_t media; 5555895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 5565895Syz147064 5575895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 5585895Syz147064 if (status != DLADM_STATUS_OK) 5595895Syz147064 return (status); 5605895Syz147064 5615895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 5625895Syz147064 prop_desc_t *pdp = &prop_table[i]; 5635895Syz147064 dladm_status_t s; 5645895Syz147064 5655895Syz147064 if (prop_name != NULL && 5665895Syz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 5675895Syz147064 continue; 5685895Syz147064 5695895Syz147064 found = B_TRUE; 5705895Syz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 5715895Syz147064 val_cnt, flags); 5723448Sdh155122 5735895Syz147064 if (prop_name != NULL) { 5745895Syz147064 status = s; 5755895Syz147064 break; 5765895Syz147064 } else { 5775895Syz147064 if (s != DLADM_STATUS_OK && 5785895Syz147064 s != DLADM_STATUS_NOTSUP) 5795895Syz147064 status = s; 5805895Syz147064 } 5815895Syz147064 } 5825903Ssowmini if (!found) { 5835903Ssowmini if (prop_name[0] == '_') { 5845903Ssowmini /* other private properties */ 585*7342SAruna.Ramakrishna@Sun.COM status = i_dladm_set_prop(linkid, prop_name, prop_val, 5865903Ssowmini val_cnt, flags); 5875903Ssowmini } else { 5885903Ssowmini status = DLADM_STATUS_NOTFOUND; 5895903Ssowmini } 5905903Ssowmini } 5915895Syz147064 5925895Syz147064 return (status); 5935895Syz147064 } 5945895Syz147064 5955895Syz147064 /* 5965895Syz147064 * Set/reset link property for specific link 5975895Syz147064 */ 5985895Syz147064 dladm_status_t 5995895Syz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 6005895Syz147064 uint_t val_cnt, uint_t flags) 6015895Syz147064 { 6025895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 6035895Syz147064 6045895Syz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 6055895Syz147064 (prop_val == NULL && val_cnt > 0) || 6065895Syz147064 (prop_val != NULL && val_cnt == 0) || 6075895Syz147064 (prop_name == NULL && prop_val != NULL)) { 6085895Syz147064 return (DLADM_STATUS_BADARG); 6095895Syz147064 } 6105895Syz147064 6115895Syz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 6125895Syz147064 val_cnt, flags); 6135895Syz147064 if (status != DLADM_STATUS_OK) 6145895Syz147064 return (status); 6155895Syz147064 6165895Syz147064 if (flags & DLADM_OPT_PERSIST) { 6175895Syz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 6183147Sxc151355 prop_val, val_cnt); 6193147Sxc151355 } 6203147Sxc151355 return (status); 6213147Sxc151355 } 6223147Sxc151355 6235895Syz147064 /* 6245895Syz147064 * Walk link properties of the given specific link. 6255895Syz147064 */ 6263147Sxc151355 dladm_status_t 6275895Syz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 6285895Syz147064 int (*func)(datalink_id_t, const char *, void *)) 6293147Sxc151355 { 6305895Syz147064 dladm_status_t status; 6315895Syz147064 datalink_class_t class; 6325895Syz147064 uint_t media; 6335895Syz147064 int i; 6345895Syz147064 6355895Syz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 6365895Syz147064 return (DLADM_STATUS_BADARG); 6375895Syz147064 6385895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6395895Syz147064 if (status != DLADM_STATUS_OK) 6405895Syz147064 return (status); 6415895Syz147064 6425895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 6435895Syz147064 if (!(prop_table[i].pd_class & class)) 6445895Syz147064 continue; 6455895Syz147064 6465895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 6475895Syz147064 continue; 6485895Syz147064 6495895Syz147064 if (func(linkid, prop_table[i].pd_name, arg) == 6505895Syz147064 DLADM_WALK_TERMINATE) { 6515895Syz147064 break; 6525895Syz147064 } 6535895Syz147064 } 6545895Syz147064 6555895Syz147064 return (DLADM_STATUS_OK); 6565895Syz147064 } 6573448Sdh155122 6585895Syz147064 /* 6595895Syz147064 * Get linkprop of the given specific link. 6605895Syz147064 */ 6615895Syz147064 dladm_status_t 6625895Syz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 6635895Syz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 6645895Syz147064 { 6655895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 6665895Syz147064 datalink_class_t class; 6675895Syz147064 uint_t media; 6685895Syz147064 prop_desc_t *pdp; 6696512Ssowmini uint_t cnt, dld_flags = 0; 6705895Syz147064 int i; 6715895Syz147064 6726512Ssowmini if (type == DLADM_PROP_VAL_DEFAULT) 6736789Sam223141 dld_flags = MAC_PROP_DEFAULT; 6746512Ssowmini 6755895Syz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 6765895Syz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 6775895Syz147064 return (DLADM_STATUS_BADARG); 6785895Syz147064 6795895Syz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 6805895Syz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 6815895Syz147064 break; 6825895Syz147064 6835903Ssowmini if (i == DLADM_MAX_PROPS) { 6845903Ssowmini if (prop_name[0] == '_') { 6855903Ssowmini /* 6865903Ssowmini * private property. 6875903Ssowmini */ 688*7342SAruna.Ramakrishna@Sun.COM return (i_dladm_get_prop(linkid, prop_name, 6896512Ssowmini prop_val, val_cntp, type, dld_flags)); 6905903Ssowmini } else { 6915903Ssowmini return (DLADM_STATUS_NOTFOUND); 6925903Ssowmini } 6935903Ssowmini } 6945895Syz147064 6955895Syz147064 pdp = &prop_table[i]; 6965895Syz147064 6975895Syz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 6985895Syz147064 if (status != DLADM_STATUS_OK) 6995895Syz147064 return (status); 7005895Syz147064 7015895Syz147064 if (!(pdp->pd_class & class)) 7025895Syz147064 return (DLADM_STATUS_BADARG); 7035895Syz147064 7045895Syz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 7053147Sxc151355 return (DLADM_STATUS_BADARG); 7063147Sxc151355 7075895Syz147064 switch (type) { 7085895Syz147064 case DLADM_PROP_VAL_CURRENT: 7096512Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media, 7106512Ssowmini dld_flags); 7115895Syz147064 break; 7125895Syz147064 7135895Syz147064 case DLADM_PROP_VAL_DEFAULT: 7146768Sar224390 /* 7156768Sar224390 * If defaults are not defined for the property, 7166768Sar224390 * pd_defval.vd_name should be null. If the driver 7176768Sar224390 * has to be contacted for the value, vd_name should 7186768Sar224390 * be the empty string (""). Otherwise, dladm will 7196768Sar224390 * just print whatever is in the table. 7206768Sar224390 */ 7215895Syz147064 if (pdp->pd_defval.vd_name == NULL) { 7225895Syz147064 status = DLADM_STATUS_NOTSUP; 7235895Syz147064 break; 7245895Syz147064 } 7256512Ssowmini 7266512Ssowmini if (strlen(pdp->pd_defval.vd_name) == 0) { 7276512Ssowmini status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, 7286512Ssowmini media, dld_flags); 7296512Ssowmini } else { 7306512Ssowmini (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 7316512Ssowmini } 7325895Syz147064 *val_cntp = 1; 7335895Syz147064 break; 7343448Sdh155122 7355895Syz147064 case DLADM_PROP_VAL_MODIFIABLE: 7365895Syz147064 if (pdp->pd_getmod != NULL) { 7375903Ssowmini status = pdp->pd_getmod(pdp, linkid, prop_val, 7386512Ssowmini val_cntp, media, dld_flags); 7395895Syz147064 break; 7405895Syz147064 } 7415895Syz147064 cnt = pdp->pd_noptval; 7425895Syz147064 if (cnt == 0) { 7435895Syz147064 status = DLADM_STATUS_NOTSUP; 7445895Syz147064 } else if (cnt > *val_cntp) { 7455895Syz147064 status = DLADM_STATUS_TOOSMALL; 7465895Syz147064 } else { 7475895Syz147064 for (i = 0; i < cnt; i++) { 7485895Syz147064 (void) strcpy(prop_val[i], 7495895Syz147064 pdp->pd_optval[i].vd_name); 7505895Syz147064 } 7515895Syz147064 *val_cntp = cnt; 7525895Syz147064 } 7535895Syz147064 break; 7545895Syz147064 case DLADM_PROP_VAL_PERSISTENT: 7555895Syz147064 if (pdp->pd_flags & PD_TEMPONLY) 7565895Syz147064 return (DLADM_STATUS_TEMPONLY); 7575895Syz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 7585895Syz147064 prop_val, val_cntp); 7595895Syz147064 break; 7605895Syz147064 default: 7615895Syz147064 status = DLADM_STATUS_BADARG; 7625895Syz147064 break; 7633147Sxc151355 } 7643448Sdh155122 7655895Syz147064 return (status); 7665895Syz147064 } 7675895Syz147064 7685895Syz147064 /*ARGSUSED*/ 7695895Syz147064 static int 7705895Syz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 7715895Syz147064 { 7725895Syz147064 char *buf, **propvals; 7735895Syz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 7745895Syz147064 7755895Syz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 7765895Syz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 7775895Syz147064 return (DLADM_WALK_CONTINUE); 7785895Syz147064 } 7795895Syz147064 7805895Syz147064 propvals = (char **)(void *)buf; 7815895Syz147064 for (i = 0; i < valcnt; i++) { 7825895Syz147064 propvals[i] = buf + 7835895Syz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 7845895Syz147064 i * DLADM_PROP_VAL_MAX; 7855895Syz147064 } 7865895Syz147064 7875895Syz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 7885895Syz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 7895895Syz147064 goto done; 7905895Syz147064 } 7915895Syz147064 7925895Syz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 7935895Syz147064 DLADM_OPT_ACTIVE); 7945895Syz147064 7955895Syz147064 done: 7965895Syz147064 if (buf != NULL) 7975895Syz147064 free(buf); 7985895Syz147064 7995895Syz147064 return (DLADM_WALK_CONTINUE); 8005895Syz147064 } 8015895Syz147064 8025895Syz147064 /*ARGSUSED*/ 8035895Syz147064 static int 8045895Syz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 8055895Syz147064 { 8066916Sartem (void) dladm_init_linkprop(linkid, B_TRUE); 8075895Syz147064 return (DLADM_WALK_CONTINUE); 8085895Syz147064 } 8095895Syz147064 8105895Syz147064 dladm_status_t 8116916Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media) 8125895Syz147064 { 8136916Sartem datalink_media_t dmedia; 8146916Sartem uint32_t media; 8156916Sartem 8166916Sartem dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI; 8176916Sartem 8185895Syz147064 if (linkid == DATALINK_ALL_LINKID) { 8195895Syz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 8206916Sartem DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST); 8216916Sartem } else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL, 8226916Sartem &media, NULL, 0) == DLADM_STATUS_OK) && 8236916Sartem DATALINK_MEDIA_ACCEPTED(dmedia, media))) { 8245895Syz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 8253448Sdh155122 } 8263448Sdh155122 return (DLADM_STATUS_OK); 8273147Sxc151355 } 8283147Sxc151355 8295903Ssowmini /* ARGSUSED */ 8305895Syz147064 static dladm_status_t 8315903Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid, 8326512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 8333147Sxc151355 { 8345895Syz147064 char zone_name[ZONENAME_MAX]; 8355895Syz147064 zoneid_t zid; 8365895Syz147064 dladm_status_t status; 837*7342SAruna.Ramakrishna@Sun.COM char *cp; 838*7342SAruna.Ramakrishna@Sun.COM dld_ioc_macprop_t *dip; 8393147Sxc151355 8406512Ssowmini if (flags != 0) 8416512Ssowmini return (DLADM_STATUS_NOTSUP); 8426512Ssowmini 843*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 8445895Syz147064 if (status != DLADM_STATUS_OK) 8453448Sdh155122 return (status); 8463448Sdh155122 847*7342SAruna.Ramakrishna@Sun.COM cp = dip->pr_val; 848*7342SAruna.Ramakrishna@Sun.COM (void) memcpy(&zid, cp, sizeof (zid)); 849*7342SAruna.Ramakrishna@Sun.COM free(dip); 850*7342SAruna.Ramakrishna@Sun.COM 8515895Syz147064 *val_cnt = 1; 8525895Syz147064 if (zid != GLOBAL_ZONEID) { 8535895Syz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8545895Syz147064 return (dladm_errno2status(errno)); 8553147Sxc151355 8565895Syz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 8573147Sxc151355 } else { 8585895Syz147064 *prop_val[0] = '\0'; 8593147Sxc151355 } 8603147Sxc151355 8613448Sdh155122 return (DLADM_STATUS_OK); 8623448Sdh155122 } 8633448Sdh155122 8643448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 8653448Sdh155122 8663448Sdh155122 static int 8673448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 8683448Sdh155122 { 8693448Sdh155122 char root[MAXPATHLEN]; 8703448Sdh155122 zone_get_devroot_t real_zone_get_devroot; 8713448Sdh155122 void *dlhandle; 8723448Sdh155122 void *sym; 8733448Sdh155122 int ret; 8743448Sdh155122 8753448Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 8763448Sdh155122 return (-1); 8773448Sdh155122 8783448Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 8793448Sdh155122 (void) dlclose(dlhandle); 8803448Sdh155122 return (-1); 8813448Sdh155122 } 8823448Sdh155122 8833448Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 8843448Sdh155122 8853448Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 8863448Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 8873448Sdh155122 (void) dlclose(dlhandle); 8883448Sdh155122 return (ret); 8893448Sdh155122 } 8903448Sdh155122 8913448Sdh155122 static dladm_status_t 8925895Syz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 8933448Sdh155122 { 8943448Sdh155122 char path[MAXPATHLEN]; 8955895Syz147064 char name[MAXLINKNAMELEN]; 8963448Sdh155122 di_prof_t prof = NULL; 8973448Sdh155122 char zone_name[ZONENAME_MAX]; 8983448Sdh155122 dladm_status_t status; 8995895Syz147064 int ret; 9003448Sdh155122 9013448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 9023448Sdh155122 return (dladm_errno2status(errno)); 9033448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 9043448Sdh155122 return (dladm_errno2status(errno)); 9053448Sdh155122 if (di_prof_init(path, &prof) != 0) 9063448Sdh155122 return (dladm_errno2status(errno)); 9073448Sdh155122 9085895Syz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 9095895Syz147064 if (status != DLADM_STATUS_OK) 9105895Syz147064 goto cleanup; 9115895Syz147064 9125895Syz147064 if (add) 9135895Syz147064 ret = di_prof_add_dev(prof, name); 9145895Syz147064 else 9155895Syz147064 ret = di_prof_add_exclude(prof, name); 9165895Syz147064 9175895Syz147064 if (ret != 0) { 9183448Sdh155122 status = dladm_errno2status(errno); 9193448Sdh155122 goto cleanup; 9203448Sdh155122 } 9213448Sdh155122 9223448Sdh155122 if (di_prof_commit(prof) != 0) 9233448Sdh155122 status = dladm_errno2status(errno); 9243448Sdh155122 cleanup: 9253448Sdh155122 if (prof) 9263448Sdh155122 di_prof_fini(prof); 9273448Sdh155122 9283448Sdh155122 return (status); 9293448Sdh155122 } 9303448Sdh155122 9315903Ssowmini /* ARGSUSED */ 9323448Sdh155122 static dladm_status_t 9335960Ssowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, 9345960Ssowmini uint_t val_cnt, uint_t flags, datalink_media_t media) 9353448Sdh155122 { 936*7342SAruna.Ramakrishna@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 9373448Sdh155122 zoneid_t zid_old, zid_new; 9385895Syz147064 char link[MAXLINKNAMELEN]; 939*7342SAruna.Ramakrishna@Sun.COM char *cp; 940*7342SAruna.Ramakrishna@Sun.COM dld_ioc_macprop_t *dip; 941*7342SAruna.Ramakrishna@Sun.COM dld_ioc_zid_t *dzp; 9423448Sdh155122 9433448Sdh155122 if (val_cnt != 1) 9443448Sdh155122 return (DLADM_STATUS_BADVALCNT); 9453448Sdh155122 946*7342SAruna.Ramakrishna@Sun.COM dzp = (dld_ioc_zid_t *)vdp->vd_val; 947*7342SAruna.Ramakrishna@Sun.COM 948*7342SAruna.Ramakrishna@Sun.COM /* 949*7342SAruna.Ramakrishna@Sun.COM * If diz_is_ppa_hack is set, then an implicit vlan must be created. 950*7342SAruna.Ramakrishna@Sun.COM * There is no old value to compare against, and vdp->vd_val is 951*7342SAruna.Ramakrishna@Sun.COM * already populated with the zoneid and linkname in the function 952*7342SAruna.Ramakrishna@Sun.COM * do_check_zone(). 953*7342SAruna.Ramakrishna@Sun.COM */ 954*7342SAruna.Ramakrishna@Sun.COM 955*7342SAruna.Ramakrishna@Sun.COM if (dzp->diz_is_ppa_hack) { 956*7342SAruna.Ramakrishna@Sun.COM zid_old = GLOBAL_ZONEID; 957*7342SAruna.Ramakrishna@Sun.COM } else { 958*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, 959*7342SAruna.Ramakrishna@Sun.COM flags, &status); 960*7342SAruna.Ramakrishna@Sun.COM if (status != DLADM_STATUS_OK) 961*7342SAruna.Ramakrishna@Sun.COM return (status); 962*7342SAruna.Ramakrishna@Sun.COM 963*7342SAruna.Ramakrishna@Sun.COM cp = dip->pr_val; 964*7342SAruna.Ramakrishna@Sun.COM (void) memcpy(&zid_old, cp, sizeof (zid_old)); 965*7342SAruna.Ramakrishna@Sun.COM free(dip); 966*7342SAruna.Ramakrishna@Sun.COM } 967*7342SAruna.Ramakrishna@Sun.COM 968*7342SAruna.Ramakrishna@Sun.COM zid_new = dzp->diz_zid; 969*7342SAruna.Ramakrishna@Sun.COM (void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN); 9703448Sdh155122 9713448Sdh155122 /* Do nothing if setting to current value */ 9723448Sdh155122 if (zid_new == zid_old) 9735895Syz147064 return (status); 9745895Syz147064 9755895Syz147064 if (zid_new != GLOBAL_ZONEID) { 9765895Syz147064 /* 9775895Syz147064 * If the new zoneid is the global zone, we could destroy 9785895Syz147064 * the link (in the case of an implicitly-created VLAN) as a 979*7342SAruna.Ramakrishna@Sun.COM * result of setting the zoneid. In that case, we defer the 980*7342SAruna.Ramakrishna@Sun.COM * operation to the end of this function to avoid recreating 981*7342SAruna.Ramakrishna@Sun.COM * the VLAN and getting a different linkid during the rollback 982*7342SAruna.Ramakrishna@Sun.COM * if other operation fails. 9835895Syz147064 * 984*7342SAruna.Ramakrishna@Sun.COM * Otherwise, this operation will hold a reference to the 9855895Syz147064 * link and prevent a link renaming, so we need to do it 9865895Syz147064 * before other operations. 9875895Syz147064 */ 988*7342SAruna.Ramakrishna@Sun.COM status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt, 989*7342SAruna.Ramakrishna@Sun.COM flags, media); 9905895Syz147064 if (status != DLADM_STATUS_OK) 9915895Syz147064 return (status); 9925895Syz147064 } 9935895Syz147064 9943448Sdh155122 if (zid_old != GLOBAL_ZONEID) { 9955895Syz147064 if (zone_remove_datalink(zid_old, link) != 0 && 9963448Sdh155122 errno != ENXIO) { 9973448Sdh155122 status = dladm_errno2status(errno); 9983448Sdh155122 goto rollback1; 9993448Sdh155122 } 10003448Sdh155122 10015895Syz147064 /* 10025895Syz147064 * It is okay to fail to update the /dev entry (some 10035895Syz147064 * vanity-named links do not have a /dev entry). 10045895Syz147064 */ 10055895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 10065895Syz147064 } 10075895Syz147064 10085895Syz147064 if (zid_new != GLOBAL_ZONEID) { 10095895Syz147064 if (zone_add_datalink(zid_new, link) != 0) { 10105895Syz147064 status = dladm_errno2status(errno); 10115895Syz147064 goto rollback2; 10125895Syz147064 } 10135895Syz147064 1014*7342SAruna.Ramakrishna@Sun.COM if (dzp->diz_is_ppa_hack) { 1015*7342SAruna.Ramakrishna@Sun.COM if ((status = dladm_name2info(link, &linkid, NULL, NULL, 1016*7342SAruna.Ramakrishna@Sun.COM NULL)) != DLADM_STATUS_OK) { 1017*7342SAruna.Ramakrishna@Sun.COM return (status); 1018*7342SAruna.Ramakrishna@Sun.COM } 1019*7342SAruna.Ramakrishna@Sun.COM } 1020*7342SAruna.Ramakrishna@Sun.COM 10215895Syz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 10225895Syz147064 } else { 1023*7342SAruna.Ramakrishna@Sun.COM status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt, 1024*7342SAruna.Ramakrishna@Sun.COM flags, media); 10253448Sdh155122 if (status != DLADM_STATUS_OK) 10263448Sdh155122 goto rollback2; 10273448Sdh155122 } 10283448Sdh155122 10293448Sdh155122 return (DLADM_STATUS_OK); 10303448Sdh155122 10313448Sdh155122 rollback2: 10323448Sdh155122 if (zid_old != GLOBAL_ZONEID) 10335895Syz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 10345895Syz147064 if (zid_old != GLOBAL_ZONEID) 10355895Syz147064 (void) zone_add_datalink(zid_old, link); 10363448Sdh155122 rollback1: 1037*7342SAruna.Ramakrishna@Sun.COM if (zid_new != GLOBAL_ZONEID) { 1038*7342SAruna.Ramakrishna@Sun.COM dzp->diz_zid = zid_old; 1039*7342SAruna.Ramakrishna@Sun.COM (void) i_dladm_set_public_prop(pd, linkid, vdp, val_cnt, 1040*7342SAruna.Ramakrishna@Sun.COM flags, media); 1041*7342SAruna.Ramakrishna@Sun.COM } 1042*7342SAruna.Ramakrishna@Sun.COM 10433448Sdh155122 return (status); 10443448Sdh155122 } 10453448Sdh155122 10463448Sdh155122 /* ARGSUSED */ 10473448Sdh155122 static dladm_status_t 10485903Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 10495960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 10503448Sdh155122 { 1051*7342SAruna.Ramakrishna@Sun.COM char *zone_name; 1052*7342SAruna.Ramakrishna@Sun.COM char linkname[MAXLINKNAMELEN]; 1053*7342SAruna.Ramakrishna@Sun.COM zoneid_t zoneid; 1054*7342SAruna.Ramakrishna@Sun.COM char *cp; 1055*7342SAruna.Ramakrishna@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 1056*7342SAruna.Ramakrishna@Sun.COM boolean_t is_ppa_hack = B_FALSE; 1057*7342SAruna.Ramakrishna@Sun.COM dld_ioc_zid_t *dzp; 10583448Sdh155122 10593448Sdh155122 if (val_cnt != 1) 10603448Sdh155122 return (DLADM_STATUS_BADVALCNT); 10613448Sdh155122 1062*7342SAruna.Ramakrishna@Sun.COM dzp = malloc(sizeof (dld_ioc_zid_t)); 1063*7342SAruna.Ramakrishna@Sun.COM if (dzp == NULL) 1064*7342SAruna.Ramakrishna@Sun.COM return (DLADM_STATUS_NOMEM); 10653448Sdh155122 1066*7342SAruna.Ramakrishna@Sun.COM if (prop_val) { 1067*7342SAruna.Ramakrishna@Sun.COM /* 1068*7342SAruna.Ramakrishna@Sun.COM * The prop_val contains zone_name{:linkname}. The linkname is 1069*7342SAruna.Ramakrishna@Sun.COM * present only when the link is a ppa-hacked vlan. 1070*7342SAruna.Ramakrishna@Sun.COM */ 1071*7342SAruna.Ramakrishna@Sun.COM cp = strchr(*prop_val, ':'); 1072*7342SAruna.Ramakrishna@Sun.COM if (cp) { 1073*7342SAruna.Ramakrishna@Sun.COM (void) strlcpy(linkname, cp + 1, MAXLINKNAMELEN); 1074*7342SAruna.Ramakrishna@Sun.COM *cp = '\0'; 1075*7342SAruna.Ramakrishna@Sun.COM is_ppa_hack = B_TRUE; 1076*7342SAruna.Ramakrishna@Sun.COM } else { 1077*7342SAruna.Ramakrishna@Sun.COM status = dladm_datalink_id2info(linkid, NULL, NULL, 1078*7342SAruna.Ramakrishna@Sun.COM NULL, linkname, MAXLINKNAMELEN); 1079*7342SAruna.Ramakrishna@Sun.COM if (status != DLADM_STATUS_OK) { 1080*7342SAruna.Ramakrishna@Sun.COM goto done; 1081*7342SAruna.Ramakrishna@Sun.COM } 1082*7342SAruna.Ramakrishna@Sun.COM } 1083*7342SAruna.Ramakrishna@Sun.COM zone_name = *prop_val; 1084*7342SAruna.Ramakrishna@Sun.COM } else { 1085*7342SAruna.Ramakrishna@Sun.COM zone_name = GLOBAL_ZONENAME; 1086*7342SAruna.Ramakrishna@Sun.COM if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 1087*7342SAruna.Ramakrishna@Sun.COM linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 1088*7342SAruna.Ramakrishna@Sun.COM goto done; 1089*7342SAruna.Ramakrishna@Sun.COM } 1090*7342SAruna.Ramakrishna@Sun.COM } 1091*7342SAruna.Ramakrishna@Sun.COM 1092*7342SAruna.Ramakrishna@Sun.COM if (strlen(linkname) > MAXLINKNAMELEN) { 1093*7342SAruna.Ramakrishna@Sun.COM status = DLADM_STATUS_BADVAL; 1094*7342SAruna.Ramakrishna@Sun.COM goto done; 1095*7342SAruna.Ramakrishna@Sun.COM } 1096*7342SAruna.Ramakrishna@Sun.COM 1097*7342SAruna.Ramakrishna@Sun.COM if ((zoneid = getzoneidbyname(zone_name)) == -1) { 1098*7342SAruna.Ramakrishna@Sun.COM status = DLADM_STATUS_BADVAL; 1099*7342SAruna.Ramakrishna@Sun.COM goto done; 1100*7342SAruna.Ramakrishna@Sun.COM } 1101*7342SAruna.Ramakrishna@Sun.COM 1102*7342SAruna.Ramakrishna@Sun.COM if (zoneid != GLOBAL_ZONEID) { 11033448Sdh155122 ushort_t flags; 11043448Sdh155122 1105*7342SAruna.Ramakrishna@Sun.COM if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags, 11063448Sdh155122 sizeof (flags)) < 0) { 1107*7342SAruna.Ramakrishna@Sun.COM status = dladm_errno2status(errno); 1108*7342SAruna.Ramakrishna@Sun.COM goto done; 11093448Sdh155122 } 11103448Sdh155122 11113448Sdh155122 if (!(flags & ZF_NET_EXCL)) { 1112*7342SAruna.Ramakrishna@Sun.COM status = DLADM_STATUS_BADVAL; 1113*7342SAruna.Ramakrishna@Sun.COM goto done; 11143448Sdh155122 } 11153448Sdh155122 } 11163448Sdh155122 1117*7342SAruna.Ramakrishna@Sun.COM (void) memset(dzp, 0, sizeof (dld_ioc_zid_t)); 1118*7342SAruna.Ramakrishna@Sun.COM 1119*7342SAruna.Ramakrishna@Sun.COM dzp->diz_zid = zoneid; 1120*7342SAruna.Ramakrishna@Sun.COM (void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN); 1121*7342SAruna.Ramakrishna@Sun.COM dzp->diz_is_ppa_hack = is_ppa_hack; 1122*7342SAruna.Ramakrishna@Sun.COM 1123*7342SAruna.Ramakrishna@Sun.COM vdp->vd_val = (uintptr_t)dzp; 11245895Syz147064 return (DLADM_STATUS_OK); 1125*7342SAruna.Ramakrishna@Sun.COM done: 1126*7342SAruna.Ramakrishna@Sun.COM free(dzp); 1127*7342SAruna.Ramakrishna@Sun.COM return (status); 11285895Syz147064 } 11295895Syz147064 11305903Ssowmini /* ARGSUSED */ 11315895Syz147064 static dladm_status_t 11325903Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid, 11336512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 11345895Syz147064 { 1135*7342SAruna.Ramakrishna@Sun.COM struct dlautopush dlap; 1136*7342SAruna.Ramakrishna@Sun.COM int i, len; 1137*7342SAruna.Ramakrishna@Sun.COM dladm_status_t status; 1138*7342SAruna.Ramakrishna@Sun.COM dld_ioc_macprop_t *dip; 11395895Syz147064 11406789Sam223141 if (flags & MAC_PROP_DEFAULT) 11416512Ssowmini return (DLADM_STATUS_NOTSUP); 11426512Ssowmini 11435895Syz147064 *val_cnt = 1; 1144*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 1145*7342SAruna.Ramakrishna@Sun.COM if (dip == NULL) { 11465895Syz147064 (*prop_val)[0] = '\0'; 11475895Syz147064 goto done; 11485895Syz147064 } 1149*7342SAruna.Ramakrishna@Sun.COM (void) memcpy(&dlap, dip->pr_val, sizeof (dlap)); 11505895Syz147064 1151*7342SAruna.Ramakrishna@Sun.COM for (i = 0, len = 0; i < dlap.dap_npush; i++) { 11525895Syz147064 if (i != 0) { 11535895Syz147064 (void) snprintf(*prop_val + len, 11545895Syz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 11555895Syz147064 len += 1; 11565895Syz147064 } 11575895Syz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 1158*7342SAruna.Ramakrishna@Sun.COM "%s", dlap.dap_aplist[i]); 1159*7342SAruna.Ramakrishna@Sun.COM len += strlen(dlap.dap_aplist[i]); 1160*7342SAruna.Ramakrishna@Sun.COM if (dlap.dap_anchor - 1 == i) { 11615895Syz147064 (void) snprintf(*prop_val + len, 11625895Syz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 11635895Syz147064 AP_ANCHOR); 11645895Syz147064 len += (strlen(AP_ANCHOR) + 1); 11655895Syz147064 } 11665895Syz147064 } 11675895Syz147064 1168*7342SAruna.Ramakrishna@Sun.COM free(dip); 11695895Syz147064 done: 11705895Syz147064 return (DLADM_STATUS_OK); 11715895Syz147064 } 11725895Syz147064 11735895Syz147064 /* 11745895Syz147064 * Add the specified module to the dlautopush structure; returns a 11755895Syz147064 * DLADM_STATUS_* code. 11765895Syz147064 */ 11775895Syz147064 dladm_status_t 11785895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 11795895Syz147064 { 11805895Syz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 11815895Syz147064 return (DLADM_STATUS_BADVAL); 11825895Syz147064 11835895Syz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 11845895Syz147064 /* 11855895Syz147064 * We don't allow multiple anchors, and the anchor must 11865895Syz147064 * be after at least one module. 11875895Syz147064 */ 11885895Syz147064 if (dlap->dap_anchor != 0) 11895895Syz147064 return (DLADM_STATUS_BADVAL); 11905895Syz147064 if (dlap->dap_npush == 0) 11915895Syz147064 return (DLADM_STATUS_BADVAL); 11925895Syz147064 11935895Syz147064 dlap->dap_anchor = dlap->dap_npush; 11945895Syz147064 return (DLADM_STATUS_OK); 11955895Syz147064 } 11965895Syz147064 if (dlap->dap_npush > MAXAPUSH) 11975895Syz147064 return (DLADM_STATUS_BADVALCNT); 11985895Syz147064 11995895Syz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 12005895Syz147064 FMNAMESZ + 1); 12015895Syz147064 12025895Syz147064 return (DLADM_STATUS_OK); 12035895Syz147064 } 12045895Syz147064 12055895Syz147064 /* 12065895Syz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 12075895Syz147064 * autopush modules. The former is used in dladm set-linkprop, and the 12085895Syz147064 * latter is used in the autopush(1M) file. 12095895Syz147064 */ 12105895Syz147064 /* ARGSUSED */ 12115895Syz147064 static dladm_status_t 12125903Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 12135960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 12145895Syz147064 { 12155895Syz147064 char *module; 12165895Syz147064 struct dlautopush *dlap; 12175895Syz147064 dladm_status_t status; 12185895Syz147064 char val[DLADM_PROP_VAL_MAX]; 12195895Syz147064 char delimiters[4]; 12205895Syz147064 12215895Syz147064 if (val_cnt != 1) 12225895Syz147064 return (DLADM_STATUS_BADVALCNT); 12235895Syz147064 1224*7342SAruna.Ramakrishna@Sun.COM if (prop_val != NULL) { 1225*7342SAruna.Ramakrishna@Sun.COM dlap = malloc(sizeof (struct dlautopush)); 1226*7342SAruna.Ramakrishna@Sun.COM if (dlap == NULL) 1227*7342SAruna.Ramakrishna@Sun.COM return (DLADM_STATUS_NOMEM); 12283448Sdh155122 1229*7342SAruna.Ramakrishna@Sun.COM (void) memset(dlap, 0, sizeof (struct dlautopush)); 1230*7342SAruna.Ramakrishna@Sun.COM (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 1231*7342SAruna.Ramakrishna@Sun.COM bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 1232*7342SAruna.Ramakrishna@Sun.COM module = strtok(val, delimiters); 1233*7342SAruna.Ramakrishna@Sun.COM while (module != NULL) { 1234*7342SAruna.Ramakrishna@Sun.COM status = i_dladm_add_ap_module(module, dlap); 1235*7342SAruna.Ramakrishna@Sun.COM if (status != DLADM_STATUS_OK) 1236*7342SAruna.Ramakrishna@Sun.COM return (status); 1237*7342SAruna.Ramakrishna@Sun.COM module = strtok(NULL, delimiters); 1238*7342SAruna.Ramakrishna@Sun.COM } 1239*7342SAruna.Ramakrishna@Sun.COM 1240*7342SAruna.Ramakrishna@Sun.COM vdp->vd_val = (uintptr_t)dlap; 1241*7342SAruna.Ramakrishna@Sun.COM } else { 1242*7342SAruna.Ramakrishna@Sun.COM vdp->vd_val = 0; 12435895Syz147064 } 12443448Sdh155122 return (DLADM_STATUS_OK); 12453448Sdh155122 } 12463448Sdh155122 12475903Ssowmini /* ARGSUSED */ 12483448Sdh155122 static dladm_status_t 12495903Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, 12505903Ssowmini char **prop_val, uint_t *val_cnt, uint_t id) 12513448Sdh155122 { 12525895Syz147064 wl_rates_t *wrp; 12535895Syz147064 uint_t i; 12545895Syz147064 wldp_t *gbuf = NULL; 12555895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 12565895Syz147064 12575895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 12585895Syz147064 status = DLADM_STATUS_NOMEM; 12595895Syz147064 goto done; 12605895Syz147064 } 12615895Syz147064 12625895Syz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 12635895Syz147064 if (status != DLADM_STATUS_OK) 12645895Syz147064 goto done; 12655895Syz147064 12665895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 12675895Syz147064 if (wrp->wl_rates_num > *val_cnt) { 12685895Syz147064 status = DLADM_STATUS_TOOSMALL; 12695895Syz147064 goto done; 12705895Syz147064 } 12715895Syz147064 12725895Syz147064 if (wrp->wl_rates_rates[0] == 0) { 12735895Syz147064 prop_val[0][0] = '\0'; 12745895Syz147064 *val_cnt = 1; 12755895Syz147064 goto done; 12765895Syz147064 } 12775895Syz147064 12785895Syz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 12795895Syz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 12805895Syz147064 wrp->wl_rates_rates[i] % 2, 12815895Syz147064 (float)wrp->wl_rates_rates[i] / 2); 12825895Syz147064 } 12835895Syz147064 *val_cnt = wrp->wl_rates_num; 12843448Sdh155122 12855895Syz147064 done: 12865895Syz147064 free(gbuf); 12875895Syz147064 return (status); 12885895Syz147064 } 12895895Syz147064 12905895Syz147064 static dladm_status_t 12915903Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, 12926512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 12935895Syz147064 { 12945960Ssowmini if (media != DL_WIFI) 1295*7342SAruna.Ramakrishna@Sun.COM return (i_dladm_speed_get(pd, linkid, prop_val, 1296*7342SAruna.Ramakrishna@Sun.COM val_cnt, flags)); 12975960Ssowmini 12985903Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 12995895Syz147064 WL_DESIRED_RATES)); 13005895Syz147064 } 13015895Syz147064 13026512Ssowmini /* ARGSUSED */ 13035895Syz147064 static dladm_status_t 13045903Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, 13056512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 13065895Syz147064 { 13075960Ssowmini switch (media) { 13085960Ssowmini case DL_ETHER: 13096512Ssowmini /* 13106512Ssowmini * Speed for ethernet links is unbounded. E.g., 802.11b 13116512Ssowmini * links can have a speed of 5.5 Gbps. 13126512Ssowmini */ 13136512Ssowmini return (DLADM_STATUS_NOTSUP); 13145960Ssowmini 13155960Ssowmini case DL_WIFI: 13165960Ssowmini return (do_get_rate_common(pd, linkid, prop_val, val_cnt, 13175960Ssowmini WL_SUPPORTED_RATES)); 13185960Ssowmini default: 13195960Ssowmini return (DLADM_STATUS_BADARG); 13205960Ssowmini } 13215895Syz147064 } 13225895Syz147064 13235895Syz147064 static dladm_status_t 13245895Syz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 13255895Syz147064 { 13265895Syz147064 int i; 13275895Syz147064 uint_t len; 13285895Syz147064 wldp_t *gbuf; 13295895Syz147064 wl_rates_t *wrp; 13305895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 13315895Syz147064 13325895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13335895Syz147064 return (DLADM_STATUS_NOMEM); 13345895Syz147064 13355895Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 13363448Sdh155122 13375895Syz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 13385895Syz147064 for (i = 0; i < rates->wr_cnt; i++) 13395895Syz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 13405895Syz147064 wrp->wl_rates_num = rates->wr_cnt; 13415895Syz147064 13425895Syz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 13435895Syz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 13445895Syz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 13455895Syz147064 WLAN_SET_PARAM, len); 13465895Syz147064 13475895Syz147064 free(gbuf); 13485895Syz147064 return (status); 13495895Syz147064 } 13503448Sdh155122 13515903Ssowmini /* ARGSUSED */ 13525895Syz147064 static dladm_status_t 13535903Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid, 13545960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 13555895Syz147064 { 13565895Syz147064 dladm_wlan_rates_t rates; 13575895Syz147064 dladm_status_t status; 13585895Syz147064 13595960Ssowmini /* 13605960Ssowmini * can currently set rate on WIFI links only. 13615960Ssowmini */ 13625960Ssowmini if (media != DL_WIFI) 13635960Ssowmini return (DLADM_STATUS_PROPRDONLY); 13645960Ssowmini 13655895Syz147064 if (val_cnt != 1) 13665895Syz147064 return (DLADM_STATUS_BADVALCNT); 13675895Syz147064 13685895Syz147064 rates.wr_cnt = 1; 13695895Syz147064 rates.wr_rates[0] = vdp[0].vd_val; 13705895Syz147064 13715895Syz147064 status = do_set_rate(linkid, &rates); 13725895Syz147064 13735895Syz147064 done: 13745895Syz147064 return (status); 13755895Syz147064 } 13763448Sdh155122 13775895Syz147064 /* ARGSUSED */ 13785895Syz147064 static dladm_status_t 13795903Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, 13805960Ssowmini uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) 13815895Syz147064 { 13825895Syz147064 int i; 13835895Syz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 13845895Syz147064 char *buf, **modval; 13855895Syz147064 dladm_status_t status; 13865895Syz147064 13875895Syz147064 if (val_cnt != 1) 13885895Syz147064 return (DLADM_STATUS_BADVALCNT); 13895895Syz147064 13905895Syz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 13915895Syz147064 MAX_SUPPORT_RATES); 13925895Syz147064 if (buf == NULL) { 13935895Syz147064 status = DLADM_STATUS_NOMEM; 13945895Syz147064 goto done; 13955895Syz147064 } 13963448Sdh155122 13975895Syz147064 modval = (char **)(void *)buf; 13985895Syz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 13995895Syz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 14005895Syz147064 i * DLADM_STRSIZE; 14015895Syz147064 } 14025895Syz147064 14036512Ssowmini status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media, 0); 14045895Syz147064 if (status != DLADM_STATUS_OK) 14055895Syz147064 goto done; 14065895Syz147064 14075895Syz147064 for (i = 0; i < modval_cnt; i++) { 14085895Syz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 14095903Ssowmini vdp->vd_val = (uintptr_t)(uint_t) 14105903Ssowmini (atof(*prop_val) * 2); 14115895Syz147064 status = DLADM_STATUS_OK; 14123448Sdh155122 break; 14133448Sdh155122 } 14145895Syz147064 } 14155895Syz147064 if (i == modval_cnt) 14165895Syz147064 status = DLADM_STATUS_BADVAL; 14175895Syz147064 done: 14185895Syz147064 free(buf); 14195895Syz147064 return (status); 14205895Syz147064 } 14215895Syz147064 14225895Syz147064 static dladm_status_t 14235895Syz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 14245895Syz147064 { 14255895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 14265895Syz147064 } 14275895Syz147064 14285903Ssowmini /* ARGSUSED */ 14295895Syz147064 static dladm_status_t 14305903Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, 14316512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 14325895Syz147064 { 14335895Syz147064 uint32_t channel; 14345895Syz147064 wldp_t *gbuf; 14355895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 14365895Syz147064 14375895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 14385895Syz147064 return (DLADM_STATUS_NOMEM); 14395895Syz147064 14405895Syz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 14415895Syz147064 goto done; 14425895Syz147064 14435895Syz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 14445895Syz147064 &channel)) { 14455895Syz147064 status = DLADM_STATUS_NOTFOUND; 14465895Syz147064 goto done; 14475895Syz147064 } 14485895Syz147064 14495895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 14505895Syz147064 *val_cnt = 1; 14513448Sdh155122 14525895Syz147064 done: 14535895Syz147064 free(gbuf); 14545895Syz147064 return (status); 14555895Syz147064 } 14565895Syz147064 14575895Syz147064 static dladm_status_t 14585895Syz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 14595895Syz147064 { 14605895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 14615895Syz147064 } 14625895Syz147064 14635903Ssowmini /* ARGSUSED */ 14645895Syz147064 static dladm_status_t 14655903Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, 14666512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 14675895Syz147064 { 14685895Syz147064 wl_ps_mode_t *mode; 14695895Syz147064 const char *s; 14705895Syz147064 wldp_t *gbuf; 14715895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 14725895Syz147064 14735895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 14745895Syz147064 return (DLADM_STATUS_NOMEM); 14755895Syz147064 14765895Syz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 14775895Syz147064 goto done; 14785895Syz147064 14795895Syz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 14805895Syz147064 switch (mode->wl_ps_mode) { 14815895Syz147064 case WL_PM_AM: 14825895Syz147064 s = "off"; 14835895Syz147064 break; 14845895Syz147064 case WL_PM_MPS: 14855895Syz147064 s = "max"; 14865895Syz147064 break; 14875895Syz147064 case WL_PM_FAST: 14885895Syz147064 s = "fast"; 14893448Sdh155122 break; 14903448Sdh155122 default: 14915895Syz147064 status = DLADM_STATUS_NOTFOUND; 14925895Syz147064 goto done; 14935895Syz147064 } 14945895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 14955895Syz147064 *val_cnt = 1; 14965895Syz147064 14975895Syz147064 done: 14985895Syz147064 free(gbuf); 14995895Syz147064 return (status); 15005895Syz147064 } 15015895Syz147064 15025895Syz147064 static dladm_status_t 15035895Syz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 15045895Syz147064 { 15055895Syz147064 wl_ps_mode_t ps_mode; 15065895Syz147064 15075895Syz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 15085895Syz147064 15095895Syz147064 switch (*pm) { 15105895Syz147064 case DLADM_WLAN_PM_OFF: 15115895Syz147064 ps_mode.wl_ps_mode = WL_PM_AM; 15123448Sdh155122 break; 15135895Syz147064 case DLADM_WLAN_PM_MAX: 15145895Syz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 15155895Syz147064 break; 15165895Syz147064 case DLADM_WLAN_PM_FAST: 15175895Syz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 15185895Syz147064 break; 15195895Syz147064 default: 15205895Syz147064 return (DLADM_STATUS_NOTSUP); 15213448Sdh155122 } 15225895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 15235895Syz147064 sizeof (ps_mode))); 15245895Syz147064 } 15255895Syz147064 15265895Syz147064 /* ARGSUSED */ 15275895Syz147064 static dladm_status_t 15285903Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, 15295960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 15305895Syz147064 { 15315895Syz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 15325895Syz147064 dladm_status_t status; 15335895Syz147064 15345895Syz147064 if (val_cnt != 1) 15355895Syz147064 return (DLADM_STATUS_BADVALCNT); 15365895Syz147064 15375895Syz147064 status = do_set_powermode(linkid, &powermode); 15383448Sdh155122 15393448Sdh155122 return (status); 15403448Sdh155122 } 15413448Sdh155122 15423448Sdh155122 static dladm_status_t 15435895Syz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 15443448Sdh155122 { 15455895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 15465895Syz147064 } 15473448Sdh155122 15485903Ssowmini /* ARGSUSED */ 15495895Syz147064 static dladm_status_t 15505903Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, 15516512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 15525895Syz147064 { 15535895Syz147064 wl_radio_t radio; 15545895Syz147064 const char *s; 15555895Syz147064 wldp_t *gbuf; 15565895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 15573448Sdh155122 15585895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 15595895Syz147064 return (DLADM_STATUS_NOMEM); 15603448Sdh155122 15615895Syz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 15625895Syz147064 goto done; 15633448Sdh155122 15645895Syz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 15655895Syz147064 switch (radio) { 15665895Syz147064 case B_TRUE: 15675895Syz147064 s = "on"; 15685895Syz147064 break; 15695895Syz147064 case B_FALSE: 15705895Syz147064 s = "off"; 15715895Syz147064 break; 15725895Syz147064 default: 15735895Syz147064 status = DLADM_STATUS_NOTFOUND; 15745895Syz147064 goto done; 15755895Syz147064 } 15765895Syz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 15775895Syz147064 *val_cnt = 1; 15783448Sdh155122 15795895Syz147064 done: 15805895Syz147064 free(gbuf); 15813448Sdh155122 return (status); 15823448Sdh155122 } 15833448Sdh155122 15843448Sdh155122 static dladm_status_t 15855895Syz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 15863448Sdh155122 { 15875895Syz147064 wl_radio_t r; 15883448Sdh155122 15895895Syz147064 switch (*radio) { 15905895Syz147064 case DLADM_WLAN_RADIO_ON: 15915895Syz147064 r = B_TRUE; 15925895Syz147064 break; 15935895Syz147064 case DLADM_WLAN_RADIO_OFF: 15945895Syz147064 r = B_FALSE; 15955895Syz147064 break; 15965895Syz147064 default: 15975895Syz147064 return (DLADM_STATUS_NOTSUP); 15985895Syz147064 } 15995895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 16005895Syz147064 } 16013448Sdh155122 16025895Syz147064 /* ARGSUSED */ 16035895Syz147064 static dladm_status_t 16045903Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid, 16055960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media) 16065895Syz147064 { 16075895Syz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 16085895Syz147064 dladm_status_t status; 16093448Sdh155122 16105895Syz147064 if (val_cnt != 1) 16115895Syz147064 return (DLADM_STATUS_BADVALCNT); 16125895Syz147064 16135895Syz147064 status = do_set_radio(linkid, &radio); 16143448Sdh155122 16153448Sdh155122 return (status); 16163448Sdh155122 } 16173448Sdh155122 16185895Syz147064 static dladm_status_t 16195895Syz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 16205895Syz147064 char **prop_val, uint_t val_cnt) 16213448Sdh155122 { 16225895Syz147064 char buf[MAXLINELEN]; 16235895Syz147064 int i; 16245895Syz147064 dladm_conf_t conf; 16255895Syz147064 dladm_status_t status; 16263448Sdh155122 16275895Syz147064 status = dladm_read_conf(linkid, &conf); 16285895Syz147064 if (status != DLADM_STATUS_OK) 16295895Syz147064 return (status); 16303448Sdh155122 16315895Syz147064 /* 16325895Syz147064 * reset case. 16335895Syz147064 */ 16345895Syz147064 if (val_cnt == 0) { 16355895Syz147064 status = dladm_unset_conf_field(conf, prop_name); 16365895Syz147064 if (status == DLADM_STATUS_OK) 16375895Syz147064 status = dladm_write_conf(conf); 16385895Syz147064 goto done; 16395895Syz147064 } 16403448Sdh155122 16415895Syz147064 buf[0] = '\0'; 16425895Syz147064 for (i = 0; i < val_cnt; i++) { 16435895Syz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 16445895Syz147064 if (i != val_cnt - 1) 16455895Syz147064 (void) strlcat(buf, ",", MAXLINELEN); 16463448Sdh155122 } 16473448Sdh155122 16485895Syz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 16495895Syz147064 if (status == DLADM_STATUS_OK) 16505895Syz147064 status = dladm_write_conf(conf); 16515895Syz147064 16525895Syz147064 done: 16535895Syz147064 dladm_destroy_conf(conf); 16545895Syz147064 return (status); 16553448Sdh155122 } 16565895Syz147064 16575895Syz147064 static dladm_status_t 16585895Syz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 16595895Syz147064 char **prop_val, uint_t *val_cntp) 16605895Syz147064 { 16615895Syz147064 char buf[MAXLINELEN], *str; 16625895Syz147064 uint_t cnt = 0; 16635895Syz147064 dladm_conf_t conf; 16645895Syz147064 dladm_status_t status; 16655895Syz147064 16665895Syz147064 status = dladm_read_conf(linkid, &conf); 16675895Syz147064 if (status != DLADM_STATUS_OK) 16685895Syz147064 return (status); 16695895Syz147064 16705895Syz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 16715895Syz147064 if (status != DLADM_STATUS_OK) 16725895Syz147064 goto done; 16735895Syz147064 16745895Syz147064 str = strtok(buf, ","); 16755895Syz147064 while (str != NULL) { 16765895Syz147064 if (cnt == *val_cntp) { 16775895Syz147064 status = DLADM_STATUS_TOOSMALL; 16785895Syz147064 goto done; 16795895Syz147064 } 16805895Syz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 16815895Syz147064 str = strtok(NULL, ","); 16825895Syz147064 } 16835895Syz147064 16845895Syz147064 *val_cntp = cnt; 16855895Syz147064 16865895Syz147064 done: 16875895Syz147064 dladm_destroy_conf(conf); 16885895Syz147064 return (status); 16895895Syz147064 } 16905903Ssowmini 1691*7342SAruna.Ramakrishna@Sun.COM static dladm_public_prop_t * 16925903Ssowmini dladm_name2prop(const char *prop_name) 16935903Ssowmini { 1694*7342SAruna.Ramakrishna@Sun.COM dladm_public_prop_t *p; 16955903Ssowmini 1696*7342SAruna.Ramakrishna@Sun.COM for (p = dladm_prop; p->pp_id != MAC_PROP_PRIVATE; p++) { 16975903Ssowmini if (strcmp(p->pp_name, prop_name) == 0) 16985903Ssowmini break; 16995903Ssowmini } 17005903Ssowmini return (p); 17015903Ssowmini } 17025903Ssowmini 17035903Ssowmini 17046789Sam223141 static dld_ioc_macprop_t * 1705*7342SAruna.Ramakrishna@Sun.COM i_dladm_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, 17066512Ssowmini uint_t flags, dladm_status_t *status) 17075903Ssowmini { 17085903Ssowmini int dsize; 17096789Sam223141 dld_ioc_macprop_t *dip; 1710*7342SAruna.Ramakrishna@Sun.COM dladm_public_prop_t *p; 17115903Ssowmini 17125903Ssowmini *status = DLADM_STATUS_OK; 17135903Ssowmini p = dladm_name2prop(prop_name); 17146789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 17155903Ssowmini valsize = p->pp_valsize; 17165903Ssowmini 17176789Sam223141 dsize = MAC_PROP_BUFSIZE(valsize); 17185903Ssowmini dip = malloc(dsize); 17195903Ssowmini if (dip == NULL) { 17205903Ssowmini *status = DLADM_STATUS_NOMEM; 17215903Ssowmini return (NULL); 17225903Ssowmini } 17235903Ssowmini bzero(dip, dsize); 17245903Ssowmini dip->pr_valsize = valsize; 17256512Ssowmini (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name)); 17266789Sam223141 dip->pr_version = MAC_PROP_VERSION; 17275960Ssowmini dip->pr_linkid = linkid; 17285903Ssowmini dip->pr_num = p->pp_id; 17296512Ssowmini dip->pr_flags = flags; 17305903Ssowmini return (dip); 17315903Ssowmini } 17325903Ssowmini 17335903Ssowmini /* ARGSUSED */ 17345903Ssowmini static dladm_status_t 1735*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, 17365960Ssowmini val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) 17375903Ssowmini { 17386789Sam223141 dld_ioc_macprop_t *dip; 17395903Ssowmini int fd, dsize; 17405903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 17415903Ssowmini uint8_t u8; 17425903Ssowmini uint16_t u16; 17435903Ssowmini uint32_t u32; 17445903Ssowmini void *val; 17455903Ssowmini 1746*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_buf_alloc(0, linkid, pd->pd_name, 0, &status); 17475903Ssowmini if (dip == NULL) 17485903Ssowmini return (status); 17495903Ssowmini 17505903Ssowmini if (pd->pd_flags & PD_CHECK_ALLOC) 17515903Ssowmini val = (void *)vdp->vd_val; 17525903Ssowmini else { 17535903Ssowmini /* 17545903Ssowmini * Currently all 1/2/4-byte size properties are byte/word/int. 17555903Ssowmini * No need (yet) to distinguish these from arrays of same size. 17565903Ssowmini */ 17575903Ssowmini switch (dip->pr_valsize) { 17585903Ssowmini case 1: 17595903Ssowmini u8 = vdp->vd_val; 17605903Ssowmini val = &u8; 17615903Ssowmini break; 17625903Ssowmini case 2: 17635903Ssowmini u16 = vdp->vd_val; 17645903Ssowmini val = &u16; 17655903Ssowmini break; 17665903Ssowmini case 4: 17675903Ssowmini u32 = vdp->vd_val; 17685903Ssowmini val = &u32; 17695903Ssowmini break; 17705903Ssowmini default: 17715903Ssowmini val = &vdp->vd_val; 17725903Ssowmini break; 17735903Ssowmini } 17745903Ssowmini } 17755903Ssowmini 1776*7342SAruna.Ramakrishna@Sun.COM if (val != NULL) 1777*7342SAruna.Ramakrishna@Sun.COM (void) memcpy(dip->pr_val, val, dip->pr_valsize); 1778*7342SAruna.Ramakrishna@Sun.COM else 1779*7342SAruna.Ramakrishna@Sun.COM dip->pr_valsize = 0; 1780*7342SAruna.Ramakrishna@Sun.COM 17816789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 17825903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 17835903Ssowmini status = dladm_errno2status(errno); 17845903Ssowmini goto done; 17855903Ssowmini } 17866789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) 17875903Ssowmini status = dladm_errno2status(errno); 17885903Ssowmini 17895903Ssowmini (void) close(fd); 17905903Ssowmini done: 17916512Ssowmini free(dip); 17925903Ssowmini return (status); 17935903Ssowmini } 17945903Ssowmini 17956789Sam223141 static dld_ioc_macprop_t * 1796*7342SAruna.Ramakrishna@Sun.COM i_dladm_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags, 17976512Ssowmini dladm_status_t *status) 17985903Ssowmini { 17995903Ssowmini int fd, dsize; 18006789Sam223141 dld_ioc_macprop_t *dip = NULL; 18016512Ssowmini 18026512Ssowmini *status = DLADM_STATUS_OK; 18036512Ssowmini 1804*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_buf_alloc(0, linkid, prop_name, flags, status); 18056512Ssowmini if (dip == NULL) 18066512Ssowmini return (NULL); 18075903Ssowmini 18086789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 18095903Ssowmini 18105903Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 18116512Ssowmini *status = dladm_errno2status(errno); 18125903Ssowmini goto done; 18135903Ssowmini } 18146789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 18156512Ssowmini *status = dladm_errno2status(errno); 18165903Ssowmini } 18176512Ssowmini 18186512Ssowmini (void) close(fd); 18195903Ssowmini done: 18206512Ssowmini if (*status != DLADM_STATUS_OK) { 18216512Ssowmini free(dip); 18226512Ssowmini return (NULL); 18236512Ssowmini } 18246512Ssowmini return (dip); 18255903Ssowmini } 18265903Ssowmini 18275903Ssowmini /* ARGSUSED */ 18285903Ssowmini static dladm_status_t 1829*7342SAruna.Ramakrishna@Sun.COM i_dladm_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, 1830*7342SAruna.Ramakrishna@Sun.COM char **prop_val, uint_t val_cnt, val_desc_t *v, datalink_media_t media) 18315903Ssowmini { 18325903Ssowmini if (val_cnt != 1) 18335903Ssowmini return (DLADM_STATUS_BADVAL); 18346512Ssowmini v->vd_val = atoi(prop_val[0]); 18355903Ssowmini return (DLADM_STATUS_OK); 18365903Ssowmini } 18375903Ssowmini 18385903Ssowmini /* ARGSUSED */ 18395903Ssowmini static dladm_status_t 1840*7342SAruna.Ramakrishna@Sun.COM i_dladm_duplex_get(struct prop_desc *pd, datalink_id_t linkid, 18416512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18425903Ssowmini { 18435903Ssowmini link_duplex_t link_duplex; 18445903Ssowmini dladm_status_t status; 18455903Ssowmini 18466789Sam223141 if (flags & MAC_PROP_DEFAULT) 18476512Ssowmini return (DLADM_STATUS_NOTSUP); 18486512Ssowmini 18495903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "link_duplex", 18505903Ssowmini KSTAT_DATA_UINT32, &link_duplex)) != 0) 18515903Ssowmini return (status); 18525903Ssowmini 18535903Ssowmini switch (link_duplex) { 18545903Ssowmini case LINK_DUPLEX_FULL: 18555903Ssowmini (void) strcpy(*prop_val, "full"); 18565903Ssowmini break; 18575903Ssowmini case LINK_DUPLEX_HALF: 18585903Ssowmini (void) strcpy(*prop_val, "half"); 18595903Ssowmini break; 18605903Ssowmini default: 18615903Ssowmini (void) strcpy(*prop_val, "unknown"); 18625903Ssowmini break; 18635903Ssowmini } 18645903Ssowmini *val_cnt = 1; 18655903Ssowmini return (DLADM_STATUS_OK); 18665903Ssowmini } 18675903Ssowmini 18685903Ssowmini /* ARGSUSED */ 18695903Ssowmini static dladm_status_t 1870*7342SAruna.Ramakrishna@Sun.COM i_dladm_speed_get(struct prop_desc *pd, datalink_id_t linkid, 18716512Ssowmini char **prop_val, uint_t *val_cnt, uint_t flags) 18725903Ssowmini { 18735903Ssowmini uint64_t ifspeed = 0; 18745903Ssowmini dladm_status_t status; 18755903Ssowmini 18766789Sam223141 if (flags & MAC_PROP_DEFAULT) 18776512Ssowmini return (DLADM_STATUS_NOTSUP); 18786512Ssowmini 18795903Ssowmini if ((status = dladm_get_single_mac_stat(linkid, "ifspeed", 18805903Ssowmini KSTAT_DATA_UINT64, &ifspeed)) != 0) 18815903Ssowmini return (status); 18826512Ssowmini 18835960Ssowmini if ((ifspeed % 1000000) != 0) { 18845960Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 18855960Ssowmini "%llf", ifspeed / (float)1000000); /* Mbps */ 18865960Ssowmini } else { 18875960Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, 18885960Ssowmini "%llu", ifspeed / 1000000); /* Mbps */ 18895960Ssowmini } 18905903Ssowmini *val_cnt = 1; 18915903Ssowmini return (DLADM_STATUS_OK); 18925903Ssowmini } 18935903Ssowmini 18945903Ssowmini /* ARGSUSED */ 18955903Ssowmini static dladm_status_t 1896*7342SAruna.Ramakrishna@Sun.COM i_dladm_status_get(struct prop_desc *pd, datalink_id_t linkid, 18976512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 18985903Ssowmini { 18996512Ssowmini link_state_t link_state; 19006512Ssowmini dladm_status_t status; 19016512Ssowmini uchar_t *cp; 19026789Sam223141 dld_ioc_macprop_t *dip; 19035903Ssowmini 19046789Sam223141 if (flags & MAC_PROP_DEFAULT) 19056512Ssowmini return (DLADM_STATUS_NOTSUP); 1906*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 19076512Ssowmini if (status != DLADM_STATUS_OK) 19085903Ssowmini return (status); 19096512Ssowmini cp = (uchar_t *)dip->pr_val; 19106512Ssowmini (void) memcpy(&link_state, cp, sizeof (link_state)); 19115903Ssowmini 19125903Ssowmini switch (link_state) { 19135903Ssowmini case LINK_STATE_UP: 19145903Ssowmini (void) strcpy(*prop_val, "up"); 19155903Ssowmini break; 19165903Ssowmini case LINK_STATE_DOWN: 19175903Ssowmini (void) strcpy(*prop_val, "down"); 19185903Ssowmini break; 19195903Ssowmini default: 19205903Ssowmini (void) strcpy(*prop_val, "unknown"); 19215903Ssowmini break; 19225903Ssowmini } 19235903Ssowmini *val_cnt = 1; 19246512Ssowmini free(dip); 19255903Ssowmini return (DLADM_STATUS_OK); 19265903Ssowmini } 19275903Ssowmini 19285903Ssowmini /* ARGSUSED */ 19295903Ssowmini static dladm_status_t 1930*7342SAruna.Ramakrishna@Sun.COM i_dladm_binary_get(struct prop_desc *pd, datalink_id_t linkid, 19316512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 19325903Ssowmini { 19336789Sam223141 dld_ioc_macprop_t *dip; 19345903Ssowmini dladm_status_t status; 19355903Ssowmini 1936*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 19376512Ssowmini if (dip == NULL) 19385903Ssowmini return (status); 19395903Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]); 19405903Ssowmini free(dip); 19415903Ssowmini *val_cnt = 1; 19425903Ssowmini return (DLADM_STATUS_OK); 19435903Ssowmini } 19445903Ssowmini 19455960Ssowmini /* ARGSUSED */ 19465903Ssowmini static dladm_status_t 1947*7342SAruna.Ramakrishna@Sun.COM i_dladm_uint32_get(struct prop_desc *pd, datalink_id_t linkid, 19486512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 19495903Ssowmini { 19506789Sam223141 dld_ioc_macprop_t *dip; 19516512Ssowmini uint32_t v = 0; 19525903Ssowmini uchar_t *cp; 19535903Ssowmini dladm_status_t status; 19545903Ssowmini 1955*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 19566512Ssowmini if (dip == NULL) 19575903Ssowmini return (status); 19585903Ssowmini cp = (uchar_t *)dip->pr_val; 19595903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 19606512Ssowmini (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v); 19615903Ssowmini free(dip); 19625903Ssowmini *val_cnt = 1; 19635903Ssowmini return (DLADM_STATUS_OK); 19645903Ssowmini } 19655903Ssowmini 19665960Ssowmini /* ARGSUSED */ 19675903Ssowmini static dladm_status_t 1968*7342SAruna.Ramakrishna@Sun.COM i_dladm_flowctl_get(struct prop_desc *pd, datalink_id_t linkid, 19696512Ssowmini char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) 19705903Ssowmini { 19716789Sam223141 dld_ioc_macprop_t *dip; 19725903Ssowmini link_flowctrl_t v; 19735903Ssowmini dladm_status_t status; 19745903Ssowmini uchar_t *cp; 19755903Ssowmini 1976*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status); 19776512Ssowmini if (dip == NULL) 19785903Ssowmini return (status); 19795903Ssowmini cp = (uchar_t *)dip->pr_val; 19805903Ssowmini (void) memcpy(&v, cp, sizeof (v)); 19815903Ssowmini switch (v) { 19825903Ssowmini case LINK_FLOWCTRL_NONE: 19835903Ssowmini (void) sprintf(*prop_val, "no"); 19845903Ssowmini break; 19855903Ssowmini case LINK_FLOWCTRL_RX: 19865903Ssowmini (void) sprintf(*prop_val, "rx"); 19875903Ssowmini break; 19885903Ssowmini case LINK_FLOWCTRL_TX: 19895903Ssowmini (void) sprintf(*prop_val, "tx"); 19905903Ssowmini break; 19915903Ssowmini case LINK_FLOWCTRL_BI: 19925903Ssowmini (void) sprintf(*prop_val, "bi"); 19935903Ssowmini break; 19945903Ssowmini } 19955903Ssowmini free(dip); 19965903Ssowmini *val_cnt = 1; 19975903Ssowmini return (DLADM_STATUS_OK); 19985903Ssowmini } 19995903Ssowmini 20005903Ssowmini 20015903Ssowmini /* ARGSUSED */ 20025903Ssowmini static dladm_status_t 2003*7342SAruna.Ramakrishna@Sun.COM i_dladm_set_prop(datalink_id_t linkid, const char *prop_name, 20045903Ssowmini char **prop_val, uint_t val_cnt, uint_t flags) 20055903Ssowmini { 20065903Ssowmini int fd, i, slen; 20075903Ssowmini int bufsize = 0, dsize; 20086789Sam223141 dld_ioc_macprop_t *dip = NULL; 20095903Ssowmini uchar_t *dp; 2010*7342SAruna.Ramakrishna@Sun.COM dladm_public_prop_t *p; 20116512Ssowmini dladm_status_t status = DLADM_STATUS_OK; 20125903Ssowmini 20135903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 20145903Ssowmini (prop_val != NULL && val_cnt == 0)) 20155903Ssowmini return (DLADM_STATUS_BADARG); 20165903Ssowmini p = dladm_name2prop(prop_name); 20176789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 20185903Ssowmini return (DLADM_STATUS_BADARG); 20195903Ssowmini 20205903Ssowmini /* 20215903Ssowmini * private properties: all parsing is done in the kernel. 20225903Ssowmini * allocate a enough space for each property + its separator (','). 20235903Ssowmini */ 20245903Ssowmini for (i = 0; i < val_cnt; i++) { 20255903Ssowmini bufsize += strlen(prop_val[i]) + 1; 20265903Ssowmini } 20276512Ssowmini 20286512Ssowmini if (prop_val == NULL) { 20296512Ssowmini /* 20306512Ssowmini * getting default value. so use more buffer space. 20316512Ssowmini */ 20326512Ssowmini bufsize += 1024; 20336512Ssowmini } 20346512Ssowmini 2035*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_buf_alloc(bufsize + 1, linkid, prop_name, 20366789Sam223141 (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status); 20375903Ssowmini if (dip == NULL) 20385903Ssowmini return (status); 20395903Ssowmini 20405903Ssowmini dp = (uchar_t *)dip->pr_val; 20416789Sam223141 dsize = sizeof (dld_ioc_macprop_t) + bufsize; 20425903Ssowmini slen = 0; 20436512Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 20446512Ssowmini status = dladm_errno2status(errno); 20456512Ssowmini goto done; 20466512Ssowmini } 20476512Ssowmini if (prop_val == NULL) { 20486789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) { 20496512Ssowmini status = dladm_errno2status(errno); 20506512Ssowmini goto done; 20516512Ssowmini } 20526512Ssowmini } else { 20536512Ssowmini for (i = 0; i < val_cnt; i++) { 20546512Ssowmini int plen = 0; 20555903Ssowmini 20566512Ssowmini plen = strlen(prop_val[i]); 20576512Ssowmini bcopy(prop_val[i], dp, plen); 20586512Ssowmini slen += plen; 20596512Ssowmini /* 20606512Ssowmini * add a "," separator and update dp. 20616512Ssowmini */ 20626512Ssowmini if (i != (val_cnt -1)) 20636512Ssowmini dp[slen++] = ','; 20646512Ssowmini dp += (plen + 1); 20656512Ssowmini } 20665903Ssowmini } 20676789Sam223141 if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) { 20686512Ssowmini status = dladm_errno2status(errno); 20695903Ssowmini } 20706512Ssowmini 20716512Ssowmini done: 20726512Ssowmini if (fd > 0) 20736512Ssowmini (void) close(fd); 20745903Ssowmini free(dip); 20756512Ssowmini return (status); 20765903Ssowmini } 20775903Ssowmini 20785903Ssowmini static dladm_status_t 2079*7342SAruna.Ramakrishna@Sun.COM i_dladm_get_prop(datalink_id_t linkid, const char *prop_name, 20806512Ssowmini char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags) 20815903Ssowmini { 20825903Ssowmini int fd; 20835903Ssowmini dladm_status_t status = DLADM_STATUS_OK; 20845903Ssowmini uint_t dsize; 20856789Sam223141 dld_ioc_macprop_t *dip = NULL; 2086*7342SAruna.Ramakrishna@Sun.COM dladm_public_prop_t *p; 20875903Ssowmini char tmp = '\0'; 20885903Ssowmini 20895903Ssowmini if ((prop_name == NULL && prop_val != NULL) || 20905903Ssowmini (prop_val != NULL && val_cnt == 0)) 20915903Ssowmini return (DLADM_STATUS_BADARG); 20925903Ssowmini 20935903Ssowmini p = dladm_name2prop(prop_name); 20946789Sam223141 if (p->pp_id != MAC_PROP_PRIVATE) 20955903Ssowmini return (DLADM_STATUS_BADARG); 20965903Ssowmini 20976512Ssowmini if (type == DLADM_PROP_VAL_MODIFIABLE) { 20985903Ssowmini *prop_val = &tmp; 20995903Ssowmini *val_cnt = 1; 21005903Ssowmini return (DLADM_STATUS_OK); 21015903Ssowmini } 21025903Ssowmini 21035903Ssowmini /* 21045903Ssowmini * private properties: all parsing is done in the kernel. 21055903Ssowmini */ 2106*7342SAruna.Ramakrishna@Sun.COM dip = i_dladm_buf_alloc(1024, linkid, prop_name, dld_flags, &status); 21075903Ssowmini if (dip == NULL) 21085903Ssowmini return (status); 21096789Sam223141 dsize = MAC_PROP_BUFSIZE(dip->pr_valsize); 21105903Ssowmini 21116512Ssowmini if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { 21126512Ssowmini free(dip); 21135903Ssowmini return (DLADM_STATUS_BADARG); 21146512Ssowmini } 21155903Ssowmini 21166789Sam223141 if ((status = i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize)) < 0) { 21175903Ssowmini status = dladm_errno2status(errno); 21185903Ssowmini } else { 21195903Ssowmini (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); 21205903Ssowmini *val_cnt = 1; 21215903Ssowmini } 21226512Ssowmini 21236512Ssowmini (void) close(fd); 21246512Ssowmini free(dip); 21255903Ssowmini return (status); 21265903Ssowmini } 21276512Ssowmini 21286512Ssowmini 21296512Ssowmini static dladm_status_t 21306512Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid, 21316512Ssowmini datalink_media_t media, uint_t flags) 21326512Ssowmini { 21336512Ssowmini dladm_status_t status; 21346512Ssowmini char **prop_vals = NULL, *buf; 21356512Ssowmini size_t bufsize; 21366512Ssowmini uint_t cnt; 21376512Ssowmini int i; 21386512Ssowmini 21396512Ssowmini /* 21406512Ssowmini * Allocate buffer needed for prop_vals array. We can have at most 21416512Ssowmini * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where 21426512Ssowmini * each entry has max size DLADM_PROP_VAL_MAX 21436512Ssowmini */ 21446512Ssowmini bufsize = 21456512Ssowmini (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 21466512Ssowmini buf = malloc(bufsize); 21476512Ssowmini prop_vals = (char **)(void *)buf; 21486512Ssowmini for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 21496512Ssowmini prop_vals[i] = buf + 21506512Ssowmini sizeof (char *) * DLADM_MAX_PROP_VALCNT + 21516512Ssowmini i * DLADM_PROP_VAL_MAX; 21526512Ssowmini } 21536768Sar224390 21546768Sar224390 /* 2155*7342SAruna.Ramakrishna@Sun.COM * For properties which have pdp->pd_defval.vd_name as a non-empty 2156*7342SAruna.Ramakrishna@Sun.COM * string, the "" itself is used to reset the property (exceptions 2157*7342SAruna.Ramakrishna@Sun.COM * are zone and autopush, which populate vdp->vd_val). So 2158*7342SAruna.Ramakrishna@Sun.COM * libdladm can copy pdp->pd_defval over to the val_desc_t passed 2159*7342SAruna.Ramakrishna@Sun.COM * down on the setprop using the global values in the table. For 2160*7342SAruna.Ramakrishna@Sun.COM * other cases (vd_name is ""), doing reset-linkprop will cause 2161*7342SAruna.Ramakrishna@Sun.COM * libdladm to do a getprop to find the default value and then do 2162*7342SAruna.Ramakrishna@Sun.COM * a setprop to reset the value to default. 21636768Sar224390 */ 21646789Sam223141 status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media, 21656789Sam223141 MAC_PROP_DEFAULT); 21666512Ssowmini if (status == DLADM_STATUS_OK) { 21676512Ssowmini status = i_dladm_set_single_prop(linkid, pdp->pd_class, 21686512Ssowmini media, pdp, prop_vals, cnt, flags); 21696512Ssowmini } 21706512Ssowmini free(buf); 21716512Ssowmini return (status); 21726512Ssowmini } 2173