1b509e89bSRishi Srivatsavai /* 2b509e89bSRishi Srivatsavai * CDDL HEADER START 3b509e89bSRishi Srivatsavai * 4b509e89bSRishi Srivatsavai * The contents of this file are subject to the terms of the 5b509e89bSRishi Srivatsavai * Common Development and Distribution License (the "License"). 6b509e89bSRishi Srivatsavai * You may not use this file except in compliance with the License. 7b509e89bSRishi Srivatsavai * 8b509e89bSRishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9b509e89bSRishi Srivatsavai * or http://www.opensolaris.org/os/licensing. 10b509e89bSRishi Srivatsavai * See the License for the specific language governing permissions 11b509e89bSRishi Srivatsavai * and limitations under the License. 12b509e89bSRishi Srivatsavai * 13b509e89bSRishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each 14b509e89bSRishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15b509e89bSRishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the 16b509e89bSRishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying 17b509e89bSRishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner] 18b509e89bSRishi Srivatsavai * 19b509e89bSRishi Srivatsavai * CDDL HEADER END 20b509e89bSRishi Srivatsavai */ 21b509e89bSRishi Srivatsavai /* 22*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23b509e89bSRishi Srivatsavai * Use is subject to license terms. 24b509e89bSRishi Srivatsavai */ 25b509e89bSRishi Srivatsavai 26b509e89bSRishi Srivatsavai /* 27b509e89bSRishi Srivatsavai * Simulated network device (simnet) driver: simulates a pseudo GLDv3 network 28b509e89bSRishi Srivatsavai * device. Can simulate an Ethernet or WiFi network device. In addition, another 29b509e89bSRishi Srivatsavai * simnet instance can be attached as a peer to create a point-to-point link on 30b509e89bSRishi Srivatsavai * the same system. 31b509e89bSRishi Srivatsavai */ 32b509e89bSRishi Srivatsavai 33b509e89bSRishi Srivatsavai #include <sys/policy.h> 34b509e89bSRishi Srivatsavai #include <sys/conf.h> 35b509e89bSRishi Srivatsavai #include <sys/modctl.h> 36b509e89bSRishi Srivatsavai #include <sys/priv_names.h> 37b509e89bSRishi Srivatsavai #include <sys/dlpi.h> 38b509e89bSRishi Srivatsavai #include <net/simnet.h> 39b509e89bSRishi Srivatsavai #include <sys/ethernet.h> 40b509e89bSRishi Srivatsavai #include <sys/mac.h> 41b509e89bSRishi Srivatsavai #include <sys/dls.h> 42b509e89bSRishi Srivatsavai #include <sys/mac_ether.h> 43b509e89bSRishi Srivatsavai #include <sys/mac_provider.h> 44b509e89bSRishi Srivatsavai #include <sys/mac_client_priv.h> 45b509e89bSRishi Srivatsavai #include <sys/vlan.h> 46b509e89bSRishi Srivatsavai #include <sys/random.h> 47b509e89bSRishi Srivatsavai #include <sys/sysmacros.h> 48b509e89bSRishi Srivatsavai #include <sys/list.h> 49b509e89bSRishi Srivatsavai #include <sys/strsubr.h> 50b509e89bSRishi Srivatsavai #include <sys/strsun.h> 51b509e89bSRishi Srivatsavai #include <sys/atomic.h> 52b509e89bSRishi Srivatsavai #include <sys/mac_wifi.h> 53b509e89bSRishi Srivatsavai #include <sys/mac_impl.h> 54b509e89bSRishi Srivatsavai #include <inet/wifi_ioctl.h> 55b509e89bSRishi Srivatsavai #include <sys/thread.h> 56b509e89bSRishi Srivatsavai #include <sys/synch.h> 570f83d385SRishi Srivatsavai #include <sys/sunddi.h> 58b509e89bSRishi Srivatsavai 59b509e89bSRishi Srivatsavai #include "simnet_impl.h" 60b509e89bSRishi Srivatsavai 61b509e89bSRishi Srivatsavai #define SIMNETINFO "Simulated Network Driver" 62b509e89bSRishi Srivatsavai 63b509e89bSRishi Srivatsavai static dev_info_t *simnet_dip; 640f83d385SRishi Srivatsavai static ddi_taskq_t *simnet_rxq; 65b509e89bSRishi Srivatsavai 66b509e89bSRishi Srivatsavai static int simnet_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 67b509e89bSRishi Srivatsavai static int simnet_attach(dev_info_t *, ddi_attach_cmd_t); 68b509e89bSRishi Srivatsavai static int simnet_detach(dev_info_t *, ddi_detach_cmd_t); 69b509e89bSRishi Srivatsavai static int simnet_ioc_create(void *, intptr_t, int, cred_t *, int *); 70b509e89bSRishi Srivatsavai static int simnet_ioc_delete(void *, intptr_t, int, cred_t *, int *); 71b509e89bSRishi Srivatsavai static int simnet_ioc_info(void *, intptr_t, int, cred_t *, int *); 72b509e89bSRishi Srivatsavai static int simnet_ioc_modify(void *, intptr_t, int, cred_t *, int *); 73b509e89bSRishi Srivatsavai static uint8_t *mcastaddr_lookup(simnet_dev_t *, const uint8_t *); 74b509e89bSRishi Srivatsavai 75b509e89bSRishi Srivatsavai static dld_ioc_info_t simnet_ioc_list[] = { 76b509e89bSRishi Srivatsavai {SIMNET_IOC_CREATE, DLDCOPYINOUT, sizeof (simnet_ioc_create_t), 772b24ab6bSSebastien Roy simnet_ioc_create, secpolicy_dl_config}, 78b509e89bSRishi Srivatsavai {SIMNET_IOC_DELETE, DLDCOPYIN, sizeof (simnet_ioc_delete_t), 792b24ab6bSSebastien Roy simnet_ioc_delete, secpolicy_dl_config}, 80b509e89bSRishi Srivatsavai {SIMNET_IOC_INFO, DLDCOPYINOUT, sizeof (simnet_ioc_info_t), 812b24ab6bSSebastien Roy simnet_ioc_info, NULL}, 82b509e89bSRishi Srivatsavai {SIMNET_IOC_MODIFY, DLDCOPYIN, sizeof (simnet_ioc_modify_t), 832b24ab6bSSebastien Roy simnet_ioc_modify, secpolicy_dl_config} 84b509e89bSRishi Srivatsavai }; 85b509e89bSRishi Srivatsavai 86b509e89bSRishi Srivatsavai DDI_DEFINE_STREAM_OPS(simnet_dev_ops, nulldev, nulldev, simnet_attach, 87b509e89bSRishi Srivatsavai simnet_detach, nodev, simnet_getinfo, D_MP, NULL, 88b509e89bSRishi Srivatsavai ddi_quiesce_not_supported); 89b509e89bSRishi Srivatsavai 90b509e89bSRishi Srivatsavai static struct modldrv simnet_modldrv = { 91b509e89bSRishi Srivatsavai &mod_driverops, /* Type of module. This one is a driver */ 92b509e89bSRishi Srivatsavai SIMNETINFO, /* short description */ 93b509e89bSRishi Srivatsavai &simnet_dev_ops /* driver specific ops */ 94b509e89bSRishi Srivatsavai }; 95b509e89bSRishi Srivatsavai 96b509e89bSRishi Srivatsavai static struct modlinkage modlinkage = { 97b509e89bSRishi Srivatsavai MODREV_1, &simnet_modldrv, NULL 98b509e89bSRishi Srivatsavai }; 99b509e89bSRishi Srivatsavai 100b509e89bSRishi Srivatsavai /* MAC callback function declarations */ 101b509e89bSRishi Srivatsavai static int simnet_m_start(void *); 102b509e89bSRishi Srivatsavai static void simnet_m_stop(void *); 103b509e89bSRishi Srivatsavai static int simnet_m_promisc(void *, boolean_t); 104b509e89bSRishi Srivatsavai static int simnet_m_multicst(void *, boolean_t, const uint8_t *); 105b509e89bSRishi Srivatsavai static int simnet_m_unicst(void *, const uint8_t *); 106b509e89bSRishi Srivatsavai static int simnet_m_stat(void *, uint_t, uint64_t *); 107b509e89bSRishi Srivatsavai static void simnet_m_ioctl(void *, queue_t *, mblk_t *); 108b509e89bSRishi Srivatsavai static mblk_t *simnet_m_tx(void *, mblk_t *); 109b509e89bSRishi Srivatsavai static int simnet_m_setprop(void *, const char *, mac_prop_id_t, 110b509e89bSRishi Srivatsavai uint_t, const void *); 111b509e89bSRishi Srivatsavai static int simnet_m_getprop(void *, const char *, mac_prop_id_t, 112*0dc2366fSVenugopal Iyer uint_t, void *); 113*0dc2366fSVenugopal Iyer static void simnet_m_propinfo(void *, const char *, mac_prop_id_t, 114*0dc2366fSVenugopal Iyer mac_prop_info_handle_t); 115b509e89bSRishi Srivatsavai 116b509e89bSRishi Srivatsavai static mac_callbacks_t simnet_m_callbacks = { 117*0dc2366fSVenugopal Iyer (MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO), 118b509e89bSRishi Srivatsavai simnet_m_stat, 119b509e89bSRishi Srivatsavai simnet_m_start, 120b509e89bSRishi Srivatsavai simnet_m_stop, 121b509e89bSRishi Srivatsavai simnet_m_promisc, 122b509e89bSRishi Srivatsavai simnet_m_multicst, 123b509e89bSRishi Srivatsavai simnet_m_unicst, 124b509e89bSRishi Srivatsavai simnet_m_tx, 125*0dc2366fSVenugopal Iyer NULL, 126b509e89bSRishi Srivatsavai simnet_m_ioctl, 127b509e89bSRishi Srivatsavai NULL, 128b509e89bSRishi Srivatsavai NULL, 129b509e89bSRishi Srivatsavai NULL, 130b509e89bSRishi Srivatsavai simnet_m_setprop, 131*0dc2366fSVenugopal Iyer simnet_m_getprop, 132*0dc2366fSVenugopal Iyer simnet_m_propinfo 133b509e89bSRishi Srivatsavai }; 134b509e89bSRishi Srivatsavai 135b509e89bSRishi Srivatsavai /* 136b509e89bSRishi Srivatsavai * simnet_dev_lock protects the simnet device list. 137b509e89bSRishi Srivatsavai * sd_instlock in each simnet_dev_t protects access to 138b509e89bSRishi Srivatsavai * a single simnet_dev_t. 139b509e89bSRishi Srivatsavai */ 140b509e89bSRishi Srivatsavai static krwlock_t simnet_dev_lock; 141b509e89bSRishi Srivatsavai static list_t simnet_dev_list; 142b509e89bSRishi Srivatsavai static int simnet_count; /* Num of simnet instances */ 143b509e89bSRishi Srivatsavai 144b509e89bSRishi Srivatsavai int 145b509e89bSRishi Srivatsavai _init(void) 146b509e89bSRishi Srivatsavai { 147b509e89bSRishi Srivatsavai int status; 148b509e89bSRishi Srivatsavai 149b509e89bSRishi Srivatsavai mac_init_ops(&simnet_dev_ops, "simnet"); 150b509e89bSRishi Srivatsavai status = mod_install(&modlinkage); 151b509e89bSRishi Srivatsavai if (status != DDI_SUCCESS) 152b509e89bSRishi Srivatsavai mac_fini_ops(&simnet_dev_ops); 153b509e89bSRishi Srivatsavai 154b509e89bSRishi Srivatsavai return (status); 155b509e89bSRishi Srivatsavai } 156b509e89bSRishi Srivatsavai 157b509e89bSRishi Srivatsavai int 158b509e89bSRishi Srivatsavai _fini(void) 159b509e89bSRishi Srivatsavai { 160b509e89bSRishi Srivatsavai int status; 161b509e89bSRishi Srivatsavai 162b509e89bSRishi Srivatsavai status = mod_remove(&modlinkage); 163b509e89bSRishi Srivatsavai if (status == DDI_SUCCESS) 164b509e89bSRishi Srivatsavai mac_fini_ops(&simnet_dev_ops); 165b509e89bSRishi Srivatsavai 166b509e89bSRishi Srivatsavai return (status); 167b509e89bSRishi Srivatsavai } 168b509e89bSRishi Srivatsavai 169b509e89bSRishi Srivatsavai int 170b509e89bSRishi Srivatsavai _info(struct modinfo *modinfop) 171b509e89bSRishi Srivatsavai { 172b509e89bSRishi Srivatsavai return (mod_info(&modlinkage, modinfop)); 173b509e89bSRishi Srivatsavai } 174b509e89bSRishi Srivatsavai 1750f83d385SRishi Srivatsavai static boolean_t 176b509e89bSRishi Srivatsavai simnet_init(void) 177b509e89bSRishi Srivatsavai { 1780f83d385SRishi Srivatsavai if ((simnet_rxq = ddi_taskq_create(simnet_dip, "simnet", 1, 1790f83d385SRishi Srivatsavai TASKQ_DEFAULTPRI, 0)) == NULL) 1800f83d385SRishi Srivatsavai return (B_FALSE); 181b509e89bSRishi Srivatsavai rw_init(&simnet_dev_lock, NULL, RW_DEFAULT, NULL); 182b509e89bSRishi Srivatsavai list_create(&simnet_dev_list, sizeof (simnet_dev_t), 183b509e89bSRishi Srivatsavai offsetof(simnet_dev_t, sd_listnode)); 1840f83d385SRishi Srivatsavai return (B_TRUE); 185b509e89bSRishi Srivatsavai } 186b509e89bSRishi Srivatsavai 187b509e89bSRishi Srivatsavai static void 188b509e89bSRishi Srivatsavai simnet_fini(void) 189b509e89bSRishi Srivatsavai { 190b509e89bSRishi Srivatsavai ASSERT(simnet_count == 0); 191b509e89bSRishi Srivatsavai rw_destroy(&simnet_dev_lock); 192b509e89bSRishi Srivatsavai list_destroy(&simnet_dev_list); 1930f83d385SRishi Srivatsavai ddi_taskq_destroy(simnet_rxq); 194b509e89bSRishi Srivatsavai } 195b509e89bSRishi Srivatsavai 196b509e89bSRishi Srivatsavai /*ARGSUSED*/ 197b509e89bSRishi Srivatsavai static int 198b509e89bSRishi Srivatsavai simnet_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 199b509e89bSRishi Srivatsavai void **result) 200b509e89bSRishi Srivatsavai { 201b509e89bSRishi Srivatsavai switch (infocmd) { 202b509e89bSRishi Srivatsavai case DDI_INFO_DEVT2DEVINFO: 203b509e89bSRishi Srivatsavai *result = simnet_dip; 204b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 205b509e89bSRishi Srivatsavai case DDI_INFO_DEVT2INSTANCE: 206b509e89bSRishi Srivatsavai *result = NULL; 207b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 208b509e89bSRishi Srivatsavai } 209b509e89bSRishi Srivatsavai return (DDI_FAILURE); 210b509e89bSRishi Srivatsavai } 211b509e89bSRishi Srivatsavai 212b509e89bSRishi Srivatsavai static int 213b509e89bSRishi Srivatsavai simnet_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 214b509e89bSRishi Srivatsavai { 215b509e89bSRishi Srivatsavai switch (cmd) { 216b509e89bSRishi Srivatsavai case DDI_ATTACH: 217b509e89bSRishi Srivatsavai if (ddi_get_instance(dip) != 0) { 218b509e89bSRishi Srivatsavai /* we only allow instance 0 to attach */ 219b509e89bSRishi Srivatsavai return (DDI_FAILURE); 220b509e89bSRishi Srivatsavai } 2210f83d385SRishi Srivatsavai 222b509e89bSRishi Srivatsavai if (dld_ioc_register(SIMNET_IOC, simnet_ioc_list, 223b509e89bSRishi Srivatsavai DLDIOCCNT(simnet_ioc_list)) != 0) 224b509e89bSRishi Srivatsavai return (DDI_FAILURE); 225b509e89bSRishi Srivatsavai 226b509e89bSRishi Srivatsavai simnet_dip = dip; 2270f83d385SRishi Srivatsavai if (!simnet_init()) 2280f83d385SRishi Srivatsavai return (DDI_FAILURE); 229b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 230b509e89bSRishi Srivatsavai 231b509e89bSRishi Srivatsavai case DDI_RESUME: 232b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 233b509e89bSRishi Srivatsavai 234b509e89bSRishi Srivatsavai default: 235b509e89bSRishi Srivatsavai return (DDI_FAILURE); 236b509e89bSRishi Srivatsavai } 237b509e89bSRishi Srivatsavai } 238b509e89bSRishi Srivatsavai 239b509e89bSRishi Srivatsavai /*ARGSUSED*/ 240b509e89bSRishi Srivatsavai static int 241b509e89bSRishi Srivatsavai simnet_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 242b509e89bSRishi Srivatsavai { 243b509e89bSRishi Srivatsavai switch (cmd) { 244b509e89bSRishi Srivatsavai case DDI_DETACH: 245b509e89bSRishi Srivatsavai /* 246b509e89bSRishi Srivatsavai * Allow the simnet instance to be detached only if there 247b509e89bSRishi Srivatsavai * are no simnets configured. 248b509e89bSRishi Srivatsavai */ 249b509e89bSRishi Srivatsavai if (simnet_count > 0) 250b509e89bSRishi Srivatsavai return (DDI_FAILURE); 251b509e89bSRishi Srivatsavai 252b509e89bSRishi Srivatsavai dld_ioc_unregister(SIMNET_IOC); 2530f83d385SRishi Srivatsavai simnet_fini(); 2540f83d385SRishi Srivatsavai simnet_dip = NULL; 255b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 256b509e89bSRishi Srivatsavai 257b509e89bSRishi Srivatsavai case DDI_SUSPEND: 258b509e89bSRishi Srivatsavai return (DDI_SUCCESS); 259b509e89bSRishi Srivatsavai 260b509e89bSRishi Srivatsavai default: 261b509e89bSRishi Srivatsavai return (DDI_FAILURE); 262b509e89bSRishi Srivatsavai } 263b509e89bSRishi Srivatsavai } 264b509e89bSRishi Srivatsavai 265b509e89bSRishi Srivatsavai /* Caller must hold simnet_dev_lock */ 266b509e89bSRishi Srivatsavai static simnet_dev_t * 267b509e89bSRishi Srivatsavai simnet_dev_lookup(datalink_id_t link_id) 268b509e89bSRishi Srivatsavai { 269b509e89bSRishi Srivatsavai simnet_dev_t *sdev; 270b509e89bSRishi Srivatsavai 2710f83d385SRishi Srivatsavai ASSERT(RW_LOCK_HELD(&simnet_dev_lock)); 272b509e89bSRishi Srivatsavai for (sdev = list_head(&simnet_dev_list); sdev != NULL; 273b509e89bSRishi Srivatsavai sdev = list_next(&simnet_dev_list, sdev)) { 274b509e89bSRishi Srivatsavai if (!(sdev->sd_flags & SDF_SHUTDOWN) && 275b509e89bSRishi Srivatsavai (sdev->sd_link_id == link_id)) { 276b509e89bSRishi Srivatsavai atomic_inc_32(&sdev->sd_refcount); 277b509e89bSRishi Srivatsavai return (sdev); 278b509e89bSRishi Srivatsavai } 279b509e89bSRishi Srivatsavai } 280b509e89bSRishi Srivatsavai 281b509e89bSRishi Srivatsavai return (NULL); 282b509e89bSRishi Srivatsavai } 283b509e89bSRishi Srivatsavai 284b509e89bSRishi Srivatsavai static void 285b509e89bSRishi Srivatsavai simnet_wifidev_free(simnet_dev_t *sdev) 286b509e89bSRishi Srivatsavai { 287b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 288b509e89bSRishi Srivatsavai int i; 289b509e89bSRishi Srivatsavai 290b509e89bSRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) { 291b509e89bSRishi Srivatsavai kmem_free(wdev->swd_esslist[i], 292b509e89bSRishi Srivatsavai sizeof (wl_ess_conf_t)); 293b509e89bSRishi Srivatsavai } 294b509e89bSRishi Srivatsavai kmem_free(wdev, sizeof (simnet_wifidev_t)); 295b509e89bSRishi Srivatsavai } 296b509e89bSRishi Srivatsavai 297b509e89bSRishi Srivatsavai static void 298b509e89bSRishi Srivatsavai simnet_dev_unref(simnet_dev_t *sdev) 299b509e89bSRishi Srivatsavai { 300b509e89bSRishi Srivatsavai 301b509e89bSRishi Srivatsavai ASSERT(sdev->sd_refcount > 0); 302b509e89bSRishi Srivatsavai if (atomic_dec_32_nv(&sdev->sd_refcount) != 0) 303b509e89bSRishi Srivatsavai return; 304b509e89bSRishi Srivatsavai 305b509e89bSRishi Srivatsavai if (sdev->sd_mh != NULL) 306b509e89bSRishi Srivatsavai (void) mac_unregister(sdev->sd_mh); 307b509e89bSRishi Srivatsavai 308b509e89bSRishi Srivatsavai if (sdev->sd_wifidev != NULL) { 309b509e89bSRishi Srivatsavai ASSERT(sdev->sd_type == DL_WIFI); 310b509e89bSRishi Srivatsavai simnet_wifidev_free(sdev); 311b509e89bSRishi Srivatsavai } 312b509e89bSRishi Srivatsavai 313b509e89bSRishi Srivatsavai mutex_destroy(&sdev->sd_instlock); 314b509e89bSRishi Srivatsavai cv_destroy(&sdev->sd_threadwait); 315b509e89bSRishi Srivatsavai kmem_free(sdev->sd_mcastaddrs, ETHERADDRL * sdev->sd_mcastaddr_count); 316b509e89bSRishi Srivatsavai kmem_free(sdev, sizeof (*sdev)); 317b509e89bSRishi Srivatsavai simnet_count--; 318b509e89bSRishi Srivatsavai } 319b509e89bSRishi Srivatsavai 320b509e89bSRishi Srivatsavai static int 321b509e89bSRishi Srivatsavai simnet_init_wifi(simnet_dev_t *sdev, mac_register_t *mac) 322b509e89bSRishi Srivatsavai { 323b509e89bSRishi Srivatsavai wifi_data_t wd = { 0 }; 324b509e89bSRishi Srivatsavai int err; 325b509e89bSRishi Srivatsavai 326b509e89bSRishi Srivatsavai sdev->sd_wifidev = kmem_zalloc(sizeof (simnet_wifidev_t), KM_NOSLEEP); 327b509e89bSRishi Srivatsavai if (sdev->sd_wifidev == NULL) 328b509e89bSRishi Srivatsavai return (ENOMEM); 329b509e89bSRishi Srivatsavai 330b509e89bSRishi Srivatsavai sdev->sd_wifidev->swd_sdev = sdev; 331b509e89bSRishi Srivatsavai sdev->sd_wifidev->swd_linkstatus = WL_NOTCONNECTED; 332b509e89bSRishi Srivatsavai wd.wd_secalloc = WIFI_SEC_NONE; 333b509e89bSRishi Srivatsavai wd.wd_opmode = IEEE80211_M_STA; 334b509e89bSRishi Srivatsavai mac->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 335b509e89bSRishi Srivatsavai mac->m_max_sdu = IEEE80211_MTU; 336b509e89bSRishi Srivatsavai mac->m_pdata = &wd; 337b509e89bSRishi Srivatsavai mac->m_pdata_size = sizeof (wd); 338b509e89bSRishi Srivatsavai err = mac_register(mac, &sdev->sd_mh); 339b509e89bSRishi Srivatsavai return (err); 340b509e89bSRishi Srivatsavai } 341b509e89bSRishi Srivatsavai 342b509e89bSRishi Srivatsavai static int 343b509e89bSRishi Srivatsavai simnet_init_ether(simnet_dev_t *sdev, mac_register_t *mac) 344b509e89bSRishi Srivatsavai { 345b509e89bSRishi Srivatsavai int err; 346b509e89bSRishi Srivatsavai 347b509e89bSRishi Srivatsavai mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 348b509e89bSRishi Srivatsavai mac->m_max_sdu = SIMNET_MAX_MTU; 349b509e89bSRishi Srivatsavai mac->m_margin = VLAN_TAGSZ; 350b509e89bSRishi Srivatsavai err = mac_register(mac, &sdev->sd_mh); 351b509e89bSRishi Srivatsavai return (err); 352b509e89bSRishi Srivatsavai } 353b509e89bSRishi Srivatsavai 354b509e89bSRishi Srivatsavai static int 355b509e89bSRishi Srivatsavai simnet_init_mac(simnet_dev_t *sdev) 356b509e89bSRishi Srivatsavai { 357b509e89bSRishi Srivatsavai mac_register_t *mac; 358b509e89bSRishi Srivatsavai int err; 359b509e89bSRishi Srivatsavai 360b509e89bSRishi Srivatsavai if ((mac = mac_alloc(MAC_VERSION)) == NULL) 361b509e89bSRishi Srivatsavai return (ENOMEM); 362b509e89bSRishi Srivatsavai 363b509e89bSRishi Srivatsavai mac->m_driver = sdev; 364b509e89bSRishi Srivatsavai mac->m_dip = simnet_dip; 365b509e89bSRishi Srivatsavai mac->m_instance = (uint_t)-1; 366b509e89bSRishi Srivatsavai mac->m_src_addr = sdev->sd_mac_addr; 367b509e89bSRishi Srivatsavai mac->m_callbacks = &simnet_m_callbacks; 368b509e89bSRishi Srivatsavai mac->m_min_sdu = 0; 369b509e89bSRishi Srivatsavai 370b509e89bSRishi Srivatsavai if (sdev->sd_type == DL_ETHER) 371b509e89bSRishi Srivatsavai err = simnet_init_ether(sdev, mac); 372b509e89bSRishi Srivatsavai else if (sdev->sd_type == DL_WIFI) 373b509e89bSRishi Srivatsavai err = simnet_init_wifi(sdev, mac); 374b509e89bSRishi Srivatsavai else 375b509e89bSRishi Srivatsavai err = EINVAL; 376b509e89bSRishi Srivatsavai 377b509e89bSRishi Srivatsavai mac_free(mac); 378b509e89bSRishi Srivatsavai return (err); 379b509e89bSRishi Srivatsavai } 380b509e89bSRishi Srivatsavai 381b509e89bSRishi Srivatsavai /* ARGSUSED */ 382b509e89bSRishi Srivatsavai static int 383b509e89bSRishi Srivatsavai simnet_ioc_create(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp) 384b509e89bSRishi Srivatsavai { 385b509e89bSRishi Srivatsavai simnet_ioc_create_t *create_arg = karg; 386b509e89bSRishi Srivatsavai simnet_dev_t *sdev; 387b509e89bSRishi Srivatsavai simnet_dev_t *sdev_tmp; 388b509e89bSRishi Srivatsavai int err = 0; 389b509e89bSRishi Srivatsavai 390b509e89bSRishi Srivatsavai sdev = kmem_zalloc(sizeof (*sdev), KM_NOSLEEP); 391b509e89bSRishi Srivatsavai if (sdev == NULL) 392b509e89bSRishi Srivatsavai return (ENOMEM); 393b509e89bSRishi Srivatsavai 394b509e89bSRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER); 395b509e89bSRishi Srivatsavai if ((sdev_tmp = simnet_dev_lookup(create_arg->sic_link_id)) != NULL) { 396b509e89bSRishi Srivatsavai simnet_dev_unref(sdev_tmp); 397b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 398b509e89bSRishi Srivatsavai kmem_free(sdev, sizeof (*sdev)); 399b509e89bSRishi Srivatsavai return (EEXIST); 400b509e89bSRishi Srivatsavai } 401b509e89bSRishi Srivatsavai 402b509e89bSRishi Srivatsavai sdev->sd_type = create_arg->sic_type; 403b509e89bSRishi Srivatsavai sdev->sd_link_id = create_arg->sic_link_id; 4042b24ab6bSSebastien Roy sdev->sd_zoneid = crgetzoneid(cred); 405b509e89bSRishi Srivatsavai sdev->sd_refcount++; 406b509e89bSRishi Srivatsavai mutex_init(&sdev->sd_instlock, NULL, MUTEX_DRIVER, NULL); 407b509e89bSRishi Srivatsavai cv_init(&sdev->sd_threadwait, NULL, CV_DRIVER, NULL); 408b509e89bSRishi Srivatsavai simnet_count++; 409b509e89bSRishi Srivatsavai 410b509e89bSRishi Srivatsavai /* Simnets created from configuration on boot pass saved MAC address */ 411b509e89bSRishi Srivatsavai if (create_arg->sic_mac_len == 0) { 412b509e89bSRishi Srivatsavai /* Generate random MAC address */ 413b509e89bSRishi Srivatsavai (void) random_get_pseudo_bytes(sdev->sd_mac_addr, ETHERADDRL); 414b509e89bSRishi Srivatsavai /* Ensure MAC address is not multicast and is local */ 415b509e89bSRishi Srivatsavai sdev->sd_mac_addr[0] = (sdev->sd_mac_addr[0] & ~1) | 2; 416b509e89bSRishi Srivatsavai sdev->sd_mac_len = ETHERADDRL; 417b509e89bSRishi Srivatsavai } else { 418b509e89bSRishi Srivatsavai (void) memcpy(sdev->sd_mac_addr, create_arg->sic_mac_addr, 419b509e89bSRishi Srivatsavai create_arg->sic_mac_len); 420b509e89bSRishi Srivatsavai sdev->sd_mac_len = create_arg->sic_mac_len; 421b509e89bSRishi Srivatsavai } 422b509e89bSRishi Srivatsavai 423b509e89bSRishi Srivatsavai if ((err = simnet_init_mac(sdev)) != 0) { 424b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 425b509e89bSRishi Srivatsavai goto exit; 426b509e89bSRishi Srivatsavai } 427b509e89bSRishi Srivatsavai 4282b24ab6bSSebastien Roy if ((err = dls_devnet_create(sdev->sd_mh, sdev->sd_link_id, 4292b24ab6bSSebastien Roy crgetzoneid(cred))) != 0) { 430b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 431b509e89bSRishi Srivatsavai goto exit; 432b509e89bSRishi Srivatsavai } 433b509e89bSRishi Srivatsavai 434b509e89bSRishi Srivatsavai mac_link_update(sdev->sd_mh, LINK_STATE_UP); 435b509e89bSRishi Srivatsavai mac_tx_update(sdev->sd_mh); 436b509e89bSRishi Srivatsavai list_insert_tail(&simnet_dev_list, sdev); 437b509e89bSRishi Srivatsavai 438b509e89bSRishi Srivatsavai /* Always return MAC address back to caller */ 439b509e89bSRishi Srivatsavai (void) memcpy(create_arg->sic_mac_addr, sdev->sd_mac_addr, 440b509e89bSRishi Srivatsavai sdev->sd_mac_len); 441b509e89bSRishi Srivatsavai create_arg->sic_mac_len = sdev->sd_mac_len; 442b509e89bSRishi Srivatsavai exit: 443b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 444b509e89bSRishi Srivatsavai return (err); 445b509e89bSRishi Srivatsavai } 446b509e89bSRishi Srivatsavai 447b509e89bSRishi Srivatsavai /* Caller must hold writer simnet_dev_lock */ 448b509e89bSRishi Srivatsavai static datalink_id_t 449b509e89bSRishi Srivatsavai simnet_remove_peer(simnet_dev_t *sdev) 450b509e89bSRishi Srivatsavai { 451b509e89bSRishi Srivatsavai simnet_dev_t *sdev_peer; 452b509e89bSRishi Srivatsavai datalink_id_t peer_link_id = DATALINK_INVALID_LINKID; 453b509e89bSRishi Srivatsavai 4540f83d385SRishi Srivatsavai ASSERT(RW_WRITE_HELD(&simnet_dev_lock)); 455b509e89bSRishi Srivatsavai if ((sdev_peer = sdev->sd_peer_dev) != NULL) { 456b509e89bSRishi Srivatsavai ASSERT(sdev == sdev_peer->sd_peer_dev); 457b509e89bSRishi Srivatsavai sdev_peer->sd_peer_dev = NULL; 458b509e89bSRishi Srivatsavai sdev->sd_peer_dev = NULL; 459b509e89bSRishi Srivatsavai peer_link_id = sdev_peer->sd_link_id; 460b509e89bSRishi Srivatsavai /* Release previous references held on both simnets */ 461b509e89bSRishi Srivatsavai simnet_dev_unref(sdev_peer); 462b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 463b509e89bSRishi Srivatsavai } 464b509e89bSRishi Srivatsavai 465b509e89bSRishi Srivatsavai return (peer_link_id); 466b509e89bSRishi Srivatsavai } 467b509e89bSRishi Srivatsavai 468b509e89bSRishi Srivatsavai /* ARGSUSED */ 469b509e89bSRishi Srivatsavai static int 470b509e89bSRishi Srivatsavai simnet_ioc_modify(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp) 471b509e89bSRishi Srivatsavai { 472b509e89bSRishi Srivatsavai simnet_ioc_modify_t *modify_arg = karg; 473b509e89bSRishi Srivatsavai simnet_dev_t *sdev; 474b509e89bSRishi Srivatsavai simnet_dev_t *sdev_peer = NULL; 475b509e89bSRishi Srivatsavai 476b509e89bSRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER); 477b509e89bSRishi Srivatsavai if ((sdev = simnet_dev_lookup(modify_arg->sim_link_id)) == NULL) { 478b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 479b509e89bSRishi Srivatsavai return (ENOENT); 480b509e89bSRishi Srivatsavai } 481b509e89bSRishi Srivatsavai 4822b24ab6bSSebastien Roy if (sdev->sd_zoneid != crgetzoneid(cred)) { 4832b24ab6bSSebastien Roy rw_exit(&simnet_dev_lock); 4842b24ab6bSSebastien Roy simnet_dev_unref(sdev); 4852b24ab6bSSebastien Roy return (ENOENT); 4862b24ab6bSSebastien Roy } 4872b24ab6bSSebastien Roy 488b509e89bSRishi Srivatsavai if (sdev->sd_link_id == modify_arg->sim_peer_link_id) { 489b509e89bSRishi Srivatsavai /* Cannot peer with self */ 490b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 491b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 492b509e89bSRishi Srivatsavai return (EINVAL); 493b509e89bSRishi Srivatsavai } 494b509e89bSRishi Srivatsavai 495b509e89bSRishi Srivatsavai if (sdev->sd_peer_dev != NULL && sdev->sd_peer_dev->sd_link_id == 496b509e89bSRishi Srivatsavai modify_arg->sim_peer_link_id) { 497b509e89bSRishi Srivatsavai /* Nothing to modify */ 498b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 499b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 500b509e89bSRishi Srivatsavai return (0); 501b509e89bSRishi Srivatsavai } 502b509e89bSRishi Srivatsavai 5032b24ab6bSSebastien Roy if (modify_arg->sim_peer_link_id != DATALINK_INVALID_LINKID) { 5042b24ab6bSSebastien Roy sdev_peer = simnet_dev_lookup(modify_arg->sim_peer_link_id); 5052b24ab6bSSebastien Roy if (sdev_peer == NULL) { 506b509e89bSRishi Srivatsavai /* Peer simnet device not available */ 507b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 508b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 509b509e89bSRishi Srivatsavai return (ENOENT); 510b509e89bSRishi Srivatsavai } 5112b24ab6bSSebastien Roy if (sdev_peer->sd_zoneid != sdev->sd_zoneid) { 5122b24ab6bSSebastien Roy /* The two peers must be in the same zone (for now). */ 5132b24ab6bSSebastien Roy rw_exit(&simnet_dev_lock); 5142b24ab6bSSebastien Roy simnet_dev_unref(sdev); 5152b24ab6bSSebastien Roy simnet_dev_unref(sdev_peer); 5162b24ab6bSSebastien Roy return (EACCES); 5172b24ab6bSSebastien Roy } 5182b24ab6bSSebastien Roy } 519b509e89bSRishi Srivatsavai 520b509e89bSRishi Srivatsavai /* First remove any previous peer */ 521b509e89bSRishi Srivatsavai (void) simnet_remove_peer(sdev); 522b509e89bSRishi Srivatsavai 523b509e89bSRishi Srivatsavai if (sdev_peer != NULL) { 524b509e89bSRishi Srivatsavai /* Remove any previous peer of sdev_peer */ 525b509e89bSRishi Srivatsavai (void) simnet_remove_peer(sdev_peer); 526b509e89bSRishi Srivatsavai /* Update both devices with the new peer */ 527b509e89bSRishi Srivatsavai sdev_peer->sd_peer_dev = sdev; 528b509e89bSRishi Srivatsavai sdev->sd_peer_dev = sdev_peer; 529b509e89bSRishi Srivatsavai /* Hold references on both devices */ 530b509e89bSRishi Srivatsavai } else { 531b509e89bSRishi Srivatsavai /* Release sdev lookup reference */ 532b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 533b509e89bSRishi Srivatsavai } 534b509e89bSRishi Srivatsavai 535b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 536b509e89bSRishi Srivatsavai return (0); 537b509e89bSRishi Srivatsavai } 538b509e89bSRishi Srivatsavai 539b509e89bSRishi Srivatsavai /* ARGSUSED */ 540b509e89bSRishi Srivatsavai static int 541b509e89bSRishi Srivatsavai simnet_ioc_delete(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp) 542b509e89bSRishi Srivatsavai { 543b509e89bSRishi Srivatsavai int err; 544b509e89bSRishi Srivatsavai simnet_dev_t *sdev; 545b509e89bSRishi Srivatsavai simnet_dev_t *sdev_peer; 546b509e89bSRishi Srivatsavai simnet_ioc_delete_t *delete_arg = karg; 547b509e89bSRishi Srivatsavai datalink_id_t tmpid; 548b509e89bSRishi Srivatsavai datalink_id_t peerid; 549b509e89bSRishi Srivatsavai 550b509e89bSRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER); 551b509e89bSRishi Srivatsavai if ((sdev = simnet_dev_lookup(delete_arg->sid_link_id)) == NULL) { 552b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 553b509e89bSRishi Srivatsavai return (ENOENT); 554b509e89bSRishi Srivatsavai } 555b509e89bSRishi Srivatsavai 5562b24ab6bSSebastien Roy if (sdev->sd_zoneid != crgetzoneid(cred)) { 5572b24ab6bSSebastien Roy rw_exit(&simnet_dev_lock); 5582b24ab6bSSebastien Roy simnet_dev_unref(sdev); 5592b24ab6bSSebastien Roy return (ENOENT); 5602b24ab6bSSebastien Roy } 5612b24ab6bSSebastien Roy 562b509e89bSRishi Srivatsavai if ((err = dls_devnet_destroy(sdev->sd_mh, &tmpid, B_TRUE)) != 0) { 563b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 564b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 565b509e89bSRishi Srivatsavai return (err); 566b509e89bSRishi Srivatsavai } 567b509e89bSRishi Srivatsavai 568b509e89bSRishi Srivatsavai ASSERT(sdev->sd_link_id == tmpid); 569b509e89bSRishi Srivatsavai /* Remove any attached peer link */ 570b509e89bSRishi Srivatsavai peerid = simnet_remove_peer(sdev); 571b509e89bSRishi Srivatsavai 572b509e89bSRishi Srivatsavai /* Prevent new threads from using the instance */ 573b509e89bSRishi Srivatsavai mutex_enter(&sdev->sd_instlock); 574b509e89bSRishi Srivatsavai sdev->sd_flags |= SDF_SHUTDOWN; 575b509e89bSRishi Srivatsavai /* Wait until all active threads using the instance exit */ 576b509e89bSRishi Srivatsavai while (sdev->sd_threadcount > 0) { 577b509e89bSRishi Srivatsavai if (cv_wait_sig(&sdev->sd_threadwait, 578b509e89bSRishi Srivatsavai &sdev->sd_instlock) == 0) { 579b509e89bSRishi Srivatsavai /* Signaled */ 580b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 581b509e89bSRishi Srivatsavai err = EINTR; 582b509e89bSRishi Srivatsavai goto fail; 583b509e89bSRishi Srivatsavai } 584b509e89bSRishi Srivatsavai } 585b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 586b509e89bSRishi Srivatsavai 587b509e89bSRishi Srivatsavai /* Try disabling the MAC */ 588b509e89bSRishi Srivatsavai if ((err = mac_disable(sdev->sd_mh)) != 0) 589b509e89bSRishi Srivatsavai goto fail; 590b509e89bSRishi Srivatsavai 591b509e89bSRishi Srivatsavai list_remove(&simnet_dev_list, sdev); 592b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 593b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); /* Release lookup ref */ 594b509e89bSRishi Srivatsavai /* Releasing the last ref performs sdev/mem free */ 595b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 596b509e89bSRishi Srivatsavai return (err); 597b509e89bSRishi Srivatsavai fail: 598b509e89bSRishi Srivatsavai /* Re-create simnet instance and add any previous peer */ 5992b24ab6bSSebastien Roy (void) dls_devnet_create(sdev->sd_mh, sdev->sd_link_id, 6002b24ab6bSSebastien Roy crgetzoneid(cred)); 601b509e89bSRishi Srivatsavai sdev->sd_flags &= ~SDF_SHUTDOWN; 602b509e89bSRishi Srivatsavai 603b509e89bSRishi Srivatsavai ASSERT(sdev->sd_peer_dev == NULL); 604b509e89bSRishi Srivatsavai if (peerid != DATALINK_INVALID_LINKID && 605b509e89bSRishi Srivatsavai ((sdev_peer = simnet_dev_lookup(peerid)) != NULL)) { 606b509e89bSRishi Srivatsavai /* Attach peer device back */ 607b509e89bSRishi Srivatsavai ASSERT(sdev_peer->sd_peer_dev == NULL); 608b509e89bSRishi Srivatsavai sdev_peer->sd_peer_dev = sdev; 609b509e89bSRishi Srivatsavai sdev->sd_peer_dev = sdev_peer; 610b509e89bSRishi Srivatsavai /* Hold reference on both devices */ 611b509e89bSRishi Srivatsavai } else { 612b509e89bSRishi Srivatsavai /* 613b509e89bSRishi Srivatsavai * No previous peer or previous peer no longer 614b509e89bSRishi Srivatsavai * available so release lookup reference. 615b509e89bSRishi Srivatsavai */ 616b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 617b509e89bSRishi Srivatsavai } 618b509e89bSRishi Srivatsavai 619b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 620b509e89bSRishi Srivatsavai return (err); 621b509e89bSRishi Srivatsavai } 622b509e89bSRishi Srivatsavai 623b509e89bSRishi Srivatsavai /* ARGSUSED */ 624b509e89bSRishi Srivatsavai static int 625b509e89bSRishi Srivatsavai simnet_ioc_info(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp) 626b509e89bSRishi Srivatsavai { 627b509e89bSRishi Srivatsavai simnet_ioc_info_t *info_arg = karg; 628b509e89bSRishi Srivatsavai simnet_dev_t *sdev; 629b509e89bSRishi Srivatsavai 6302b24ab6bSSebastien Roy /* Make sure that the simnet link is visible from the caller's zone. */ 6312b24ab6bSSebastien Roy if (!dls_devnet_islinkvisible(info_arg->sii_link_id, crgetzoneid(cred))) 6322b24ab6bSSebastien Roy return (ENOENT); 6332b24ab6bSSebastien Roy 634b509e89bSRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_READER); 635b509e89bSRishi Srivatsavai if ((sdev = simnet_dev_lookup(info_arg->sii_link_id)) == NULL) { 636b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 637b509e89bSRishi Srivatsavai return (ENOENT); 638b509e89bSRishi Srivatsavai } 639b509e89bSRishi Srivatsavai 640b509e89bSRishi Srivatsavai (void) memcpy(info_arg->sii_mac_addr, sdev->sd_mac_addr, 641b509e89bSRishi Srivatsavai sdev->sd_mac_len); 642b509e89bSRishi Srivatsavai info_arg->sii_mac_len = sdev->sd_mac_len; 643b509e89bSRishi Srivatsavai info_arg->sii_type = sdev->sd_type; 644b509e89bSRishi Srivatsavai if (sdev->sd_peer_dev != NULL) 645b509e89bSRishi Srivatsavai info_arg->sii_peer_link_id = sdev->sd_peer_dev->sd_link_id; 646b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 647b509e89bSRishi Srivatsavai simnet_dev_unref(sdev); 648b509e89bSRishi Srivatsavai return (0); 649b509e89bSRishi Srivatsavai } 650b509e89bSRishi Srivatsavai 6510f83d385SRishi Srivatsavai static boolean_t 6520f83d385SRishi Srivatsavai simnet_thread_ref(simnet_dev_t *sdev) 653b509e89bSRishi Srivatsavai { 6540f83d385SRishi Srivatsavai mutex_enter(&sdev->sd_instlock); 6550f83d385SRishi Srivatsavai if (sdev->sd_flags & SDF_SHUTDOWN || 6560f83d385SRishi Srivatsavai !(sdev->sd_flags & SDF_STARTED)) { 6570f83d385SRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 6580f83d385SRishi Srivatsavai return (B_FALSE); 6590f83d385SRishi Srivatsavai } 6600f83d385SRishi Srivatsavai sdev->sd_threadcount++; 6610f83d385SRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 6620f83d385SRishi Srivatsavai return (B_TRUE); 6630f83d385SRishi Srivatsavai } 6640f83d385SRishi Srivatsavai 6650f83d385SRishi Srivatsavai static void 6660f83d385SRishi Srivatsavai simnet_thread_unref(simnet_dev_t *sdev) 6670f83d385SRishi Srivatsavai { 6680f83d385SRishi Srivatsavai mutex_enter(&sdev->sd_instlock); 6690f83d385SRishi Srivatsavai if (--sdev->sd_threadcount == 0) 6700f83d385SRishi Srivatsavai cv_broadcast(&sdev->sd_threadwait); 6710f83d385SRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 6720f83d385SRishi Srivatsavai } 6730f83d385SRishi Srivatsavai 6740f83d385SRishi Srivatsavai static void 6750f83d385SRishi Srivatsavai simnet_rx(void *arg) 6760f83d385SRishi Srivatsavai { 6770f83d385SRishi Srivatsavai mblk_t *mp = arg; 678b509e89bSRishi Srivatsavai mac_header_info_t hdr_info; 6790f83d385SRishi Srivatsavai simnet_dev_t *sdev; 6800f83d385SRishi Srivatsavai 6810f83d385SRishi Srivatsavai sdev = (simnet_dev_t *)mp->b_next; 6820f83d385SRishi Srivatsavai mp->b_next = NULL; 683b509e89bSRishi Srivatsavai 684b509e89bSRishi Srivatsavai /* Check for valid packet header */ 685b509e89bSRishi Srivatsavai if (mac_header_info(sdev->sd_mh, mp, &hdr_info) != 0) { 686b509e89bSRishi Srivatsavai freemsg(mp); 687b509e89bSRishi Srivatsavai sdev->sd_stats.recv_errors++; 6880f83d385SRishi Srivatsavai goto rx_done; 689b509e89bSRishi Srivatsavai } 690b509e89bSRishi Srivatsavai 691b509e89bSRishi Srivatsavai /* 692b509e89bSRishi Srivatsavai * When we are NOT in promiscuous mode we only receive 693b509e89bSRishi Srivatsavai * unicast packets addressed to us and multicast packets that 694b509e89bSRishi Srivatsavai * MAC clients have requested. 695b509e89bSRishi Srivatsavai */ 696b509e89bSRishi Srivatsavai if (!sdev->sd_promisc && 697b509e89bSRishi Srivatsavai hdr_info.mhi_dsttype != MAC_ADDRTYPE_BROADCAST) { 698b509e89bSRishi Srivatsavai if (hdr_info.mhi_dsttype == MAC_ADDRTYPE_UNICAST && 699b509e89bSRishi Srivatsavai bcmp(hdr_info.mhi_daddr, sdev->sd_mac_addr, 700b509e89bSRishi Srivatsavai ETHERADDRL) != 0) { 701b509e89bSRishi Srivatsavai freemsg(mp); 7020f83d385SRishi Srivatsavai goto rx_done; 703b509e89bSRishi Srivatsavai } else if (hdr_info.mhi_dsttype == MAC_ADDRTYPE_MULTICAST) { 704b509e89bSRishi Srivatsavai mutex_enter(&sdev->sd_instlock); 705b509e89bSRishi Srivatsavai if (mcastaddr_lookup(sdev, hdr_info.mhi_daddr) == 706b509e89bSRishi Srivatsavai NULL) { 707b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 708b509e89bSRishi Srivatsavai freemsg(mp); 7090f83d385SRishi Srivatsavai goto rx_done; 710b509e89bSRishi Srivatsavai } 711b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 712b509e89bSRishi Srivatsavai } 713b509e89bSRishi Srivatsavai } 714b509e89bSRishi Srivatsavai 715b509e89bSRishi Srivatsavai sdev->sd_stats.recv_count++; 716b509e89bSRishi Srivatsavai sdev->sd_stats.rbytes += msgdsize(mp); 717b509e89bSRishi Srivatsavai mac_rx(sdev->sd_mh, NULL, mp); 7180f83d385SRishi Srivatsavai rx_done: 7190f83d385SRishi Srivatsavai simnet_thread_unref(sdev); 720b509e89bSRishi Srivatsavai } 721b509e89bSRishi Srivatsavai 722b509e89bSRishi Srivatsavai static mblk_t * 723b509e89bSRishi Srivatsavai simnet_m_tx(void *arg, mblk_t *mp_chain) 724b509e89bSRishi Srivatsavai { 725b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 726b509e89bSRishi Srivatsavai simnet_dev_t *sdev_rx; 727b509e89bSRishi Srivatsavai mblk_t *mpnext = mp_chain; 728b509e89bSRishi Srivatsavai mblk_t *mp; 729b509e89bSRishi Srivatsavai 730b509e89bSRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_READER); 731b509e89bSRishi Srivatsavai if ((sdev_rx = sdev->sd_peer_dev) == NULL) { 732b509e89bSRishi Srivatsavai /* Discard packets when no peer exists */ 733b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 734b509e89bSRishi Srivatsavai freemsgchain(mp_chain); 735b509e89bSRishi Srivatsavai return (NULL); 736b509e89bSRishi Srivatsavai } 737b509e89bSRishi Srivatsavai 738b509e89bSRishi Srivatsavai /* 739b509e89bSRishi Srivatsavai * Discard packets when either device is shutting down or not ready. 740b509e89bSRishi Srivatsavai * Though MAC layer ensures a reference is held on the MAC while we 741b509e89bSRishi Srivatsavai * process the packet chain, there is no guarantee the peer MAC will 742b509e89bSRishi Srivatsavai * remain enabled. So we increment per-instance threadcount to ensure 743b509e89bSRishi Srivatsavai * either MAC instance is not disabled while we handle the chain of 744b509e89bSRishi Srivatsavai * packets. It is okay if the peer device is disconnected while we are 745b509e89bSRishi Srivatsavai * here since we lookup the peer device while holding simnet_dev_lock 746b509e89bSRishi Srivatsavai * (reader lock) and increment the threadcount of the peer, the peer 747b509e89bSRishi Srivatsavai * MAC cannot be disabled in simnet_ioc_delete. 748b509e89bSRishi Srivatsavai */ 7490f83d385SRishi Srivatsavai if (!simnet_thread_ref(sdev_rx)) { 750b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 751b509e89bSRishi Srivatsavai freemsgchain(mp_chain); 752b509e89bSRishi Srivatsavai return (NULL); 753b509e89bSRishi Srivatsavai } 754b509e89bSRishi Srivatsavai rw_exit(&simnet_dev_lock); 755b509e89bSRishi Srivatsavai 7560f83d385SRishi Srivatsavai if (!simnet_thread_ref(sdev)) { 7570f83d385SRishi Srivatsavai simnet_thread_unref(sdev_rx); 758b509e89bSRishi Srivatsavai freemsgchain(mp_chain); 759b509e89bSRishi Srivatsavai return (NULL); 760b509e89bSRishi Srivatsavai } 761b509e89bSRishi Srivatsavai 762b509e89bSRishi Srivatsavai while ((mp = mpnext) != NULL) { 763b509e89bSRishi Srivatsavai int len; 764b509e89bSRishi Srivatsavai int size; 765b509e89bSRishi Srivatsavai mblk_t *mp_new; 766b509e89bSRishi Srivatsavai mblk_t *mp_tmp; 767b509e89bSRishi Srivatsavai 768b509e89bSRishi Srivatsavai mpnext = mp->b_next; 769b509e89bSRishi Srivatsavai mp->b_next = NULL; 770b509e89bSRishi Srivatsavai len = msgdsize(mp); 771b509e89bSRishi Srivatsavai 772b509e89bSRishi Srivatsavai /* Pad packet to minimum Ethernet frame size */ 773b509e89bSRishi Srivatsavai if (len < ETHERMIN) { 774b509e89bSRishi Srivatsavai size = ETHERMIN - len; 775b509e89bSRishi Srivatsavai mp_new = allocb(size, BPRI_HI); 776b509e89bSRishi Srivatsavai if (mp_new == NULL) { 777b509e89bSRishi Srivatsavai sdev->sd_stats.xmit_errors++; 778b509e89bSRishi Srivatsavai freemsg(mp); 779b509e89bSRishi Srivatsavai continue; 780b509e89bSRishi Srivatsavai } 781b509e89bSRishi Srivatsavai bzero(mp_new->b_wptr, size); 782b509e89bSRishi Srivatsavai mp_new->b_wptr += size; 783b509e89bSRishi Srivatsavai 784b509e89bSRishi Srivatsavai mp_tmp = mp; 785b509e89bSRishi Srivatsavai while (mp_tmp->b_cont != NULL) 786b509e89bSRishi Srivatsavai mp_tmp = mp_tmp->b_cont; 787b509e89bSRishi Srivatsavai mp_tmp->b_cont = mp_new; 788b509e89bSRishi Srivatsavai len += size; 789b509e89bSRishi Srivatsavai } 790b509e89bSRishi Srivatsavai 791b509e89bSRishi Srivatsavai /* Pullup packet into a single mblk */ 792b509e89bSRishi Srivatsavai if (!pullupmsg(mp, -1)) { 793b509e89bSRishi Srivatsavai sdev->sd_stats.xmit_errors++; 794b509e89bSRishi Srivatsavai freemsg(mp); 795b509e89bSRishi Srivatsavai continue; 796b509e89bSRishi Srivatsavai } 797b509e89bSRishi Srivatsavai 798b509e89bSRishi Srivatsavai /* Fix mblk checksum as the pkt dest is local */ 799b509e89bSRishi Srivatsavai if ((mp = mac_fix_cksum(mp)) == NULL) { 800b509e89bSRishi Srivatsavai sdev->sd_stats.xmit_errors++; 801b509e89bSRishi Srivatsavai continue; 802b509e89bSRishi Srivatsavai } 803b509e89bSRishi Srivatsavai 8040f83d385SRishi Srivatsavai /* Hold reference for taskq receive processing per-pkt */ 8050f83d385SRishi Srivatsavai if (!simnet_thread_ref(sdev_rx)) { 8060f83d385SRishi Srivatsavai freemsg(mp); 8070f83d385SRishi Srivatsavai freemsgchain(mpnext); 8080f83d385SRishi Srivatsavai break; 809b509e89bSRishi Srivatsavai } 810b509e89bSRishi Srivatsavai 8110f83d385SRishi Srivatsavai /* Use taskq for pkt receive to avoid kernel stack explosion */ 8120f83d385SRishi Srivatsavai mp->b_next = (mblk_t *)sdev_rx; 8130f83d385SRishi Srivatsavai if (ddi_taskq_dispatch(simnet_rxq, simnet_rx, mp, 8140f83d385SRishi Srivatsavai DDI_NOSLEEP) == DDI_SUCCESS) { 8150f83d385SRishi Srivatsavai sdev->sd_stats.xmit_count++; 8160f83d385SRishi Srivatsavai sdev->sd_stats.obytes += len; 8170f83d385SRishi Srivatsavai } else { 8180f83d385SRishi Srivatsavai simnet_thread_unref(sdev_rx); 8190f83d385SRishi Srivatsavai mp->b_next = NULL; 8200f83d385SRishi Srivatsavai freemsg(mp); 8210f83d385SRishi Srivatsavai sdev_rx->sd_stats.recv_errors++; 8220f83d385SRishi Srivatsavai } 8230f83d385SRishi Srivatsavai } 8240f83d385SRishi Srivatsavai 8250f83d385SRishi Srivatsavai simnet_thread_unref(sdev); 8260f83d385SRishi Srivatsavai simnet_thread_unref(sdev_rx); 827b509e89bSRishi Srivatsavai return (NULL); 828b509e89bSRishi Srivatsavai } 829b509e89bSRishi Srivatsavai 830b509e89bSRishi Srivatsavai static int 831b509e89bSRishi Srivatsavai simnet_wifi_ioctl(simnet_dev_t *sdev, mblk_t *mp) 832b509e89bSRishi Srivatsavai { 833b509e89bSRishi Srivatsavai int rc = WL_SUCCESS; 834b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 835b509e89bSRishi Srivatsavai 836b509e89bSRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */ 837b509e89bSRishi Srivatsavai switch (((wldp_t *)mp->b_rptr)->wldp_id) { 838b509e89bSRishi Srivatsavai case WL_DISASSOCIATE: 839b509e89bSRishi Srivatsavai wdev->swd_linkstatus = WL_NOTCONNECTED; 840b509e89bSRishi Srivatsavai break; 841b509e89bSRishi Srivatsavai default: 842b509e89bSRishi Srivatsavai break; 843b509e89bSRishi Srivatsavai } 844b509e89bSRishi Srivatsavai return (rc); 845b509e89bSRishi Srivatsavai } 846b509e89bSRishi Srivatsavai 847b509e89bSRishi Srivatsavai static void 848b509e89bSRishi Srivatsavai simnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 849b509e89bSRishi Srivatsavai { 850b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 851b509e89bSRishi Srivatsavai struct iocblk *iocp; 852b509e89bSRishi Srivatsavai mblk_t *mp1; 853b509e89bSRishi Srivatsavai uint32_t cmd; 854b509e89bSRishi Srivatsavai int rc; 855b509e89bSRishi Srivatsavai 856b509e89bSRishi Srivatsavai if (sdev->sd_type != DL_WIFI) { 857b509e89bSRishi Srivatsavai miocnak(q, mp, 0, ENOTSUP); 858b509e89bSRishi Srivatsavai return; 859b509e89bSRishi Srivatsavai } 860b509e89bSRishi Srivatsavai 861b509e89bSRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */ 862b509e89bSRishi Srivatsavai iocp = (struct iocblk *)mp->b_rptr; 863b509e89bSRishi Srivatsavai if (iocp->ioc_count == 0) { 864b509e89bSRishi Srivatsavai miocnak(q, mp, 0, EINVAL); 865b509e89bSRishi Srivatsavai return; 866b509e89bSRishi Srivatsavai } 867b509e89bSRishi Srivatsavai 868b509e89bSRishi Srivatsavai /* We only claim support for WiFi operation commands */ 869b509e89bSRishi Srivatsavai cmd = iocp->ioc_cmd; 870b509e89bSRishi Srivatsavai switch (cmd) { 871b509e89bSRishi Srivatsavai default: 872b509e89bSRishi Srivatsavai miocnak(q, mp, 0, EINVAL); 873b509e89bSRishi Srivatsavai return; 874b509e89bSRishi Srivatsavai case WLAN_GET_PARAM: 875b509e89bSRishi Srivatsavai case WLAN_SET_PARAM: 876b509e89bSRishi Srivatsavai case WLAN_COMMAND: 877b509e89bSRishi Srivatsavai break; 878b509e89bSRishi Srivatsavai } 879b509e89bSRishi Srivatsavai 880b509e89bSRishi Srivatsavai mp1 = mp->b_cont; 881b509e89bSRishi Srivatsavai freemsg(mp1->b_cont); 882b509e89bSRishi Srivatsavai mp1->b_cont = NULL; 883b509e89bSRishi Srivatsavai /* overwrite everything */ 884b509e89bSRishi Srivatsavai mp1->b_wptr = mp1->b_rptr; 885b509e89bSRishi Srivatsavai rc = simnet_wifi_ioctl(sdev, mp1); 886b509e89bSRishi Srivatsavai miocack(q, mp, msgdsize(mp1), rc); 887b509e89bSRishi Srivatsavai } 888b509e89bSRishi Srivatsavai 889b509e89bSRishi Srivatsavai static int 890b509e89bSRishi Srivatsavai simnet_m_stat(void *arg, uint_t stat, uint64_t *val) 891b509e89bSRishi Srivatsavai { 892b509e89bSRishi Srivatsavai int rval = 0; 893b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 894b509e89bSRishi Srivatsavai 895b509e89bSRishi Srivatsavai ASSERT(sdev->sd_mh != NULL); 896b509e89bSRishi Srivatsavai 897b509e89bSRishi Srivatsavai switch (stat) { 898b509e89bSRishi Srivatsavai case MAC_STAT_IFSPEED: 899b509e89bSRishi Srivatsavai *val = 100 * 1000000ull; /* 100 Mbps */ 900b509e89bSRishi Srivatsavai break; 901b509e89bSRishi Srivatsavai case MAC_STAT_LINK_STATE: 902b509e89bSRishi Srivatsavai *val = LINK_DUPLEX_FULL; 903b509e89bSRishi Srivatsavai break; 904b509e89bSRishi Srivatsavai case MAC_STAT_LINK_UP: 905b509e89bSRishi Srivatsavai if (sdev->sd_flags & SDF_STARTED) 906b509e89bSRishi Srivatsavai *val = LINK_STATE_UP; 907b509e89bSRishi Srivatsavai else 908b509e89bSRishi Srivatsavai *val = LINK_STATE_DOWN; 909b509e89bSRishi Srivatsavai break; 910b509e89bSRishi Srivatsavai case MAC_STAT_PROMISC: 911b509e89bSRishi Srivatsavai case MAC_STAT_MULTIRCV: 912b509e89bSRishi Srivatsavai case MAC_STAT_MULTIXMT: 913b509e89bSRishi Srivatsavai case MAC_STAT_BRDCSTRCV: 914b509e89bSRishi Srivatsavai case MAC_STAT_BRDCSTXMT: 915b509e89bSRishi Srivatsavai rval = ENOTSUP; 916b509e89bSRishi Srivatsavai break; 917b509e89bSRishi Srivatsavai case MAC_STAT_OPACKETS: 918b509e89bSRishi Srivatsavai *val = sdev->sd_stats.xmit_count; 919b509e89bSRishi Srivatsavai break; 920b509e89bSRishi Srivatsavai case MAC_STAT_OBYTES: 921b509e89bSRishi Srivatsavai *val = sdev->sd_stats.obytes; 922b509e89bSRishi Srivatsavai break; 923b509e89bSRishi Srivatsavai case MAC_STAT_IERRORS: 924b509e89bSRishi Srivatsavai *val = sdev->sd_stats.recv_errors; 925b509e89bSRishi Srivatsavai break; 926b509e89bSRishi Srivatsavai case MAC_STAT_OERRORS: 927b509e89bSRishi Srivatsavai *val = sdev->sd_stats.xmit_errors; 928b509e89bSRishi Srivatsavai break; 929b509e89bSRishi Srivatsavai case MAC_STAT_RBYTES: 930b509e89bSRishi Srivatsavai *val = sdev->sd_stats.rbytes; 931b509e89bSRishi Srivatsavai break; 932b509e89bSRishi Srivatsavai case MAC_STAT_IPACKETS: 933b509e89bSRishi Srivatsavai *val = sdev->sd_stats.recv_count; 934b509e89bSRishi Srivatsavai break; 935b509e89bSRishi Srivatsavai case WIFI_STAT_FCS_ERRORS: 936b509e89bSRishi Srivatsavai case WIFI_STAT_WEP_ERRORS: 937b509e89bSRishi Srivatsavai case WIFI_STAT_TX_FRAGS: 938b509e89bSRishi Srivatsavai case WIFI_STAT_MCAST_TX: 939b509e89bSRishi Srivatsavai case WIFI_STAT_RTS_SUCCESS: 940b509e89bSRishi Srivatsavai case WIFI_STAT_RTS_FAILURE: 941b509e89bSRishi Srivatsavai case WIFI_STAT_ACK_FAILURE: 942b509e89bSRishi Srivatsavai case WIFI_STAT_RX_FRAGS: 943b509e89bSRishi Srivatsavai case WIFI_STAT_MCAST_RX: 944b509e89bSRishi Srivatsavai case WIFI_STAT_RX_DUPS: 945b509e89bSRishi Srivatsavai rval = ENOTSUP; 946b509e89bSRishi Srivatsavai break; 947b509e89bSRishi Srivatsavai default: 948b509e89bSRishi Srivatsavai rval = ENOTSUP; 949b509e89bSRishi Srivatsavai break; 950b509e89bSRishi Srivatsavai } 951b509e89bSRishi Srivatsavai 952b509e89bSRishi Srivatsavai return (rval); 953b509e89bSRishi Srivatsavai } 954b509e89bSRishi Srivatsavai 955b509e89bSRishi Srivatsavai static int 956b509e89bSRishi Srivatsavai simnet_m_start(void *arg) 957b509e89bSRishi Srivatsavai { 958b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 959b509e89bSRishi Srivatsavai 960b509e89bSRishi Srivatsavai sdev->sd_flags |= SDF_STARTED; 961b509e89bSRishi Srivatsavai return (0); 962b509e89bSRishi Srivatsavai } 963b509e89bSRishi Srivatsavai 964b509e89bSRishi Srivatsavai static void 965b509e89bSRishi Srivatsavai simnet_m_stop(void *arg) 966b509e89bSRishi Srivatsavai { 967b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 968b509e89bSRishi Srivatsavai 969b509e89bSRishi Srivatsavai sdev->sd_flags &= ~SDF_STARTED; 970b509e89bSRishi Srivatsavai } 971b509e89bSRishi Srivatsavai 972b509e89bSRishi Srivatsavai static int 973b509e89bSRishi Srivatsavai simnet_m_promisc(void *arg, boolean_t on) 974b509e89bSRishi Srivatsavai { 975b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 976b509e89bSRishi Srivatsavai 977b509e89bSRishi Srivatsavai sdev->sd_promisc = on; 978b509e89bSRishi Srivatsavai return (0); 979b509e89bSRishi Srivatsavai } 980b509e89bSRishi Srivatsavai 981b509e89bSRishi Srivatsavai /* 982b509e89bSRishi Srivatsavai * Returns matching multicast address enabled on the simnet instance. 983b509e89bSRishi Srivatsavai * Assumes simnet instance mutex lock is held. 984b509e89bSRishi Srivatsavai */ 985b509e89bSRishi Srivatsavai static uint8_t * 986b509e89bSRishi Srivatsavai mcastaddr_lookup(simnet_dev_t *sdev, const uint8_t *addrp) 987b509e89bSRishi Srivatsavai { 988b509e89bSRishi Srivatsavai int idx; 989b509e89bSRishi Srivatsavai uint8_t *maddrptr; 990b509e89bSRishi Srivatsavai 9910f83d385SRishi Srivatsavai ASSERT(MUTEX_HELD(&sdev->sd_instlock)); 992b509e89bSRishi Srivatsavai maddrptr = sdev->sd_mcastaddrs; 993b509e89bSRishi Srivatsavai for (idx = 0; idx < sdev->sd_mcastaddr_count; idx++) { 994b509e89bSRishi Srivatsavai if (bcmp(maddrptr, addrp, ETHERADDRL) == 0) 995b509e89bSRishi Srivatsavai return (maddrptr); 996b509e89bSRishi Srivatsavai maddrptr += ETHERADDRL; 997b509e89bSRishi Srivatsavai } 998b509e89bSRishi Srivatsavai 999b509e89bSRishi Srivatsavai return (NULL); 1000b509e89bSRishi Srivatsavai } 1001b509e89bSRishi Srivatsavai 1002b509e89bSRishi Srivatsavai /* Add or remove Multicast addresses on simnet instance */ 1003b509e89bSRishi Srivatsavai static int 1004b509e89bSRishi Srivatsavai simnet_m_multicst(void *arg, boolean_t add, const uint8_t *addrp) 1005b509e89bSRishi Srivatsavai { 1006b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 1007b509e89bSRishi Srivatsavai uint8_t *maddrptr; 1008b509e89bSRishi Srivatsavai uint8_t *newbuf; 1009b509e89bSRishi Srivatsavai size_t prevsize; 1010b509e89bSRishi Srivatsavai size_t newsize; 1011b509e89bSRishi Srivatsavai ptrdiff_t len; 1012b509e89bSRishi Srivatsavai ptrdiff_t len2; 1013b509e89bSRishi Srivatsavai 1014b509e89bSRishi Srivatsavai alloc_retry: 1015b509e89bSRishi Srivatsavai prevsize = sdev->sd_mcastaddr_count * ETHERADDRL; 1016b509e89bSRishi Srivatsavai newsize = prevsize + (add ? ETHERADDRL:-ETHERADDRL); 1017b509e89bSRishi Srivatsavai newbuf = kmem_alloc(newsize, KM_SLEEP); 1018b509e89bSRishi Srivatsavai 1019b509e89bSRishi Srivatsavai mutex_enter(&sdev->sd_instlock); 1020b509e89bSRishi Srivatsavai if (prevsize != (sdev->sd_mcastaddr_count * ETHERADDRL)) { 1021b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 1022b509e89bSRishi Srivatsavai kmem_free(newbuf, newsize); 1023b509e89bSRishi Srivatsavai goto alloc_retry; 1024b509e89bSRishi Srivatsavai } 1025b509e89bSRishi Srivatsavai 1026b509e89bSRishi Srivatsavai maddrptr = mcastaddr_lookup(sdev, addrp); 1027b509e89bSRishi Srivatsavai if (!add && maddrptr != NULL) { 1028b509e89bSRishi Srivatsavai /* Removing a Multicast address */ 1029b509e89bSRishi Srivatsavai if (newbuf != NULL) { 1030b509e89bSRishi Srivatsavai /* LINTED: E_PTRDIFF_OVERFLOW */ 1031b509e89bSRishi Srivatsavai len = maddrptr - sdev->sd_mcastaddrs; 1032b509e89bSRishi Srivatsavai (void) memcpy(newbuf, sdev->sd_mcastaddrs, len); 1033b509e89bSRishi Srivatsavai len2 = prevsize - len - ETHERADDRL; 1034b509e89bSRishi Srivatsavai (void) memcpy(newbuf + len, 1035b509e89bSRishi Srivatsavai maddrptr + ETHERADDRL, len2); 1036b509e89bSRishi Srivatsavai } 1037b509e89bSRishi Srivatsavai sdev->sd_mcastaddr_count--; 1038b509e89bSRishi Srivatsavai } else if (add && maddrptr == NULL) { 1039b509e89bSRishi Srivatsavai /* Adding a new Multicast address */ 1040b509e89bSRishi Srivatsavai (void) memcpy(newbuf, sdev->sd_mcastaddrs, prevsize); 1041b509e89bSRishi Srivatsavai (void) memcpy(newbuf + prevsize, addrp, ETHERADDRL); 1042b509e89bSRishi Srivatsavai sdev->sd_mcastaddr_count++; 1043b509e89bSRishi Srivatsavai } else { 1044b509e89bSRishi Srivatsavai /* Error: removing a non-existing Multicast address */ 1045b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 1046b509e89bSRishi Srivatsavai kmem_free(newbuf, newsize); 1047b509e89bSRishi Srivatsavai cmn_err(CE_WARN, "simnet: MAC call to remove a " 1048b509e89bSRishi Srivatsavai "Multicast address failed"); 1049b509e89bSRishi Srivatsavai return (EINVAL); 1050b509e89bSRishi Srivatsavai } 1051b509e89bSRishi Srivatsavai 1052b509e89bSRishi Srivatsavai kmem_free(sdev->sd_mcastaddrs, prevsize); 1053b509e89bSRishi Srivatsavai sdev->sd_mcastaddrs = newbuf; 1054b509e89bSRishi Srivatsavai mutex_exit(&sdev->sd_instlock); 1055b509e89bSRishi Srivatsavai return (0); 1056b509e89bSRishi Srivatsavai } 1057b509e89bSRishi Srivatsavai 1058b509e89bSRishi Srivatsavai static int 1059b509e89bSRishi Srivatsavai simnet_m_unicst(void *arg, const uint8_t *macaddr) 1060b509e89bSRishi Srivatsavai { 1061b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 1062b509e89bSRishi Srivatsavai 1063b509e89bSRishi Srivatsavai (void) memcpy(sdev->sd_mac_addr, macaddr, ETHERADDRL); 1064b509e89bSRishi Srivatsavai return (0); 1065b509e89bSRishi Srivatsavai } 1066b509e89bSRishi Srivatsavai 1067b509e89bSRishi Srivatsavai /* Parse WiFi scan list entry arguments and return the arg count */ 1068b509e89bSRishi Srivatsavai static int 1069b509e89bSRishi Srivatsavai parse_esslist_args(const void *pr_val, uint_t pr_valsize, 1070b509e89bSRishi Srivatsavai char args[][MAX_ESSLIST_ARGLEN]) 1071b509e89bSRishi Srivatsavai { 1072b509e89bSRishi Srivatsavai char *sep; 1073b509e89bSRishi Srivatsavai ptrdiff_t len = pr_valsize; 1074b509e89bSRishi Srivatsavai const char *piece = pr_val; 1075b509e89bSRishi Srivatsavai const char *end = (const char *)pr_val + pr_valsize - 1; 1076b509e89bSRishi Srivatsavai int arg = 0; 1077b509e89bSRishi Srivatsavai 1078b509e89bSRishi Srivatsavai while (piece < end && (arg < MAX_ESSLIST_ARGS)) { 1079b509e89bSRishi Srivatsavai sep = strchr(piece, ','); 1080b509e89bSRishi Srivatsavai if (sep == NULL) 1081b509e89bSRishi Srivatsavai sep = (char *)end; 1082b509e89bSRishi Srivatsavai /* LINTED E_PTRDIFF_OVERFLOW */ 1083b509e89bSRishi Srivatsavai len = sep - piece; 1084b509e89bSRishi Srivatsavai /* If first arg is zero then return none to delete all */ 1085b509e89bSRishi Srivatsavai if (arg == 0 && strnlen(piece, len) == 1 && piece[0] == '0') 1086b509e89bSRishi Srivatsavai return (0); 1087b509e89bSRishi Srivatsavai if (len > MAX_ESSLIST_ARGLEN) 1088b509e89bSRishi Srivatsavai len = MAX_ESSLIST_ARGLEN - 1; 1089b509e89bSRishi Srivatsavai (void) memcpy(&args[arg][0], piece, len); 1090b509e89bSRishi Srivatsavai args[arg][len] = '\0'; 1091b509e89bSRishi Srivatsavai piece = sep + 1; 1092b509e89bSRishi Srivatsavai arg++; 1093b509e89bSRishi Srivatsavai } 1094b509e89bSRishi Srivatsavai 1095b509e89bSRishi Srivatsavai return (arg); 1096b509e89bSRishi Srivatsavai } 1097b509e89bSRishi Srivatsavai 1098b509e89bSRishi Srivatsavai /* Set WiFi scan list entry from private property _wl_esslist */ 1099b509e89bSRishi Srivatsavai static int 1100b509e89bSRishi Srivatsavai set_wl_esslist_priv_prop(simnet_wifidev_t *wdev, uint_t pr_valsize, 1101b509e89bSRishi Srivatsavai const void *pr_val) 1102b509e89bSRishi Srivatsavai { 1103b509e89bSRishi Srivatsavai char essargs[MAX_ESSLIST_ARGS][MAX_ESSLIST_ARGLEN]; 1104b509e89bSRishi Srivatsavai wl_ess_conf_t *wls; 1105b509e89bSRishi Srivatsavai long result; 1106b509e89bSRishi Srivatsavai int i; 1107b509e89bSRishi Srivatsavai 1108b509e89bSRishi Srivatsavai bzero(essargs, sizeof (essargs)); 1109b509e89bSRishi Srivatsavai if (parse_esslist_args(pr_val, pr_valsize, essargs) == 0) { 1110b509e89bSRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) { 1111b509e89bSRishi Srivatsavai kmem_free(wdev->swd_esslist[i], sizeof (wl_ess_conf_t)); 1112b509e89bSRishi Srivatsavai wdev->swd_esslist[i] = NULL; 1113b509e89bSRishi Srivatsavai } 1114b509e89bSRishi Srivatsavai wdev->swd_esslist_num = 0; 1115b509e89bSRishi Srivatsavai return (0); 1116b509e89bSRishi Srivatsavai } 1117b509e89bSRishi Srivatsavai 1118b509e89bSRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) { 1119b509e89bSRishi Srivatsavai wls = wdev->swd_esslist[i]; 1120b509e89bSRishi Srivatsavai if (strcasecmp(wls->wl_ess_conf_essid.wl_essid_essid, 1121b509e89bSRishi Srivatsavai essargs[0]) == 0) 1122b509e89bSRishi Srivatsavai return (EEXIST); 1123b509e89bSRishi Srivatsavai } 1124b509e89bSRishi Srivatsavai 1125b509e89bSRishi Srivatsavai if (wdev->swd_esslist_num >= MAX_SIMNET_ESSCONF) 1126b509e89bSRishi Srivatsavai return (EINVAL); 1127b509e89bSRishi Srivatsavai 1128b509e89bSRishi Srivatsavai wls = kmem_zalloc(sizeof (wl_ess_conf_t), KM_SLEEP); 1129b509e89bSRishi Srivatsavai (void) strlcpy(wls->wl_ess_conf_essid.wl_essid_essid, 1130b509e89bSRishi Srivatsavai essargs[0], sizeof (wls->wl_ess_conf_essid.wl_essid_essid)); 1131b509e89bSRishi Srivatsavai wls->wl_ess_conf_essid.wl_essid_length = 1132b509e89bSRishi Srivatsavai strlen(wls->wl_ess_conf_essid.wl_essid_essid); 1133b509e89bSRishi Srivatsavai (void) random_get_pseudo_bytes((uint8_t *) 1134b509e89bSRishi Srivatsavai &wls->wl_ess_conf_bssid, sizeof (wl_bssid_t)); 1135b509e89bSRishi Srivatsavai (void) ddi_strtol(essargs[1], (char **)NULL, 0, &result); 1136b509e89bSRishi Srivatsavai wls->wl_ess_conf_sl = (wl_rssi_t) 1137b509e89bSRishi Srivatsavai ((result > MAX_RSSI || result < 0) ? 0:result); 1138b509e89bSRishi Srivatsavai wdev->swd_esslist[wdev->swd_esslist_num] = wls; 1139b509e89bSRishi Srivatsavai wdev->swd_esslist_num++; 1140b509e89bSRishi Srivatsavai 1141b509e89bSRishi Srivatsavai return (0); 1142b509e89bSRishi Srivatsavai } 1143b509e89bSRishi Srivatsavai 1144b509e89bSRishi Srivatsavai static int 1145b509e89bSRishi Srivatsavai simnet_set_priv_prop(simnet_dev_t *sdev, const char *pr_name, 1146b509e89bSRishi Srivatsavai uint_t pr_valsize, const void *pr_val) 1147b509e89bSRishi Srivatsavai { 1148b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 1149b509e89bSRishi Srivatsavai long result; 1150b509e89bSRishi Srivatsavai 1151b509e89bSRishi Srivatsavai if (strcmp(pr_name, "_wl_esslist") == 0) { 1152b509e89bSRishi Srivatsavai if (pr_val == NULL) 1153b509e89bSRishi Srivatsavai return (EINVAL); 1154b509e89bSRishi Srivatsavai return (set_wl_esslist_priv_prop(wdev, pr_valsize, pr_val)); 1155b509e89bSRishi Srivatsavai } else if (strcmp(pr_name, "_wl_connected") == 0) { 1156b509e89bSRishi Srivatsavai if (pr_val == NULL) 1157b509e89bSRishi Srivatsavai return (EINVAL); 1158b509e89bSRishi Srivatsavai (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1159b509e89bSRishi Srivatsavai wdev->swd_linkstatus = ((result == 1) ? 1160b509e89bSRishi Srivatsavai WL_CONNECTED:WL_NOTCONNECTED); 1161b509e89bSRishi Srivatsavai return (0); 1162b509e89bSRishi Srivatsavai } 1163b509e89bSRishi Srivatsavai 1164b509e89bSRishi Srivatsavai return (EINVAL); 1165b509e89bSRishi Srivatsavai } 1166b509e89bSRishi Srivatsavai 1167b509e89bSRishi Srivatsavai static int 1168b509e89bSRishi Srivatsavai simnet_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 1169b509e89bSRishi Srivatsavai uint_t wldp_length, const void *wldp_buf) 1170b509e89bSRishi Srivatsavai { 1171b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 1172b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 1173b509e89bSRishi Srivatsavai int err = 0; 1174b509e89bSRishi Srivatsavai uint32_t mtu; 1175b509e89bSRishi Srivatsavai 1176b509e89bSRishi Srivatsavai switch (wldp_pr_num) { 1177b509e89bSRishi Srivatsavai case MAC_PROP_MTU: 1178b509e89bSRishi Srivatsavai (void) memcpy(&mtu, wldp_buf, sizeof (mtu)); 1179b509e89bSRishi Srivatsavai if (mtu > ETHERMIN && mtu < SIMNET_MAX_MTU) 1180b509e89bSRishi Srivatsavai return (mac_maxsdu_update(sdev->sd_mh, mtu)); 1181b509e89bSRishi Srivatsavai else 1182b509e89bSRishi Srivatsavai return (EINVAL); 1183b509e89bSRishi Srivatsavai default: 1184b509e89bSRishi Srivatsavai break; 1185b509e89bSRishi Srivatsavai } 1186b509e89bSRishi Srivatsavai 1187b509e89bSRishi Srivatsavai if (sdev->sd_type == DL_ETHER) 1188b509e89bSRishi Srivatsavai return (ENOTSUP); 1189b509e89bSRishi Srivatsavai 1190b509e89bSRishi Srivatsavai /* mac_prop_id */ 1191b509e89bSRishi Srivatsavai switch (wldp_pr_num) { 1192b509e89bSRishi Srivatsavai case MAC_PROP_WL_ESSID: { 1193b509e89bSRishi Srivatsavai int i; 1194b509e89bSRishi Srivatsavai wl_ess_conf_t *wls; 1195b509e89bSRishi Srivatsavai 1196b509e89bSRishi Srivatsavai (void) memcpy(&wdev->swd_essid, wldp_buf, 1197b509e89bSRishi Srivatsavai sizeof (wl_essid_t)); 1198b509e89bSRishi Srivatsavai wdev->swd_linkstatus = WL_CONNECTED; 1199b509e89bSRishi Srivatsavai 1200b509e89bSRishi Srivatsavai /* Lookup the signal strength of the connected ESSID */ 1201b509e89bSRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) { 1202b509e89bSRishi Srivatsavai wls = wdev->swd_esslist[i]; 1203b509e89bSRishi Srivatsavai if (strcasecmp(wls->wl_ess_conf_essid.wl_essid_essid, 1204b509e89bSRishi Srivatsavai wdev->swd_essid.wl_essid_essid) == 0) { 1205b509e89bSRishi Srivatsavai wdev->swd_rssi = wls->wl_ess_conf_sl; 1206b509e89bSRishi Srivatsavai break; 1207b509e89bSRishi Srivatsavai } 1208b509e89bSRishi Srivatsavai } 1209b509e89bSRishi Srivatsavai break; 1210b509e89bSRishi Srivatsavai } 1211b509e89bSRishi Srivatsavai case MAC_PROP_WL_BSSID: { 1212b509e89bSRishi Srivatsavai (void) memcpy(&wdev->swd_bssid, wldp_buf, 1213b509e89bSRishi Srivatsavai sizeof (wl_bssid_t)); 1214b509e89bSRishi Srivatsavai break; 1215b509e89bSRishi Srivatsavai } 1216b509e89bSRishi Srivatsavai case MAC_PROP_WL_PHY_CONFIG: 1217b509e89bSRishi Srivatsavai case MAC_PROP_WL_KEY_TAB: 1218b509e89bSRishi Srivatsavai case MAC_PROP_WL_AUTH_MODE: 1219b509e89bSRishi Srivatsavai case MAC_PROP_WL_ENCRYPTION: 1220b509e89bSRishi Srivatsavai case MAC_PROP_WL_BSSTYPE: 1221b509e89bSRishi Srivatsavai case MAC_PROP_WL_DESIRED_RATES: 1222b509e89bSRishi Srivatsavai break; 1223b509e89bSRishi Srivatsavai case MAC_PROP_PRIVATE: 1224b509e89bSRishi Srivatsavai err = simnet_set_priv_prop(sdev, pr_name, 1225b509e89bSRishi Srivatsavai wldp_length, wldp_buf); 1226b509e89bSRishi Srivatsavai break; 1227b509e89bSRishi Srivatsavai default: 1228b509e89bSRishi Srivatsavai break; 1229b509e89bSRishi Srivatsavai } 1230b509e89bSRishi Srivatsavai 1231b509e89bSRishi Srivatsavai return (err); 1232b509e89bSRishi Srivatsavai } 1233b509e89bSRishi Srivatsavai 1234b509e89bSRishi Srivatsavai static int 1235*0dc2366fSVenugopal Iyer simnet_get_priv_prop(simnet_dev_t *sdev, const char *pr_name, 1236b509e89bSRishi Srivatsavai uint_t pr_valsize, void *pr_val) 1237b509e89bSRishi Srivatsavai { 1238b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 1239b509e89bSRishi Srivatsavai int err = 0; 1240b509e89bSRishi Srivatsavai int value; 1241b509e89bSRishi Srivatsavai 1242b509e89bSRishi Srivatsavai if (strcmp(pr_name, "_wl_esslist") == 0) { 1243b509e89bSRishi Srivatsavai /* Returns num of _wl_ess_conf_t that have been set */ 1244*0dc2366fSVenugopal Iyer value = wdev->swd_esslist_num; 1245b509e89bSRishi Srivatsavai } else if (strcmp(pr_name, "_wl_connected") == 0) { 1246b509e89bSRishi Srivatsavai value = ((wdev->swd_linkstatus == WL_CONNECTED) ? 1:0); 1247b509e89bSRishi Srivatsavai } else { 1248b509e89bSRishi Srivatsavai err = ENOTSUP; 1249b509e89bSRishi Srivatsavai } 1250b509e89bSRishi Srivatsavai 1251b509e89bSRishi Srivatsavai if (err == 0) 1252b509e89bSRishi Srivatsavai (void) snprintf(pr_val, pr_valsize, "%d", value); 1253b509e89bSRishi Srivatsavai return (err); 1254b509e89bSRishi Srivatsavai } 1255b509e89bSRishi Srivatsavai 1256b509e89bSRishi Srivatsavai static int 1257b509e89bSRishi Srivatsavai simnet_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 1258*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 1259b509e89bSRishi Srivatsavai { 1260b509e89bSRishi Srivatsavai simnet_dev_t *sdev = arg; 1261b509e89bSRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev; 1262b509e89bSRishi Srivatsavai int err = 0; 1263b509e89bSRishi Srivatsavai int i; 1264b509e89bSRishi Srivatsavai 1265b509e89bSRishi Srivatsavai if (sdev->sd_type == DL_ETHER) 1266b509e89bSRishi Srivatsavai return (ENOTSUP); 1267b509e89bSRishi Srivatsavai 1268b509e89bSRishi Srivatsavai /* mac_prop_id */ 1269b509e89bSRishi Srivatsavai switch (wldp_pr_num) { 1270b509e89bSRishi Srivatsavai case MAC_PROP_WL_ESSID: 1271b509e89bSRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_essid, 1272b509e89bSRishi Srivatsavai sizeof (wl_essid_t)); 1273b509e89bSRishi Srivatsavai break; 1274b509e89bSRishi Srivatsavai case MAC_PROP_WL_BSSID: 1275b509e89bSRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_bssid, 1276b509e89bSRishi Srivatsavai sizeof (wl_bssid_t)); 1277b509e89bSRishi Srivatsavai break; 1278b509e89bSRishi Srivatsavai case MAC_PROP_WL_PHY_CONFIG: 1279b509e89bSRishi Srivatsavai case MAC_PROP_WL_AUTH_MODE: 1280b509e89bSRishi Srivatsavai case MAC_PROP_WL_ENCRYPTION: 1281b509e89bSRishi Srivatsavai break; 1282b509e89bSRishi Srivatsavai case MAC_PROP_WL_LINKSTATUS: 1283b509e89bSRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_linkstatus, 1284b509e89bSRishi Srivatsavai sizeof (wdev->swd_linkstatus)); 1285b509e89bSRishi Srivatsavai break; 1286b509e89bSRishi Srivatsavai case MAC_PROP_WL_ESS_LIST: { 1287b509e89bSRishi Srivatsavai wl_ess_conf_t *w_ess_conf; 1288b509e89bSRishi Srivatsavai 1289b509e89bSRishi Srivatsavai ((wl_ess_list_t *)wldp_buf)->wl_ess_list_num = 1290b509e89bSRishi Srivatsavai wdev->swd_esslist_num; 1291b509e89bSRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */ 1292b509e89bSRishi Srivatsavai w_ess_conf = (wl_ess_conf_t *)((char *)wldp_buf + 1293b509e89bSRishi Srivatsavai offsetof(wl_ess_list_t, wl_ess_list_ess)); 1294b509e89bSRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) { 1295b509e89bSRishi Srivatsavai (void) memcpy(w_ess_conf, wdev->swd_esslist[i], 1296b509e89bSRishi Srivatsavai sizeof (wl_ess_conf_t)); 1297b509e89bSRishi Srivatsavai w_ess_conf++; 1298b509e89bSRishi Srivatsavai } 1299b509e89bSRishi Srivatsavai break; 1300b509e89bSRishi Srivatsavai } 1301b509e89bSRishi Srivatsavai case MAC_PROP_WL_RSSI: 1302b509e89bSRishi Srivatsavai *(wl_rssi_t *)wldp_buf = wdev->swd_rssi; 1303b509e89bSRishi Srivatsavai break; 1304b509e89bSRishi Srivatsavai case MAC_PROP_WL_RADIO: 1305b509e89bSRishi Srivatsavai *(wl_radio_t *)wldp_buf = B_TRUE; 1306b509e89bSRishi Srivatsavai break; 1307b509e89bSRishi Srivatsavai case MAC_PROP_WL_POWER_MODE: 1308b509e89bSRishi Srivatsavai break; 1309b509e89bSRishi Srivatsavai case MAC_PROP_WL_DESIRED_RATES: 1310b509e89bSRishi Srivatsavai break; 1311b509e89bSRishi Srivatsavai case MAC_PROP_PRIVATE: 1312*0dc2366fSVenugopal Iyer err = simnet_get_priv_prop(sdev, pr_name, wldp_length, 1313*0dc2366fSVenugopal Iyer wldp_buf); 1314b509e89bSRishi Srivatsavai break; 1315b509e89bSRishi Srivatsavai default: 1316b509e89bSRishi Srivatsavai err = ENOTSUP; 1317b509e89bSRishi Srivatsavai break; 1318b509e89bSRishi Srivatsavai } 1319b509e89bSRishi Srivatsavai 1320b509e89bSRishi Srivatsavai return (err); 1321b509e89bSRishi Srivatsavai } 1322*0dc2366fSVenugopal Iyer 1323*0dc2366fSVenugopal Iyer static void 1324*0dc2366fSVenugopal Iyer simnet_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh) 1325*0dc2366fSVenugopal Iyer { 1326*0dc2366fSVenugopal Iyer char valstr[MAXNAMELEN]; 1327*0dc2366fSVenugopal Iyer 1328*0dc2366fSVenugopal Iyer bzero(valstr, sizeof (valstr)); 1329*0dc2366fSVenugopal Iyer 1330*0dc2366fSVenugopal Iyer if (strcmp(pr_name, "_wl_esslist") == 0) { 1331*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 0); 1332*0dc2366fSVenugopal Iyer } 1333*0dc2366fSVenugopal Iyer 1334*0dc2366fSVenugopal Iyer if (strlen(valstr) > 0) 1335*0dc2366fSVenugopal Iyer mac_prop_info_set_default_str(prh, valstr); 1336*0dc2366fSVenugopal Iyer } 1337*0dc2366fSVenugopal Iyer 1338*0dc2366fSVenugopal Iyer static void 1339*0dc2366fSVenugopal Iyer simnet_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 1340*0dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 1341*0dc2366fSVenugopal Iyer { 1342*0dc2366fSVenugopal Iyer simnet_dev_t *sdev = arg; 1343*0dc2366fSVenugopal Iyer 1344*0dc2366fSVenugopal Iyer if (sdev->sd_type == DL_ETHER) 1345*0dc2366fSVenugopal Iyer return; 1346*0dc2366fSVenugopal Iyer 1347*0dc2366fSVenugopal Iyer switch (wldp_pr_num) { 1348*0dc2366fSVenugopal Iyer case MAC_PROP_WL_BSSTYPE: 1349*0dc2366fSVenugopal Iyer case MAC_PROP_WL_ESS_LIST: 1350*0dc2366fSVenugopal Iyer case MAC_PROP_WL_SUPPORTED_RATES: 1351*0dc2366fSVenugopal Iyer case MAC_PROP_WL_RSSI: 1352*0dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 1353*0dc2366fSVenugopal Iyer break; 1354*0dc2366fSVenugopal Iyer case MAC_PROP_PRIVATE: 1355*0dc2366fSVenugopal Iyer simnet_priv_propinfo(pr_name, prh); 1356*0dc2366fSVenugopal Iyer break; 1357*0dc2366fSVenugopal Iyer } 1358*0dc2366fSVenugopal Iyer } 1359