Path: blob/main/usr.sbin/bsnmpd/modules/snmp_wlan/wlan_sys.c
105774 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2010 The FreeBSD Foundation4*5* This software was developed by Shteryana Sotirova Shopova under6* sponsorship from the FreeBSD Foundation.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*/2930#include <sys/ioctl.h>31#include <sys/param.h>32#include <sys/module.h>33#include <sys/linker.h>34#include <sys/socket.h>35#include <sys/sysctl.h>3637#include <net/if.h>38#include <net/if_dl.h>39#include <net/if_media.h>40#include <net/if_mib.h>41#include <net/if_types.h>42#include <net80211/ieee80211.h>43#include <net80211/ieee80211_ioctl.h>44#include <net80211/ieee80211_regdomain.h>4546#include <errno.h>47#include <ifaddrs.h>48#include <stdarg.h>49#include <stdlib.h>50#include <stdio.h>51#include <string.h>52#include <syslog.h>5354#include <bsnmp/snmpmod.h>55#include <bsnmp/snmp_mibII.h>5657#define SNMPTREE_TYPES58#include "wlan_tree.h"59#include "wlan_snmp.h"6061static int sock = -1;6263static int wlan_ioctl(char *, uint16_t, int *, void *, size_t *, int);64static int wlan_kmod_load(const char *);65static uint32_t wlan_drivercaps_to_snmp(uint32_t);66static uint32_t wlan_cryptocaps_to_snmp(uint32_t);67static uint32_t wlan_htcaps_to_snmp(uint32_t);68static uint32_t wlan_peerstate_to_snmp(uint32_t);69static uint32_t wlan_peercaps_to_snmp(uint32_t );70static enum WlanIfPhyMode wlan_channel_flags_to_snmp_phy(uint32_t);71static enum WlanRegDomainCode wlan_regdomain_to_snmp(int);72static uint32_t wlan_snmp_to_scan_flags(int);73static int wlan_config_snmp2ioctl(int);74static int wlan_snmp_to_regdomain(enum WlanRegDomainCode);75static int wlan_config_get_country(struct wlan_iface *);76static int wlan_config_set_country(struct wlan_iface *, char *, int);77static int wlan_config_get_dchannel(struct wlan_iface *wif);78static int wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t);79static int wlan_config_get_bssid(struct wlan_iface *);80static int wlan_config_set_bssid(struct wlan_iface *, uint8_t *);81static void wlan_config_set_snmp_intval(struct wlan_iface *, int, int);82static int wlan_config_snmp2value(int, int, int *);83static int wlan_config_check(struct wlan_iface *, int);84static int wlan_config_get_intval(struct wlan_iface *, int);85static int wlan_config_set_intval(struct wlan_iface *, int, int);86static int wlan_add_new_scan_result(struct wlan_iface *,87const struct ieee80211req_scan_result *, uint8_t *);88static int wlan_add_mac_macinfo(struct wlan_iface *,89const struct ieee80211req_maclist *);90static struct wlan_peer *wlan_add_peerinfo(const struct ieee80211req_sta_info *);9192int93wlan_ioctl_init(void)94{95if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {96syslog(LOG_ERR, "cannot open socket : %s", strerror(errno));97return (-1);98}99100return (0);101}102/*103* Load the needed modules in kernel if not already there.104*/105enum wlan_kmodules {106WLAN_KMOD = 0,107WLAN_KMOD_ACL,108WLAN_KMOD_WEP,109WLAN_KMODS_MAX110};111112static const char *wmod_names[] = {113"wlan",114"wlan_wlan_acl",115"wlan_wep",116NULL117};118119static int120wlan_kmod_load(const char *modname)121{122int fileid, modid;123struct module_stat mstat;124125mstat.version = sizeof(struct module_stat);126for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {127for (modid = kldfirstmod(fileid); modid > 0;128modid = modfnext(modid)) {129if (modstat(modid, &mstat) < 0)130continue;131if (strcmp(modname, mstat.name) == 0)132return (0);133}134}135136/* Not present - load it. */137if (kldload(modname) < 0) {138syslog(LOG_ERR, "failed to load %s kernel module - %s", modname,139strerror(errno));140return (-1);141}142143return (1);144}145146int147wlan_kmodules_load(void)148{149if (wlan_kmod_load(wmod_names[WLAN_KMOD]) < 0)150return (-1);151152if (wlan_kmod_load(wmod_names[WLAN_KMOD_ACL]) > 0)153syslog(LOG_NOTICE, "SNMP wlan loaded %s module",154wmod_names[WLAN_KMOD_ACL]);155156if (wlan_kmod_load(wmod_names[WLAN_KMOD_WEP]) > 0)157syslog(LOG_NOTICE, "SNMP wlan loaded %s module",158wmod_names[WLAN_KMOD_WEP]);159160return (0);161}162163/* XXX: FIXME */164static int165wlan_ioctl(char *wif_name, uint16_t req_type, int *val, void *arg,166size_t *argsize, int set)167{168struct ieee80211req ireq;169170memset(&ireq, 0, sizeof(struct ieee80211req));171strlcpy(ireq.i_name, wif_name, IFNAMSIZ);172173ireq.i_type = req_type;174ireq.i_val = *val;175ireq.i_len = *argsize;176ireq.i_data = arg;177178if (ioctl(sock, set ? SIOCS80211 : SIOCG80211, &ireq) < 0) {179syslog(LOG_ERR, "iface %s - %s param: ioctl(%d) "180"failed: %s", wif_name, set ? "set" : "get",181req_type, strerror(errno));182return (-1);183}184185*argsize = ireq.i_len;186*val = ireq.i_val;187188return (0);189}190191int192wlan_check_media(char *ifname)193{194struct ifmediareq ifmr;195196memset(&ifmr, 0, sizeof(struct ifmediareq));197strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));198199if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0 || ifmr.ifm_count == 0)200return (0); /* Interface doesn't support SIOCGIFMEDIA. */201202if ((ifmr.ifm_status & IFM_AVALID) == 0)203return (0);204205return (IFM_TYPE(ifmr.ifm_active));206}207208int209wlan_get_opmode(struct wlan_iface *wif)210{211struct ifmediareq ifmr;212213memset(&ifmr, 0, sizeof(struct ifmediareq));214strlcpy(ifmr.ifm_name, wif->wname, sizeof(ifmr.ifm_name));215216if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0) {217if (errno == ENXIO)218return (-1);219wif->mode = WlanIfaceOperatingModeType_station;220return (0);221}222223if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {224if (ifmr.ifm_current & IFM_FLAG0)225wif->mode = WlanIfaceOperatingModeType_adhocDemo;226else227wif->mode = WlanIfaceOperatingModeType_ibss;228} else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)229wif->mode = WlanIfaceOperatingModeType_hostAp;230else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)231wif->mode = WlanIfaceOperatingModeType_monitor;232else if (ifmr.ifm_current & IFM_IEEE80211_MBSS)233wif->mode = WlanIfaceOperatingModeType_meshPoint;234else if (ifmr.ifm_current & IFM_IEEE80211_WDS)235wif->mode = WlanIfaceOperatingModeType_wds;236237return (0);238}239240int241wlan_config_state(struct wlan_iface *wif, uint8_t set)242{243int flags;244struct ifreq ifr;245246memset(&ifr, 0, sizeof(ifr));247strcpy(ifr.ifr_name, wif->wname);248249if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {250syslog(LOG_ERR, "set %s status: ioctl(SIOCGIFFLAGS) "251"failed: %s", wif->wname, strerror(errno));252return (-1);253}254255if (set == 0) {256if ((ifr.ifr_flags & IFF_UP) != 0)257wif->state = wlanIfaceState_up;258else259wif->state = wlanIfaceState_down;260return (0);261}262263flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);264265if (wif->state == wlanIfaceState_up)266flags |= IFF_UP;267else268flags &= ~IFF_UP;269270ifr.ifr_flags = flags & 0xffff;271ifr.ifr_flagshigh = flags >> 16;272if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {273syslog(LOG_ERR, "set %s %s: ioctl(SIOCSIFFLAGS) failed: %s",274wif->wname, wif->state == wlanIfaceState_up?"up":"down",275strerror(errno));276return (-1);277}278279return (0);280}281282int283wlan_get_local_addr(struct wlan_iface *wif)284{285int len;286char ifname[IFNAMSIZ];287struct ifaddrs *ifap, *ifa;288struct sockaddr_dl sdl;289290if (getifaddrs(&ifap) != 0) {291syslog(LOG_ERR, "wlan get mac: getifaddrs() failed - %s",292strerror(errno));293return (-1);294}295296for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {297if (ifa->ifa_addr->sa_family != AF_LINK)298continue;299memcpy(&sdl, ifa->ifa_addr, sizeof(struct sockaddr_dl));300if (sdl.sdl_alen > IEEE80211_ADDR_LEN)301continue;302if ((len = sdl.sdl_nlen) >= IFNAMSIZ)303len = IFNAMSIZ - 1;304memcpy(ifname, sdl.sdl_data, len);305ifname[len] = '\0';306if (strcmp(wif->wname, ifname) == 0)307break;308}309310freeifaddrs(ifap);311return (0);312}313314int315wlan_get_parent(struct wlan_iface *wif __unused)316{317/* XXX: There's no way to fetch this from the kernel. */318return (0);319}320321/* XXX */322#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */323#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */324#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */325#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/326#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */327#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */328#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */329#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */330#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */331#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */332#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */333#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */334#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */335#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/336#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */337/* 0x7c0000 available */338#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */339#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */340#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/341#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */342#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */343#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */344/* 0x10000000 reserved */345#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */346#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */347#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */348349static uint32_t350wlan_drivercaps_to_snmp(uint32_t dcaps)351{352uint32_t scaps = 0;353354if ((dcaps & IEEE80211_C_STA) != 0)355scaps |= (0x1 << WlanDriverCaps_station);356if ((dcaps & IEEE80211_C_8023ENCAP) != 0)357scaps |= (0x1 << WlanDriverCaps_ieee8023encap);358if ((dcaps & IEEE80211_C_FF) != 0)359scaps |= (0x1 << WlanDriverCaps_athFastFrames);360if ((dcaps & IEEE80211_C_TURBOP) != 0)361scaps |= (0x1 << WlanDriverCaps_athTurbo);362if ((dcaps & IEEE80211_C_IBSS) != 0)363scaps |= (0x1 << WlanDriverCaps_ibss);364if ((dcaps & IEEE80211_C_PMGT) != 0)365scaps |= (0x1 << WlanDriverCaps_pmgt);366if ((dcaps & IEEE80211_C_HOSTAP) != 0)367scaps |= (0x1 << WlanDriverCaps_hostAp);368if ((dcaps & IEEE80211_C_AHDEMO) != 0)369scaps |= (0x1 << WlanDriverCaps_ahDemo);370if ((dcaps & IEEE80211_C_SWRETRY) != 0)371scaps |= (0x1 << WlanDriverCaps_swRetry);372if ((dcaps & IEEE80211_C_TXPMGT) != 0)373scaps |= (0x1 << WlanDriverCaps_txPmgt);374if ((dcaps & IEEE80211_C_SHSLOT) != 0)375scaps |= (0x1 << WlanDriverCaps_shortSlot);376if ((dcaps & IEEE80211_C_SHPREAMBLE) != 0)377scaps |= (0x1 << WlanDriverCaps_shortPreamble);378if ((dcaps & IEEE80211_C_MONITOR) != 0)379scaps |= (0x1 << WlanDriverCaps_monitor);380if ((dcaps & IEEE80211_C_DFS) != 0)381scaps |= (0x1 << WlanDriverCaps_dfs);382if ((dcaps & IEEE80211_C_MBSS) != 0)383scaps |= (0x1 << WlanDriverCaps_mbss);384if ((dcaps & IEEE80211_C_WPA1) != 0)385scaps |= (0x1 << WlanDriverCaps_wpa1);386if ((dcaps & IEEE80211_C_WPA2) != 0)387scaps |= (0x1 << WlanDriverCaps_wpa2);388if ((dcaps & IEEE80211_C_BURST) != 0)389scaps |= (0x1 << WlanDriverCaps_burst);390if ((dcaps & IEEE80211_C_WME) != 0)391scaps |= (0x1 << WlanDriverCaps_wme);392if ((dcaps & IEEE80211_C_WDS) != 0)393scaps |= (0x1 << WlanDriverCaps_wds);394if ((dcaps & IEEE80211_C_BGSCAN) != 0)395scaps |= (0x1 << WlanDriverCaps_bgScan);396if ((dcaps & IEEE80211_C_TXFRAG) != 0)397scaps |= (0x1 << WlanDriverCaps_txFrag);398if ((dcaps & IEEE80211_C_TDMA) != 0)399scaps |= (0x1 << WlanDriverCaps_tdma);400401return (scaps);402}403404static uint32_t405wlan_cryptocaps_to_snmp(uint32_t ccaps)406{407uint32_t scaps = 0;408409#if NOT_YET410if ((ccaps & IEEE80211_CRYPTO_WEP) != 0)411scaps |= (0x1 << wlanCryptoCaps_wep);412if ((ccaps & IEEE80211_CRYPTO_TKIP) != 0)413scaps |= (0x1 << wlanCryptoCaps_tkip);414if ((ccaps & IEEE80211_CRYPTO_AES_OCB) != 0)415scaps |= (0x1 << wlanCryptoCaps_aes);416if ((ccaps & IEEE80211_CRYPTO_AES_CCM) != 0)417scaps |= (0x1 << wlanCryptoCaps_aesCcm);418if ((ccaps & IEEE80211_CRYPTO_TKIPMIC) != 0)419scaps |= (0x1 << wlanCryptoCaps_tkipMic);420if ((ccaps & IEEE80211_CRYPTO_CKIP) != 0)421scaps |= (0x1 << wlanCryptoCaps_ckip);422#else /* !NOT_YET */423scaps = ccaps;424#endif425return (scaps);426}427428#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */429#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */430/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */431#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */432#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/433#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */434435static uint32_t436wlan_htcaps_to_snmp(uint32_t hcaps)437{438uint32_t scaps = 0;439440if ((hcaps & IEEE80211_HTCAP_LDPC) != 0)441scaps |= (0x1 << WlanHTCaps_ldpc);442if ((hcaps & IEEE80211_HTCAP_CHWIDTH40) != 0)443scaps |= (0x1 << WlanHTCaps_chwidth40);444if ((hcaps & IEEE80211_HTCAP_GREENFIELD) != 0)445scaps |= (0x1 << WlanHTCaps_greenField);446if ((hcaps & IEEE80211_HTCAP_SHORTGI20) != 0)447scaps |= (0x1 << WlanHTCaps_shortGi20);448if ((hcaps & IEEE80211_HTCAP_SHORTGI40) != 0)449scaps |= (0x1 << WlanHTCaps_shortGi40);450if ((hcaps & IEEE80211_HTCAP_TXSTBC) != 0)451scaps |= (0x1 << WlanHTCaps_txStbc);452if ((hcaps & IEEE80211_HTCAP_DELBA) != 0)453scaps |= (0x1 << WlanHTCaps_delba);454if ((hcaps & IEEE80211_HTCAP_MAXAMSDU_7935) != 0)455scaps |= (0x1 << WlanHTCaps_amsdu7935);456if ((hcaps & IEEE80211_HTCAP_DSSSCCK40) != 0)457scaps |= (0x1 << WlanHTCaps_dssscck40);458if ((hcaps & IEEE80211_HTCAP_PSMP) != 0)459scaps |= (0x1 << WlanHTCaps_psmp);460if ((hcaps & IEEE80211_HTCAP_40INTOLERANT) != 0)461scaps |= (0x1 << WlanHTCaps_fortyMHzIntolerant);462if ((hcaps & IEEE80211_HTCAP_LSIGTXOPPROT) != 0)463scaps |= (0x1 << WlanHTCaps_lsigTxOpProt);464if ((hcaps & IEEE80211_HTC_AMPDU) != 0)465scaps |= (0x1 << WlanHTCaps_htcAmpdu);466if ((hcaps & IEEE80211_HTC_AMSDU) != 0)467scaps |= (0x1 << WlanHTCaps_htcAmsdu);468if ((hcaps & IEEE80211_HTC_HT) != 0)469scaps |= (0x1 << WlanHTCaps_htcHt);470if ((hcaps & IEEE80211_HTC_SMPS) != 0)471scaps |= (0x1 << WlanHTCaps_htcSmps);472if ((hcaps & IEEE80211_HTC_RIFS) != 0)473scaps |= (0x1 << WlanHTCaps_htcRifs);474475return (scaps);476}477478/* XXX: Not here? */479#define WLAN_SET_TDMA_OPMODE(w) do { \480if ((w)->mode == WlanIfaceOperatingModeType_adhocDemo && \481((w)->drivercaps & WlanDriverCaps_tdma) != 0) \482(w)->mode = WlanIfaceOperatingModeType_tdma; \483} while (0)484int485wlan_get_driver_caps(struct wlan_iface *wif)486{487int val = 0;488size_t argsize;489struct ieee80211_devcaps_req dc;490491memset(&dc, 0, sizeof(struct ieee80211_devcaps_req));492argsize = sizeof(struct ieee80211_devcaps_req);493494if (wlan_ioctl(wif->wname, IEEE80211_IOC_DEVCAPS, &val, &dc,495&argsize, 0) < 0)496return (-1);497498wif->drivercaps = wlan_drivercaps_to_snmp(dc.dc_drivercaps);499wif->cryptocaps = wlan_cryptocaps_to_snmp(dc.dc_cryptocaps);500wif->htcaps = wlan_htcaps_to_snmp(dc.dc_htcaps);501502WLAN_SET_TDMA_OPMODE(wif);503504argsize = dc.dc_chaninfo.ic_nchans * sizeof(struct ieee80211_channel);505wif->chanlist = (struct ieee80211_channel *)malloc(argsize);506if (wif->chanlist == NULL)507return (0);508509memcpy(wif->chanlist, dc.dc_chaninfo.ic_chans, argsize);510wif->nchannels = dc.dc_chaninfo.ic_nchans;511512return (0);513}514515uint8_t516wlan_channel_state_to_snmp(uint8_t cstate)517{518uint8_t cs = 0;519520if ((cstate & IEEE80211_CHANSTATE_RADAR) != 0)521cs |= (0x1 << WlanIfaceChannelStateType_radar);522if ((cstate & IEEE80211_CHANSTATE_CACDONE) != 0)523cs |= (0x1 << WlanIfaceChannelStateType_cacDone);524if ((cstate & IEEE80211_CHANSTATE_CWINT) != 0)525cs |= (0x1 << WlanIfaceChannelStateType_interferenceDetected);526if ((cstate & IEEE80211_CHANSTATE_NORADAR) != 0)527cs |= (0x1 << WlanIfaceChannelStateType_radarClear);528529return (cs);530}531532uint32_t533wlan_channel_flags_to_snmp(uint32_t cflags)534{535uint32_t cf = 0;536537if ((cflags & IEEE80211_CHAN_TURBO) != 0)538cf |= (0x1 << WlanIfaceChannelFlagsType_turbo);539if ((cflags & IEEE80211_CHAN_CCK) != 0)540cf |= (0x1 << WlanIfaceChannelFlagsType_cck);541if ((cflags & IEEE80211_CHAN_OFDM) != 0)542cf |= (0x1 << WlanIfaceChannelFlagsType_ofdm);543if ((cflags & IEEE80211_CHAN_2GHZ) != 0)544cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum2Ghz);545if ((cflags & IEEE80211_CHAN_5GHZ) != 0)546cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum5Ghz);547if ((cflags & IEEE80211_CHAN_PASSIVE) != 0)548cf |= (0x1 << WlanIfaceChannelFlagsType_passiveScan);549if ((cflags & IEEE80211_CHAN_DYN) != 0)550cf |= (0x1 << WlanIfaceChannelFlagsType_dynamicCckOfdm);551if ((cflags & IEEE80211_CHAN_GFSK) != 0)552cf |= (0x1 << WlanIfaceChannelFlagsType_gfsk);553if ((cflags & IEEE80211_CHAN_GSM) != 0)554cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum900Mhz);555if ((cflags & IEEE80211_CHAN_STURBO) != 0)556cf |= (0x1 << WlanIfaceChannelFlagsType_dot11aStaticTurbo);557if ((cflags & IEEE80211_CHAN_HALF) != 0)558cf |= (0x1 << WlanIfaceChannelFlagsType_halfRate);559if ((cflags & IEEE80211_CHAN_QUARTER) != 0)560cf |= (0x1 << WlanIfaceChannelFlagsType_quarterRate);561if ((cflags & IEEE80211_CHAN_HT20) != 0)562cf |= (0x1 << WlanIfaceChannelFlagsType_ht20);563if ((cflags & IEEE80211_CHAN_HT40U) != 0)564cf |= (0x1 << WlanIfaceChannelFlagsType_ht40u);565if ((cflags & IEEE80211_CHAN_HT40D) != 0)566cf |= (0x1 << WlanIfaceChannelFlagsType_ht40d);567if ((cflags & IEEE80211_CHAN_DFS) != 0)568cf |= (0x1 << WlanIfaceChannelFlagsType_dfs);569if ((cflags & IEEE80211_CHAN_4MSXMIT) != 0)570cf |= (0x1 << WlanIfaceChannelFlagsType_xmit4ms);571if ((cflags & IEEE80211_CHAN_NOADHOC) != 0)572cf |= (0x1 << WlanIfaceChannelFlagsType_noAdhoc);573if ((cflags & IEEE80211_CHAN_NOHOSTAP) != 0)574cf |= (0x1 << WlanIfaceChannelFlagsType_noHostAp);575if ((cflags & IEEE80211_CHAN_11D) != 0)576cf |= (0x1 << WlanIfaceChannelFlagsType_dot11d);577578return (cf);579}580581/* XXX: */582#define WLAN_SNMP_MAX_CHANS 256583int584wlan_get_channel_list(struct wlan_iface *wif)585{586int val = 0;587uint32_t i, nchans;588size_t argsize;589struct ieee80211req_chaninfo *chaninfo;590struct ieee80211req_chanlist active;591const struct ieee80211_channel *c;592593argsize = sizeof(struct ieee80211req_chaninfo) +594sizeof(struct ieee80211_channel) * WLAN_SNMP_MAX_CHANS;595chaninfo = (struct ieee80211req_chaninfo *)malloc(argsize);596if (chaninfo == NULL)597return (-1);598599if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANINFO, &val, chaninfo,600&argsize, 0) < 0)601return (-1);602603argsize = sizeof(active);604if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANLIST, &val, &active,605&argsize, 0) < 0)606goto error;607608for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {609c = &chaninfo->ic_chans[i];610if (!isset(active.ic_channels, c->ic_ieee))611continue;612nchans++;613}614wif->chanlist = (struct ieee80211_channel *)reallocf(wif->chanlist,615nchans * sizeof(*c));616if (wif->chanlist == NULL)617goto error;618wif->nchannels = nchans;619for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) {620c = &chaninfo->ic_chans[i];621if (!isset(active.ic_channels, c->ic_ieee))622continue;623memcpy(wif->chanlist + nchans, c, sizeof (*c));624nchans++;625}626627free(chaninfo);628return (0);629error:630wif->nchannels = 0;631free(chaninfo);632return (-1);633}634635static enum WlanIfPhyMode636wlan_channel_flags_to_snmp_phy(uint32_t cflags)637{638/* XXX: recheck */639if ((cflags & IEEE80211_CHAN_A) != 0)640return (WlanIfPhyMode_dot11a);641if ((cflags & IEEE80211_CHAN_B) != 0)642return (WlanIfPhyMode_dot11b);643if ((cflags & IEEE80211_CHAN_G) != 0 ||644(cflags & IEEE80211_CHAN_PUREG) != 0)645return (WlanIfPhyMode_dot11g);646if ((cflags & IEEE80211_CHAN_FHSS) != 0)647return (WlanIfPhyMode_fh);648if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&649(cflags & IEEE80211_CHAN_A) != 0)650return (WlanIfPhyMode_turboA);651if ((cflags & IEEE80211_CHAN_TURBO) != 0 &&652(cflags & IEEE80211_CHAN_G) != 0)653return (WlanIfPhyMode_turboG);654if ((cflags & IEEE80211_CHAN_STURBO) != 0)655return (WlanIfPhyMode_sturboA);656if ((cflags & IEEE80211_CHAN_HALF) != 0)657return (WlanIfPhyMode_ofdmHalf);658if ((cflags & IEEE80211_CHAN_QUARTER) != 0)659return (WlanIfPhyMode_ofdmQuarter);660661return (WlanIfPhyMode_auto);662}663664int665wlan_get_roam_params(struct wlan_iface *wif)666{667int val = 0;668size_t argsize;669670argsize = sizeof(struct ieee80211_roamparams_req);671if (wlan_ioctl(wif->wname, IEEE80211_IOC_ROAM, &val,672&wif->roamparams, &argsize, 0) < 0)673return (-1);674675return (0);676}677678int679wlan_get_tx_params(struct wlan_iface *wif)680{681int val = 0;682size_t argsize;683684/*685* XXX: Reset IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA686* and IEEE80211_MODE_11NG modes.687*/688argsize = sizeof(struct ieee80211_txparams_req);689if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,690&wif->txparams, &argsize, 0) < 0)691return (-1);692693return (0);694}695696int697wlan_set_tx_params(struct wlan_iface *wif, int32_t pmode __unused)698{699int val = 0;700size_t argsize;701702/*703* XXX: Set IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA704* and IEEE80211_MODE_11NG modes.705*/706argsize = sizeof(struct ieee80211_txparams_req);707if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val,708&wif->txparams, &argsize, 1) < 0)709return (-1);710711return (0);712}713714int715wlan_clone_create(struct wlan_iface *wif)716{717struct ifreq ifr;718struct ieee80211_clone_params wcp;719static const uint8_t zerobssid[IEEE80211_ADDR_LEN];720721memset(&wcp, 0, sizeof(wcp));722memset(&ifr, 0, sizeof(ifr));723724/* Sanity checks. */725if (wif == NULL || wif->pname[0] == '\0' || wif->mode > WLAN_IFMODE_MAX)726return (SNMP_ERR_INCONS_VALUE);727728if (wif->mode == WlanIfaceOperatingModeType_wds &&729memcmp(wif->dbssid, zerobssid, IEEE80211_ADDR_LEN) == 0)730return (SNMP_ERR_INCONS_VALUE);731732strlcpy(wcp.icp_parent, wif->pname, IFNAMSIZ);733if ((wif->flags & WlanIfaceFlagsType_uniqueBssid) != 0)734wcp.icp_flags |= IEEE80211_CLONE_BSSID;735if ((wif->flags & WlanIfaceFlagsType_noBeacons) != 0)736wcp.icp_flags |= IEEE80211_CLONE_NOBEACONS;737if (wif->mode == WlanIfaceOperatingModeType_wds &&738(wif->flags & WlanIfaceFlagsType_wdsLegacy) != 0)739wcp.icp_flags |= IEEE80211_CLONE_WDSLEGACY;740741switch (wif->mode) {742case WlanIfaceOperatingModeType_ibss:743wcp.icp_opmode = IEEE80211_M_IBSS;744break;745case WlanIfaceOperatingModeType_station:746wcp.icp_opmode = IEEE80211_M_STA;747break;748case WlanIfaceOperatingModeType_wds:749wcp.icp_opmode = IEEE80211_M_WDS;750break;751case WlanIfaceOperatingModeType_adhocDemo:752wcp.icp_opmode = IEEE80211_M_AHDEMO;753break;754case WlanIfaceOperatingModeType_hostAp:755wcp.icp_opmode = IEEE80211_M_HOSTAP;756break;757case WlanIfaceOperatingModeType_monitor:758wcp.icp_opmode = IEEE80211_M_MONITOR;759break;760case WlanIfaceOperatingModeType_meshPoint:761wcp.icp_opmode = IEEE80211_M_MBSS;762break;763case WlanIfaceOperatingModeType_tdma:764wcp.icp_opmode = IEEE80211_M_AHDEMO;765wcp.icp_flags |= IEEE80211_CLONE_TDMA;766break;767}768769memcpy(wcp.icp_bssid, wif->dbssid, IEEE80211_ADDR_LEN);770if (memcmp(wif->dlmac, zerobssid, IEEE80211_ADDR_LEN) != 0) {771memcpy(wcp.icp_macaddr, wif->dlmac, IEEE80211_ADDR_LEN);772wcp.icp_flags |= IEEE80211_CLONE_MACADDR;773}774775strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);776ifr.ifr_data = (caddr_t) &wcp;777778if (ioctl(sock, SIOCIFCREATE2, (caddr_t) &ifr) < 0) {779syslog(LOG_ERR, "wlan clone create: ioctl(SIOCIFCREATE2) "780"failed: %s", strerror(errno));781return (SNMP_ERR_GENERR);782}783784return (SNMP_ERR_NOERROR);785}786787int788wlan_clone_destroy(struct wlan_iface *wif)789{790struct ifreq ifr;791792if (wif == NULL)793return (SNMP_ERR_INCONS_VALUE);794795memset(&ifr, 0, sizeof(ifr));796strcpy(ifr.ifr_name, wif->wname);797798if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) {799syslog(LOG_ERR, "wlan clone destroy: ioctl(SIOCIFDESTROY) "800"failed: %s", strerror(errno));801return (SNMP_ERR_GENERR);802}803804return (SNMP_ERR_NOERROR);805}806807static int808wlan_config_snmp2ioctl(int which)809{810int op;811812switch (which) {813case LEAF_wlanIfacePacketBurst:814op = IEEE80211_IOC_BURST;815break;816case LEAF_wlanIfaceCountryCode:817op = IEEE80211_IOC_REGDOMAIN;818break;819case LEAF_wlanIfaceRegDomain:820op = IEEE80211_IOC_REGDOMAIN;821break;822case LEAF_wlanIfaceDesiredSsid:823op = IEEE80211_IOC_SSID;824break;825case LEAF_wlanIfaceDesiredChannel:826op = IEEE80211_IOC_CURCHAN;827break;828case LEAF_wlanIfaceDynamicFreqSelection:829op = IEEE80211_IOC_DFS;830break;831case LEAF_wlanIfaceFastFrames:832op = IEEE80211_IOC_FF;833break;834case LEAF_wlanIfaceDturbo:835op = IEEE80211_IOC_TURBOP;836break;837case LEAF_wlanIfaceTxPower:838op = IEEE80211_IOC_TXPOWER;839break;840case LEAF_wlanIfaceFragmentThreshold:841op = IEEE80211_IOC_FRAGTHRESHOLD;842break;843case LEAF_wlanIfaceRTSThreshold:844op = IEEE80211_IOC_RTSTHRESHOLD;845break;846case LEAF_wlanIfaceWlanPrivacySubscribe:847op = IEEE80211_IOC_WPS;848break;849case LEAF_wlanIfaceBgScan:850op = IEEE80211_IOC_BGSCAN;851break;852case LEAF_wlanIfaceBgScanIdle:853op = IEEE80211_IOC_BGSCAN_IDLE;854break;855case LEAF_wlanIfaceBgScanInterval:856op = IEEE80211_IOC_BGSCAN_INTERVAL;857break;858case LEAF_wlanIfaceBeaconMissedThreshold:859op = IEEE80211_IOC_BMISSTHRESHOLD;860break;861case LEAF_wlanIfaceDesiredBssid:862op = IEEE80211_IOC_BSSID;863break;864case LEAF_wlanIfaceRoamingMode:865op = IEEE80211_IOC_ROAMING;866break;867case LEAF_wlanIfaceDot11d:868op = IEEE80211_IOC_DOTD;869break;870case LEAF_wlanIfaceDot11h:871op = IEEE80211_IOC_DOTH;872break;873case LEAF_wlanIfaceDynamicWds:874op = IEEE80211_IOC_DWDS;875break;876case LEAF_wlanIfacePowerSave:877op = IEEE80211_IOC_POWERSAVE;878break;879case LEAF_wlanIfaceApBridge:880op = IEEE80211_IOC_APBRIDGE;881break;882case LEAF_wlanIfaceBeaconInterval:883op = IEEE80211_IOC_BEACON_INTERVAL;884break;885case LEAF_wlanIfaceDtimPeriod:886op = IEEE80211_IOC_DTIM_PERIOD;887break;888case LEAF_wlanIfaceHideSsid:889op = IEEE80211_IOC_HIDESSID;890break;891case LEAF_wlanIfaceInactivityProccess:892op = IEEE80211_IOC_INACTIVITY;893break;894case LEAF_wlanIfaceDot11gProtMode:895op = IEEE80211_IOC_PROTMODE;896break;897case LEAF_wlanIfaceDot11gPureMode:898op = IEEE80211_IOC_PUREG;899break;900case LEAF_wlanIfaceDot11nPureMode:901op = IEEE80211_IOC_PUREN;902break;903case LEAF_wlanIfaceDot11nAmpdu:904op = IEEE80211_IOC_AMPDU;905break;906case LEAF_wlanIfaceDot11nAmpduDensity:907op = IEEE80211_IOC_AMPDU_DENSITY;908break;909case LEAF_wlanIfaceDot11nAmpduLimit:910op = IEEE80211_IOC_AMPDU_LIMIT;911break;912case LEAF_wlanIfaceDot11nAmsdu:913op = IEEE80211_IOC_AMSDU;914break;915case LEAF_wlanIfaceDot11nAmsduLimit:916op = IEEE80211_IOC_AMSDU_LIMIT;917break;918case LEAF_wlanIfaceDot11nHighThroughput:919op = IEEE80211_IOC_HTCONF;920break;921case LEAF_wlanIfaceDot11nHTCompatible:922op = IEEE80211_IOC_HTCOMPAT;923break;924case LEAF_wlanIfaceDot11nHTProtMode:925op = IEEE80211_IOC_HTPROTMODE;926break;927case LEAF_wlanIfaceDot11nRIFS:928op = IEEE80211_IOC_RIFS;929break;930case LEAF_wlanIfaceDot11nShortGI:931op = IEEE80211_IOC_SHORTGI;932break;933case LEAF_wlanIfaceDot11nSMPSMode:934op = IEEE80211_IOC_SMPS;935break;936case LEAF_wlanIfaceTdmaSlot:937op = IEEE80211_IOC_TDMA_SLOT;938break;939case LEAF_wlanIfaceTdmaSlotCount:940op = IEEE80211_IOC_TDMA_SLOTCNT;941break;942case LEAF_wlanIfaceTdmaSlotLength:943op = IEEE80211_IOC_TDMA_SLOTLEN;944break;945case LEAF_wlanIfaceTdmaBeaconInterval:946op = IEEE80211_IOC_TDMA_BINTERVAL;947break;948default:949op = -1;950}951952return (op);953}954955static enum WlanRegDomainCode956wlan_regdomain_to_snmp(int which)957{958enum WlanRegDomainCode reg_domain;959960switch (which) {961case SKU_FCC:962reg_domain = WlanRegDomainCode_fcc;963break;964case SKU_CA:965reg_domain = WlanRegDomainCode_ca;966break;967case SKU_ETSI:968reg_domain = WlanRegDomainCode_etsi;969break;970case SKU_ETSI2:971reg_domain = WlanRegDomainCode_etsi2;972break;973case SKU_ETSI3:974reg_domain = WlanRegDomainCode_etsi3;975break;976case SKU_FCC3:977reg_domain = WlanRegDomainCode_fcc3;978break;979case SKU_JAPAN:980reg_domain = WlanRegDomainCode_japan;981break;982case SKU_KOREA:983reg_domain = WlanRegDomainCode_korea;984break;985case SKU_APAC:986reg_domain = WlanRegDomainCode_apac;987break;988case SKU_APAC2:989reg_domain = WlanRegDomainCode_apac2;990break;991case SKU_APAC3:992reg_domain = WlanRegDomainCode_apac3;993break;994case SKU_ROW:995reg_domain = WlanRegDomainCode_row;996break;997case SKU_NONE:998reg_domain = WlanRegDomainCode_none;999break;1000case SKU_DEBUG:1001reg_domain = WlanRegDomainCode_debug;1002break;1003case SKU_SR9:1004reg_domain = WlanRegDomainCode_sr9;1005break;1006case SKU_XR9:1007reg_domain = WlanRegDomainCode_xr9;1008break;1009case SKU_GZ901:1010reg_domain = WlanRegDomainCode_gz901;1011break;1012case 0:1013reg_domain = WlanRegDomainCode_none;1014break;1015default:1016syslog(LOG_ERR, "unknown regdomain (0x%x) ", which);1017reg_domain = WlanRegDomainCode_none;1018break;1019}10201021return (reg_domain);1022}10231024static int1025wlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain)1026{1027int which;10281029switch (regdomain) {1030case WlanRegDomainCode_fcc:1031which = SKU_FCC;1032break;1033case WlanRegDomainCode_ca:1034which = SKU_CA;1035break;1036case WlanRegDomainCode_etsi:1037which = SKU_ETSI;1038break;1039case WlanRegDomainCode_etsi2:1040which = SKU_ETSI2;1041break;1042case WlanRegDomainCode_etsi3:1043which = SKU_ETSI3;1044break;1045case WlanRegDomainCode_fcc3:1046which = SKU_FCC3;1047break;1048case WlanRegDomainCode_japan:1049which = SKU_JAPAN;1050break;1051case WlanRegDomainCode_korea:1052which = SKU_KOREA;1053break;1054case WlanRegDomainCode_apac:1055which = SKU_APAC;1056break;1057case WlanRegDomainCode_apac2:1058which = SKU_APAC2;1059break;1060case WlanRegDomainCode_apac3:1061which = SKU_APAC3;1062break;1063case WlanRegDomainCode_row:1064which = SKU_ROW;1065break;1066case WlanRegDomainCode_none:1067which = SKU_NONE;1068break;1069case WlanRegDomainCode_debug:1070which = SKU_DEBUG;1071break;1072case WlanRegDomainCode_sr9:1073which = SKU_SR9;1074break;1075case WlanRegDomainCode_xr9:1076which = SKU_XR9;1077break;1078case WlanRegDomainCode_gz901:1079which = SKU_GZ901;1080break;1081default:1082syslog(LOG_ERR, "unknown snmp regdomain (0x%x) ", regdomain);1083which = SKU_NONE;1084break;1085}10861087return (which);1088}10891090static int1091wlan_config_get_country(struct wlan_iface *wif)1092{1093int val = 0;1094size_t argsize;1095struct ieee80211_regdomain regdomain;10961097memset(®domain, 0, sizeof(regdomain));1098argsize = sizeof(regdomain);10991100if (wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, ®domain,1101&argsize, 0) < 0)1102return (-1);11031104wif->reg_domain = wlan_regdomain_to_snmp(regdomain.regdomain);1105wif->country_code[0] = regdomain.isocc[0];1106wif->country_code[1] = regdomain.isocc[1];1107wif->country_code[2] = regdomain.location;11081109return (0);1110}11111112static int1113wlan_config_set_country(struct wlan_iface *wif, char *ccode, int rdomain)1114{1115int val = 0, txpowermax;1116uint32_t i;1117size_t argsize = 0;1118struct ieee80211_regdomain_req *regdomain;11191120if (wlan_get_channel_list(wif) < 0)1121return (-1);11221123if (wif->nchannels == 0) {1124syslog(LOG_ERR, "iface %s - set regdomain failed", wif->wname);1125return (-1);1126}11271128if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPOWMAX, &txpowermax, 0,1129&argsize, 0) < 0)1130return (-1);11311132regdomain = malloc(IEEE80211_REGDOMAIN_SIZE(wif->nchannels));1133if (regdomain == NULL)1134return (-1);1135memset(regdomain, 0, IEEE80211_REGDOMAIN_SIZE(wif->nchannels));1136argsize = IEEE80211_REGDOMAIN_SIZE(wif->nchannels);11371138/* XXX: recheck with how this is done by ifconfig(8) */1139regdomain->rd.regdomain = wlan_snmp_to_regdomain(rdomain);1140regdomain->rd.isocc[0] = ccode[0];1141regdomain->rd.isocc[1] = ccode[1];1142regdomain->rd.location = ccode[2];11431144/* XXX: fill the channel list properly */1145regdomain->chaninfo.ic_nchans = wif->nchannels;1146memcpy(regdomain->chaninfo.ic_chans, wif->chanlist,1147wif->nchannels * sizeof(struct ieee80211_channel));1148for (i = 0; i < wif->nchannels; i++)1149regdomain->chaninfo.ic_chans[i].ic_maxregpower = txpowermax;11501151wif->state = wlanIfaceState_down;1152if (wlan_config_state(wif, 1) < 0 ||1153wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, regdomain,1154&argsize, 1) < 0) {1155free(regdomain);1156return (-1);1157}11581159wif->state = wlanIfaceState_up;1160(void)wlan_config_state(wif, 1);1161wif->reg_domain = wlan_regdomain_to_snmp(regdomain->rd.regdomain);1162wif->country_code[0] = regdomain->rd.isocc[0];1163wif->country_code[1] = regdomain->rd.isocc[1];1164wif->country_code[2] = regdomain->rd.location;1165free(regdomain);11661167return (0);1168}11691170int1171wlan_config_get_dssid(struct wlan_iface *wif)1172{1173int val = -1;1174size_t argsize = IEEE80211_NWID_LEN + 1;1175char ssid[IEEE80211_NWID_LEN + 1];11761177memset(ssid, 0, IEEE80211_NWID_LEN + 1);11781179if (wlan_ioctl(wif->wname,1180(wif->mode == WlanIfaceOperatingModeType_meshPoint) ?1181IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,1182&argsize, 0) < 0)1183return (-1);11841185if (argsize > IEEE80211_NWID_LEN)1186argsize = IEEE80211_NWID_LEN;1187memcpy(wif->desired_ssid, ssid, argsize);1188wif->desired_ssid[argsize] = '\0';11891190return (0);1191}11921193int1194wlan_config_set_dssid(struct wlan_iface *wif, char *ssid, int slen)1195{1196int val = 0;1197size_t argsize = slen;11981199if (wlan_ioctl(wif->wname,1200(wif->mode == WlanIfaceOperatingModeType_meshPoint) ?1201IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid,1202&argsize, 1) < 0)1203return (-1);12041205if (argsize > IEEE80211_NWID_LEN)1206argsize = IEEE80211_NWID_LEN;1207memcpy(wif->desired_ssid, ssid, argsize);1208wif->desired_ssid[argsize] = '\0';12091210return (0);1211}12121213static int1214wlan_config_get_dchannel(struct wlan_iface *wif)1215{1216uint32_t i = 0;1217int val = 0;1218size_t argsize = sizeof(struct ieee80211_channel);1219struct ieee80211_channel chan;12201221if (wlan_get_channel_list(wif) < 0)1222return (-1);12231224memset(&chan, 0, sizeof(chan));1225if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,1226&argsize, 0) < 0)1227return (-1);12281229for (i = 0; i < wif->nchannels; i++)1230if (chan.ic_ieee == wif->chanlist[i].ic_ieee &&1231chan.ic_flags == wif->chanlist[i].ic_flags) {1232wif->desired_channel = i + 1;1233break;1234}12351236return (0);1237}12381239static int1240wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t dchannel)1241{1242int val = 0;1243size_t argsize = sizeof(struct ieee80211_channel);1244struct ieee80211_channel chan;12451246if (wlan_get_channel_list(wif) < 0)1247return (-1);12481249if (dchannel > wif->nchannels)1250return (-1);12511252memcpy(&chan, wif->chanlist + dchannel - 1, sizeof(chan));1253if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan,1254&argsize, 1) < 0)1255return (-1);12561257wif->desired_channel = dchannel;12581259return (0);1260}12611262static int1263wlan_config_get_bssid(struct wlan_iface *wif)1264{1265int val = 0;1266size_t argsize = IEEE80211_ADDR_LEN;1267char bssid[IEEE80211_ADDR_LEN];12681269memset(bssid, 0, IEEE80211_ADDR_LEN);12701271if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,1272&argsize, 0) < 0 || argsize != IEEE80211_ADDR_LEN)1273return (-1);12741275memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);12761277return (0);1278}12791280static int1281wlan_config_set_bssid(struct wlan_iface *wif, uint8_t *bssid)1282{1283int val = 0;1284size_t argsize = IEEE80211_ADDR_LEN;12851286if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid,1287&argsize, 1) < 0 || argsize != IEEE80211_ADDR_LEN)1288return (-1);12891290memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN);12911292return (0);1293}12941295/*1296* Convert the value returned by the kernel to the appropriate SNMP1297* representation and set the corresponding interface member accordingly.1298*/1299static void1300wlan_config_set_snmp_intval(struct wlan_iface *wif, int op, int val)1301{1302switch (op) {1303case IEEE80211_IOC_BURST:1304if (val == 0)1305wif->packet_burst = TruthValue_false;1306else1307wif->packet_burst = TruthValue_true;1308break;1309case IEEE80211_IOC_DFS:1310if (val == 0)1311wif->dyn_frequency = TruthValue_false;1312else1313wif->dyn_frequency = TruthValue_true;1314break;1315case IEEE80211_IOC_FF:1316if (val == 0)1317wif->fast_frames = TruthValue_false;1318else1319wif->fast_frames = TruthValue_true;1320break;1321case IEEE80211_IOC_TURBOP:1322if (val == 0)1323wif->dturbo = TruthValue_false;1324else1325wif->dturbo = TruthValue_true;1326break;1327case IEEE80211_IOC_TXPOWER:1328wif->tx_power = val / 2;1329break;1330case IEEE80211_IOC_FRAGTHRESHOLD:1331wif->frag_threshold = val;1332break;1333case IEEE80211_IOC_RTSTHRESHOLD:1334wif->rts_threshold = val;1335break;1336case IEEE80211_IOC_WPS:1337if (val == 0)1338wif->priv_subscribe = TruthValue_false;1339else1340wif->priv_subscribe = TruthValue_true;1341break;1342case IEEE80211_IOC_BGSCAN:1343if (val == 0)1344wif->bg_scan = TruthValue_false;1345else1346wif->bg_scan = TruthValue_true;1347break;1348case IEEE80211_IOC_BGSCAN_IDLE:1349wif->bg_scan_idle = val;1350break;1351case IEEE80211_IOC_BGSCAN_INTERVAL:1352wif->bg_scan_interval = val;1353break;1354case IEEE80211_IOC_BMISSTHRESHOLD:1355wif->beacons_missed = val;1356break;1357case IEEE80211_IOC_ROAMING:1358switch (val) {1359case IEEE80211_ROAMING_DEVICE:1360wif->roam_mode = wlanIfaceRoamingMode_device;1361break;1362case IEEE80211_ROAMING_MANUAL:1363wif->roam_mode = wlanIfaceRoamingMode_manual;1364break;1365case IEEE80211_ROAMING_AUTO:1366/* FALTHROUGH */1367default:1368wif->roam_mode = wlanIfaceRoamingMode_auto;1369break;1370}1371break;1372case IEEE80211_IOC_DOTD:1373if (val == 0)1374wif->dot11d = TruthValue_false;1375else1376wif->dot11d = TruthValue_true;1377break;1378case IEEE80211_IOC_DOTH:1379if (val == 0)1380wif->dot11h = TruthValue_false;1381else1382wif->dot11h = TruthValue_true;1383break;1384case IEEE80211_IOC_DWDS:1385if (val == 0)1386wif->dynamic_wds = TruthValue_false;1387else1388wif->dynamic_wds = TruthValue_true;1389break;1390case IEEE80211_IOC_POWERSAVE:1391if (val == 0)1392wif->power_save = TruthValue_false;1393else1394wif->power_save = TruthValue_true;1395break;1396case IEEE80211_IOC_APBRIDGE:1397if (val == 0)1398wif->ap_bridge = TruthValue_false;1399else1400wif->ap_bridge = TruthValue_true;1401break;1402case IEEE80211_IOC_BEACON_INTERVAL:1403wif->beacon_interval = val;1404break;1405case IEEE80211_IOC_DTIM_PERIOD:1406wif->dtim_period = val;1407break;1408case IEEE80211_IOC_HIDESSID:1409if (val == 0)1410wif->hide_ssid = TruthValue_false;1411else1412wif->hide_ssid = TruthValue_true;1413break;1414case IEEE80211_IOC_INACTIVITY:1415if (val == 0)1416wif->inact_process = TruthValue_false;1417else1418wif->inact_process = TruthValue_true;1419break;1420case IEEE80211_IOC_PROTMODE:1421switch (val) {1422case IEEE80211_PROTMODE_CTS:1423wif->do11g_protect = wlanIfaceDot11gProtMode_cts;1424break;1425case IEEE80211_PROTMODE_RTSCTS:1426wif->do11g_protect = wlanIfaceDot11gProtMode_rtscts;1427break;1428case IEEE80211_PROTMODE_OFF:1429/* FALLTHROUGH */1430default:1431wif->do11g_protect = wlanIfaceDot11gProtMode_off;1432break;1433}1434break;1435case IEEE80211_IOC_PUREG:1436if (val == 0)1437wif->dot11g_pure = TruthValue_false;1438else1439wif->dot11g_pure = TruthValue_true;1440break;1441case IEEE80211_IOC_PUREN:1442if (val == 0)1443wif->dot11n_pure = TruthValue_false;1444else1445wif->dot11n_pure = TruthValue_true;1446break;1447case IEEE80211_IOC_AMPDU:1448switch (val) {1449case 0:1450wif->ampdu = WlanIfaceDot11nPduType_disabled;1451break;1452case 1:1453wif->ampdu = WlanIfaceDot11nPduType_txOnly;1454break;1455case 2:1456wif->ampdu = WlanIfaceDot11nPduType_rxOnly;1457break;1458case 3:1459/* FALLTHROUGH */1460default:1461wif->ampdu = WlanIfaceDot11nPduType_txAndRx;1462break;1463}1464break;1465case IEEE80211_IOC_AMPDU_DENSITY:1466switch (val) {1467case IEEE80211_HTCAP_MPDUDENSITY_025:1468wif->ampdu_density = 25;1469break;1470case IEEE80211_HTCAP_MPDUDENSITY_05:1471wif->ampdu_density = 50;1472break;1473case IEEE80211_HTCAP_MPDUDENSITY_1:1474wif->ampdu_density = 100;1475break;1476case IEEE80211_HTCAP_MPDUDENSITY_2:1477wif->ampdu_density = 200;1478break;1479case IEEE80211_HTCAP_MPDUDENSITY_4:1480wif->ampdu_density = 400;1481break;1482case IEEE80211_HTCAP_MPDUDENSITY_8:1483wif->ampdu_density = 800;1484break;1485case IEEE80211_HTCAP_MPDUDENSITY_16:1486wif->ampdu_density = 1600;1487break;1488case IEEE80211_HTCAP_MPDUDENSITY_NA:1489default:1490wif->ampdu_density = 0;1491break;1492}1493break;1494case IEEE80211_IOC_AMPDU_LIMIT:1495switch (val) {1496case IEEE80211_HTCAP_MAXRXAMPDU_8K:1497wif->ampdu_limit = 8192;1498break;1499case IEEE80211_HTCAP_MAXRXAMPDU_16K:1500wif->ampdu_limit = 16384;1501break;1502case IEEE80211_HTCAP_MAXRXAMPDU_32K:1503wif->ampdu_limit = 32768;1504break;1505case IEEE80211_HTCAP_MAXRXAMPDU_64K:1506default:1507wif->ampdu_limit = 65536;1508break;1509}1510break;1511case IEEE80211_IOC_AMSDU:1512switch (val) {1513case 0:1514wif->amsdu = WlanIfaceDot11nPduType_disabled;1515break;1516case 1:1517wif->amsdu = WlanIfaceDot11nPduType_txOnly;1518break;1519case 3:1520wif->amsdu = WlanIfaceDot11nPduType_txAndRx;1521break;1522case 2:1523default:1524/* FALLTHROUGH */1525wif->amsdu = WlanIfaceDot11nPduType_rxOnly;1526break;1527}1528break;1529case IEEE80211_IOC_AMSDU_LIMIT:1530wif->amsdu_limit = val;1531break;1532case IEEE80211_IOC_HTCONF:1533if (val == 0) /* XXX */1534wif->ht_enabled = TruthValue_false;1535else1536wif->ht_enabled = TruthValue_true;1537break;1538case IEEE80211_IOC_HTCOMPAT:1539if (val == 0)1540wif->ht_compatible = TruthValue_false;1541else1542wif->ht_compatible = TruthValue_true;1543break;1544case IEEE80211_IOC_HTPROTMODE:1545if (val == IEEE80211_PROTMODE_RTSCTS)1546wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_rts;1547else1548wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_off;1549break;1550case IEEE80211_IOC_RIFS:1551if (val == 0)1552wif->rifs = TruthValue_false;1553else1554wif->rifs = TruthValue_true;1555break;1556case IEEE80211_IOC_SHORTGI:1557if (val == 0)1558wif->short_gi = TruthValue_false;1559else1560wif->short_gi = TruthValue_true;1561break;1562case IEEE80211_IOC_SMPS:1563switch (val) {1564case IEEE80211_HTCAP_SMPS_DYNAMIC:1565wif->smps_mode = wlanIfaceDot11nSMPSMode_dynamic;1566break;1567case IEEE80211_HTCAP_SMPS_ENA:1568wif->smps_mode = wlanIfaceDot11nSMPSMode_static;1569break;1570case IEEE80211_HTCAP_SMPS_OFF:1571/* FALLTHROUGH */1572default:1573wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;1574break;1575}1576break;1577case IEEE80211_IOC_TDMA_SLOT:1578wif->tdma_slot = val;1579break;1580case IEEE80211_IOC_TDMA_SLOTCNT:1581wif->tdma_slot_count = val;1582break;1583case IEEE80211_IOC_TDMA_SLOTLEN:1584wif->tdma_slot_length = val;1585break;1586case IEEE80211_IOC_TDMA_BINTERVAL:1587wif->tdma_binterval = val;1588break;1589default:1590break;1591}1592}15931594/*1595* Convert an SNMP value to the kernel equivalent and also do sanity check1596* for each specific type.1597*/1598static int1599wlan_config_snmp2value(int which, int sval, int *value)1600{1601*value = 0;16021603switch (which) {1604case IEEE80211_IOC_BURST:1605case IEEE80211_IOC_DFS:1606case IEEE80211_IOC_FF:1607case IEEE80211_IOC_TURBOP:1608case IEEE80211_IOC_WPS:1609case IEEE80211_IOC_BGSCAN:1610case IEEE80211_IOC_DOTD:1611case IEEE80211_IOC_DOTH:1612case IEEE80211_IOC_DWDS:1613case IEEE80211_IOC_POWERSAVE:1614case IEEE80211_IOC_APBRIDGE:1615case IEEE80211_IOC_HIDESSID:1616case IEEE80211_IOC_INACTIVITY:1617case IEEE80211_IOC_PUREG:1618case IEEE80211_IOC_PUREN:1619case IEEE80211_IOC_HTCONF:1620case IEEE80211_IOC_HTCOMPAT:1621case IEEE80211_IOC_RIFS:1622if (sval == TruthValue_true)1623*value = 1;1624else if (sval != TruthValue_false)1625return (SNMP_ERR_INCONS_VALUE);1626break;1627case IEEE80211_IOC_REGDOMAIN:1628break;1629case IEEE80211_IOC_SSID:1630break;1631case IEEE80211_IOC_CURCHAN:1632break;1633case IEEE80211_IOC_TXPOWER:1634*value = sval * 2;1635break;1636case IEEE80211_IOC_FRAGTHRESHOLD:1637if (sval < IEEE80211_FRAG_MIN || sval > IEEE80211_FRAG_MAX)1638return (SNMP_ERR_INCONS_VALUE);1639*value = sval;1640break;1641case IEEE80211_IOC_RTSTHRESHOLD:1642if (sval < IEEE80211_RTS_MIN || sval > IEEE80211_RTS_MAX)1643return (SNMP_ERR_INCONS_VALUE);1644*value = sval;1645break;1646case IEEE80211_IOC_BGSCAN_IDLE:1647if (sval < WLAN_BGSCAN_IDLE_MIN)1648return (SNMP_ERR_INCONS_VALUE);1649*value = sval;1650break;1651case IEEE80211_IOC_BGSCAN_INTERVAL:1652if (sval < WLAN_SCAN_VALID_MIN)1653return (SNMP_ERR_INCONS_VALUE);1654*value = sval;1655break;1656case IEEE80211_IOC_BMISSTHRESHOLD:1657if (sval < IEEE80211_HWBMISS_MIN || sval > IEEE80211_HWBMISS_MAX)1658return (SNMP_ERR_INCONS_VALUE);1659*value = sval;1660break;1661case IEEE80211_IOC_BSSID:1662break;1663case IEEE80211_IOC_ROAMING:1664switch (sval) {1665case wlanIfaceRoamingMode_device:1666*value = IEEE80211_ROAMING_DEVICE;1667break;1668case wlanIfaceRoamingMode_manual:1669*value = IEEE80211_ROAMING_MANUAL;1670break;1671case wlanIfaceRoamingMode_auto:1672*value = IEEE80211_ROAMING_AUTO;1673break;1674default:1675return (SNMP_ERR_INCONS_VALUE);1676}1677break;1678case IEEE80211_IOC_BEACON_INTERVAL:1679if (sval < IEEE80211_BINTVAL_MIN || sval > IEEE80211_BINTVAL_MAX)1680return (SNMP_ERR_INCONS_VALUE);1681*value = sval;1682break;1683case IEEE80211_IOC_DTIM_PERIOD:1684if (sval < IEEE80211_DTIM_MIN || sval > IEEE80211_DTIM_MAX)1685return (SNMP_ERR_INCONS_VALUE);1686*value = sval;1687break;1688case IEEE80211_IOC_PROTMODE:1689switch (sval) {1690case wlanIfaceDot11gProtMode_cts:1691*value = IEEE80211_PROTMODE_CTS;1692break;1693case wlanIfaceDot11gProtMode_rtscts:1694*value = IEEE80211_PROTMODE_RTSCTS;1695break;1696case wlanIfaceDot11gProtMode_off:1697*value = IEEE80211_PROTMODE_OFF;1698break;1699default:1700return (SNMP_ERR_INCONS_VALUE);1701}1702break;1703case IEEE80211_IOC_AMPDU:1704switch (sval) {1705case WlanIfaceDot11nPduType_disabled:1706break;1707case WlanIfaceDot11nPduType_txOnly:1708*value = 1;1709break;1710case WlanIfaceDot11nPduType_rxOnly:1711*value = 2;1712break;1713case WlanIfaceDot11nPduType_txAndRx:1714*value = 3;1715break;1716default:1717return (SNMP_ERR_INCONS_VALUE);1718}1719break;1720case IEEE80211_IOC_AMPDU_DENSITY:1721switch (sval) {1722case 0:1723*value = IEEE80211_HTCAP_MPDUDENSITY_NA;1724break;1725case 25:1726*value = IEEE80211_HTCAP_MPDUDENSITY_025;1727break;1728case 50:1729*value = IEEE80211_HTCAP_MPDUDENSITY_05;1730break;1731case 100:1732*value = IEEE80211_HTCAP_MPDUDENSITY_1;1733break;1734case 200:1735*value = IEEE80211_HTCAP_MPDUDENSITY_2;1736break;1737case 400:1738*value = IEEE80211_HTCAP_MPDUDENSITY_4;1739break;1740case 800:1741*value = IEEE80211_HTCAP_MPDUDENSITY_8;1742break;1743case 1600:1744*value = IEEE80211_HTCAP_MPDUDENSITY_16;1745break;1746default:1747return (SNMP_ERR_INCONS_VALUE);1748}1749break;1750case IEEE80211_IOC_AMPDU_LIMIT:1751switch (sval) {1752case 8192:1753*value = IEEE80211_HTCAP_MAXRXAMPDU_8K;1754break;1755case 16384:1756*value = IEEE80211_HTCAP_MAXRXAMPDU_16K;1757break;1758case 32768:1759*value = IEEE80211_HTCAP_MAXRXAMPDU_32K;1760break;1761case 65536:1762*value = IEEE80211_HTCAP_MAXRXAMPDU_64K;1763break;1764default:1765return (SNMP_ERR_INCONS_VALUE);1766}1767break;1768case IEEE80211_IOC_AMSDU:1769switch (sval) {1770case WlanIfaceDot11nPduType_disabled:1771break;1772case WlanIfaceDot11nPduType_txOnly:1773*value = 1;1774break;1775case WlanIfaceDot11nPduType_rxOnly:1776*value = 2;1777break;1778case WlanIfaceDot11nPduType_txAndRx:1779*value = 3;1780break;1781default:1782return (SNMP_ERR_INCONS_VALUE);1783}1784break;1785case IEEE80211_IOC_AMSDU_LIMIT:1786if (sval == 3839 || sval == 0)1787*value = IEEE80211_HTCAP_MAXAMSDU_3839;1788else if (sval == 7935)1789*value = IEEE80211_HTCAP_MAXAMSDU_7935;1790else1791return (SNMP_ERR_INCONS_VALUE);1792break;1793case IEEE80211_IOC_HTPROTMODE:1794switch (sval) {1795case wlanIfaceDot11nHTProtMode_rts:1796*value = IEEE80211_PROTMODE_RTSCTS;1797break;1798case wlanIfaceDot11nHTProtMode_off:1799break;1800default:1801return (SNMP_ERR_INCONS_VALUE);1802}1803break;1804case IEEE80211_IOC_SHORTGI:1805if (sval == TruthValue_true)1806*value = IEEE80211_HTCAP_SHORTGI20 |1807IEEE80211_HTCAP_SHORTGI40;1808else if (sval != TruthValue_false)1809return (SNMP_ERR_INCONS_VALUE);1810break;1811case IEEE80211_IOC_SMPS:1812switch (sval) {1813case wlanIfaceDot11nSMPSMode_disabled:1814*value = IEEE80211_HTCAP_SMPS_OFF;1815break;1816case wlanIfaceDot11nSMPSMode_static:1817*value = IEEE80211_HTCAP_SMPS_ENA;1818break;1819case wlanIfaceDot11nSMPSMode_dynamic:1820*value = IEEE80211_HTCAP_SMPS_DYNAMIC;1821break;1822default:1823return (SNMP_ERR_INCONS_VALUE);1824}1825break;1826case IEEE80211_IOC_TDMA_SLOT:1827if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */1828return (SNMP_ERR_INCONS_VALUE);1829*value = sval;1830break;1831case IEEE80211_IOC_TDMA_SLOTCNT:1832if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */1833return (SNMP_ERR_INCONS_VALUE);1834*value = sval;1835break;1836case IEEE80211_IOC_TDMA_SLOTLEN:1837if (sval < 2*100 || sval > 0xfffff) /* XXX */1838return (SNMP_ERR_INCONS_VALUE);1839*value = sval;1840break;1841case IEEE80211_IOC_TDMA_BINTERVAL:1842if (sval < 1) /* XXX */1843return (SNMP_ERR_INCONS_VALUE);1844*value = sval;1845break;1846default:1847return (SNMP_ERR_INCONS_VALUE);1848}18491850return (SNMP_ERR_NOERROR);1851}18521853/*1854* Sanity checks for the wlanIfaceConfigTable.1855*/1856static int1857wlan_config_check(struct wlan_iface *wif, int op)1858{1859switch (op) {1860case IEEE80211_IOC_BURST:1861if ((wif->drivercaps & (0x1 << WlanDriverCaps_burst)) == 0) {1862wif->packet_burst = TruthValue_false;1863return (-1);1864}1865break;1866case IEEE80211_IOC_DFS:1867if ((wif->drivercaps & (0x1 << WlanDriverCaps_dfs)) == 0) {1868wif->dyn_frequency = TruthValue_false;1869return (-1);1870}1871break;1872case IEEE80211_IOC_FF:1873if ((wif->drivercaps & (0x1 << WlanDriverCaps_athFastFrames))1874== 0) {1875wif->fast_frames = TruthValue_false;1876return (-1);1877}1878break;1879case IEEE80211_IOC_TURBOP:1880if ((wif->drivercaps & (0x1 << WlanDriverCaps_athTurbo)) == 0) {1881wif->dturbo = TruthValue_false;1882return (-1);1883}1884break;1885case IEEE80211_IOC_TXPOWER:1886if ((wif->drivercaps & (0x1 << WlanDriverCaps_txPmgt)) == 0) {1887wif->tx_power = 0;1888return (-1);1889}1890break;1891case IEEE80211_IOC_FRAGTHRESHOLD:1892if ((wif->drivercaps & (0x1 << WlanDriverCaps_txFrag)) == 0) {1893wif->frag_threshold = IEEE80211_FRAG_MAX;1894return (-1);1895}1896break;1897case IEEE80211_IOC_DWDS:1898if ((wif->drivercaps & (0x1 << WlanDriverCaps_wds)) == 0) {1899wif->dynamic_wds = TruthValue_false;1900return (-1);1901}1902break;1903case IEEE80211_IOC_POWERSAVE:1904if ((wif->drivercaps & (0x1 << WlanDriverCaps_pmgt)) == 0) {1905wif->power_save = TruthValue_false;1906return (-1);1907}1908break;1909case IEEE80211_IOC_BEACON_INTERVAL:1910if (wif->mode != WlanIfaceOperatingModeType_hostAp &&1911wif->mode != WlanIfaceOperatingModeType_meshPoint &&1912wif->mode != WlanIfaceOperatingModeType_ibss) {1913wif->beacon_interval = 100; /* XXX */1914return (-1);1915}1916break;1917case IEEE80211_IOC_DTIM_PERIOD:1918if (wif->mode != WlanIfaceOperatingModeType_hostAp &&1919wif->mode != WlanIfaceOperatingModeType_meshPoint &&1920wif->mode != WlanIfaceOperatingModeType_ibss) {1921wif->dtim_period = 1; /* XXX */1922return (-1);1923}1924break;1925case IEEE80211_IOC_PUREN:1926if ((wif->htcaps & (0x1 << WlanHTCaps_htcHt)) == 0) {1927wif->dot11n_pure = TruthValue_false;1928return (-1);1929}1930break;1931case IEEE80211_IOC_AMPDU:1932if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmpdu)) == 0) {1933wif->ampdu = WlanIfaceDot11nPduType_disabled;1934return (-1);1935}1936break;1937case IEEE80211_IOC_AMSDU:1938if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmsdu)) == 0) {1939wif->amsdu = WlanIfaceDot11nPduType_disabled;1940return (-1);1941}1942break;1943case IEEE80211_IOC_RIFS:1944if ((wif->htcaps & (0x1 << WlanHTCaps_htcRifs)) == 0) {1945wif->rifs = TruthValue_false;1946return (-1);1947}1948break;1949case IEEE80211_IOC_SHORTGI:1950if ((wif->htcaps & (0x1 << WlanHTCaps_shortGi20 |19510x1 << WlanHTCaps_shortGi40)) == 0) {1952wif->short_gi = TruthValue_false;1953return (-1);1954}1955break;1956case IEEE80211_IOC_SMPS:1957if ((wif->htcaps & (0x1 << WlanHTCaps_htcSmps)) == 0) {1958wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled;1959return (-1);1960}1961break;1962case IEEE80211_IOC_TDMA_SLOT:1963if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {1964wif->tdma_slot = 0;1965return (-1);1966}1967break;1968case IEEE80211_IOC_TDMA_SLOTCNT:1969if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {1970wif->tdma_slot_count = 0;1971return (-1);1972}1973break;1974case IEEE80211_IOC_TDMA_SLOTLEN:1975if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {1976wif->tdma_slot_length = 0;1977return (-1);1978}1979break;1980case IEEE80211_IOC_TDMA_BINTERVAL:1981if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) {1982wif->tdma_binterval = 0;1983return (-1);1984}1985break;1986default:1987break;1988}19891990return (0);1991}19921993static int1994wlan_config_get_intval(struct wlan_iface *wif, int op)1995{1996int val = 0;1997size_t argsize = 0;19981999if (wlan_config_check(wif, op) < 0)2000return (0);2001if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)2002return (-1);2003wlan_config_set_snmp_intval(wif, op, val);20042005return (0);2006}20072008static int2009wlan_config_set_intval(struct wlan_iface *wif, int op, int sval)2010{2011size_t argsize = 0;2012int val;20132014if (wlan_config_check(wif, op) < 0)2015return (-1);2016if (wlan_config_snmp2value(op, sval, &val) != SNMP_ERR_NOERROR)2017return (-1);2018if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)2019return (-1);2020wlan_config_set_snmp_intval(wif, op, val);20212022return (0);2023}20242025int2026wlan_config_get_ioctl(struct wlan_iface *wif, int which)2027{2028int op;20292030switch (which) {2031case LEAF_wlanIfaceCountryCode:2032/* FALLTHROUGH */2033case LEAF_wlanIfaceRegDomain:2034return (wlan_config_get_country(wif));2035case LEAF_wlanIfaceDesiredSsid:2036return (wlan_config_get_dssid(wif));2037case LEAF_wlanIfaceDesiredChannel:2038return (wlan_config_get_dchannel(wif));2039case LEAF_wlanIfaceDesiredBssid:2040return (wlan_config_get_bssid(wif));2041default:2042op = wlan_config_snmp2ioctl(which);2043return (wlan_config_get_intval(wif, op));2044}20452046return (-1);2047}20482049int2050wlan_config_set_ioctl(struct wlan_iface *wif, int which, int val,2051char *strval, int len)2052{2053int op;20542055switch (which) {2056case LEAF_wlanIfaceCountryCode:2057return (wlan_config_set_country(wif, strval,2058wif->reg_domain));2059case LEAF_wlanIfaceRegDomain:2060return (wlan_config_set_country(wif, wif->country_code,2061val));2062case LEAF_wlanIfaceDesiredSsid:2063return (wlan_config_set_dssid(wif, strval, len));2064case LEAF_wlanIfaceDesiredChannel:2065return (wlan_config_set_dchannel(wif, val));2066case LEAF_wlanIfaceDesiredBssid:2067return (wlan_config_set_bssid(wif, strval));2068default:2069op = wlan_config_snmp2ioctl(which);2070return (wlan_config_set_intval(wif, op, val));2071}20722073return (-1);2074}20752076static uint32_t2077wlan_snmp_to_scan_flags(int flags)2078{2079int sr_flags = 0;20802081if ((flags & (0x1 << WlanScanFlagsType_noSelection)) != 0)2082sr_flags |= IEEE80211_IOC_SCAN_NOPICK;2083if ((flags & (0x1 << WlanScanFlagsType_activeScan)) != 0)2084sr_flags |= IEEE80211_IOC_SCAN_ACTIVE;2085if ((flags & (0x1 << WlanScanFlagsType_pickFirst)) != 0)2086sr_flags |= IEEE80211_IOC_SCAN_PICK1ST;2087if ((flags & (0x1 << WlanScanFlagsType_backgroundScan)) != 0)2088sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;2089if ((flags & (0x1 << WlanScanFlagsType_once)) != 0)2090sr_flags |= IEEE80211_IOC_SCAN_ONCE;2091if ((flags & (0x1 << WlanScanFlagsType_noBroadcast)) != 0)2092sr_flags |= IEEE80211_IOC_SCAN_NOBCAST;2093if ((flags & (0x1 << WlanScanFlagsType_noAutoSequencing)) != 0)2094sr_flags |= IEEE80211_IOC_SCAN_NOJOIN;2095if ((flags & (0x1 << WlanScanFlagsType_flushCashe)) != 0)2096sr_flags |= IEEE80211_IOC_SCAN_FLUSH;2097if ((flags & (0x1 << WlanScanFlagsType_chechCashe)) != 0)2098sr_flags |= IEEE80211_IOC_SCAN_CHECK;20992100return (sr_flags);2101}21022103int2104wlan_set_scan_config(struct wlan_iface *wif)2105{2106int val = 0;2107size_t argsize;2108struct ieee80211_scan_req sr;210921102111memset(&sr, 0, sizeof(sr));2112argsize = sizeof(struct ieee80211_scan_req);2113sr.sr_flags = wlan_snmp_to_scan_flags(wif->scan_flags);2114sr.sr_flags |= IEEE80211_IOC_SCAN_BGSCAN;2115sr.sr_duration = wif->scan_duration;2116sr.sr_mindwell = wif->scan_mindwell;2117sr.sr_maxdwell = wif->scan_maxdwell;2118sr.sr_nssid = 0;21192120if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_REQ,2121&val, &sr, &argsize, 1) < 0)2122return (-1);21232124wif->scan_status = wlanScanConfigStatus_running;2125return (0);2126}21272128static uint32_t2129wlan_peercaps_to_snmp(uint32_t pcaps)2130{2131uint32_t scaps = 0;21322133if ((pcaps & IEEE80211_CAPINFO_ESS) != 0)2134scaps |= (0x1 << WlanPeerCapabilityFlags_ess);2135if ((pcaps & IEEE80211_CAPINFO_IBSS) != 0)2136scaps |= (0x1 << WlanPeerCapabilityFlags_ibss);2137if ((pcaps & IEEE80211_CAPINFO_CF_POLLABLE) != 0)2138scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollable);2139if ((pcaps & IEEE80211_CAPINFO_CF_POLLREQ) != 0)2140scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollRequest);2141if ((pcaps & IEEE80211_CAPINFO_PRIVACY) != 0)2142scaps |= (0x1 << WlanPeerCapabilityFlags_privacy);2143if ((pcaps & IEEE80211_CAPINFO_SHORT_PREAMBLE) != 0)2144scaps |= (0x1 << WlanPeerCapabilityFlags_shortPreamble);2145if ((pcaps & IEEE80211_CAPINFO_PBCC) != 0)2146scaps |= (0x1 << WlanPeerCapabilityFlags_pbcc);2147if ((pcaps & IEEE80211_CAPINFO_CHNL_AGILITY) != 0)2148scaps |= (0x1 << WlanPeerCapabilityFlags_channelAgility);2149if ((pcaps & IEEE80211_CAPINFO_SHORT_SLOTTIME) != 0)2150scaps |= (0x1 << WlanPeerCapabilityFlags_shortSlotTime);2151if ((pcaps & IEEE80211_CAPINFO_RSN) != 0)2152scaps |= (0x1 << WlanPeerCapabilityFlags_rsn);2153if ((pcaps & IEEE80211_CAPINFO_DSSSOFDM) != 0)2154scaps |= (0x1 << WlanPeerCapabilityFlags_dsssofdm);21552156return (scaps);2157}21582159static int2160wlan_add_new_scan_result(struct wlan_iface *wif,2161const struct ieee80211req_scan_result *isr, uint8_t *ssid)2162{2163struct wlan_scan_result *sr;21642165if ((sr = wlan_scan_new_result(ssid, isr->isr_bssid)) == NULL)2166return (-1);21672168sr->opchannel = wlan_channel_flags_to_snmp_phy(isr->isr_flags);2169sr->rssi = (isr->isr_rssi / 2) - isr->isr_noise;2170sr->frequency = isr->isr_freq;2171sr->noise = isr->isr_noise;2172sr->bintval = isr->isr_intval;2173sr->capinfo = wlan_peercaps_to_snmp(isr->isr_capinfo);21742175if (wlan_scan_add_result(wif, sr) < 0) {2176wlan_scan_free_result(sr);2177return (-1);2178}21792180return (0);2181}21822183int2184wlan_get_scan_results(struct wlan_iface *wif)2185{2186int ssidlen, val = 0;2187uint8_t buf[24 * 1024];2188size_t argsize;2189const uint8_t *cp, *idp;2190uint8_t ssid[IEEE80211_NWID_LEN + 1];2191struct ieee80211req_scan_result isr;21922193argsize = sizeof(buf);2194if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_RESULTS, &val, &buf,2195&argsize, 0) < 0)2196return (-1);21972198if (argsize < sizeof(struct ieee80211req_scan_result))2199return (0);22002201cp = buf;2202do {2203memcpy(&isr, cp, sizeof(struct ieee80211req_scan_result));2204memset(ssid, 0, IEEE80211_NWID_LEN + 1);22052206if (isr.isr_meshid_len) {2207idp = cp + isr.isr_ie_off + isr.isr_ssid_len;2208ssidlen = isr.isr_meshid_len;2209} else {2210idp = cp + isr.isr_ie_off;2211ssidlen = isr.isr_ssid_len;2212}2213if (ssidlen > IEEE80211_NWID_LEN)2214ssidlen = IEEE80211_NWID_LEN;2215memcpy(ssid, idp, ssidlen);2216ssid[IEEE80211_NWID_LEN] = '\0';2217(void)wlan_add_new_scan_result(wif, &isr, ssid);2218cp += isr.isr_len;2219argsize -= isr.isr_len;2220} while (argsize >= sizeof(struct ieee80211req_scan_result));22212222return (0);2223}22242225int2226wlan_get_stats(struct wlan_iface *wif)2227{2228struct ifreq ifr;22292230memset(&ifr, 0, sizeof(struct ifreq));2231strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ);22322233ifr.ifr_data = (caddr_t) &wif->stats;22342235if (ioctl(sock, SIOCG80211STATS, &ifr) < 0) {2236syslog(LOG_ERR, "iface %s - ioctl(SIOCG80211STATS) failed: %s",2237wif->wname, strerror(errno));2238return (-1);2239}22402241return (0);2242}22432244int2245wlan_get_wepmode(struct wlan_iface *wif)2246{2247int val = 0;2248size_t argsize = 0;22492250if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,2251&argsize, 0) < 0 || val == IEEE80211_WEP_NOSUP) {2252wif->wepsupported = 0; /* XXX */2253wif->wepmode = wlanWepMode_off;2254wif->weptxkey = 0;2255return (-1);2256}22572258wif->wepsupported = 1;22592260switch (val) {2261case IEEE80211_WEP_ON:2262wif->wepmode = wlanWepMode_on;2263break;2264case IEEE80211_WEP_MIXED:2265wif->wepmode = wlanWepMode_mixed;2266break;2267case IEEE80211_WEP_OFF:2268/* FALLTHROUGH */2269default:2270wif->wepmode = wlanWepMode_off;2271break;2272}22732274return (0);2275}22762277int2278wlan_set_wepmode(struct wlan_iface *wif)2279{2280int val;2281size_t argsize = 0;22822283if (!wif->wepsupported)2284return (-1);22852286switch (wif->wepmode) {2287case wlanWepMode_off:2288val = IEEE80211_WEP_OFF;2289break;2290case wlanWepMode_on:2291val = IEEE80211_WEP_ON;2292break;2293case wlanWepMode_mixed:2294val = IEEE80211_WEP_MIXED;2295break;2296default:2297return (-1);2298}22992300if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL,2301&argsize, 1) < 0)2302return (-1);23032304return (0);2305}23062307int2308wlan_get_weptxkey(struct wlan_iface *wif)2309{2310int val;2311size_t argsize = 0;23122313if (!wif->wepsupported)2314return (0);23152316if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,2317&argsize, 0) < 0)2318return (-1);23192320if (val == IEEE80211_KEYIX_NONE)2321wif->weptxkey = 0;2322else2323wif->weptxkey = val + 1;23242325return (0);2326}23272328int2329wlan_set_weptxkey(struct wlan_iface *wif)2330{2331int val;2332size_t argsize = 0;23332334if (!wif->wepsupported)2335return (0);23362337if (wif->weptxkey >= IEEE80211_WEP_NKID)2338return (-1);23392340if (wif->weptxkey == 0)2341val = IEEE80211_KEYIX_NONE;2342else2343val = wif->weptxkey - 1;2344if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL,2345&argsize, 1) < 0)2346return (-1);23472348return (0);2349}23502351int2352wlan_get_wepkeys(struct wlan_iface *wif __unused)2353{2354/* XXX: should they be visible via SNMP */2355return (0);2356}23572358int2359wlan_set_wepkeys(struct wlan_iface *wif __unused)2360{2361/* XXX: should they be configurable via SNMP */2362return (0);2363}23642365int2366wlan_get_mac_policy(struct wlan_iface *wif)2367{2368int val = IEEE80211_MACCMD_POLICY;2369size_t argsize = 0;2370struct ieee80211req ireq;23712372memset(&ireq, 0, sizeof(struct ieee80211req));2373strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);2374ireq.i_type = IEEE80211_IOC_MACCMD;2375ireq.i_val = IEEE80211_MACCMD_POLICY;23762377if (ioctl(sock, SIOCG80211, &ireq) < 0) {2378if (errno != EINVAL) {2379syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "2380"failed: %s", wif->wname, ireq.i_type,2381strerror(errno));2382wif->macsupported = 0;2383return (-1);2384} else {2385wif->macsupported = 1;2386wif->mac_policy = wlanMACAccessControlPolicy_open;2387return (0);2388}23892390}23912392wif->macsupported = 1;23932394switch (val) {2395case IEEE80211_MACCMD_POLICY_ALLOW:2396wif->mac_policy = wlanMACAccessControlPolicy_allow;2397break;2398case IEEE80211_MACCMD_POLICY_DENY:2399wif->mac_policy = wlanMACAccessControlPolicy_deny;2400break;2401case IEEE80211_MACCMD_POLICY_RADIUS:2402wif->mac_policy = wlanMACAccessControlPolicy_radius;2403break;2404case IEEE80211_MACCMD_POLICY_OPEN:2405/* FALLTHROUGH */2406default:2407wif->mac_policy = wlanMACAccessControlPolicy_open;2408break;2409}24102411argsize = 0;2412val = IEEE80211_MACCMD_LIST;2413if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,2414&argsize, 0) < 0)2415return (-1);24162417wif->mac_nacls = argsize / sizeof(struct ieee80211req_maclist *);2418return (0);2419}24202421int2422wlan_set_mac_policy(struct wlan_iface *wif)2423{2424int val;2425size_t argsize = 0;24262427if (!wif->macsupported)2428return (-1);24292430switch (wif->mac_policy) {2431case wlanMACAccessControlPolicy_allow:2432val = IEEE80211_MACCMD_POLICY_ALLOW;2433break;2434case wlanMACAccessControlPolicy_deny:2435val = IEEE80211_MACCMD_POLICY_DENY;2436break;2437case wlanMACAccessControlPolicy_radius:2438val = IEEE80211_MACCMD_POLICY_RADIUS;2439break;2440case wlanMACAccessControlPolicy_open:2441val = IEEE80211_MACCMD_POLICY_OPEN;2442break;2443default:2444return (-1);2445}24462447if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,2448&argsize, 1) < 0)2449return (-1);24502451return (0);2452}24532454int2455wlan_flush_mac_mac(struct wlan_iface *wif)2456{2457int val = IEEE80211_MACCMD_FLUSH;2458size_t argsize = 0;24592460if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL,2461&argsize, 1) < 0)2462return (-1);24632464return (0);2465}24662467static int2468wlan_add_mac_macinfo(struct wlan_iface *wif,2469const struct ieee80211req_maclist *ml)2470{2471struct wlan_mac_mac *mmac;24722473if ((mmac = wlan_mac_new_mac(ml->ml_macaddr)) == NULL)2474return (-1);24752476mmac->mac_status = RowStatus_active;2477if (wlan_mac_add_mac(wif, mmac) < 0) {2478wlan_mac_free_mac(mmac);2479return (-1);2480}24812482return (0);2483}24842485int2486wlan_get_mac_acl_macs(struct wlan_iface *wif)2487{2488int i, nacls, val = IEEE80211_MACCMD_LIST;2489size_t argsize = 0;2490uint8_t *data;2491struct ieee80211req ireq;2492const struct ieee80211req_maclist *acllist;24932494if (wif->mac_policy == wlanMACAccessControlPolicy_radius) {2495wif->mac_nacls = 0;2496return (0);2497}24982499memset(&ireq, 0, sizeof(struct ieee80211req));2500strlcpy(ireq.i_name, wif->wname, IFNAMSIZ);2501ireq.i_type = IEEE80211_IOC_MACCMD;2502ireq.i_val = IEEE80211_MACCMD_LIST;250325042505if (ioctl(sock, SIOCG80211, &ireq) < 0) {2506if (errno != EINVAL) {2507syslog(LOG_ERR, "iface %s - get param: ioctl(%d) "2508"failed: %s", wif->wname, ireq.i_type,2509strerror(errno));2510wif->macsupported = 0;2511return (-1);2512}2513}25142515if (argsize == 0) {2516wif->mac_nacls = 0;2517return (0);2518}25192520if ((data = (uint8_t *)malloc(argsize)) == NULL)2521return (-1);25222523if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, data,2524&argsize, 0) < 0)2525return (-1);25262527nacls = argsize / sizeof(*acllist);2528acllist = (struct ieee80211req_maclist *) data;2529for (i = 0; i < nacls; i++)2530(void)wlan_add_mac_macinfo(wif, acllist + i);25312532wif->mac_nacls = nacls;2533return (0);2534}25352536int2537wlan_add_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)2538{2539int val = 0;2540size_t argsize = IEEE80211_ADDR_LEN;2541struct ieee80211req_mlme mlme;25422543if (wlan_ioctl(wif->wname, IEEE80211_IOC_ADDMAC, &val,2544mmac->mac, &argsize, 1) < 0)2545return (-1);25462547mmac->mac_status = RowStatus_active;25482549/* If policy is deny, try to kick the station just in case. */2550if (wif->mac_policy != wlanMACAccessControlPolicy_deny)2551return (0);25522553memset(&mlme, 0, sizeof(mlme));2554mlme.im_op = IEEE80211_MLME_DEAUTH;2555mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;2556memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);2557argsize = sizeof(struct ieee80211req_mlme);25582559if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,2560&argsize, 1) < 0 && errno != ENOENT)2561return (-1);25622563return (0);2564}25652566int2567wlan_del_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac)2568{2569int val = 0;2570size_t argsize = IEEE80211_ADDR_LEN;2571struct ieee80211req_mlme mlme;25722573if (wlan_ioctl(wif->wname, IEEE80211_IOC_DELMAC, &val,2574mmac->mac, &argsize, 1) < 0)2575return (-1);25762577mmac->mac_status = RowStatus_active;25782579/* If policy is allow, try to kick the station just in case. */2580if (wif->mac_policy != wlanMACAccessControlPolicy_allow)2581return (0);25822583memset(&mlme, 0, sizeof(mlme));2584mlme.im_op = IEEE80211_MLME_DEAUTH;2585mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;2586memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN);2587argsize = sizeof(struct ieee80211req_mlme);25882589if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme,2590&argsize, 1) < 0 && errno != ENOENT)2591return (-1);25922593return (0);2594}25952596int2597wlan_peer_set_vlan(struct wlan_iface *wif, struct wlan_peer *wip, int vlan)2598{2599int val = 0;2600size_t argsize;2601struct ieee80211req_sta_vlan vreq;26022603memcpy(vreq.sv_macaddr, wip->pmac, IEEE80211_ADDR_LEN);2604vreq.sv_vlan = vlan;2605argsize = sizeof(struct ieee80211req_sta_vlan);26062607if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_VLAN,2608&val, &vreq, &argsize, 1) < 0)2609return (-1);26102611wip->vlan = vlan;26122613return (0);2614}26152616/* XXX */2617#ifndef IEEE80211_NODE_AUTH2618#define IEEE80211_NODE_AUTH 0x000001 /* authorized for data */2619#define IEEE80211_NODE_QOS 0x000002 /* QoS enabled */2620#define IEEE80211_NODE_ERP 0x000004 /* ERP enabled */2621#define IEEE80211_NODE_PWR_MGT 0x000010 /* power save mode enabled */2622#define IEEE80211_NODE_AREF 0x000020 /* authentication ref held */2623#define IEEE80211_NODE_HT 0x000040 /* HT enabled */2624#define IEEE80211_NODE_HTCOMPAT 0x000080 /* HT setup w/ vendor OUI's */2625#define IEEE80211_NODE_WPS 0x000100 /* WPS association */2626#define IEEE80211_NODE_TSN 0x000200 /* TSN association */2627#define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */2628#define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */2629#define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */2630#define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */2631#define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */2632#define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */2633#define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */2634#define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */2635#define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */2636#define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */2637#endif26382639static uint32_t2640wlan_peerstate_to_snmp(uint32_t pstate)2641{2642uint32_t sstate = 0;26432644if ((pstate & IEEE80211_NODE_AUTH) != 0)2645sstate |= (0x1 << WlanIfacePeerFlagsType_authorizedForData);2646if ((pstate & IEEE80211_NODE_QOS) != 0)2647sstate |= (0x1 << WlanIfacePeerFlagsType_qosEnabled);2648if ((pstate & IEEE80211_NODE_ERP) != 0)2649sstate |= (0x1 << WlanIfacePeerFlagsType_erpEnabled);2650if ((pstate & IEEE80211_NODE_PWR_MGT) != 0)2651sstate |= (0x1 << WlanIfacePeerFlagsType_powerSaveMode);2652if ((pstate & IEEE80211_NODE_AREF) != 0)2653sstate |= (0x1 << WlanIfacePeerFlagsType_authRefHeld);2654if ((pstate & IEEE80211_NODE_HT) != 0)2655sstate |= (0x1 << WlanIfacePeerFlagsType_htEnabled);2656if ((pstate & IEEE80211_NODE_HTCOMPAT) != 0)2657sstate |= (0x1 << WlanIfacePeerFlagsType_htCompat);2658if ((pstate & IEEE80211_NODE_WPS) != 0)2659sstate |= (0x1 << WlanIfacePeerFlagsType_wpsAssoc);2660if ((pstate & IEEE80211_NODE_TSN) != 0)2661sstate |= (0x1 << WlanIfacePeerFlagsType_tsnAssoc);2662if ((pstate & IEEE80211_NODE_AMPDU_RX) != 0)2663sstate |= (0x1 << WlanIfacePeerFlagsType_ampduRx);2664if ((pstate & IEEE80211_NODE_AMPDU_TX) != 0)2665sstate |= (0x1 << WlanIfacePeerFlagsType_ampduTx);2666if ((pstate & IEEE80211_NODE_MIMO_PS) != 0)2667sstate |= (0x1 << WlanIfacePeerFlagsType_mimoPowerSave);2668if ((pstate & IEEE80211_NODE_MIMO_RTS) != 0)2669sstate |= (0x1 << WlanIfacePeerFlagsType_sendRts);2670if ((pstate & IEEE80211_NODE_RIFS) != 0)2671sstate |= (0x1 << WlanIfacePeerFlagsType_rifs);2672if ((pstate & IEEE80211_NODE_SGI20) != 0)2673sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT20);2674if ((pstate & IEEE80211_NODE_SGI40) != 0)2675sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT40);2676if ((pstate & IEEE80211_NODE_AMSDU_RX) != 0)2677sstate |= (0x1 << WlanIfacePeerFlagsType_amsduRx);2678if ((pstate & IEEE80211_NODE_AMSDU_TX) != 0)2679sstate |= (0x1 << WlanIfacePeerFlagsType_amsduTx);26802681return (sstate);2682}26832684static struct wlan_peer *2685wlan_add_peerinfo(const struct ieee80211req_sta_info *si)2686{2687struct wlan_peer *wip;26882689if ((wip = wlan_new_peer(si->isi_macaddr))== NULL)2690return (NULL);26912692wip->associd = IEEE80211_AID(si->isi_associd);2693wip->vlan = si->isi_vlan;2694wip->frequency = si->isi_freq;2695wip->fflags = si->isi_flags;2696wip->txrate = si->isi_txrate;2697wip->rssi = si->isi_rssi;2698wip->idle = si->isi_inact;2699wip->txseqs = si->isi_txseqs[0]; /* XXX */2700wip->rxseqs = si->isi_rxseqs[0]; /* XXX */2701wip->txpower = si->isi_txpower;2702wip->capinfo = wlan_peercaps_to_snmp(si->isi_capinfo);2703wip->state = wlan_peerstate_to_snmp(si->isi_state);2704wip->local_id = si->isi_localid;2705wip->peer_id = si->isi_peerid;27062707return (wip);2708}27092710int2711wlan_get_peerinfo(struct wlan_iface *wif)2712{2713union {2714struct ieee80211req_sta_req req;2715uint8_t buf[24 * 1024];2716} u;2717const uint8_t *cp;2718int val = 0;2719size_t len;2720struct ieee80211req_sta_info si;2721struct wlan_peer *wip;27222723/* Get all stations - broadcast address */2724(void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN);2725len = sizeof(u);27262727if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_INFO,2728& val, &u, &len, 0) < 0)2729return (-1);27302731if (len < sizeof(struct ieee80211req_sta_info))2732return (-1);27332734cp = (const uint8_t *) u.req.info;2735do {2736memcpy(&si, cp, sizeof(struct ieee80211req_sta_info));2737if ((wip = wlan_add_peerinfo(&si)) != NULL &&2738wlan_add_peer(wif, wip) < 0)2739wlan_free_peer(wip);2740cp += si.isi_len, len -= si.isi_len;2741} while (len >= sizeof(struct ieee80211req_sta_info));27422743return (0);2744}27452746/************************************************************************2747* Wireless MESH & HWMP sysctl config.2748*/2749const char wlan_sysctl_name[] = "net.wlan.";27502751static const char *wlan_sysctl[] = {2752"mesh.retrytimeout",2753"mesh.holdingtimeout",2754"mesh.confirmtimeout",2755"mesh.maxretries",2756"hwmp.targetonly",2757"hwmp.replyforward",2758"hwmp.pathlifetime",2759"hwmp.roottimeout",2760"hwmp.rootint",2761"hwmp.rannint",2762"hwmp.inact",2763};27642765int32_t2766wlan_do_sysctl(struct wlan_config *cfg, enum wlan_syscl which, int set)2767{2768char mib_name[100];2769int val, sval;2770size_t len, vlen;27712772if (set) {2773vlen = sizeof(sval);2774switch (which) {2775case WLAN_MESH_RETRY_TO:2776sval = cfg->mesh_retryto;2777break;2778case WLAN_MESH_HOLDING_TO:2779sval = cfg->mesh_holdingto;2780break;2781case WLAN_MESH_CONFIRM_TO:2782sval = cfg->mesh_confirmto;2783break;2784case WLAN_MESH_MAX_RETRIES:2785sval = cfg->mesh_maxretries;2786break;2787case WLAN_HWMP_TARGET_ONLY:2788sval = cfg->hwmp_targetonly;2789break;2790case WLAN_HWMP_REPLY_FORWARD:2791sval = cfg->hwmp_replyforward;2792break;2793case WLAN_HWMP_PATH_LIFETIME:2794sval = cfg->hwmp_pathlifetime;2795break;2796case WLAN_HWMP_ROOT_TO:2797sval = cfg->hwmp_roottimeout;2798break;2799case WLAN_HWMP_ROOT_INT:2800sval = cfg->hwmp_rootint;2801break;2802case WLAN_HWMP_RANN_INT:2803sval = cfg->hwmp_rannint;2804break;2805case WLAN_HWMP_INACTIVITY_TO:2806sval = cfg->hwmp_inact;2807break;2808default:2809return (-1);2810}2811} else {2812if (which >= WLAN_SYSCTL_MAX)2813return (-1);2814vlen = 0;2815}28162817strlcpy(mib_name, wlan_sysctl_name, sizeof(mib_name));2818strlcat(mib_name, wlan_sysctl[which], sizeof(mib_name));2819len = sizeof (val);28202821if (sysctlbyname(mib_name, &val, &len, (set? &sval : NULL), vlen) < 0) {2822syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_name,2823strerror(errno));2824return (-1);2825}28262827switch (which) {2828case WLAN_MESH_RETRY_TO:2829cfg->mesh_retryto = val;2830break;2831case WLAN_MESH_HOLDING_TO:2832cfg->mesh_holdingto = val;2833break;2834case WLAN_MESH_CONFIRM_TO:2835cfg->mesh_confirmto = val;2836break;2837case WLAN_MESH_MAX_RETRIES:2838cfg->mesh_maxretries = val;2839break;2840case WLAN_HWMP_TARGET_ONLY:2841cfg->hwmp_targetonly = val;2842break;2843case WLAN_HWMP_REPLY_FORWARD:2844cfg->hwmp_replyforward = val;2845break;2846case WLAN_HWMP_PATH_LIFETIME:2847cfg->hwmp_pathlifetime = val;2848break;2849case WLAN_HWMP_ROOT_TO:2850cfg->hwmp_roottimeout = val;2851break;2852case WLAN_HWMP_ROOT_INT:2853cfg->hwmp_rootint = val;2854break;2855case WLAN_HWMP_RANN_INT:2856cfg->hwmp_rannint = val;2857break;2858case WLAN_HWMP_INACTIVITY_TO:2859cfg->hwmp_inact = val;2860break;2861default:2862/* NOTREACHED */2863abort();2864}28652866return (0);2867}28682869int2870wlan_mesh_config_get(struct wlan_iface *wif, int which)2871{2872int op, val = 0;2873size_t argsize = 0;2874uint8_t data[32], *pd = NULL;28752876switch (which) {2877case LEAF_wlanMeshTTL:2878op = IEEE80211_IOC_MESH_TTL;2879break;2880case LEAF_wlanMeshPeeringEnabled:2881op = IEEE80211_IOC_MESH_AP;2882break;2883case LEAF_wlanMeshForwardingEnabled:2884op = IEEE80211_IOC_MESH_FWRD;2885break;2886case LEAF_wlanMeshMetric:2887op = IEEE80211_IOC_MESH_PR_METRIC;2888pd = data;2889argsize = sizeof(data);2890break;2891case LEAF_wlanMeshPath:2892op = IEEE80211_IOC_MESH_PR_PATH;2893pd = data;2894argsize = sizeof(data);2895break;2896case LEAF_wlanMeshRoutesFlush:2897return (0);2898default:2899return (-1);2900}29012902if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 0) < 0)2903return (-1);29042905switch (which) {2906case LEAF_wlanMeshTTL:2907wif->mesh_ttl = val;2908break;2909case LEAF_wlanMeshPeeringEnabled:2910if (val)2911wif->mesh_peering = wlanMeshPeeringEnabled_true;2912else2913wif->mesh_peering = wlanMeshPeeringEnabled_false;2914break;2915case LEAF_wlanMeshForwardingEnabled:2916if (val)2917wif->mesh_forwarding = wlanMeshForwardingEnabled_true;2918else2919wif->mesh_forwarding = wlanMeshForwardingEnabled_false;2920break;2921case LEAF_wlanMeshMetric:2922data[argsize] = '\0';2923if (strcmp(data, "AIRTIME") == 0)2924wif->mesh_metric = wlanMeshMetric_airtime;2925else2926wif->mesh_metric = wlanMeshMetric_unknown;2927break;2928case LEAF_wlanMeshPath:2929data[argsize] = '\0';2930if (strcmp(data, "HWMP") == 0)2931wif->mesh_path = wlanMeshPath_hwmp;2932else2933wif->mesh_path = wlanMeshPath_unknown;2934}29352936return (0);2937}29382939int2940wlan_mesh_config_set(struct wlan_iface *wif, int which)2941{2942int op, val = 0;2943size_t argsize = 0;2944uint8_t data[32], *pd = NULL;29452946switch (which) {2947case LEAF_wlanMeshTTL:2948op = IEEE80211_IOC_MESH_TTL;2949val = wif->mesh_ttl;2950break;2951case LEAF_wlanMeshPeeringEnabled:2952op = IEEE80211_IOC_MESH_AP;2953if (wif->mesh_peering == wlanMeshPeeringEnabled_true)2954val = 1;2955break;2956case LEAF_wlanMeshForwardingEnabled:2957if (wif->mesh_forwarding == wlanMeshForwardingEnabled_true)2958val = 1;2959op = IEEE80211_IOC_MESH_FWRD;2960break;2961case LEAF_wlanMeshMetric:2962op = IEEE80211_IOC_MESH_PR_METRIC;2963if (wif->mesh_metric == wlanMeshMetric_airtime)2964strcpy(data, "AIRTIME");2965else2966return (-1);2967pd = data;2968argsize = sizeof(data);2969break;2970case LEAF_wlanMeshPath:2971op = IEEE80211_IOC_MESH_PR_PATH;2972if (wif->mesh_path == wlanMeshPath_hwmp)2973strcpy(data, "HWMP");2974else2975return (-1);2976pd = data;2977argsize = sizeof(data);2978break;2979default:2980return (-1);2981}29822983if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 1) < 0)2984return (-1);29852986return(0);2987}29882989int2990wlan_mesh_flush_routes(struct wlan_iface *wif)2991{2992int val = IEEE80211_MESH_RTCMD_FLUSH;2993size_t argsize = 0;29942995if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, NULL,2996&argsize, 1) < 0)2997return (-1);29982999return (0);3000}30013002int3003wlan_mesh_add_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)3004{3005int val = IEEE80211_MESH_RTCMD_ADD;3006size_t argsize = IEEE80211_ADDR_LEN;30073008if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,3009wmr->imroute.imr_dest, &argsize, 1) < 0)3010return (-1);30113012wmr->mroute_status = RowStatus_active;30133014return (0);3015}30163017int3018wlan_mesh_del_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr)3019{3020int val = IEEE80211_MESH_RTCMD_DELETE;3021size_t argsize = IEEE80211_ADDR_LEN;30223023if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val,3024wmr->imroute.imr_dest, &argsize, 1) < 0)3025return (-1);30263027wmr->mroute_status = RowStatus_destroy;30283029return (0);3030}30313032int3033wlan_mesh_get_routelist(struct wlan_iface *wif)3034{3035int i, nroutes, val = IEEE80211_MESH_RTCMD_LIST;3036size_t argsize;3037struct ieee80211req_mesh_route routes[128];3038struct ieee80211req_mesh_route *rt;3039struct wlan_mesh_route *wmr;30403041argsize = sizeof(routes);3042if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, routes,3043&argsize, 0) < 0) /* XXX: ENOMEM? */3044return (-1);30453046nroutes = argsize / sizeof(*rt);3047for (i = 0; i < nroutes; i++) {3048rt = routes + i;3049if ((wmr = wlan_mesh_new_route(rt->imr_dest)) == NULL)3050return (-1);3051memcpy(&wmr->imroute, rt, sizeof(*rt));3052wmr->mroute_status = RowStatus_active;3053if (wlan_mesh_add_rtentry(wif, wmr) < 0)3054wlan_mesh_free_route(wmr);3055}30563057return (0);3058}30593060int3061wlan_hwmp_config_get(struct wlan_iface *wif, int which)3062{3063int op, val = 0;3064size_t argsize = 0;30653066switch (which) {3067case LEAF_wlanHWMPRootMode:3068op = IEEE80211_IOC_HWMP_ROOTMODE;3069break;3070case LEAF_wlanHWMPMaxHops:3071op = IEEE80211_IOC_HWMP_MAXHOPS;3072break;3073default:3074return (-1);3075}30763077if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0)3078return (-1);30793080switch (which) {3081case LEAF_wlanHWMPRootMode:3082switch (val) {3083case IEEE80211_HWMP_ROOTMODE_NORMAL:3084wif->hwmp_root_mode = wlanHWMPRootMode_normal;3085break;3086case IEEE80211_HWMP_ROOTMODE_PROACTIVE:3087wif->hwmp_root_mode = wlanHWMPRootMode_proactive;3088break;3089case IEEE80211_HWMP_ROOTMODE_RANN:3090wif->hwmp_root_mode = wlanHWMPRootMode_rann;3091break;3092case IEEE80211_HWMP_ROOTMODE_DISABLED:3093default:3094wif->hwmp_root_mode = wlanHWMPRootMode_disabled;3095break;3096}3097break;3098case LEAF_wlanHWMPMaxHops:3099wif->hwmp_max_hops = val;3100break;3101}31023103return (0);3104}31053106int3107wlan_hwmp_config_set(struct wlan_iface *wif, int which)3108{3109int op, val = 0;3110size_t argsize = 0;31113112switch (which) {3113case LEAF_wlanHWMPRootMode:3114op = IEEE80211_IOC_HWMP_ROOTMODE;3115switch (wif->hwmp_root_mode) {3116case wlanHWMPRootMode_disabled:3117val = IEEE80211_HWMP_ROOTMODE_DISABLED;3118break;3119case wlanHWMPRootMode_normal:3120val = IEEE80211_HWMP_ROOTMODE_NORMAL;3121break;3122case wlanHWMPRootMode_proactive:3123val = IEEE80211_HWMP_ROOTMODE_PROACTIVE;3124break;3125case wlanHWMPRootMode_rann:3126val = IEEE80211_HWMP_ROOTMODE_RANN;3127break;3128default:3129return (-1);3130}3131break;3132case LEAF_wlanHWMPMaxHops:3133op = IEEE80211_IOC_HWMP_MAXHOPS;3134val = wif->hwmp_max_hops;3135break;3136default:3137return (-1);3138}31393140if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0)3141return (-1);31423143return (0);3144}314531463147