10ba2cbe9Sxc151355 /* 20ba2cbe9Sxc151355 * CDDL HEADER START 30ba2cbe9Sxc151355 * 40ba2cbe9Sxc151355 * The contents of this file are subject to the terms of the 50ba2cbe9Sxc151355 * Common Development and Distribution License (the "License"). 60ba2cbe9Sxc151355 * You may not use this file except in compliance with the License. 70ba2cbe9Sxc151355 * 80ba2cbe9Sxc151355 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90ba2cbe9Sxc151355 * or http://www.opensolaris.org/os/licensing. 100ba2cbe9Sxc151355 * See the License for the specific language governing permissions 110ba2cbe9Sxc151355 * and limitations under the License. 120ba2cbe9Sxc151355 * 130ba2cbe9Sxc151355 * When distributing Covered Code, include this CDDL HEADER in each 140ba2cbe9Sxc151355 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150ba2cbe9Sxc151355 * If applicable, add the following below this CDDL HEADER, with the 160ba2cbe9Sxc151355 * fields enclosed by brackets "[]" replaced with your own identifying 170ba2cbe9Sxc151355 * information: Portions Copyright [yyyy] [name of copyright owner] 180ba2cbe9Sxc151355 * 190ba2cbe9Sxc151355 * CDDL HEADER END 200ba2cbe9Sxc151355 */ 210ba2cbe9Sxc151355 /* 22*d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230ba2cbe9Sxc151355 * Use is subject to license terms. 240ba2cbe9Sxc151355 */ 250ba2cbe9Sxc151355 260ba2cbe9Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 270ba2cbe9Sxc151355 280ba2cbe9Sxc151355 #include <stdlib.h> 290ba2cbe9Sxc151355 #include <strings.h> 300ba2cbe9Sxc151355 #include <errno.h> 310ba2cbe9Sxc151355 #include <ctype.h> 32*d62bc4baSyz147064 #include <stddef.h> 33f4b3ec61Sdh155122 #include <sys/types.h> 340ba2cbe9Sxc151355 #include <sys/stat.h> 35f4b3ec61Sdh155122 #include <sys/dld.h> 36f4b3ec61Sdh155122 #include <sys/zone.h> 37f4b3ec61Sdh155122 #include <fcntl.h> 38f4b3ec61Sdh155122 #include <unistd.h> 39f4b3ec61Sdh155122 #include <libdevinfo.h> 40f4b3ec61Sdh155122 #include <zone.h> 41f595a68aSyz147064 #include <libdllink.h> 420ba2cbe9Sxc151355 #include <libdladm_impl.h> 43*d62bc4baSyz147064 #include <libdlwlan_impl.h> 44f595a68aSyz147064 #include <libdlwlan.h> 45*d62bc4baSyz147064 #include <libdlvlan.h> 46f4b3ec61Sdh155122 #include <dlfcn.h> 47f4b3ec61Sdh155122 #include <link.h> 48*d62bc4baSyz147064 #include <inet/wifi_ioctl.h> 49f4b3ec61Sdh155122 50*d62bc4baSyz147064 /* 51*d62bc4baSyz147064 * The linkprop get() callback. 52*d62bc4baSyz147064 * - propstrp: a property string array to keep the returned property. 53*d62bc4baSyz147064 * Caller allocated. 54*d62bc4baSyz147064 * - cntp: number of returned properties. 55*d62bc4baSyz147064 * Caller also uses it to indicate how many it expects. 56*d62bc4baSyz147064 */ 57*d62bc4baSyz147064 typedef dladm_status_t pd_getf_t(datalink_id_t, char **propstp, uint_t *cntp); 58f4b3ec61Sdh155122 59*d62bc4baSyz147064 /* 60*d62bc4baSyz147064 * The linkprop set() callback. 61*d62bc4baSyz147064 * - propval: a val_desc_t array which keeps the property values to be set. 62*d62bc4baSyz147064 * - cnt: number of properties to be set. 63*d62bc4baSyz147064 */ 64*d62bc4baSyz147064 typedef dladm_status_t pd_setf_t(datalink_id_t, val_desc_t *propval, 65*d62bc4baSyz147064 uint_t cnt); 66f4b3ec61Sdh155122 67*d62bc4baSyz147064 #define PD_TEMPONLY 0x1 68f4b3ec61Sdh155122 69*d62bc4baSyz147064 /* 70*d62bc4baSyz147064 * The linkprop check() callback. 71*d62bc4baSyz147064 * - propstrp: property string array which keeps the property to be checked. 72*d62bc4baSyz147064 * - cnt: number of properties. 73*d62bc4baSyz147064 * - propval: return value; the property values of the given property strings. 74*d62bc4baSyz147064 * - dofree: indicates whether the caller needs to free propvalp->vd_val. 75*d62bc4baSyz147064 */ 76*d62bc4baSyz147064 typedef dladm_status_t pd_checkf_t(datalink_id_t, char **propstrp, 77*d62bc4baSyz147064 uint_t cnt, val_desc_t *propval, boolean_t *dofree); 78f4b3ec61Sdh155122 79*d62bc4baSyz147064 static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, 80*d62bc4baSyz147064 do_get_rate_prop, do_get_channel_prop, 81*d62bc4baSyz147064 do_get_powermode_prop, do_get_radio_prop; 82*d62bc4baSyz147064 static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop, 83*d62bc4baSyz147064 do_set_powermode_prop, do_set_radio_prop; 84*d62bc4baSyz147064 static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate; 85f4b3ec61Sdh155122 86f4b3ec61Sdh155122 typedef struct prop_desc { 87*d62bc4baSyz147064 /* 88*d62bc4baSyz147064 * link property name 89*d62bc4baSyz147064 */ 90f4b3ec61Sdh155122 char *pd_name; 91*d62bc4baSyz147064 92*d62bc4baSyz147064 /* 93*d62bc4baSyz147064 * default property value, can be set to { "", NULL } 94*d62bc4baSyz147064 */ 95f4b3ec61Sdh155122 val_desc_t pd_defval; 96*d62bc4baSyz147064 97*d62bc4baSyz147064 /* 98*d62bc4baSyz147064 * list of optional property values, can be NULL. 99*d62bc4baSyz147064 * 100*d62bc4baSyz147064 * This is set to non-NULL if there is a list of possible property 101*d62bc4baSyz147064 * values. pd_optval would point to the array of possible values. 102*d62bc4baSyz147064 */ 103*d62bc4baSyz147064 val_desc_t *pd_optval; 104*d62bc4baSyz147064 105*d62bc4baSyz147064 /* 106*d62bc4baSyz147064 * count of the above optional property values. 0 if pd_optval is NULL. 107*d62bc4baSyz147064 */ 108*d62bc4baSyz147064 uint_t pd_noptval; 109*d62bc4baSyz147064 110*d62bc4baSyz147064 /* 111*d62bc4baSyz147064 * callback to set link property; 112*d62bc4baSyz147064 * set to NULL if this property is read-only 113*d62bc4baSyz147064 */ 114f4b3ec61Sdh155122 pd_setf_t *pd_set; 115*d62bc4baSyz147064 116*d62bc4baSyz147064 /* 117*d62bc4baSyz147064 * callback to get modifiable link property 118*d62bc4baSyz147064 */ 119f4b3ec61Sdh155122 pd_getf_t *pd_getmod; 120*d62bc4baSyz147064 121*d62bc4baSyz147064 /* 122*d62bc4baSyz147064 * callback to get current link property 123*d62bc4baSyz147064 */ 124f4b3ec61Sdh155122 pd_getf_t *pd_get; 125*d62bc4baSyz147064 126*d62bc4baSyz147064 /* 127*d62bc4baSyz147064 * callback to validate link property value, set to NULL if pd_optval 128*d62bc4baSyz147064 * is not NULL. In that case, validate the value by comparing it with 129*d62bc4baSyz147064 * the pd_optval. Return a val_desc_t array pointer if the value is 130*d62bc4baSyz147064 * valid. 131*d62bc4baSyz147064 */ 132f4b3ec61Sdh155122 pd_checkf_t *pd_check; 133*d62bc4baSyz147064 134*d62bc4baSyz147064 /* 135*d62bc4baSyz147064 * currently only PD_TEMPONLY is valid, which indicates the property 136*d62bc4baSyz147064 * is temporary only. 137*d62bc4baSyz147064 */ 138*d62bc4baSyz147064 uint_t pd_flags; 139*d62bc4baSyz147064 140*d62bc4baSyz147064 /* 141*d62bc4baSyz147064 * indicate link classes this property applies to. 142*d62bc4baSyz147064 */ 143*d62bc4baSyz147064 datalink_class_t pd_class; 144*d62bc4baSyz147064 145*d62bc4baSyz147064 /* 146*d62bc4baSyz147064 * indicate link media type this property applies to. 147*d62bc4baSyz147064 */ 148*d62bc4baSyz147064 datalink_media_t pd_dmedia; 149f4b3ec61Sdh155122 } prop_desc_t; 150f4b3ec61Sdh155122 151*d62bc4baSyz147064 static val_desc_t dladm_wlan_radio_vals[] = { 152*d62bc4baSyz147064 { "on", DLADM_WLAN_RADIO_ON }, 153*d62bc4baSyz147064 { "off", DLADM_WLAN_RADIO_OFF } 154*d62bc4baSyz147064 }; 155*d62bc4baSyz147064 156*d62bc4baSyz147064 static val_desc_t dladm_wlan_powermode_vals[] = { 157*d62bc4baSyz147064 { "off", DLADM_WLAN_PM_OFF }, 158*d62bc4baSyz147064 { "fast", DLADM_WLAN_PM_FAST }, 159*d62bc4baSyz147064 { "max", DLADM_WLAN_PM_MAX } 160*d62bc4baSyz147064 }; 161*d62bc4baSyz147064 162f4b3ec61Sdh155122 static prop_desc_t prop_table[] = { 163*d62bc4baSyz147064 164*d62bc4baSyz147064 { "channel", { NULL, 0 }, NULL, 0, NULL, NULL, 165*d62bc4baSyz147064 do_get_channel_prop, NULL, 0, 166*d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI}, 167*d62bc4baSyz147064 168*d62bc4baSyz147064 { "powermode", { "off", DLADM_WLAN_PM_OFF }, 169*d62bc4baSyz147064 dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals), 170*d62bc4baSyz147064 do_set_powermode_prop, NULL, 171*d62bc4baSyz147064 do_get_powermode_prop, NULL, 0, 172*d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI}, 173*d62bc4baSyz147064 174*d62bc4baSyz147064 { "radio", { "on", DLADM_WLAN_RADIO_ON }, 175*d62bc4baSyz147064 dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals), 176*d62bc4baSyz147064 do_set_radio_prop, NULL, 177*d62bc4baSyz147064 do_get_radio_prop, NULL, 0, 178*d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI}, 179*d62bc4baSyz147064 180*d62bc4baSyz147064 { "speed", { "", 0 }, NULL, 0, 181*d62bc4baSyz147064 do_set_rate_prop, do_get_rate_mod, 182*d62bc4baSyz147064 do_get_rate_prop, do_check_rate, 0, 183*d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI}, 184*d62bc4baSyz147064 185*d62bc4baSyz147064 { "autopush", { "", NULL }, NULL, 0, 186*d62bc4baSyz147064 do_set_autopush, NULL, 187*d62bc4baSyz147064 do_get_autopush, do_check_autopush, 0, 188*d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE}, 189*d62bc4baSyz147064 190*d62bc4baSyz147064 { "zone", { "", NULL }, NULL, 0, 191f4b3ec61Sdh155122 do_set_zone, NULL, 192*d62bc4baSyz147064 do_get_zone, do_check_zone, PD_TEMPONLY, 193*d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE} 194f4b3ec61Sdh155122 }; 195f4b3ec61Sdh155122 196*d62bc4baSyz147064 #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 1970ba2cbe9Sxc151355 198*d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, 199*d62bc4baSyz147064 char **, uint_t); 200*d62bc4baSyz147064 static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, 201*d62bc4baSyz147064 char **, uint_t *); 202*d62bc4baSyz147064 static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t, 203*d62bc4baSyz147064 uint32_t, prop_desc_t *, char **, uint_t, uint_t); 204*d62bc4baSyz147064 static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *, 205*d62bc4baSyz147064 char **, uint_t, uint_t); 206*d62bc4baSyz147064 207*d62bc4baSyz147064 /* 208*d62bc4baSyz147064 * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all 209*d62bc4baSyz147064 * rates to be retrieved. However, we cannot increase it at this 210*d62bc4baSyz147064 * time because it will break binary compatibility with unbundled 211*d62bc4baSyz147064 * WiFi drivers and utilities. So for now we define an additional 212*d62bc4baSyz147064 * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved. 213*d62bc4baSyz147064 */ 214*d62bc4baSyz147064 #define MAX_SUPPORT_RATES 64 215*d62bc4baSyz147064 216*d62bc4baSyz147064 #define AP_ANCHOR "[anchor]" 217*d62bc4baSyz147064 #define AP_DELIMITER '.' 218*d62bc4baSyz147064 219*d62bc4baSyz147064 static dladm_status_t 220*d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 221*d62bc4baSyz147064 val_desc_t *vdp) 2220ba2cbe9Sxc151355 { 223*d62bc4baSyz147064 int i, j; 2240ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 2250ba2cbe9Sxc151355 226*d62bc4baSyz147064 for (j = 0; j < val_cnt; j++) { 227*d62bc4baSyz147064 for (i = 0; i < pdp->pd_noptval; i++) { 228*d62bc4baSyz147064 if (strcasecmp(*prop_val, 229*d62bc4baSyz147064 pdp->pd_optval[i].vd_name) == 0) { 2300ba2cbe9Sxc151355 break; 2310ba2cbe9Sxc151355 } 2320ba2cbe9Sxc151355 } 233*d62bc4baSyz147064 if (i == pdp->pd_noptval) { 234*d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 235*d62bc4baSyz147064 goto done; 236*d62bc4baSyz147064 } 237*d62bc4baSyz147064 (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t)); 2380ba2cbe9Sxc151355 } 2390ba2cbe9Sxc151355 240*d62bc4baSyz147064 done: 241*d62bc4baSyz147064 return (status); 2420ba2cbe9Sxc151355 } 2430ba2cbe9Sxc151355 2440ba2cbe9Sxc151355 static dladm_status_t 245*d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class, 246*d62bc4baSyz147064 uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 247*d62bc4baSyz147064 uint_t flags) 2480ba2cbe9Sxc151355 { 2490ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 250*d62bc4baSyz147064 val_desc_t *vdp = NULL; 251*d62bc4baSyz147064 boolean_t needfree = B_FALSE; 252*d62bc4baSyz147064 uint_t cnt, i; 2530ba2cbe9Sxc151355 254*d62bc4baSyz147064 if (!(pdp->pd_class & class)) 255*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 2560ba2cbe9Sxc151355 257*d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 258*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 259*d62bc4baSyz147064 260*d62bc4baSyz147064 if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY)) 261*d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 262*d62bc4baSyz147064 263*d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE)) 264*d62bc4baSyz147064 return (DLADM_STATUS_OK); 265*d62bc4baSyz147064 266*d62bc4baSyz147064 if (pdp->pd_set == NULL) 267*d62bc4baSyz147064 return (DLADM_STATUS_PROPRDONLY); 268*d62bc4baSyz147064 269*d62bc4baSyz147064 if (prop_val != NULL) { 270*d62bc4baSyz147064 vdp = malloc(sizeof (val_desc_t) * val_cnt); 271*d62bc4baSyz147064 if (vdp == NULL) 272*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 273*d62bc4baSyz147064 274*d62bc4baSyz147064 if (pdp->pd_check != NULL) { 275*d62bc4baSyz147064 status = pdp->pd_check(linkid, prop_val, val_cnt, vdp, 276*d62bc4baSyz147064 &needfree); 277*d62bc4baSyz147064 } else if (pdp->pd_optval != NULL) { 278*d62bc4baSyz147064 status = do_check_prop(pdp, prop_val, val_cnt, vdp); 279*d62bc4baSyz147064 } else { 280*d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2810ba2cbe9Sxc151355 } 2820ba2cbe9Sxc151355 283*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 284*d62bc4baSyz147064 goto done; 285*d62bc4baSyz147064 286*d62bc4baSyz147064 cnt = val_cnt; 287*d62bc4baSyz147064 } else { 288*d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) 289*d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 290*d62bc4baSyz147064 291*d62bc4baSyz147064 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 292*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 293*d62bc4baSyz147064 294*d62bc4baSyz147064 (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t)); 295*d62bc4baSyz147064 cnt = 1; 296*d62bc4baSyz147064 } 297*d62bc4baSyz147064 status = pdp->pd_set(linkid, vdp, cnt); 298*d62bc4baSyz147064 if (needfree) { 299*d62bc4baSyz147064 for (i = 0; i < cnt; i++) 300*d62bc4baSyz147064 free((void *)(((val_desc_t *)vdp + i)->vd_val)); 301*d62bc4baSyz147064 } 302*d62bc4baSyz147064 done: 303*d62bc4baSyz147064 free(vdp); 304*d62bc4baSyz147064 return (status); 305*d62bc4baSyz147064 } 306*d62bc4baSyz147064 307*d62bc4baSyz147064 static dladm_status_t 308*d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, 309*d62bc4baSyz147064 char **prop_val, uint_t val_cnt, uint_t flags) 310*d62bc4baSyz147064 { 311*d62bc4baSyz147064 int i; 312*d62bc4baSyz147064 boolean_t found = B_FALSE; 313*d62bc4baSyz147064 datalink_class_t class; 314*d62bc4baSyz147064 uint32_t media; 315*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 316*d62bc4baSyz147064 317*d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 318*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3190ba2cbe9Sxc151355 return (status); 3200ba2cbe9Sxc151355 321*d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 322*d62bc4baSyz147064 prop_desc_t *pdp = &prop_table[i]; 323*d62bc4baSyz147064 dladm_status_t s; 3240ba2cbe9Sxc151355 325*d62bc4baSyz147064 if (prop_name != NULL && 326*d62bc4baSyz147064 (strcasecmp(prop_name, pdp->pd_name) != 0)) 327*d62bc4baSyz147064 continue; 328*d62bc4baSyz147064 329*d62bc4baSyz147064 found = B_TRUE; 330*d62bc4baSyz147064 s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val, 331*d62bc4baSyz147064 val_cnt, flags); 332*d62bc4baSyz147064 333*d62bc4baSyz147064 if (prop_name != NULL) { 334*d62bc4baSyz147064 status = s; 335*d62bc4baSyz147064 break; 336*d62bc4baSyz147064 } else { 337*d62bc4baSyz147064 if (s != DLADM_STATUS_OK && 338*d62bc4baSyz147064 s != DLADM_STATUS_NOTSUP) 339*d62bc4baSyz147064 status = s; 340*d62bc4baSyz147064 } 341*d62bc4baSyz147064 } 342*d62bc4baSyz147064 if (!found) 3430ba2cbe9Sxc151355 status = DLADM_STATUS_NOTFOUND; 3440ba2cbe9Sxc151355 3450ba2cbe9Sxc151355 return (status); 3460ba2cbe9Sxc151355 } 3470ba2cbe9Sxc151355 348*d62bc4baSyz147064 /* 349*d62bc4baSyz147064 * Set/reset link property for specific link 350*d62bc4baSyz147064 */ 351*d62bc4baSyz147064 dladm_status_t 352*d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val, 353*d62bc4baSyz147064 uint_t val_cnt, uint_t flags) 3540ba2cbe9Sxc151355 { 355*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 3560ba2cbe9Sxc151355 357*d62bc4baSyz147064 if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) || 358*d62bc4baSyz147064 (prop_val == NULL && val_cnt > 0) || 359*d62bc4baSyz147064 (prop_val != NULL && val_cnt == 0) || 360*d62bc4baSyz147064 (prop_name == NULL && prop_val != NULL)) { 361*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 3620ba2cbe9Sxc151355 } 3630ba2cbe9Sxc151355 364*d62bc4baSyz147064 status = i_dladm_set_linkprop(linkid, prop_name, prop_val, 365*d62bc4baSyz147064 val_cnt, flags); 366*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 367*d62bc4baSyz147064 return (status); 368*d62bc4baSyz147064 369*d62bc4baSyz147064 if (flags & DLADM_OPT_PERSIST) { 370*d62bc4baSyz147064 status = i_dladm_set_linkprop_db(linkid, prop_name, 371*d62bc4baSyz147064 prop_val, val_cnt); 372*d62bc4baSyz147064 } 373*d62bc4baSyz147064 return (status); 374*d62bc4baSyz147064 } 375*d62bc4baSyz147064 376*d62bc4baSyz147064 /* 377*d62bc4baSyz147064 * Walk link properties of the given specific link. 378*d62bc4baSyz147064 */ 379*d62bc4baSyz147064 dladm_status_t 380*d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg, 381*d62bc4baSyz147064 int (*func)(datalink_id_t, const char *, void *)) 3820ba2cbe9Sxc151355 { 383*d62bc4baSyz147064 dladm_status_t status; 384*d62bc4baSyz147064 datalink_class_t class; 385*d62bc4baSyz147064 uint_t media; 386*d62bc4baSyz147064 int i; 3870ba2cbe9Sxc151355 388*d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || func == NULL) 389*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 3900ba2cbe9Sxc151355 391*d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 392*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 393*d62bc4baSyz147064 return (status); 394*d62bc4baSyz147064 395*d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) { 396*d62bc4baSyz147064 if (!(prop_table[i].pd_class & class)) 397*d62bc4baSyz147064 continue; 398*d62bc4baSyz147064 399*d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media)) 400*d62bc4baSyz147064 continue; 401*d62bc4baSyz147064 402*d62bc4baSyz147064 if (func(linkid, prop_table[i].pd_name, arg) == 403*d62bc4baSyz147064 DLADM_WALK_TERMINATE) { 404*d62bc4baSyz147064 break; 405*d62bc4baSyz147064 } 406*d62bc4baSyz147064 } 407*d62bc4baSyz147064 408*d62bc4baSyz147064 return (DLADM_STATUS_OK); 409*d62bc4baSyz147064 } 410*d62bc4baSyz147064 411*d62bc4baSyz147064 /* 412*d62bc4baSyz147064 * Get linkprop of the given specific link. 413*d62bc4baSyz147064 */ 414*d62bc4baSyz147064 dladm_status_t 415*d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type, 416*d62bc4baSyz147064 const char *prop_name, char **prop_val, uint_t *val_cntp) 417*d62bc4baSyz147064 { 418*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 419*d62bc4baSyz147064 datalink_class_t class; 420*d62bc4baSyz147064 uint_t media; 421*d62bc4baSyz147064 prop_desc_t *pdp; 422*d62bc4baSyz147064 uint_t cnt; 423*d62bc4baSyz147064 int i; 424*d62bc4baSyz147064 425*d62bc4baSyz147064 if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL || 426*d62bc4baSyz147064 prop_val == NULL || val_cntp == NULL || *val_cntp == 0) 427*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 428*d62bc4baSyz147064 429*d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROPS; i++) 430*d62bc4baSyz147064 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 431*d62bc4baSyz147064 break; 432*d62bc4baSyz147064 433*d62bc4baSyz147064 if (i == DLADM_MAX_PROPS) 434*d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 435*d62bc4baSyz147064 436*d62bc4baSyz147064 pdp = &prop_table[i]; 437*d62bc4baSyz147064 438*d62bc4baSyz147064 status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0); 439*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 440*d62bc4baSyz147064 return (status); 441*d62bc4baSyz147064 442*d62bc4baSyz147064 if (!(pdp->pd_class & class)) 443*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 444*d62bc4baSyz147064 445*d62bc4baSyz147064 if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media)) 446*d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 447*d62bc4baSyz147064 448*d62bc4baSyz147064 switch (type) { 449*d62bc4baSyz147064 case DLADM_PROP_VAL_CURRENT: 450*d62bc4baSyz147064 status = pdp->pd_get(linkid, prop_val, val_cntp); 451*d62bc4baSyz147064 break; 452*d62bc4baSyz147064 453*d62bc4baSyz147064 case DLADM_PROP_VAL_DEFAULT: 454*d62bc4baSyz147064 if (pdp->pd_defval.vd_name == NULL) { 455*d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 456*d62bc4baSyz147064 break; 457*d62bc4baSyz147064 } 458*d62bc4baSyz147064 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 459*d62bc4baSyz147064 *val_cntp = 1; 460*d62bc4baSyz147064 break; 461*d62bc4baSyz147064 462*d62bc4baSyz147064 case DLADM_PROP_VAL_MODIFIABLE: 463*d62bc4baSyz147064 if (pdp->pd_getmod != NULL) { 464*d62bc4baSyz147064 status = pdp->pd_getmod(linkid, prop_val, val_cntp); 465*d62bc4baSyz147064 break; 466*d62bc4baSyz147064 } 467*d62bc4baSyz147064 cnt = pdp->pd_noptval; 468*d62bc4baSyz147064 if (cnt == 0) { 469*d62bc4baSyz147064 status = DLADM_STATUS_NOTSUP; 470*d62bc4baSyz147064 } else if (cnt > *val_cntp) { 471*d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 472*d62bc4baSyz147064 } else { 473*d62bc4baSyz147064 for (i = 0; i < cnt; i++) { 474*d62bc4baSyz147064 (void) strcpy(prop_val[i], 475*d62bc4baSyz147064 pdp->pd_optval[i].vd_name); 476*d62bc4baSyz147064 } 477*d62bc4baSyz147064 *val_cntp = cnt; 478*d62bc4baSyz147064 } 479*d62bc4baSyz147064 break; 480*d62bc4baSyz147064 case DLADM_PROP_VAL_PERSISTENT: 481*d62bc4baSyz147064 if (pdp->pd_flags & PD_TEMPONLY) 482*d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 483*d62bc4baSyz147064 status = i_dladm_get_linkprop_db(linkid, prop_name, 484*d62bc4baSyz147064 prop_val, val_cntp); 485*d62bc4baSyz147064 break; 486*d62bc4baSyz147064 default: 487*d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 488*d62bc4baSyz147064 break; 489*d62bc4baSyz147064 } 490*d62bc4baSyz147064 491*d62bc4baSyz147064 return (status); 492*d62bc4baSyz147064 } 493*d62bc4baSyz147064 494*d62bc4baSyz147064 /*ARGSUSED*/ 495*d62bc4baSyz147064 static int 496*d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg) 497*d62bc4baSyz147064 { 498*d62bc4baSyz147064 char *buf, **propvals; 499*d62bc4baSyz147064 uint_t i, valcnt = DLADM_MAX_PROP_VALCNT; 500*d62bc4baSyz147064 501*d62bc4baSyz147064 if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 502*d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT)) == NULL) { 503*d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 504*d62bc4baSyz147064 } 505*d62bc4baSyz147064 506*d62bc4baSyz147064 propvals = (char **)(void *)buf; 507*d62bc4baSyz147064 for (i = 0; i < valcnt; i++) { 508*d62bc4baSyz147064 propvals[i] = buf + 509*d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 510*d62bc4baSyz147064 i * DLADM_PROP_VAL_MAX; 511*d62bc4baSyz147064 } 512*d62bc4baSyz147064 513*d62bc4baSyz147064 if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name, 514*d62bc4baSyz147064 propvals, &valcnt) != DLADM_STATUS_OK) { 515*d62bc4baSyz147064 goto done; 516*d62bc4baSyz147064 } 517*d62bc4baSyz147064 518*d62bc4baSyz147064 (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt, 519*d62bc4baSyz147064 DLADM_OPT_ACTIVE); 520*d62bc4baSyz147064 521*d62bc4baSyz147064 done: 522*d62bc4baSyz147064 if (buf != NULL) 523*d62bc4baSyz147064 free(buf); 524*d62bc4baSyz147064 525*d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 526*d62bc4baSyz147064 } 527*d62bc4baSyz147064 528*d62bc4baSyz147064 /*ARGSUSED*/ 529*d62bc4baSyz147064 static int 530*d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 531*d62bc4baSyz147064 { 532*d62bc4baSyz147064 (void) dladm_init_linkprop(linkid); 533*d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5340ba2cbe9Sxc151355 } 5350ba2cbe9Sxc151355 5360ba2cbe9Sxc151355 dladm_status_t 537*d62bc4baSyz147064 dladm_init_linkprop(datalink_id_t linkid) 5380ba2cbe9Sxc151355 { 539*d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 540*d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 541*d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 542*d62bc4baSyz147064 DLADM_OPT_PERSIST); 543*d62bc4baSyz147064 } else { 544*d62bc4baSyz147064 (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop); 545*d62bc4baSyz147064 } 546*d62bc4baSyz147064 return (DLADM_STATUS_OK); 5470ba2cbe9Sxc151355 } 548f4b3ec61Sdh155122 549f4b3ec61Sdh155122 static dladm_status_t 550*d62bc4baSyz147064 do_get_zone(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 551f4b3ec61Sdh155122 { 552*d62bc4baSyz147064 char zone_name[ZONENAME_MAX]; 553*d62bc4baSyz147064 zoneid_t zid; 554*d62bc4baSyz147064 dladm_status_t status; 555f4b3ec61Sdh155122 556*d62bc4baSyz147064 status = dladm_getzid(linkid, &zid); 557*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 558*d62bc4baSyz147064 return (status); 559*d62bc4baSyz147064 560*d62bc4baSyz147064 *val_cnt = 1; 561*d62bc4baSyz147064 if (zid != GLOBAL_ZONEID) { 562*d62bc4baSyz147064 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 563f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 564f4b3ec61Sdh155122 565*d62bc4baSyz147064 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 56647a01978Sbw } else { 567*d62bc4baSyz147064 *prop_val[0] = '\0'; 56847a01978Sbw } 569f4b3ec61Sdh155122 570f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 571f4b3ec61Sdh155122 } 572f4b3ec61Sdh155122 573f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 574f4b3ec61Sdh155122 575f4b3ec61Sdh155122 static int 576f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 577f4b3ec61Sdh155122 { 578f4b3ec61Sdh155122 char root[MAXPATHLEN]; 579f4b3ec61Sdh155122 zone_get_devroot_t real_zone_get_devroot; 580f4b3ec61Sdh155122 void *dlhandle; 581f4b3ec61Sdh155122 void *sym; 582f4b3ec61Sdh155122 int ret; 583f4b3ec61Sdh155122 584f4b3ec61Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 585f4b3ec61Sdh155122 return (-1); 586f4b3ec61Sdh155122 587f4b3ec61Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 588f4b3ec61Sdh155122 (void) dlclose(dlhandle); 589f4b3ec61Sdh155122 return (-1); 590f4b3ec61Sdh155122 } 591f4b3ec61Sdh155122 592f4b3ec61Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 593f4b3ec61Sdh155122 594f4b3ec61Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 595f4b3ec61Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 596f4b3ec61Sdh155122 (void) dlclose(dlhandle); 597f4b3ec61Sdh155122 return (ret); 598f4b3ec61Sdh155122 } 599f4b3ec61Sdh155122 600f4b3ec61Sdh155122 static dladm_status_t 601*d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add) 602f4b3ec61Sdh155122 { 603f4b3ec61Sdh155122 char path[MAXPATHLEN]; 604*d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 605f4b3ec61Sdh155122 di_prof_t prof = NULL; 606f4b3ec61Sdh155122 char zone_name[ZONENAME_MAX]; 607f4b3ec61Sdh155122 dladm_status_t status; 608*d62bc4baSyz147064 int ret; 609f4b3ec61Sdh155122 610f4b3ec61Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 611f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 612f4b3ec61Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 613f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 614f4b3ec61Sdh155122 if (di_prof_init(path, &prof) != 0) 615f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 616f4b3ec61Sdh155122 617*d62bc4baSyz147064 status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN); 618f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 619*d62bc4baSyz147064 goto cleanup; 620f4b3ec61Sdh155122 621*d62bc4baSyz147064 if (add) 622*d62bc4baSyz147064 ret = di_prof_add_dev(prof, name); 623*d62bc4baSyz147064 else 624*d62bc4baSyz147064 ret = di_prof_add_exclude(prof, name); 625f4b3ec61Sdh155122 626*d62bc4baSyz147064 if (ret != 0) { 627*d62bc4baSyz147064 status = dladm_errno2status(errno); 628*d62bc4baSyz147064 goto cleanup; 629f4b3ec61Sdh155122 } 630f4b3ec61Sdh155122 631*d62bc4baSyz147064 if (di_prof_commit(prof) != 0) 632*d62bc4baSyz147064 status = dladm_errno2status(errno); 633*d62bc4baSyz147064 cleanup: 634*d62bc4baSyz147064 if (prof) 635*d62bc4baSyz147064 di_prof_fini(prof); 636*d62bc4baSyz147064 637*d62bc4baSyz147064 return (status); 638f4b3ec61Sdh155122 } 639f4b3ec61Sdh155122 640f4b3ec61Sdh155122 static dladm_status_t 641*d62bc4baSyz147064 do_set_zone(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt) 642f4b3ec61Sdh155122 { 643f4b3ec61Sdh155122 dladm_status_t status; 644f4b3ec61Sdh155122 zoneid_t zid_old, zid_new; 645*d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 646f4b3ec61Sdh155122 647f4b3ec61Sdh155122 if (val_cnt != 1) 648f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 649f4b3ec61Sdh155122 650*d62bc4baSyz147064 status = dladm_getzid(linkid, &zid_old); 651f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 652f4b3ec61Sdh155122 return (status); 653f4b3ec61Sdh155122 654f4b3ec61Sdh155122 /* Do nothing if setting to current value */ 655*d62bc4baSyz147064 zid_new = vdp->vd_val; 656f4b3ec61Sdh155122 if (zid_new == zid_old) 657f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 658f4b3ec61Sdh155122 659*d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, 660*d62bc4baSyz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 661*d62bc4baSyz147064 return (status); 662*d62bc4baSyz147064 } 663f4b3ec61Sdh155122 664*d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 665*d62bc4baSyz147064 /* 666*d62bc4baSyz147064 * If the new zoneid is the global zone, we could destroy 667*d62bc4baSyz147064 * the link (in the case of an implicitly-created VLAN) as a 668*d62bc4baSyz147064 * result of the dladm_setzid() operation. In that case, 669*d62bc4baSyz147064 * we defer the operation to the end of this function to avoid 670*d62bc4baSyz147064 * recreating the VLAN and getting a different linkid during 671*d62bc4baSyz147064 * the rollback if other operation fails. 672*d62bc4baSyz147064 * 673*d62bc4baSyz147064 * Otherwise, dladm_setzid() will hold a reference to the 674*d62bc4baSyz147064 * link and prevent a link renaming, so we need to do it 675*d62bc4baSyz147064 * before other operations. 676*d62bc4baSyz147064 */ 677*d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 678*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 679*d62bc4baSyz147064 return (status); 680*d62bc4baSyz147064 } 681*d62bc4baSyz147064 682*d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) { 683*d62bc4baSyz147064 if (zone_remove_datalink(zid_old, link) != 0 && 684f4b3ec61Sdh155122 errno != ENXIO) { 685f4b3ec61Sdh155122 status = dladm_errno2status(errno); 686f4b3ec61Sdh155122 goto rollback1; 687f4b3ec61Sdh155122 } 688f4b3ec61Sdh155122 689*d62bc4baSyz147064 /* 690*d62bc4baSyz147064 * It is okay to fail to update the /dev entry (some 691*d62bc4baSyz147064 * vanity-named links do not have a /dev entry). 692*d62bc4baSyz147064 */ 693*d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE); 694*d62bc4baSyz147064 } 695*d62bc4baSyz147064 696*d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) { 697*d62bc4baSyz147064 if (zone_add_datalink(zid_new, link) != 0) { 698*d62bc4baSyz147064 status = dladm_errno2status(errno); 699*d62bc4baSyz147064 goto rollback2; 700*d62bc4baSyz147064 } 701*d62bc4baSyz147064 702*d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE); 703*d62bc4baSyz147064 } else { 704*d62bc4baSyz147064 status = dladm_setzid(link, zid_new); 705f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 706f4b3ec61Sdh155122 goto rollback2; 707f4b3ec61Sdh155122 } 708f4b3ec61Sdh155122 709f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 710f4b3ec61Sdh155122 711f4b3ec61Sdh155122 rollback2: 712f4b3ec61Sdh155122 if (zid_old != GLOBAL_ZONEID) 713*d62bc4baSyz147064 (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE); 714*d62bc4baSyz147064 if (zid_old != GLOBAL_ZONEID) 715*d62bc4baSyz147064 (void) zone_add_datalink(zid_old, link); 716f4b3ec61Sdh155122 rollback1: 717*d62bc4baSyz147064 if (zid_new != GLOBAL_ZONEID) 718*d62bc4baSyz147064 (void) dladm_setzid(link, zid_old); 719f4b3ec61Sdh155122 return (status); 720f4b3ec61Sdh155122 } 721f4b3ec61Sdh155122 722f4b3ec61Sdh155122 /* ARGSUSED */ 723f4b3ec61Sdh155122 static dladm_status_t 724*d62bc4baSyz147064 do_check_zone(datalink_id_t linkid, char **prop_val, uint_t val_cnt, 725*d62bc4baSyz147064 val_desc_t *vdp, boolean_t *needfreep) 726f4b3ec61Sdh155122 { 727f4b3ec61Sdh155122 zoneid_t zid; 728f4b3ec61Sdh155122 729f4b3ec61Sdh155122 if (val_cnt != 1) 730f4b3ec61Sdh155122 return (DLADM_STATUS_BADVALCNT); 731f4b3ec61Sdh155122 732f4b3ec61Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 733f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 734f4b3ec61Sdh155122 735f4b3ec61Sdh155122 if (zid != GLOBAL_ZONEID) { 736f4b3ec61Sdh155122 ushort_t flags; 737f4b3ec61Sdh155122 738f4b3ec61Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 739f4b3ec61Sdh155122 sizeof (flags)) < 0) { 740f4b3ec61Sdh155122 return (dladm_errno2status(errno)); 741f4b3ec61Sdh155122 } 742f4b3ec61Sdh155122 743f4b3ec61Sdh155122 if (!(flags & ZF_NET_EXCL)) { 744f4b3ec61Sdh155122 return (DLADM_STATUS_BADVAL); 745f4b3ec61Sdh155122 } 746f4b3ec61Sdh155122 } 747f4b3ec61Sdh155122 748*d62bc4baSyz147064 vdp->vd_val = zid; 749*d62bc4baSyz147064 *needfreep = B_FALSE; 750f4b3ec61Sdh155122 return (DLADM_STATUS_OK); 751f4b3ec61Sdh155122 } 752f4b3ec61Sdh155122 753f4b3ec61Sdh155122 static dladm_status_t 754*d62bc4baSyz147064 do_get_autopush(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 755*d62bc4baSyz147064 { 756*d62bc4baSyz147064 dld_ioc_ap_t dia; 757*d62bc4baSyz147064 int fd, i, len; 758*d62bc4baSyz147064 759*d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 760*d62bc4baSyz147064 return (dladm_errno2status(errno)); 761*d62bc4baSyz147064 762*d62bc4baSyz147064 *val_cnt = 1; 763*d62bc4baSyz147064 dia.dia_linkid = linkid; 764*d62bc4baSyz147064 if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) { 765*d62bc4baSyz147064 (*prop_val)[0] = '\0'; 766*d62bc4baSyz147064 goto done; 767*d62bc4baSyz147064 } 768*d62bc4baSyz147064 769*d62bc4baSyz147064 for (i = 0, len = 0; i < dia.dia_npush; i++) { 770*d62bc4baSyz147064 if (i != 0) { 771*d62bc4baSyz147064 (void) snprintf(*prop_val + len, 772*d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER); 773*d62bc4baSyz147064 len += 1; 774*d62bc4baSyz147064 } 775*d62bc4baSyz147064 (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len, 776*d62bc4baSyz147064 "%s", dia.dia_aplist[i]); 777*d62bc4baSyz147064 len += strlen(dia.dia_aplist[i]); 778*d62bc4baSyz147064 if (dia.dia_anchor - 1 == i) { 779*d62bc4baSyz147064 (void) snprintf(*prop_val + len, 780*d62bc4baSyz147064 DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER, 781*d62bc4baSyz147064 AP_ANCHOR); 782*d62bc4baSyz147064 len += (strlen(AP_ANCHOR) + 1); 783*d62bc4baSyz147064 } 784*d62bc4baSyz147064 } 785*d62bc4baSyz147064 786*d62bc4baSyz147064 done: 787*d62bc4baSyz147064 (void) close(fd); 788*d62bc4baSyz147064 return (DLADM_STATUS_OK); 789*d62bc4baSyz147064 } 790*d62bc4baSyz147064 791*d62bc4baSyz147064 static dladm_status_t 792*d62bc4baSyz147064 do_set_autopush(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt) 793*d62bc4baSyz147064 { 794*d62bc4baSyz147064 dld_ioc_ap_t dia; 795*d62bc4baSyz147064 struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val; 796*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 797*d62bc4baSyz147064 int fd, i; 798*d62bc4baSyz147064 int ic_cmd; 799*d62bc4baSyz147064 800*d62bc4baSyz147064 if (val_cnt != 1) 801*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 802*d62bc4baSyz147064 803*d62bc4baSyz147064 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 804*d62bc4baSyz147064 return (dladm_errno2status(errno)); 805*d62bc4baSyz147064 806*d62bc4baSyz147064 dia.dia_linkid = linkid; 807*d62bc4baSyz147064 if (dlap != NULL) { 808*d62bc4baSyz147064 dia.dia_anchor = dlap->dap_anchor; 809*d62bc4baSyz147064 dia.dia_npush = dlap->dap_npush; 810*d62bc4baSyz147064 for (i = 0; i < dia.dia_npush; i++) { 811*d62bc4baSyz147064 (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i], 812*d62bc4baSyz147064 FMNAMESZ+1); 813*d62bc4baSyz147064 } 814*d62bc4baSyz147064 ic_cmd = DLDIOC_SETAUTOPUSH; 815*d62bc4baSyz147064 } else { 816*d62bc4baSyz147064 ic_cmd = DLDIOC_CLRAUTOPUSH; 817*d62bc4baSyz147064 } 818*d62bc4baSyz147064 819*d62bc4baSyz147064 if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0) 820*d62bc4baSyz147064 status = dladm_errno2status(errno); 821*d62bc4baSyz147064 822*d62bc4baSyz147064 (void) close(fd); 823*d62bc4baSyz147064 return (status); 824*d62bc4baSyz147064 } 825*d62bc4baSyz147064 826*d62bc4baSyz147064 /* 827*d62bc4baSyz147064 * Add the specified module to the dlautopush structure; returns a 828*d62bc4baSyz147064 * DLADM_STATUS_* code. 829*d62bc4baSyz147064 */ 830*d62bc4baSyz147064 dladm_status_t 831*d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap) 832*d62bc4baSyz147064 { 833*d62bc4baSyz147064 if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ)) 834*d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 835*d62bc4baSyz147064 836*d62bc4baSyz147064 if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) { 837*d62bc4baSyz147064 /* 838*d62bc4baSyz147064 * We don't allow multiple anchors, and the anchor must 839*d62bc4baSyz147064 * be after at least one module. 840*d62bc4baSyz147064 */ 841*d62bc4baSyz147064 if (dlap->dap_anchor != 0) 842*d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 843*d62bc4baSyz147064 if (dlap->dap_npush == 0) 844*d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 845*d62bc4baSyz147064 846*d62bc4baSyz147064 dlap->dap_anchor = dlap->dap_npush; 847*d62bc4baSyz147064 return (DLADM_STATUS_OK); 848*d62bc4baSyz147064 } 849*d62bc4baSyz147064 if (dlap->dap_npush > MAXAPUSH) 850*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 851*d62bc4baSyz147064 852*d62bc4baSyz147064 (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module, 853*d62bc4baSyz147064 FMNAMESZ + 1); 854*d62bc4baSyz147064 855*d62bc4baSyz147064 return (DLADM_STATUS_OK); 856*d62bc4baSyz147064 } 857*d62bc4baSyz147064 858*d62bc4baSyz147064 /* 859*d62bc4baSyz147064 * Currently, both '.' and ' '(space) can be used as the delimiters between 860*d62bc4baSyz147064 * autopush modules. The former is used in dladm set-linkprop, and the 861*d62bc4baSyz147064 * latter is used in the autopush(1M) file. 862*d62bc4baSyz147064 */ 863*d62bc4baSyz147064 /* ARGSUSED */ 864*d62bc4baSyz147064 static dladm_status_t 865*d62bc4baSyz147064 do_check_autopush(datalink_id_t linkid, char **prop_val, uint_t val_cnt, 866*d62bc4baSyz147064 val_desc_t *vdp, boolean_t *needfreep) 867*d62bc4baSyz147064 { 868*d62bc4baSyz147064 char *module; 869*d62bc4baSyz147064 struct dlautopush *dlap; 870*d62bc4baSyz147064 dladm_status_t status; 871*d62bc4baSyz147064 char val[DLADM_PROP_VAL_MAX]; 872*d62bc4baSyz147064 char delimiters[4]; 873*d62bc4baSyz147064 874*d62bc4baSyz147064 if (val_cnt != 1) 875*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 876*d62bc4baSyz147064 877*d62bc4baSyz147064 dlap = malloc(sizeof (struct dlautopush)); 878*d62bc4baSyz147064 if (dlap == NULL) 879*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 880*d62bc4baSyz147064 881*d62bc4baSyz147064 (void) memset(dlap, 0, sizeof (struct dlautopush)); 882*d62bc4baSyz147064 (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER); 883*d62bc4baSyz147064 bcopy(*prop_val, val, DLADM_PROP_VAL_MAX); 884*d62bc4baSyz147064 module = strtok(val, delimiters); 885*d62bc4baSyz147064 while (module != NULL) { 886*d62bc4baSyz147064 status = i_dladm_add_ap_module(module, dlap); 887*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 888*d62bc4baSyz147064 return (status); 889*d62bc4baSyz147064 module = strtok(NULL, delimiters); 890*d62bc4baSyz147064 } 891*d62bc4baSyz147064 892*d62bc4baSyz147064 vdp->vd_val = (uintptr_t)dlap; 893*d62bc4baSyz147064 *needfreep = B_TRUE; 894*d62bc4baSyz147064 return (DLADM_STATUS_OK); 895*d62bc4baSyz147064 } 896*d62bc4baSyz147064 897*d62bc4baSyz147064 static dladm_status_t 898*d62bc4baSyz147064 do_get_rate_common(datalink_id_t linkid, char **prop_val, uint_t *val_cnt, 899*d62bc4baSyz147064 uint_t id) 900*d62bc4baSyz147064 { 901*d62bc4baSyz147064 wl_rates_t *wrp; 902*d62bc4baSyz147064 uint_t i; 903*d62bc4baSyz147064 wldp_t *gbuf = NULL; 904*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 905*d62bc4baSyz147064 906*d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 907*d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 908*d62bc4baSyz147064 goto done; 909*d62bc4baSyz147064 } 910*d62bc4baSyz147064 911*d62bc4baSyz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); 912*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 913*d62bc4baSyz147064 goto done; 914*d62bc4baSyz147064 915*d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 916*d62bc4baSyz147064 if (wrp->wl_rates_num > *val_cnt) { 917*d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 918*d62bc4baSyz147064 goto done; 919*d62bc4baSyz147064 } 920*d62bc4baSyz147064 921*d62bc4baSyz147064 if (wrp->wl_rates_rates[0] == 0) { 922*d62bc4baSyz147064 prop_val[0][0] = '\0'; 923*d62bc4baSyz147064 *val_cnt = 1; 924*d62bc4baSyz147064 goto done; 925*d62bc4baSyz147064 } 926*d62bc4baSyz147064 927*d62bc4baSyz147064 for (i = 0; i < wrp->wl_rates_num; i++) { 928*d62bc4baSyz147064 (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f", 929*d62bc4baSyz147064 wrp->wl_rates_rates[i] % 2, 930*d62bc4baSyz147064 (float)wrp->wl_rates_rates[i] / 2); 931*d62bc4baSyz147064 } 932*d62bc4baSyz147064 *val_cnt = wrp->wl_rates_num; 933*d62bc4baSyz147064 934*d62bc4baSyz147064 done: 935*d62bc4baSyz147064 free(gbuf); 936*d62bc4baSyz147064 return (status); 937*d62bc4baSyz147064 } 938*d62bc4baSyz147064 939*d62bc4baSyz147064 static dladm_status_t 940*d62bc4baSyz147064 do_get_rate_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 941*d62bc4baSyz147064 { 942*d62bc4baSyz147064 return (do_get_rate_common(linkid, prop_val, val_cnt, 943*d62bc4baSyz147064 WL_DESIRED_RATES)); 944*d62bc4baSyz147064 } 945*d62bc4baSyz147064 946*d62bc4baSyz147064 static dladm_status_t 947*d62bc4baSyz147064 do_get_rate_mod(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 948*d62bc4baSyz147064 { 949*d62bc4baSyz147064 return (do_get_rate_common(linkid, prop_val, val_cnt, 950*d62bc4baSyz147064 WL_SUPPORTED_RATES)); 951*d62bc4baSyz147064 } 952*d62bc4baSyz147064 953*d62bc4baSyz147064 static dladm_status_t 954*d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) 955f4b3ec61Sdh155122 { 956f4b3ec61Sdh155122 int i; 957*d62bc4baSyz147064 uint_t len; 958*d62bc4baSyz147064 wldp_t *gbuf; 959*d62bc4baSyz147064 wl_rates_t *wrp; 960*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 961*d62bc4baSyz147064 962*d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 963*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 964*d62bc4baSyz147064 965*d62bc4baSyz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 966*d62bc4baSyz147064 967*d62bc4baSyz147064 wrp = (wl_rates_t *)gbuf->wldp_buf; 968*d62bc4baSyz147064 for (i = 0; i < rates->wr_cnt; i++) 969*d62bc4baSyz147064 wrp->wl_rates_rates[i] = rates->wr_rates[i]; 970*d62bc4baSyz147064 wrp->wl_rates_num = rates->wr_cnt; 971*d62bc4baSyz147064 972*d62bc4baSyz147064 len = offsetof(wl_rates_t, wl_rates_rates) + 973*d62bc4baSyz147064 (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; 974*d62bc4baSyz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, 975*d62bc4baSyz147064 WLAN_SET_PARAM, len); 976*d62bc4baSyz147064 977*d62bc4baSyz147064 free(gbuf); 978*d62bc4baSyz147064 return (status); 979*d62bc4baSyz147064 } 980*d62bc4baSyz147064 981*d62bc4baSyz147064 static dladm_status_t 982*d62bc4baSyz147064 do_set_rate_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt) 983*d62bc4baSyz147064 { 984*d62bc4baSyz147064 dladm_wlan_rates_t rates; 985f4b3ec61Sdh155122 dladm_status_t status; 986f4b3ec61Sdh155122 987*d62bc4baSyz147064 if (val_cnt != 1) 988*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 989f4b3ec61Sdh155122 990*d62bc4baSyz147064 rates.wr_cnt = 1; 991*d62bc4baSyz147064 rates.wr_rates[0] = vdp[0].vd_val; 992f4b3ec61Sdh155122 993*d62bc4baSyz147064 status = do_set_rate(linkid, &rates); 994f4b3ec61Sdh155122 995*d62bc4baSyz147064 done: 996*d62bc4baSyz147064 return (status); 997*d62bc4baSyz147064 } 998*d62bc4baSyz147064 999*d62bc4baSyz147064 /* ARGSUSED */ 1000*d62bc4baSyz147064 static dladm_status_t 1001*d62bc4baSyz147064 do_check_rate(datalink_id_t linkid, char **prop_val, uint_t val_cnt, 1002*d62bc4baSyz147064 val_desc_t *vdp, boolean_t *needfreep) 1003*d62bc4baSyz147064 { 1004*d62bc4baSyz147064 int i; 1005*d62bc4baSyz147064 uint_t modval_cnt = MAX_SUPPORT_RATES; 1006*d62bc4baSyz147064 char *buf, **modval; 1007*d62bc4baSyz147064 dladm_status_t status; 1008*d62bc4baSyz147064 1009*d62bc4baSyz147064 if (val_cnt != 1) 1010*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1011*d62bc4baSyz147064 1012*d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_STRSIZE) * 1013*d62bc4baSyz147064 MAX_SUPPORT_RATES); 1014*d62bc4baSyz147064 if (buf == NULL) { 1015*d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1016*d62bc4baSyz147064 goto done; 1017*d62bc4baSyz147064 } 1018*d62bc4baSyz147064 1019*d62bc4baSyz147064 modval = (char **)(void *)buf; 1020*d62bc4baSyz147064 for (i = 0; i < MAX_SUPPORT_RATES; i++) { 1021*d62bc4baSyz147064 modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES + 1022*d62bc4baSyz147064 i * DLADM_STRSIZE; 1023*d62bc4baSyz147064 } 1024*d62bc4baSyz147064 1025*d62bc4baSyz147064 status = do_get_rate_mod(linkid, modval, &modval_cnt); 1026*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1027*d62bc4baSyz147064 goto done; 1028*d62bc4baSyz147064 1029*d62bc4baSyz147064 for (i = 0; i < modval_cnt; i++) { 1030*d62bc4baSyz147064 if (strcasecmp(*prop_val, modval[i]) == 0) { 1031*d62bc4baSyz147064 vdp->vd_val = (uint_t)(atof(*prop_val) * 2); 1032f4b3ec61Sdh155122 status = DLADM_STATUS_OK; 1033f4b3ec61Sdh155122 1034*d62bc4baSyz147064 /* 1035*d62bc4baSyz147064 * Does not need the caller to free the vdp->vd_val 1036*d62bc4baSyz147064 */ 1037*d62bc4baSyz147064 *needfreep = B_FALSE; 1038f4b3ec61Sdh155122 break; 1039f4b3ec61Sdh155122 } 1040*d62bc4baSyz147064 } 1041*d62bc4baSyz147064 if (i == modval_cnt) 1042*d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 1043*d62bc4baSyz147064 done: 1044*d62bc4baSyz147064 free(buf); 1045*d62bc4baSyz147064 return (status); 1046*d62bc4baSyz147064 } 1047f4b3ec61Sdh155122 1048*d62bc4baSyz147064 static dladm_status_t 1049*d62bc4baSyz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) 1050*d62bc4baSyz147064 { 1051*d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 1052*d62bc4baSyz147064 } 1053*d62bc4baSyz147064 1054*d62bc4baSyz147064 static dladm_status_t 1055*d62bc4baSyz147064 do_get_channel_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 1056*d62bc4baSyz147064 { 1057*d62bc4baSyz147064 uint32_t channel; 1058*d62bc4baSyz147064 wldp_t *gbuf; 1059*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1060*d62bc4baSyz147064 1061*d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1062*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1063*d62bc4baSyz147064 1064*d62bc4baSyz147064 if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) 1065*d62bc4baSyz147064 goto done; 1066*d62bc4baSyz147064 1067*d62bc4baSyz147064 if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, 1068*d62bc4baSyz147064 &channel)) { 1069*d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1070*d62bc4baSyz147064 goto done; 1071*d62bc4baSyz147064 } 1072*d62bc4baSyz147064 1073*d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel); 1074*d62bc4baSyz147064 *val_cnt = 1; 1075*d62bc4baSyz147064 1076*d62bc4baSyz147064 done: 1077*d62bc4baSyz147064 free(gbuf); 1078*d62bc4baSyz147064 return (status); 1079*d62bc4baSyz147064 } 1080*d62bc4baSyz147064 1081*d62bc4baSyz147064 static dladm_status_t 1082*d62bc4baSyz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) 1083*d62bc4baSyz147064 { 1084*d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); 1085*d62bc4baSyz147064 } 1086*d62bc4baSyz147064 1087*d62bc4baSyz147064 static dladm_status_t 1088*d62bc4baSyz147064 do_get_powermode_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 1089*d62bc4baSyz147064 { 1090*d62bc4baSyz147064 wl_ps_mode_t *mode; 1091*d62bc4baSyz147064 const char *s; 1092*d62bc4baSyz147064 wldp_t *gbuf; 1093*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1094*d62bc4baSyz147064 1095*d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1096*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1097*d62bc4baSyz147064 1098*d62bc4baSyz147064 if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) 1099*d62bc4baSyz147064 goto done; 1100*d62bc4baSyz147064 1101*d62bc4baSyz147064 mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 1102*d62bc4baSyz147064 switch (mode->wl_ps_mode) { 1103*d62bc4baSyz147064 case WL_PM_AM: 1104*d62bc4baSyz147064 s = "off"; 1105f4b3ec61Sdh155122 break; 1106*d62bc4baSyz147064 case WL_PM_MPS: 1107*d62bc4baSyz147064 s = "max"; 1108*d62bc4baSyz147064 break; 1109*d62bc4baSyz147064 case WL_PM_FAST: 1110*d62bc4baSyz147064 s = "fast"; 1111f4b3ec61Sdh155122 break; 1112f4b3ec61Sdh155122 default: 1113*d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1114*d62bc4baSyz147064 goto done; 1115f4b3ec61Sdh155122 } 1116*d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1117*d62bc4baSyz147064 *val_cnt = 1; 1118*d62bc4baSyz147064 1119*d62bc4baSyz147064 done: 1120*d62bc4baSyz147064 free(gbuf); 1121*d62bc4baSyz147064 return (status); 1122*d62bc4baSyz147064 } 1123*d62bc4baSyz147064 1124*d62bc4baSyz147064 static dladm_status_t 1125*d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) 1126*d62bc4baSyz147064 { 1127*d62bc4baSyz147064 wl_ps_mode_t ps_mode; 1128*d62bc4baSyz147064 1129*d62bc4baSyz147064 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 1130*d62bc4baSyz147064 1131*d62bc4baSyz147064 switch (*pm) { 1132*d62bc4baSyz147064 case DLADM_WLAN_PM_OFF: 1133*d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_AM; 1134*d62bc4baSyz147064 break; 1135*d62bc4baSyz147064 case DLADM_WLAN_PM_MAX: 1136*d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_MPS; 1137*d62bc4baSyz147064 break; 1138*d62bc4baSyz147064 case DLADM_WLAN_PM_FAST: 1139*d62bc4baSyz147064 ps_mode.wl_ps_mode = WL_PM_FAST; 1140*d62bc4baSyz147064 break; 1141*d62bc4baSyz147064 default: 1142*d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1143*d62bc4baSyz147064 } 1144*d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, 1145*d62bc4baSyz147064 sizeof (ps_mode))); 1146*d62bc4baSyz147064 } 1147*d62bc4baSyz147064 1148*d62bc4baSyz147064 /* ARGSUSED */ 1149*d62bc4baSyz147064 static dladm_status_t 1150*d62bc4baSyz147064 do_set_powermode_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt) 1151*d62bc4baSyz147064 { 1152*d62bc4baSyz147064 dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val; 1153*d62bc4baSyz147064 dladm_status_t status; 1154*d62bc4baSyz147064 1155*d62bc4baSyz147064 if (val_cnt != 1) 1156*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1157*d62bc4baSyz147064 1158*d62bc4baSyz147064 status = do_set_powermode(linkid, &powermode); 1159f4b3ec61Sdh155122 1160f4b3ec61Sdh155122 return (status); 1161f4b3ec61Sdh155122 } 1162f4b3ec61Sdh155122 1163f4b3ec61Sdh155122 static dladm_status_t 1164*d62bc4baSyz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf) 1165f4b3ec61Sdh155122 { 1166*d62bc4baSyz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); 1167*d62bc4baSyz147064 } 1168*d62bc4baSyz147064 1169*d62bc4baSyz147064 static dladm_status_t 1170*d62bc4baSyz147064 do_get_radio_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt) 1171*d62bc4baSyz147064 { 1172*d62bc4baSyz147064 wl_radio_t radio; 1173*d62bc4baSyz147064 const char *s; 1174*d62bc4baSyz147064 wldp_t *gbuf; 1175*d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1176*d62bc4baSyz147064 1177*d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1178*d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1179*d62bc4baSyz147064 1180*d62bc4baSyz147064 if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) 1181*d62bc4baSyz147064 goto done; 1182*d62bc4baSyz147064 1183*d62bc4baSyz147064 radio = *(wl_radio_t *)(gbuf->wldp_buf); 1184*d62bc4baSyz147064 switch (radio) { 1185*d62bc4baSyz147064 case B_TRUE: 1186*d62bc4baSyz147064 s = "on"; 1187*d62bc4baSyz147064 break; 1188*d62bc4baSyz147064 case B_FALSE: 1189*d62bc4baSyz147064 s = "off"; 1190*d62bc4baSyz147064 break; 1191*d62bc4baSyz147064 default: 1192*d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1193*d62bc4baSyz147064 goto done; 1194*d62bc4baSyz147064 } 1195*d62bc4baSyz147064 (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s); 1196*d62bc4baSyz147064 *val_cnt = 1; 1197*d62bc4baSyz147064 1198*d62bc4baSyz147064 done: 1199*d62bc4baSyz147064 free(gbuf); 1200*d62bc4baSyz147064 return (status); 1201*d62bc4baSyz147064 } 1202*d62bc4baSyz147064 1203*d62bc4baSyz147064 static dladm_status_t 1204*d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) 1205*d62bc4baSyz147064 { 1206*d62bc4baSyz147064 wl_radio_t r; 1207*d62bc4baSyz147064 1208*d62bc4baSyz147064 switch (*radio) { 1209*d62bc4baSyz147064 case DLADM_WLAN_RADIO_ON: 1210*d62bc4baSyz147064 r = B_TRUE; 1211*d62bc4baSyz147064 break; 1212*d62bc4baSyz147064 case DLADM_WLAN_RADIO_OFF: 1213*d62bc4baSyz147064 r = B_FALSE; 1214*d62bc4baSyz147064 break; 1215*d62bc4baSyz147064 default: 1216*d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1217*d62bc4baSyz147064 } 1218*d62bc4baSyz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); 1219*d62bc4baSyz147064 } 1220*d62bc4baSyz147064 1221*d62bc4baSyz147064 /* ARGSUSED */ 1222*d62bc4baSyz147064 static dladm_status_t 1223*d62bc4baSyz147064 do_set_radio_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt) 1224*d62bc4baSyz147064 { 1225*d62bc4baSyz147064 dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; 1226f4b3ec61Sdh155122 dladm_status_t status; 1227f4b3ec61Sdh155122 1228*d62bc4baSyz147064 if (val_cnt != 1) 1229*d62bc4baSyz147064 return (DLADM_STATUS_BADVALCNT); 1230f4b3ec61Sdh155122 1231*d62bc4baSyz147064 status = do_set_radio(linkid, &radio); 1232f4b3ec61Sdh155122 1233*d62bc4baSyz147064 return (status); 1234*d62bc4baSyz147064 } 1235f4b3ec61Sdh155122 1236*d62bc4baSyz147064 static dladm_status_t 1237*d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name, 1238*d62bc4baSyz147064 char **prop_val, uint_t val_cnt) 1239*d62bc4baSyz147064 { 1240*d62bc4baSyz147064 char buf[MAXLINELEN]; 1241*d62bc4baSyz147064 int i; 1242*d62bc4baSyz147064 dladm_conf_t conf; 1243*d62bc4baSyz147064 dladm_status_t status; 1244*d62bc4baSyz147064 1245*d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1246f4b3ec61Sdh155122 if (status != DLADM_STATUS_OK) 1247f4b3ec61Sdh155122 return (status); 1248f4b3ec61Sdh155122 1249*d62bc4baSyz147064 /* 1250*d62bc4baSyz147064 * reset case. 1251*d62bc4baSyz147064 */ 1252*d62bc4baSyz147064 if (val_cnt == 0) { 1253*d62bc4baSyz147064 status = dladm_unset_conf_field(conf, prop_name); 1254*d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1255*d62bc4baSyz147064 status = dladm_write_conf(conf); 1256*d62bc4baSyz147064 goto done; 1257f4b3ec61Sdh155122 } 1258f4b3ec61Sdh155122 1259*d62bc4baSyz147064 buf[0] = '\0'; 1260*d62bc4baSyz147064 for (i = 0; i < val_cnt; i++) { 1261*d62bc4baSyz147064 (void) strlcat(buf, prop_val[i], MAXLINELEN); 1262*d62bc4baSyz147064 if (i != val_cnt - 1) 1263*d62bc4baSyz147064 (void) strlcat(buf, ",", MAXLINELEN); 1264*d62bc4baSyz147064 } 1265f4b3ec61Sdh155122 1266*d62bc4baSyz147064 status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf); 1267*d62bc4baSyz147064 if (status == DLADM_STATUS_OK) 1268*d62bc4baSyz147064 status = dladm_write_conf(conf); 1269*d62bc4baSyz147064 1270*d62bc4baSyz147064 done: 1271*d62bc4baSyz147064 dladm_destroy_conf(conf); 1272f4b3ec61Sdh155122 return (status); 1273f4b3ec61Sdh155122 } 1274f4b3ec61Sdh155122 1275f4b3ec61Sdh155122 static dladm_status_t 1276*d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name, 1277*d62bc4baSyz147064 char **prop_val, uint_t *val_cntp) 1278f4b3ec61Sdh155122 { 1279*d62bc4baSyz147064 char buf[MAXLINELEN], *str; 1280*d62bc4baSyz147064 uint_t cnt = 0; 1281*d62bc4baSyz147064 dladm_conf_t conf; 1282*d62bc4baSyz147064 dladm_status_t status; 1283f4b3ec61Sdh155122 1284*d62bc4baSyz147064 status = dladm_read_conf(linkid, &conf); 1285*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1286f4b3ec61Sdh155122 return (status); 1287*d62bc4baSyz147064 1288*d62bc4baSyz147064 status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN); 1289*d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1290*d62bc4baSyz147064 goto done; 1291*d62bc4baSyz147064 1292*d62bc4baSyz147064 str = strtok(buf, ","); 1293*d62bc4baSyz147064 while (str != NULL) { 1294*d62bc4baSyz147064 if (cnt == *val_cntp) { 1295*d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL; 1296*d62bc4baSyz147064 goto done; 1297*d62bc4baSyz147064 } 1298*d62bc4baSyz147064 (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX); 1299*d62bc4baSyz147064 str = strtok(NULL, ","); 1300f4b3ec61Sdh155122 } 1301f4b3ec61Sdh155122 1302*d62bc4baSyz147064 *val_cntp = cnt; 1303f4b3ec61Sdh155122 1304*d62bc4baSyz147064 done: 1305*d62bc4baSyz147064 dladm_destroy_conf(conf); 1306*d62bc4baSyz147064 return (status); 1307f4b3ec61Sdh155122 } 1308