b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * CDDL HEADER START
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * The contents of this file are subject to the terms of the
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Common Development and Distribution License (the "License").
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * You may not use this file except in compliance with the License.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * or http://www.opensolaris.org/os/licensing.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * See the License for the specific language governing permissions
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * and limitations under the License.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner]
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * CDDL HEADER END
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Use is subject to license terms.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Simulated network device (simnet) driver: simulates a pseudo GLDv3 network
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * device. Can simulate an Ethernet or WiFi network device. In addition, another
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * simnet instance can be attached as a peer to create a point-to-point link on
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * the same system.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/policy.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/conf.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/modctl.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/priv_names.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/dlpi.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <net/simnet.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/ethernet.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/dls.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac_ether.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac_provider.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac_client_priv.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/vlan.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/random.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/sysmacros.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/list.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/strsubr.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/strsun.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/atomic.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac_wifi.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/mac_impl.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <inet/wifi_ioctl.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/thread.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include <sys/synch.h>
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai#include <sys/sunddi.h>
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#include "simnet_impl.h"
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai#define SIMNETINFO "Simulated Network Driver"
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic dev_info_t *simnet_dip;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaistatic ddi_taskq_t *simnet_rxq;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_attach(dev_info_t *, ddi_attach_cmd_t);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_detach(dev_info_t *, ddi_detach_cmd_t);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_ioc_create(void *, intptr_t, int, cred_t *, int *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_ioc_delete(void *, intptr_t, int, cred_t *, int *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_ioc_info(void *, intptr_t, int, cred_t *, int *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_ioc_modify(void *, intptr_t, int, cred_t *, int *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic uint8_t *mcastaddr_lookup(simnet_dev_t *, const uint8_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic dld_ioc_info_t simnet_ioc_list[] = {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai {SIMNET_IOC_CREATE, DLDCOPYINOUT, sizeof (simnet_ioc_create_t),
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_ioc_create, secpolicy_dl_config},
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai {SIMNET_IOC_DELETE, DLDCOPYIN, sizeof (simnet_ioc_delete_t),
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_ioc_delete, secpolicy_dl_config},
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai {SIMNET_IOC_INFO, DLDCOPYINOUT, sizeof (simnet_ioc_info_t),
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_ioc_info, NULL},
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai {SIMNET_IOC_MODIFY, DLDCOPYIN, sizeof (simnet_ioc_modify_t),
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_ioc_modify, secpolicy_dl_config}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai};
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi SrivatsavaiDDI_DEFINE_STREAM_OPS(simnet_dev_ops, nulldev, nulldev, simnet_attach,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_detach, nodev, simnet_getinfo, D_MP, NULL,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ddi_quiesce_not_supported);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic struct modldrv simnet_modldrv = {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai &mod_driverops, /* Type of module. This one is a driver */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai SIMNETINFO, /* short description */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai &simnet_dev_ops /* driver specific ops */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai};
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic struct modlinkage modlinkage = {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai MODREV_1, &simnet_modldrv, NULL
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai};
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* MAC callback function declarations */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_start(void *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void simnet_m_stop(void *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_promisc(void *, boolean_t);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_multicst(void *, boolean_t, const uint8_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_unicst(void *, const uint8_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_stat(void *, uint_t, uint64_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void simnet_m_ioctl(void *, queue_t *, mblk_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic mblk_t *simnet_m_tx(void *, mblk_t *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_setprop(void *, const char *, mac_prop_id_t,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint_t, const void *);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_m_getprop(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t, void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void simnet_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic mac_callbacks_t simnet_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO),
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_stat,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_start,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_stop,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_promisc,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_multicst,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_unicst,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_ioctl,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai NULL,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai NULL,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai NULL,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer simnet_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer simnet_m_propinfo
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai};
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * simnet_dev_lock protects the simnet device list.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * sd_instlock in each simnet_dev_t protects access to
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * a single simnet_dev_t.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic krwlock_t simnet_dev_lock;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic list_t simnet_dev_list;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int simnet_count; /* Num of simnet instances */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiint
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai_init(void)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int status;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_init_ops(&simnet_dev_ops, "simnet");
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai status = mod_install(&modlinkage);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (status != DDI_SUCCESS)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_fini_ops(&simnet_dev_ops);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (status);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiint
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai_fini(void)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int status;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai status = mod_remove(&modlinkage);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (status == DDI_SUCCESS)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_fini_ops(&simnet_dev_ops);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (status);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiint
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai_info(struct modinfo *modinfop)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (mod_info(&modlinkage, modinfop));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaistatic boolean_t
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_init(void)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if ((simnet_rxq = ddi_taskq_create(simnet_dip, "simnet", 1,
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai TASKQ_DEFAULTPRI, 0)) == NULL)
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai return (B_FALSE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_init(&simnet_dev_lock, NULL, RW_DEFAULT, NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai list_create(&simnet_dev_list, sizeof (simnet_dev_t),
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai offsetof(simnet_dev_t, sd_listnode));
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai return (B_TRUE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_fini(void)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(simnet_count == 0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_destroy(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai list_destroy(&simnet_dev_list);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai ddi_taskq_destroy(simnet_rxq);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*ARGSUSED*/
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai void **result)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (infocmd) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_INFO_DEVT2DEVINFO:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *result = simnet_dip;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_INFO_DEVT2INSTANCE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *result = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (cmd) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_ATTACH:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (ddi_get_instance(dip) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* we only allow instance 0 to attach */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (dld_ioc_register(SIMNET_IOC, simnet_ioc_list,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai DLDIOCCNT(simnet_ioc_list)) != 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dip = dip;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (!simnet_init())
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_RESUME:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*ARGSUSED*/
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (cmd) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_DETACH:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Allow the simnet instance to be detached only if there
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * are no simnets configured.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (simnet_count > 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai dld_ioc_unregister(SIMNET_IOC);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_fini();
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_dip = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case DDI_SUSPEND:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_SUCCESS);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (DDI_FAILURE);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* Caller must hold simnet_dev_lock */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic simnet_dev_t *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_dev_lookup(datalink_id_t link_id)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai ASSERT(RW_LOCK_HELD(&simnet_dev_lock));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (sdev = list_head(&simnet_dev_list); sdev != NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev = list_next(&simnet_dev_list, sdev)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (!(sdev->sd_flags & SDF_SHUTDOWN) &&
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (sdev->sd_link_id == link_id)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai atomic_inc_32(&sdev->sd_refcount);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_wifidev_free(simnet_dev_t *sdev)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int i;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(wdev->swd_esslist[i],
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_ess_conf_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(wdev, sizeof (simnet_wifidev_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_dev_unref(simnet_dev_t *sdev)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev->sd_refcount > 0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (atomic_dec_32_nv(&sdev->sd_refcount) != 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_mh != NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) mac_unregister(sdev->sd_mh);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_wifidev != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev->sd_type == DL_WIFI);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_free(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_destroy(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai cv_destroy(&sdev->sd_threadwait);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(sdev->sd_mcastaddrs, ETHERADDRL * sdev->sd_mcastaddr_count);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(sdev, sizeof (*sdev));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_count--;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_init_wifi(simnet_dev_t *sdev, mac_register_t *mac)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wifi_data_t wd = { 0 };
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_wifidev = kmem_zalloc(sizeof (simnet_wifidev_t), KM_NOSLEEP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_wifidev == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOMEM);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_wifidev->swd_sdev = sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_wifidev->swd_linkstatus = WL_NOTCONNECTED;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wd.wd_secalloc = WIFI_SEC_NONE;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wd.wd_opmode = IEEE80211_M_STA;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_max_sdu = IEEE80211_MTU;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_pdata = &wd;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_pdata_size = sizeof (wd);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = mac_register(mac, &sdev->sd_mh);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_init_ether(simnet_dev_t *sdev, mac_register_t *mac)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_max_sdu = SIMNET_MAX_MTU;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_margin = VLAN_TAGSZ;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = mac_register(mac, &sdev->sd_mh);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_init_mac(simnet_dev_t *sdev)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_register_t *mac;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((mac = mac_alloc(MAC_VERSION)) == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOMEM);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_driver = sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_dip = simnet_dip;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_instance = (uint_t)-1;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_src_addr = sdev->sd_mac_addr;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_callbacks = &simnet_m_callbacks;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac->m_min_sdu = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_type == DL_ETHER)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = simnet_init_ether(sdev, mac);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai else if (sdev->sd_type == DL_WIFI)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = simnet_init_wifi(sdev, mac);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai else
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = EINVAL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_free(mac);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* ARGSUSED */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_ioc_create(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_ioc_create_t *create_arg = karg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev_tmp;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev = kmem_zalloc(sizeof (*sdev), KM_NOSLEEP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOMEM);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev_tmp = simnet_dev_lookup(create_arg->sic_link_id)) != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev_tmp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(sdev, sizeof (*sdev));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EEXIST);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_type = create_arg->sic_type;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_link_id = create_arg->sic_link_id;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy sdev->sd_zoneid = crgetzoneid(cred);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_refcount++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_init(&sdev->sd_instlock, NULL, MUTEX_DRIVER, NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai cv_init(&sdev->sd_threadwait, NULL, CV_DRIVER, NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_count++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Simnets created from configuration on boot pass saved MAC address */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (create_arg->sic_mac_len == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Generate random MAC address */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) random_get_pseudo_bytes(sdev->sd_mac_addr, ETHERADDRL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Ensure MAC address is not multicast and is local */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mac_addr[0] = (sdev->sd_mac_addr[0] & ~1) | 2;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mac_len = ETHERADDRL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(sdev->sd_mac_addr, create_arg->sic_mac_addr,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai create_arg->sic_mac_len);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mac_len = create_arg->sic_mac_len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((err = simnet_init_mac(sdev)) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai goto exit;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if ((err = dls_devnet_create(sdev->sd_mh, sdev->sd_link_id,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy crgetzoneid(cred))) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai goto exit;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_link_update(sdev->sd_mh, LINK_STATE_UP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_tx_update(sdev->sd_mh);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai list_insert_tail(&simnet_dev_list, sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Always return MAC address back to caller */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(create_arg->sic_mac_addr, sdev->sd_mac_addr,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mac_len);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai create_arg->sic_mac_len = sdev->sd_mac_len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiexit:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* Caller must hold writer simnet_dev_lock */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic datalink_id_t
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_remove_peer(simnet_dev_t *sdev)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev_peer;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai datalink_id_t peer_link_id = DATALINK_INVALID_LINKID;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai ASSERT(RW_WRITE_HELD(&simnet_dev_lock));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev_peer = sdev->sd_peer_dev) != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev == sdev_peer->sd_peer_dev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev_peer->sd_peer_dev = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_peer_dev = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai peer_link_id = sdev_peer->sd_link_id;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Release previous references held on both simnets */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev_peer);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (peer_link_id);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* ARGSUSED */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_ioc_modify(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_ioc_modify_t *modify_arg = karg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev_peer = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev = simnet_dev_lookup(modify_arg->sim_link_id)) == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOENT);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (sdev->sd_zoneid != crgetzoneid(cred)) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy rw_exit(&simnet_dev_lock);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_dev_unref(sdev);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (ENOENT);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_link_id == modify_arg->sim_peer_link_id) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Cannot peer with self */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_peer_dev != NULL && sdev->sd_peer_dev->sd_link_id ==
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai modify_arg->sim_peer_link_id) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Nothing to modify */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (modify_arg->sim_peer_link_id != DATALINK_INVALID_LINKID) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy sdev_peer = simnet_dev_lookup(modify_arg->sim_peer_link_id);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (sdev_peer == NULL) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* Peer simnet device not available */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy rw_exit(&simnet_dev_lock);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_dev_unref(sdev);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (ENOENT);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (sdev_peer->sd_zoneid != sdev->sd_zoneid) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* The two peers must be in the same zone (for now). */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy rw_exit(&simnet_dev_lock);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_dev_unref(sdev);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_dev_unref(sdev_peer);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (EACCES);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* First remove any previous peer */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) simnet_remove_peer(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev_peer != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Remove any previous peer of sdev_peer */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) simnet_remove_peer(sdev_peer);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Update both devices with the new peer */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev_peer->sd_peer_dev = sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_peer_dev = sdev_peer;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Hold references on both devices */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Release sdev lookup reference */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* ARGSUSED */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_ioc_delete(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev_peer;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_ioc_delete_t *delete_arg = karg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai datalink_id_t tmpid;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai datalink_id_t peerid;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_WRITER);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev = simnet_dev_lookup(delete_arg->sid_link_id)) == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOENT);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (sdev->sd_zoneid != crgetzoneid(cred)) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy rw_exit(&simnet_dev_lock);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy simnet_dev_unref(sdev);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (ENOENT);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((err = dls_devnet_destroy(sdev->sd_mh, &tmpid, B_TRUE)) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev->sd_link_id == tmpid);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Remove any attached peer link */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai peerid = simnet_remove_peer(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Prevent new threads from using the instance */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_enter(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_flags |= SDF_SHUTDOWN;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Wait until all active threads using the instance exit */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai while (sdev->sd_threadcount > 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (cv_wait_sig(&sdev->sd_threadwait,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai &sdev->sd_instlock) == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Signaled */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = EINTR;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai goto fail;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Try disabling the MAC */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((err = mac_disable(sdev->sd_mh)) != 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai goto fail;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai list_remove(&simnet_dev_list, sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev); /* Release lookup ref */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Releasing the last ref performs sdev/mem free */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaifail:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Re-create simnet instance and add any previous peer */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (void) dls_devnet_create(sdev->sd_mh, sdev->sd_link_id,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy crgetzoneid(cred));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_flags &= ~SDF_SHUTDOWN;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev->sd_peer_dev == NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (peerid != DATALINK_INVALID_LINKID &&
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ((sdev_peer = simnet_dev_lookup(peerid)) != NULL)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Attach peer device back */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev_peer->sd_peer_dev == NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev_peer->sd_peer_dev = sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_peer_dev = sdev_peer;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Hold reference on both devices */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * No previous peer or previous peer no longer
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * available so release lookup reference.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* ARGSUSED */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_ioc_info(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_ioc_info_t *info_arg = karg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* Make sure that the simnet link is visible from the caller's zone. */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (!dls_devnet_islinkvisible(info_arg->sii_link_id, crgetzoneid(cred)))
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (ENOENT);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_READER);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev = simnet_dev_lookup(info_arg->sii_link_id)) == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOENT);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(info_arg->sii_mac_addr, sdev->sd_mac_addr,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mac_len);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai info_arg->sii_mac_len = sdev->sd_mac_len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai info_arg->sii_type = sdev->sd_type;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_peer_dev != NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai info_arg->sii_peer_link_id = sdev->sd_peer_dev->sd_link_id;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaistatic boolean_t
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaisimnet_thread_ref(simnet_dev_t *sdev)
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai{
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mutex_enter(&sdev->sd_instlock);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (sdev->sd_flags & SDF_SHUTDOWN ||
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai !(sdev->sd_flags & SDF_STARTED)) {
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mutex_exit(&sdev->sd_instlock);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai return (B_FALSE);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai }
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai sdev->sd_threadcount++;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mutex_exit(&sdev->sd_instlock);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai return (B_TRUE);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai}
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaisimnet_thread_unref(simnet_dev_t *sdev)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mutex_enter(&sdev->sd_instlock);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (--sdev->sd_threadcount == 0)
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai cv_broadcast(&sdev->sd_threadwait);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mutex_exit(&sdev->sd_instlock);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai}
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaistatic void
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavaisimnet_rx(void *arg)
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai{
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mblk_t *mp = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_header_info_t hdr_info;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_dev_t *sdev;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai sdev = (simnet_dev_t *)mp->b_next;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mp->b_next = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Check for valid packet header */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (mac_header_info(sdev->sd_mh, mp, &hdr_info) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.recv_errors++;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai goto rx_done;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * When we are NOT in promiscuous mode we only receive
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * unicast packets addressed to us and multicast packets that
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * MAC clients have requested.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (!sdev->sd_promisc &&
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai hdr_info.mhi_dsttype != MAC_ADDRTYPE_BROADCAST) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (hdr_info.mhi_dsttype == MAC_ADDRTYPE_UNICAST &&
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai bcmp(hdr_info.mhi_daddr, sdev->sd_mac_addr,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ETHERADDRL) != 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai goto rx_done;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else if (hdr_info.mhi_dsttype == MAC_ADDRTYPE_MULTICAST) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_enter(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (mcastaddr_lookup(sdev, hdr_info.mhi_daddr) ==
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai goto rx_done;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.recv_count++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.rbytes += msgdsize(mp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mac_rx(sdev->sd_mh, NULL, mp);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavairx_done:
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_thread_unref(sdev);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic mblk_t *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_tx(void *arg, mblk_t *mp_chain)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev_rx;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mblk_t *mpnext = mp_chain;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mblk_t *mp;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_enter(&simnet_dev_lock, RW_READER);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((sdev_rx = sdev->sd_peer_dev) == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Discard packets when no peer exists */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsgchain(mp_chain);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Discard packets when either device is shutting down or not ready.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Though MAC layer ensures a reference is held on the MAC while we
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * process the packet chain, there is no guarantee the peer MAC will
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * remain enabled. So we increment per-instance threadcount to ensure
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * either MAC instance is not disabled while we handle the chain of
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * packets. It is okay if the peer device is disconnected while we are
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * here since we lookup the peer device while holding simnet_dev_lock
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * (reader lock) and increment the threadcount of the peer, the peer
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * MAC cannot be disabled in simnet_ioc_delete.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (!simnet_thread_ref(sdev_rx)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsgchain(mp_chain);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rw_exit(&simnet_dev_lock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (!simnet_thread_ref(sdev)) {
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_thread_unref(sdev_rx);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsgchain(mp_chain);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai while ((mp = mpnext) != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int size;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mblk_t *mp_new;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mblk_t *mp_tmp;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mpnext = mp->b_next;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp->b_next = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len = msgdsize(mp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Pad packet to minimum Ethernet frame size */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (len < ETHERMIN) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai size = ETHERMIN - len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp_new = allocb(size, BPRI_HI);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (mp_new == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.xmit_errors++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai continue;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai bzero(mp_new->b_wptr, size);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp_new->b_wptr += size;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp_tmp = mp;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai while (mp_tmp->b_cont != NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp_tmp = mp_tmp->b_cont;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp_tmp->b_cont = mp_new;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len += size;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Pullup packet into a single mblk */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (!pullupmsg(mp, -1)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.xmit_errors++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai continue;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Fix mblk checksum as the pkt dest is local */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if ((mp = mac_fix_cksum(mp)) == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_stats.xmit_errors++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai continue;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai /* Hold reference for taskq receive processing per-pkt */
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (!simnet_thread_ref(sdev_rx)) {
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai freemsg(mp);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai freemsgchain(mpnext);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai break;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai }
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai /* Use taskq for pkt receive to avoid kernel stack explosion */
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mp->b_next = (mblk_t *)sdev_rx;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai if (ddi_taskq_dispatch(simnet_rxq, simnet_rx, mp,
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai DDI_NOSLEEP) == DDI_SUCCESS) {
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai sdev->sd_stats.xmit_count++;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai sdev->sd_stats.obytes += len;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai } else {
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_thread_unref(sdev_rx);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai mp->b_next = NULL;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai freemsg(mp);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai sdev_rx->sd_stats.recv_errors++;
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_thread_unref(sdev);
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai simnet_thread_unref(sdev_rx);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_wifi_ioctl(simnet_dev_t *sdev, mblk_t *mp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int rc = WL_SUCCESS;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (((wldp_t *)mp->b_rptr)->wldp_id) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WL_DISASSOCIATE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_linkstatus = WL_NOTCONNECTED;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (rc);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai struct iocblk *iocp;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mblk_t *mp1;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint32_t cmd;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int rc;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_type != DL_WIFI) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai miocnak(q, mp, 0, ENOTSUP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai iocp = (struct iocblk *)mp->b_rptr;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (iocp->ioc_count == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai miocnak(q, mp, 0, EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* We only claim support for WiFi operation commands */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai cmd = iocp->ioc_cmd;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (cmd) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai miocnak(q, mp, 0, EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WLAN_GET_PARAM:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WLAN_SET_PARAM:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WLAN_COMMAND:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp1 = mp->b_cont;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai freemsg(mp1->b_cont);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp1->b_cont = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* overwrite everything */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mp1->b_wptr = mp1->b_rptr;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rc = simnet_wifi_ioctl(sdev, mp1);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai miocack(q, mp, msgdsize(mp1), rc);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_stat(void *arg, uint_t stat, uint64_t *val)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int rval = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ASSERT(sdev->sd_mh != NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (stat) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_IFSPEED:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = 100 * 1000000ull; /* 100 Mbps */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_LINK_STATE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = LINK_DUPLEX_FULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_LINK_UP:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_flags & SDF_STARTED)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = LINK_STATE_UP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai else
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = LINK_STATE_DOWN;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_PROMISC:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_MULTIRCV:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_MULTIXMT:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_BRDCSTRCV:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_BRDCSTXMT:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rval = ENOTSUP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_OPACKETS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.xmit_count;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_OBYTES:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.obytes;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_IERRORS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.recv_errors;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_OERRORS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.xmit_errors;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_RBYTES:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.rbytes;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_STAT_IPACKETS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *val = sdev->sd_stats.recv_count;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_FCS_ERRORS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_WEP_ERRORS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_TX_FRAGS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_MCAST_TX:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_RTS_SUCCESS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_RTS_FAILURE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_ACK_FAILURE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_RX_FRAGS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_MCAST_RX:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case WIFI_STAT_RX_DUPS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rval = ENOTSUP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai rval = ENOTSUP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (rval);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_start(void *arg)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_flags |= SDF_STARTED;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic void
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_stop(void *arg)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_flags &= ~SDF_STARTED;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_promisc(void *arg, boolean_t on)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_promisc = on;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/*
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Returns matching multicast address enabled on the simnet instance.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai * Assumes simnet instance mutex lock is held.
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic uint8_t *
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaimcastaddr_lookup(simnet_dev_t *sdev, const uint8_t *addrp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int idx;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint8_t *maddrptr;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
0f83d385c54b2d67790eb5ee77344de60f0966c8Rishi Srivatsavai ASSERT(MUTEX_HELD(&sdev->sd_instlock));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai maddrptr = sdev->sd_mcastaddrs;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (idx = 0; idx < sdev->sd_mcastaddr_count; idx++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (bcmp(maddrptr, addrp, ETHERADDRL) == 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (maddrptr);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai maddrptr += ETHERADDRL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (NULL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* Add or remove Multicast addresses on simnet instance */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_multicst(void *arg, boolean_t add, const uint8_t *addrp)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint8_t *maddrptr;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint8_t *newbuf;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai size_t prevsize;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai size_t newsize;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ptrdiff_t len;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ptrdiff_t len2;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaialloc_retry:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai prevsize = sdev->sd_mcastaddr_count * ETHERADDRL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai newsize = prevsize + (add ? ETHERADDRL:-ETHERADDRL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai newbuf = kmem_alloc(newsize, KM_SLEEP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_enter(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (prevsize != (sdev->sd_mcastaddr_count * ETHERADDRL)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(newbuf, newsize);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai goto alloc_retry;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai maddrptr = mcastaddr_lookup(sdev, addrp);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (!add && maddrptr != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Removing a Multicast address */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (newbuf != NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* LINTED: E_PTRDIFF_OVERFLOW */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len = maddrptr - sdev->sd_mcastaddrs;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(newbuf, sdev->sd_mcastaddrs, len);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len2 = prevsize - len - ETHERADDRL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(newbuf + len,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai maddrptr + ETHERADDRL, len2);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mcastaddr_count--;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else if (add && maddrptr == NULL) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Adding a new Multicast address */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(newbuf, sdev->sd_mcastaddrs, prevsize);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(newbuf + prevsize, addrp, ETHERADDRL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mcastaddr_count++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Error: removing a non-existing Multicast address */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(newbuf, newsize);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai cmn_err(CE_WARN, "simnet: MAC call to remove a "
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai "Multicast address failed");
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(sdev->sd_mcastaddrs, prevsize);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sdev->sd_mcastaddrs = newbuf;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai mutex_exit(&sdev->sd_instlock);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_unicst(void *arg, const uint8_t *macaddr)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(sdev->sd_mac_addr, macaddr, ETHERADDRL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* Parse WiFi scan list entry arguments and return the arg count */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiparse_esslist_args(const void *pr_val, uint_t pr_valsize,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai char args[][MAX_ESSLIST_ARGLEN])
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai char *sep;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ptrdiff_t len = pr_valsize;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai const char *piece = pr_val;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai const char *end = (const char *)pr_val + pr_valsize - 1;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int arg = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai while (piece < end && (arg < MAX_ESSLIST_ARGS)) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sep = strchr(piece, ',');
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sep == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sep = (char *)end;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* LINTED E_PTRDIFF_OVERFLOW */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len = sep - piece;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* If first arg is zero then return none to delete all */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (arg == 0 && strnlen(piece, len) == 1 && piece[0] == '0')
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (len > MAX_ESSLIST_ARGLEN)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai len = MAX_ESSLIST_ARGLEN - 1;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(&args[arg][0], piece, len);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai args[arg][len] = '\0';
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai piece = sep + 1;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai arg++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (arg);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai/* Set WiFi scan list entry from private property _wl_esslist */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaiset_wl_esslist_priv_prop(simnet_wifidev_t *wdev, uint_t pr_valsize,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai const void *pr_val)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai char essargs[MAX_ESSLIST_ARGS][MAX_ESSLIST_ARGLEN];
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wl_ess_conf_t *wls;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai long result;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int i;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai bzero(essargs, sizeof (essargs));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (parse_esslist_args(pr_val, pr_valsize, essargs) == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai kmem_free(wdev->swd_esslist[i], sizeof (wl_ess_conf_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_esslist[i] = NULL;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_esslist_num = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wls = wdev->swd_esslist[i];
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (strcasecmp(wls->wl_ess_conf_essid.wl_essid_essid,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai essargs[0]) == 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EEXIST);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (wdev->swd_esslist_num >= MAX_SIMNET_ESSCONF)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wls = kmem_zalloc(sizeof (wl_ess_conf_t), KM_SLEEP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) strlcpy(wls->wl_ess_conf_essid.wl_essid_essid,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai essargs[0], sizeof (wls->wl_ess_conf_essid.wl_essid_essid));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wls->wl_ess_conf_essid.wl_essid_length =
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai strlen(wls->wl_ess_conf_essid.wl_essid_essid);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) random_get_pseudo_bytes((uint8_t *)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai &wls->wl_ess_conf_bssid, sizeof (wl_bssid_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) ddi_strtol(essargs[1], (char **)NULL, 0, &result);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wls->wl_ess_conf_sl = (wl_rssi_t)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ((result > MAX_RSSI || result < 0) ? 0:result);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_esslist[wdev->swd_esslist_num] = wls;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_esslist_num++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_set_priv_prop(simnet_dev_t *sdev, const char *pr_name,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint_t pr_valsize, const void *pr_val)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai long result;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (strcmp(pr_name, "_wl_esslist") == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (pr_val == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (set_wl_esslist_priv_prop(wdev, pr_valsize, pr_val));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else if (strcmp(pr_name, "_wl_connected") == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (pr_val == NULL)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_linkstatus = ((result == 1) ?
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai WL_CONNECTED:WL_NOTCONNECTED);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint_t wldp_length, const void *wldp_buf)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint32_t mtu;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (wldp_pr_num) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_MTU:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(&mtu, wldp_buf, sizeof (mtu));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (mtu > ETHERMIN && mtu < SIMNET_MAX_MTU)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (mac_maxsdu_update(sdev->sd_mh, mtu));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai else
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (EINVAL);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_type == DL_ETHER)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOTSUP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* mac_prop_id */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (wldp_pr_num) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_ESSID: {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int i;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wl_ess_conf_t *wls;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(&wdev->swd_essid, wldp_buf,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_essid_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_linkstatus = WL_CONNECTED;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Lookup the signal strength of the connected ESSID */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wls = wdev->swd_esslist[i];
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (strcasecmp(wls->wl_ess_conf_essid.wl_essid_essid,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_essid.wl_essid_essid) == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_rssi = wls->wl_ess_conf_sl;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_BSSID: {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(&wdev->swd_bssid, wldp_buf,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_bssid_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_PHY_CONFIG:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_KEY_TAB:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_AUTH_MODE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_ENCRYPTION:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_BSSTYPE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_DESIRED_RATES:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_PRIVATE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = simnet_set_priv_prop(sdev, pr_name,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wldp_length, wldp_buf);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyersimnet_get_priv_prop(simnet_dev_t *sdev, const char *pr_name,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai uint_t pr_valsize, void *pr_val)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int value;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (strcmp(pr_name, "_wl_esslist") == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* Returns num of _wl_ess_conf_t that have been set */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer value = wdev->swd_esslist_num;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else if (strcmp(pr_name, "_wl_connected") == 0) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai value = ((wdev->swd_linkstatus == WL_CONNECTED) ? 1:0);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai } else {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = ENOTSUP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (err == 0)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) snprintf(pr_val, pr_valsize, "%d", value);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaistatic int
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavaisimnet_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t wldp_length, void *wldp_buf)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai{
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_dev_t *sdev = arg;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai simnet_wifidev_t *wdev = sdev->sd_wifidev;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int err = 0;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai int i;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai if (sdev->sd_type == DL_ETHER)
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (ENOTSUP);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* mac_prop_id */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai switch (wldp_pr_num) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_ESSID:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_essid,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_essid_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_BSSID:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_bssid,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_bssid_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_PHY_CONFIG:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_AUTH_MODE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_ENCRYPTION:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_LINKSTATUS:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(wldp_buf, &wdev->swd_linkstatus,
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wdev->swd_linkstatus));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_ESS_LIST: {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wl_ess_conf_t *w_ess_conf;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai ((wl_ess_list_t *)wldp_buf)->wl_ess_list_num =
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai wdev->swd_esslist_num;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai /* LINTED E_BAD_PTR_CAST_ALIGN */
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai w_ess_conf = (wl_ess_conf_t *)((char *)wldp_buf +
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai offsetof(wl_ess_list_t, wl_ess_list_ess));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai for (i = 0; i < wdev->swd_esslist_num; i++) {
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai (void) memcpy(w_ess_conf, wdev->swd_esslist[i],
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai sizeof (wl_ess_conf_t));
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai w_ess_conf++;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_RSSI:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *(wl_rssi_t *)wldp_buf = wdev->swd_rssi;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_RADIO:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai *(wl_radio_t *)wldp_buf = B_TRUE;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_POWER_MODE:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_WL_DESIRED_RATES:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai case MAC_PROP_PRIVATE:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer err = simnet_get_priv_prop(sdev, pr_name, wldp_length,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer wldp_buf);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai default:
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai err = ENOTSUP;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai break;
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai }
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai return (err);
b509e89b2befbaa42939abad9da1d7f5a8c6aaaeRishi Srivatsavai}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyersimnet_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer char valstr[MAXNAMELEN];
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bzero(valstr, sizeof (valstr));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (strcmp(pr_name, "_wl_esslist") == 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 0);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (strlen(valstr) > 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_default_str(prh, valstr);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyersimnet_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer simnet_dev_t *sdev = arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (sdev->sd_type == DL_ETHER)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (wldp_pr_num) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_WL_BSSTYPE:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_WL_ESS_LIST:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_WL_SUPPORTED_RATES:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_WL_RSSI:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_PRIVATE:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer simnet_priv_propinfo(pr_name, prh);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}