1210502Ssyrinx/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4210502Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation 5210502Ssyrinx * All rights reserved. 6310901Sngie 7210502Ssyrinx * This software was developed by Shteryana Sotirova Shopova under 8210502Ssyrinx * sponsorship from the FreeBSD Foundation. 9210502Ssyrinx * 10210502Ssyrinx * Redistribution and use in source and binary forms, with or without 11210502Ssyrinx * modification, are permitted provided that the following conditions 12210502Ssyrinx * are met: 13210502Ssyrinx * 1. Redistributions of source code must retain the above copyright 14210502Ssyrinx * notice, this list of conditions and the following disclaimer. 15210502Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 16210502Ssyrinx * notice, this list of conditions and the following disclaimer in the 17210502Ssyrinx * documentation and/or other materials provided with the distribution. 18210502Ssyrinx * 19210502Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20210502Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21210502Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22210502Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23210502Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24210502Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25210502Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26210502Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27210502Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28210502Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29210502Ssyrinx * SUCH DAMAGE. 30210502Ssyrinx * 31210502Ssyrinx * $FreeBSD: stable/11/usr.sbin/bsnmpd/modules/snmp_wlan/wlan_sys.c 330449 2018-03-05 07:26:05Z eadler $ 32210502Ssyrinx */ 33210502Ssyrinx 34210502Ssyrinx#include <sys/ioctl.h> 35210502Ssyrinx#include <sys/param.h> 36210502Ssyrinx#include <sys/module.h> 37210502Ssyrinx#include <sys/linker.h> 38210502Ssyrinx#include <sys/socket.h> 39210502Ssyrinx#include <sys/sysctl.h> 40210502Ssyrinx 41210502Ssyrinx#include <net/if.h> 42210502Ssyrinx#include <net/if_dl.h> 43210502Ssyrinx#include <net/if_media.h> 44210502Ssyrinx#include <net/if_mib.h> 45210502Ssyrinx#include <net/if_types.h> 46210502Ssyrinx#include <net80211/ieee80211.h> 47210502Ssyrinx#include <net80211/ieee80211_ioctl.h> 48210502Ssyrinx#include <net80211/ieee80211_regdomain.h> 49210502Ssyrinx 50210502Ssyrinx#include <errno.h> 51210502Ssyrinx#include <ifaddrs.h> 52210502Ssyrinx#include <stdarg.h> 53210502Ssyrinx#include <stdlib.h> 54210502Ssyrinx#include <stdio.h> 55210502Ssyrinx#include <string.h> 56210502Ssyrinx#include <syslog.h> 57210502Ssyrinx 58210502Ssyrinx#include <bsnmp/snmpmod.h> 59210502Ssyrinx#include <bsnmp/snmp_mibII.h> 60210502Ssyrinx 61210502Ssyrinx#include "wlan_tree.h" 62210502Ssyrinx#include "wlan_snmp.h" 63210502Ssyrinx 64210502Ssyrinxstatic int sock = -1; 65210502Ssyrinx 66210502Ssyrinxstatic int wlan_ioctl(char *, uint16_t, int *, void *, size_t *, int); 67210502Ssyrinxstatic int wlan_kmod_load(const char *); 68210502Ssyrinxstatic uint32_t wlan_drivercaps_to_snmp(uint32_t); 69210502Ssyrinxstatic uint32_t wlan_cryptocaps_to_snmp(uint32_t); 70210502Ssyrinxstatic uint32_t wlan_htcaps_to_snmp(uint32_t); 71210502Ssyrinxstatic uint32_t wlan_peerstate_to_snmp(uint32_t); 72210502Ssyrinxstatic uint32_t wlan_peercaps_to_snmp(uint32_t ); 73210502Ssyrinxstatic uint32_t wlan_channel_flags_to_snmp_phy(uint32_t); 74210502Ssyrinxstatic uint32_t wlan_regdomain_to_snmp(int); 75210502Ssyrinxstatic uint32_t wlan_snmp_to_scan_flags(int); 76210502Ssyrinxstatic int wlan_config_snmp2ioctl(int); 77210502Ssyrinxstatic int wlan_snmp_to_regdomain(enum WlanRegDomainCode); 78210502Ssyrinxstatic int wlan_config_get_country(struct wlan_iface *); 79210502Ssyrinxstatic int wlan_config_set_country(struct wlan_iface *, char *, int); 80210502Ssyrinxstatic int wlan_config_get_dchannel(struct wlan_iface *wif); 81210502Ssyrinxstatic int wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t); 82210502Ssyrinxstatic int wlan_config_get_bssid(struct wlan_iface *); 83210502Ssyrinxstatic int wlan_config_set_bssid(struct wlan_iface *, uint8_t *); 84210502Ssyrinxstatic void wlan_config_set_snmp_intval(struct wlan_iface *, int, int); 85210502Ssyrinxstatic int wlan_config_snmp2value(int, int, int *); 86210502Ssyrinxstatic int wlan_config_check(struct wlan_iface *, int); 87210502Ssyrinxstatic int wlan_config_get_intval(struct wlan_iface *, int); 88210502Ssyrinxstatic int wlan_config_set_intval(struct wlan_iface *, int, int); 89210502Ssyrinxstatic int wlan_add_new_scan_result(struct wlan_iface *, 90210502Ssyrinx const struct ieee80211req_scan_result *, uint8_t *); 91210502Ssyrinxstatic int wlan_add_mac_macinfo(struct wlan_iface *, 92210502Ssyrinx const struct ieee80211req_maclist *); 93210502Ssyrinxstatic struct wlan_peer *wlan_add_peerinfo(const struct ieee80211req_sta_info *); 94210502Ssyrinx 95210502Ssyrinxint 96210502Ssyrinxwlan_ioctl_init(void) 97210502Ssyrinx{ 98210502Ssyrinx if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 99210502Ssyrinx syslog(LOG_ERR, "cannot open socket : %s", strerror(errno)); 100210502Ssyrinx return (-1); 101210502Ssyrinx } 102210502Ssyrinx 103210502Ssyrinx return (0); 104210502Ssyrinx} 105210502Ssyrinx/* 106210502Ssyrinx * Load the needed modules in kernel if not already there. 107210502Ssyrinx */ 108210502Ssyrinxenum wlan_kmodules { 109210502Ssyrinx WLAN_KMOD = 0, 110210502Ssyrinx WLAN_KMOD_ACL, 111210502Ssyrinx WLAN_KMOD_WEP, 112210502Ssyrinx WLAN_KMODS_MAX 113210502Ssyrinx}; 114210502Ssyrinx 115210502Ssyrinxstatic const char *wmod_names[] = { 116210502Ssyrinx "wlan", 117210502Ssyrinx "wlan_wlan_acl", 118210502Ssyrinx "wlan_wep", 119210502Ssyrinx NULL 120210502Ssyrinx}; 121210502Ssyrinx 122210502Ssyrinxstatic int 123210502Ssyrinxwlan_kmod_load(const char *modname) 124210502Ssyrinx{ 125210502Ssyrinx int fileid, modid; 126210502Ssyrinx struct module_stat mstat; 127210502Ssyrinx 128210502Ssyrinx mstat.version = sizeof(struct module_stat); 129210502Ssyrinx for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 130210502Ssyrinx for (modid = kldfirstmod(fileid); modid > 0; 131210502Ssyrinx modid = modfnext(modid)) { 132210502Ssyrinx if (modstat(modid, &mstat) < 0) 133210502Ssyrinx continue; 134210502Ssyrinx if (strcmp(modname, mstat.name) == 0) 135210502Ssyrinx return (0); 136210502Ssyrinx } 137210502Ssyrinx } 138210502Ssyrinx 139210502Ssyrinx /* Not present - load it. */ 140210502Ssyrinx if (kldload(modname) < 0) { 141210502Ssyrinx syslog(LOG_ERR, "failed to load %s kernel module - %s", modname, 142210502Ssyrinx strerror(errno)); 143210502Ssyrinx return (-1); 144210502Ssyrinx } 145210502Ssyrinx 146210502Ssyrinx return (1); 147210502Ssyrinx} 148210502Ssyrinx 149210502Ssyrinxint 150210502Ssyrinxwlan_kmodules_load(void) 151210502Ssyrinx{ 152210502Ssyrinx if (wlan_kmod_load(wmod_names[WLAN_KMOD]) < 0) 153210502Ssyrinx return (-1); 154210502Ssyrinx 155210502Ssyrinx if (wlan_kmod_load(wmod_names[WLAN_KMOD_ACL]) > 0) 156210502Ssyrinx syslog(LOG_NOTICE, "SNMP wlan loaded %s module", 157210502Ssyrinx wmod_names[WLAN_KMOD_ACL]); 158210502Ssyrinx 159210502Ssyrinx if (wlan_kmod_load(wmod_names[WLAN_KMOD_WEP]) > 0) 160210502Ssyrinx syslog(LOG_NOTICE, "SNMP wlan loaded %s module", 161210502Ssyrinx wmod_names[WLAN_KMOD_WEP]); 162210502Ssyrinx 163310901Sngie return (0); 164210502Ssyrinx} 165210502Ssyrinx 166210502Ssyrinx/* XXX: FIXME */ 167210502Ssyrinxstatic int 168210502Ssyrinxwlan_ioctl(char *wif_name, uint16_t req_type, int *val, void *arg, 169210502Ssyrinx size_t *argsize, int set) 170210502Ssyrinx{ 171210502Ssyrinx struct ieee80211req ireq; 172210502Ssyrinx 173210502Ssyrinx memset(&ireq, 0, sizeof(struct ieee80211req)); 174210502Ssyrinx strlcpy(ireq.i_name, wif_name, IFNAMSIZ); 175210502Ssyrinx 176210502Ssyrinx ireq.i_type = req_type; 177210502Ssyrinx ireq.i_val = *val; 178210502Ssyrinx ireq.i_len = *argsize; 179210502Ssyrinx ireq.i_data = arg; 180210502Ssyrinx 181210502Ssyrinx if (ioctl(sock, set ? SIOCS80211 : SIOCG80211, &ireq) < 0) { 182210502Ssyrinx syslog(LOG_ERR, "iface %s - %s param: ioctl(%d) " 183210502Ssyrinx "failed: %s", wif_name, set ? "set" : "get", 184210502Ssyrinx req_type, strerror(errno)); 185210502Ssyrinx return (-1); 186210502Ssyrinx } 187210502Ssyrinx 188210502Ssyrinx *argsize = ireq.i_len; 189210502Ssyrinx *val = ireq.i_val; 190210502Ssyrinx 191210502Ssyrinx return (0); 192210502Ssyrinx} 193210502Ssyrinx 194210502Ssyrinxint 195210502Ssyrinxwlan_check_media(char *ifname) 196210502Ssyrinx{ 197210502Ssyrinx struct ifmediareq ifmr; 198210502Ssyrinx 199210502Ssyrinx memset(&ifmr, 0, sizeof(struct ifmediareq)); 200210502Ssyrinx strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 201210502Ssyrinx 202210502Ssyrinx if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0 || ifmr.ifm_count == 0) 203210502Ssyrinx return (0); /* Interface doesn't support SIOCGIFMEDIA. */ 204210502Ssyrinx 205210502Ssyrinx if ((ifmr.ifm_status & IFM_AVALID) == 0) 206210502Ssyrinx return (0); 207210502Ssyrinx 208210502Ssyrinx return (IFM_TYPE(ifmr.ifm_active)); 209210502Ssyrinx} 210210502Ssyrinx 211210502Ssyrinxint 212210502Ssyrinxwlan_get_opmode(struct wlan_iface *wif) 213210502Ssyrinx{ 214210502Ssyrinx struct ifmediareq ifmr; 215210502Ssyrinx 216210502Ssyrinx memset(&ifmr, 0, sizeof(struct ifmediareq)); 217210502Ssyrinx strlcpy(ifmr.ifm_name, wif->wname, sizeof(ifmr.ifm_name)); 218210502Ssyrinx 219210502Ssyrinx if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0) { 220210502Ssyrinx if (errno == ENXIO) 221210502Ssyrinx return (-1); 222210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_station; 223210502Ssyrinx return (0); 224210502Ssyrinx } 225210502Ssyrinx 226210502Ssyrinx if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { 227210502Ssyrinx if (ifmr.ifm_current & IFM_FLAG0) 228210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_adhocDemo; 229210502Ssyrinx else 230210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_ibss; 231210502Ssyrinx } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 232210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_hostAp; 233210502Ssyrinx else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 234210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_monitor; 235210502Ssyrinx else if (ifmr.ifm_current & IFM_IEEE80211_MBSS) 236210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_meshPoint; 237210502Ssyrinx else if (ifmr.ifm_current & IFM_IEEE80211_WDS) 238210502Ssyrinx wif->mode = WlanIfaceOperatingModeType_wds; 239210502Ssyrinx 240210502Ssyrinx return (0); 241210502Ssyrinx} 242210502Ssyrinx 243210502Ssyrinxint 244210502Ssyrinxwlan_config_state(struct wlan_iface *wif, uint8_t set) 245210502Ssyrinx{ 246210502Ssyrinx int flags; 247210502Ssyrinx struct ifreq ifr; 248210502Ssyrinx 249210502Ssyrinx memset(&ifr, 0, sizeof(ifr)); 250210502Ssyrinx strcpy(ifr.ifr_name, wif->wname); 251210502Ssyrinx 252210502Ssyrinx if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 253210502Ssyrinx syslog(LOG_ERR, "set %s status: ioctl(SIOCGIFFLAGS) " 254210502Ssyrinx "failed: %s", wif->wname, strerror(errno)); 255210502Ssyrinx return (-1); 256210502Ssyrinx } 257210502Ssyrinx 258210502Ssyrinx if (set == 0) { 259210502Ssyrinx if ((ifr.ifr_flags & IFF_UP) != 0) 260210502Ssyrinx wif->state = wlanIfaceState_up; 261210502Ssyrinx else 262210502Ssyrinx wif->state = wlanIfaceState_down; 263210502Ssyrinx return (0); 264210502Ssyrinx } 265210502Ssyrinx 266210502Ssyrinx flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 267210502Ssyrinx 268210502Ssyrinx if (wif->state == wlanIfaceState_up) 269210502Ssyrinx flags |= IFF_UP; 270210502Ssyrinx else 271210502Ssyrinx flags &= ~IFF_UP; 272210502Ssyrinx 273210502Ssyrinx ifr.ifr_flags = flags & 0xffff; 274210502Ssyrinx ifr.ifr_flagshigh = flags >> 16; 275210502Ssyrinx if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 276210502Ssyrinx syslog(LOG_ERR, "set %s %s: ioctl(SIOCSIFFLAGS) failed: %s", 277210502Ssyrinx wif->wname, wif->state == wlanIfaceState_up?"up":"down", 278210502Ssyrinx strerror(errno)); 279210502Ssyrinx return (-1); 280210502Ssyrinx } 281210502Ssyrinx 282210502Ssyrinx return (0); 283210502Ssyrinx} 284210502Ssyrinx 285210502Ssyrinxint 286210502Ssyrinxwlan_get_local_addr(struct wlan_iface *wif) 287210502Ssyrinx{ 288210502Ssyrinx int len; 289210502Ssyrinx char ifname[IFNAMSIZ]; 290210502Ssyrinx struct ifaddrs *ifap, *ifa; 291210502Ssyrinx struct sockaddr_dl sdl; 292210502Ssyrinx 293210502Ssyrinx if (getifaddrs(&ifap) != 0) { 294210502Ssyrinx syslog(LOG_ERR, "wlan get mac: getifaddrs() failed - %s", 295210502Ssyrinx strerror(errno)); 296210502Ssyrinx return (-1); 297210502Ssyrinx } 298210502Ssyrinx 299210502Ssyrinx for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 300210502Ssyrinx if (ifa->ifa_addr->sa_family != AF_LINK) 301210502Ssyrinx continue; 302210502Ssyrinx memcpy(&sdl, ifa->ifa_addr, sizeof(struct sockaddr_dl)); 303210502Ssyrinx if (sdl.sdl_alen > IEEE80211_ADDR_LEN) 304210502Ssyrinx continue; 305210502Ssyrinx if ((len = sdl.sdl_nlen) >= IFNAMSIZ) 306210502Ssyrinx len = IFNAMSIZ - 1; 307210502Ssyrinx memcpy(ifname, sdl.sdl_data, len); 308210502Ssyrinx ifname[len] = '\0'; 309210502Ssyrinx if (strcmp(wif->wname, ifname) == 0) 310210502Ssyrinx break; 311210502Ssyrinx } 312210502Ssyrinx 313210502Ssyrinx freeifaddrs(ifap); 314210502Ssyrinx return (0); 315210502Ssyrinx} 316210502Ssyrinx 317210502Ssyrinxint 318210502Ssyrinxwlan_get_parent(struct wlan_iface *wif __unused) 319210502Ssyrinx{ 320210502Ssyrinx /* XXX: There's no way to fetch this from the kernel. */ 321210502Ssyrinx return (0); 322210502Ssyrinx} 323210502Ssyrinx 324210502Ssyrinx/* XXX */ 325210502Ssyrinx#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */ 326210502Ssyrinx#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */ 327210502Ssyrinx#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */ 328210502Ssyrinx#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/ 329210502Ssyrinx#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */ 330210502Ssyrinx#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */ 331210502Ssyrinx#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ 332210502Ssyrinx#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */ 333210502Ssyrinx#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */ 334210502Ssyrinx#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */ 335210502Ssyrinx#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */ 336210502Ssyrinx#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */ 337210502Ssyrinx#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */ 338210502Ssyrinx#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/ 339210502Ssyrinx#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ 340210502Ssyrinx/* 0x7c0000 available */ 341210502Ssyrinx#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ 342210502Ssyrinx#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ 343210502Ssyrinx#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ 344210502Ssyrinx#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */ 345210502Ssyrinx#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */ 346210502Ssyrinx#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */ 347210502Ssyrinx/* 0x10000000 reserved */ 348210502Ssyrinx#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */ 349210502Ssyrinx#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */ 350210502Ssyrinx#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */ 351210502Ssyrinx 352210502Ssyrinxstatic uint32_t 353210502Ssyrinxwlan_drivercaps_to_snmp(uint32_t dcaps) 354210502Ssyrinx{ 355210502Ssyrinx uint32_t scaps = 0; 356210502Ssyrinx 357210502Ssyrinx if ((dcaps & IEEE80211_C_STA) != 0) 358210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_station); 359210502Ssyrinx if ((dcaps & IEEE80211_C_8023ENCAP) != 0) 360210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_ieee8023encap); 361210502Ssyrinx if ((dcaps & IEEE80211_C_FF) != 0) 362210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_athFastFrames); 363210502Ssyrinx if ((dcaps & IEEE80211_C_TURBOP) != 0) 364210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_athTurbo); 365210502Ssyrinx if ((dcaps & IEEE80211_C_IBSS) != 0) 366210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_ibss); 367210502Ssyrinx if ((dcaps & IEEE80211_C_PMGT) != 0) 368210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_pmgt); 369210502Ssyrinx if ((dcaps & IEEE80211_C_HOSTAP) != 0) 370210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_hostAp); 371210502Ssyrinx if ((dcaps & IEEE80211_C_AHDEMO) != 0) 372210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_ahDemo); 373210502Ssyrinx if ((dcaps & IEEE80211_C_SWRETRY) != 0) 374210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_swRetry); 375210502Ssyrinx if ((dcaps & IEEE80211_C_TXPMGT) != 0) 376210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_txPmgt); 377210502Ssyrinx if ((dcaps & IEEE80211_C_SHSLOT) != 0) 378210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_shortSlot); 379210502Ssyrinx if ((dcaps & IEEE80211_C_SHPREAMBLE) != 0) 380210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_shortPreamble); 381210502Ssyrinx if ((dcaps & IEEE80211_C_MONITOR) != 0) 382210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_monitor); 383210502Ssyrinx if ((dcaps & IEEE80211_C_DFS) != 0) 384210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_dfs); 385210502Ssyrinx if ((dcaps & IEEE80211_C_MBSS) != 0) 386210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_mbss); 387210502Ssyrinx if ((dcaps & IEEE80211_C_WPA1) != 0) 388210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_wpa1); 389210502Ssyrinx if ((dcaps & IEEE80211_C_WPA2) != 0) 390210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_wpa2); 391210502Ssyrinx if ((dcaps & IEEE80211_C_BURST) != 0) 392210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_burst); 393210502Ssyrinx if ((dcaps & IEEE80211_C_WME) != 0) 394210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_wme); 395210502Ssyrinx if ((dcaps & IEEE80211_C_WDS) != 0) 396210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_wds); 397210502Ssyrinx if ((dcaps & IEEE80211_C_BGSCAN) != 0) 398210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_bgScan); 399210502Ssyrinx if ((dcaps & IEEE80211_C_TXFRAG) != 0) 400210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_txFrag); 401210502Ssyrinx if ((dcaps & IEEE80211_C_TDMA) != 0) 402210502Ssyrinx scaps |= (0x1 << WlanDriverCaps_tdma); 403210502Ssyrinx 404210502Ssyrinx return (scaps); 405210502Ssyrinx} 406210502Ssyrinx 407210502Ssyrinxstatic uint32_t 408210502Ssyrinxwlan_cryptocaps_to_snmp(uint32_t ccaps) 409210502Ssyrinx{ 410210502Ssyrinx uint32_t scaps = 0; 411210502Ssyrinx 412210502Ssyrinx#if NOT_YET 413210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_WEP) != 0) 414210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_wep); 415210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_TKIP) != 0) 416210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_tkip); 417210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_AES_OCB) != 0) 418210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_aes); 419210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_AES_CCM) != 0) 420210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_aesCcm); 421210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_TKIPMIC) != 0) 422210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_tkipMic); 423210502Ssyrinx if ((ccaps & IEEE80211_CRYPTO_CKIP) != 0) 424210502Ssyrinx scaps |= (0x1 << wlanCryptoCaps_ckip); 425210502Ssyrinx#else /* !NOT_YET */ 426210502Ssyrinx scaps = ccaps; 427210502Ssyrinx#endif 428210502Ssyrinx return (scaps); 429210502Ssyrinx} 430210502Ssyrinx 431210502Ssyrinx#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */ 432210502Ssyrinx#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */ 433210502Ssyrinx/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */ 434210502Ssyrinx#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */ 435210502Ssyrinx#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/ 436210502Ssyrinx#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */ 437210502Ssyrinx 438210502Ssyrinxstatic uint32_t 439210502Ssyrinxwlan_htcaps_to_snmp(uint32_t hcaps) 440210502Ssyrinx{ 441210502Ssyrinx uint32_t scaps = 0; 442210502Ssyrinx 443210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_LDPC) != 0) 444210502Ssyrinx scaps |= (0x1 << WlanHTCaps_ldpc); 445210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_CHWIDTH40) != 0) 446210502Ssyrinx scaps |= (0x1 << WlanHTCaps_chwidth40); 447210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_GREENFIELD) != 0) 448210502Ssyrinx scaps |= (0x1 << WlanHTCaps_greenField); 449210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_SHORTGI20) != 0) 450210502Ssyrinx scaps |= (0x1 << WlanHTCaps_shortGi20); 451210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_SHORTGI40) != 0) 452210502Ssyrinx scaps |= (0x1 << WlanHTCaps_shortGi40); 453210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_TXSTBC) != 0) 454210502Ssyrinx scaps |= (0x1 << WlanHTCaps_txStbc); 455210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_DELBA) != 0) 456210502Ssyrinx scaps |= (0x1 << WlanHTCaps_delba); 457210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_MAXAMSDU_7935) != 0) 458210502Ssyrinx scaps |= (0x1 << WlanHTCaps_amsdu7935); 459210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_DSSSCCK40) != 0) 460210502Ssyrinx scaps |= (0x1 << WlanHTCaps_dssscck40); 461210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_PSMP) != 0) 462210502Ssyrinx scaps |= (0x1 << WlanHTCaps_psmp); 463210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_40INTOLERANT) != 0) 464210502Ssyrinx scaps |= (0x1 << WlanHTCaps_fortyMHzIntolerant); 465210502Ssyrinx if ((hcaps & IEEE80211_HTCAP_LSIGTXOPPROT) != 0) 466210502Ssyrinx scaps |= (0x1 << WlanHTCaps_lsigTxOpProt); 467210502Ssyrinx if ((hcaps & IEEE80211_HTC_AMPDU) != 0) 468210502Ssyrinx scaps |= (0x1 << WlanHTCaps_htcAmpdu); 469210502Ssyrinx if ((hcaps & IEEE80211_HTC_AMSDU) != 0) 470210502Ssyrinx scaps |= (0x1 << WlanHTCaps_htcAmsdu); 471210502Ssyrinx if ((hcaps & IEEE80211_HTC_HT) != 0) 472210502Ssyrinx scaps |= (0x1 << WlanHTCaps_htcHt); 473210502Ssyrinx if ((hcaps & IEEE80211_HTC_SMPS) != 0) 474210502Ssyrinx scaps |= (0x1 << WlanHTCaps_htcSmps); 475210502Ssyrinx if ((hcaps & IEEE80211_HTC_RIFS) != 0) 476210502Ssyrinx scaps |= (0x1 << WlanHTCaps_htcRifs); 477210502Ssyrinx 478210502Ssyrinx return (scaps); 479210502Ssyrinx} 480210502Ssyrinx 481210502Ssyrinx/* XXX: Not here? */ 482210502Ssyrinx#define WLAN_SET_TDMA_OPMODE(w) do { \ 483210502Ssyrinx if ((w)->mode == WlanIfaceOperatingModeType_adhocDemo && \ 484210502Ssyrinx ((w)->drivercaps & WlanDriverCaps_tdma) != 0) \ 485210502Ssyrinx (w)->mode = WlanIfaceOperatingModeType_tdma; \ 486210502Ssyrinx} while (0) 487210502Ssyrinxint 488210502Ssyrinxwlan_get_driver_caps(struct wlan_iface *wif) 489210502Ssyrinx{ 490210502Ssyrinx int val = 0; 491210502Ssyrinx size_t argsize; 492210502Ssyrinx struct ieee80211_devcaps_req dc; 493210502Ssyrinx 494210502Ssyrinx memset(&dc, 0, sizeof(struct ieee80211_devcaps_req)); 495210502Ssyrinx argsize = sizeof(struct ieee80211_devcaps_req); 496210502Ssyrinx 497210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_DEVCAPS, &val, &dc, 498210502Ssyrinx &argsize, 0) < 0) 499210502Ssyrinx return (-1); 500210502Ssyrinx 501210502Ssyrinx wif->drivercaps = wlan_drivercaps_to_snmp(dc.dc_drivercaps); 502210502Ssyrinx wif->cryptocaps = wlan_cryptocaps_to_snmp(dc.dc_cryptocaps); 503210502Ssyrinx wif->htcaps = wlan_htcaps_to_snmp(dc.dc_htcaps); 504210502Ssyrinx 505210502Ssyrinx WLAN_SET_TDMA_OPMODE(wif); 506210502Ssyrinx 507210502Ssyrinx argsize = dc.dc_chaninfo.ic_nchans * sizeof(struct ieee80211_channel); 508210502Ssyrinx wif->chanlist = (struct ieee80211_channel *)malloc(argsize); 509210502Ssyrinx if (wif->chanlist == NULL) 510210502Ssyrinx return (0); 511210502Ssyrinx 512210502Ssyrinx memcpy(wif->chanlist, dc.dc_chaninfo.ic_chans, argsize); 513210502Ssyrinx wif->nchannels = dc.dc_chaninfo.ic_nchans; 514210502Ssyrinx 515210502Ssyrinx return (0); 516210502Ssyrinx} 517210502Ssyrinx 518210502Ssyrinxuint8_t 519210502Ssyrinxwlan_channel_state_to_snmp(uint8_t cstate) 520210502Ssyrinx{ 521210502Ssyrinx uint8_t cs = 0; 522210502Ssyrinx 523210502Ssyrinx if ((cstate & IEEE80211_CHANSTATE_RADAR) != 0) 524210502Ssyrinx cs |= (0x1 << WlanIfaceChannelStateType_radar); 525210502Ssyrinx if ((cstate & IEEE80211_CHANSTATE_CACDONE) != 0) 526210502Ssyrinx cs |= (0x1 << WlanIfaceChannelStateType_cacDone); 527210502Ssyrinx if ((cstate & IEEE80211_CHANSTATE_CWINT) != 0) 528210502Ssyrinx cs |= (0x1 << WlanIfaceChannelStateType_interferenceDetected); 529210502Ssyrinx if ((cstate & IEEE80211_CHANSTATE_NORADAR) != 0) 530210502Ssyrinx cs |= (0x1 << WlanIfaceChannelStateType_radarClear); 531210502Ssyrinx 532210502Ssyrinx return (cs); 533210502Ssyrinx} 534210502Ssyrinx 535210502Ssyrinxuint32_t 536210502Ssyrinxwlan_channel_flags_to_snmp(uint32_t cflags) 537210502Ssyrinx{ 538210502Ssyrinx uint32_t cf = 0; 539210502Ssyrinx 540210502Ssyrinx if ((cflags & IEEE80211_CHAN_TURBO) != 0) 541210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_turbo); 542210502Ssyrinx if ((cflags & IEEE80211_CHAN_CCK) != 0) 543210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_cck); 544210502Ssyrinx if ((cflags & IEEE80211_CHAN_OFDM) != 0) 545210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_ofdm); 546210502Ssyrinx if ((cflags & IEEE80211_CHAN_2GHZ) != 0) 547210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum2Ghz); 548210502Ssyrinx if ((cflags & IEEE80211_CHAN_5GHZ) != 0) 549210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum5Ghz); 550210502Ssyrinx if ((cflags & IEEE80211_CHAN_PASSIVE) != 0) 551210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_passiveScan); 552210502Ssyrinx if ((cflags & IEEE80211_CHAN_DYN) != 0) 553210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_dynamicCckOfdm); 554210502Ssyrinx if ((cflags & IEEE80211_CHAN_GFSK) != 0) 555210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_gfsk); 556210502Ssyrinx if ((cflags & IEEE80211_CHAN_GSM) != 0) 557210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum900Mhz); 558210502Ssyrinx if ((cflags & IEEE80211_CHAN_STURBO) != 0) 559210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_dot11aStaticTurbo); 560210502Ssyrinx if ((cflags & IEEE80211_CHAN_HALF) != 0) 561210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_halfRate); 562210502Ssyrinx if ((cflags & IEEE80211_CHAN_QUARTER) != 0) 563210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_quarterRate); 564210502Ssyrinx if ((cflags & IEEE80211_CHAN_HT20) != 0) 565210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_ht20); 566210502Ssyrinx if ((cflags & IEEE80211_CHAN_HT40U) != 0) 567210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_ht40u); 568210502Ssyrinx if ((cflags & IEEE80211_CHAN_HT40D) != 0) 569210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_ht40d); 570210502Ssyrinx if ((cflags & IEEE80211_CHAN_DFS) != 0) 571210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_dfs); 572210502Ssyrinx if ((cflags & IEEE80211_CHAN_4MSXMIT) != 0) 573210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_xmit4ms); 574210502Ssyrinx if ((cflags & IEEE80211_CHAN_NOADHOC) != 0) 575210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_noAdhoc); 576210502Ssyrinx if ((cflags & IEEE80211_CHAN_NOHOSTAP) != 0) 577210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_noHostAp); 578210502Ssyrinx if ((cflags & IEEE80211_CHAN_11D) != 0) 579210502Ssyrinx cf |= (0x1 << WlanIfaceChannelFlagsType_dot11d); 580210502Ssyrinx 581210502Ssyrinx return (cf); 582210502Ssyrinx} 583210502Ssyrinx 584210502Ssyrinx/* XXX: */ 585210502Ssyrinx#define WLAN_SNMP_MAX_CHANS 256 586210502Ssyrinxint 587210502Ssyrinxwlan_get_channel_list(struct wlan_iface *wif) 588210502Ssyrinx{ 589210502Ssyrinx int val = 0; 590210502Ssyrinx uint32_t i, nchans; 591210502Ssyrinx size_t argsize; 592210502Ssyrinx struct ieee80211req_chaninfo *chaninfo; 593210502Ssyrinx struct ieee80211req_chanlist active; 594210502Ssyrinx const struct ieee80211_channel *c; 595210502Ssyrinx 596210502Ssyrinx argsize = sizeof(struct ieee80211req_chaninfo) + 597210502Ssyrinx sizeof(struct ieee80211_channel) * WLAN_SNMP_MAX_CHANS; 598210502Ssyrinx chaninfo = (struct ieee80211req_chaninfo *)malloc(argsize); 599210502Ssyrinx if (chaninfo == NULL) 600210502Ssyrinx return (-1); 601210502Ssyrinx 602210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANINFO, &val, chaninfo, 603210502Ssyrinx &argsize, 0) < 0) 604210502Ssyrinx return (-1); 605210502Ssyrinx 606210502Ssyrinx argsize = sizeof(active); 607210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANLIST, &val, &active, 608210502Ssyrinx &argsize, 0) < 0) 609210502Ssyrinx goto error; 610210502Ssyrinx 611210502Ssyrinx for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) { 612210502Ssyrinx c = &chaninfo->ic_chans[i]; 613210502Ssyrinx if (!isset(active.ic_channels, c->ic_ieee)) 614210502Ssyrinx continue; 615210502Ssyrinx nchans++; 616210502Ssyrinx } 617210502Ssyrinx wif->chanlist = (struct ieee80211_channel *)reallocf(wif->chanlist, 618210502Ssyrinx nchans * sizeof(*c)); 619210502Ssyrinx if (wif->chanlist == NULL) 620210502Ssyrinx goto error; 621210502Ssyrinx wif->nchannels = nchans; 622210502Ssyrinx for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) { 623210502Ssyrinx c = &chaninfo->ic_chans[i]; 624210502Ssyrinx if (!isset(active.ic_channels, c->ic_ieee)) 625210502Ssyrinx continue; 626210502Ssyrinx memcpy(wif->chanlist + nchans, c, sizeof (*c)); 627210502Ssyrinx nchans++; 628210502Ssyrinx } 629210502Ssyrinx 630210502Ssyrinx free(chaninfo); 631210502Ssyrinx return (0); 632210502Ssyrinxerror: 633210502Ssyrinx wif->nchannels = 0; 634210502Ssyrinx free(chaninfo); 635210502Ssyrinx return (-1); 636210502Ssyrinx} 637210502Ssyrinx 638210502Ssyrinxstatic enum WlanIfPhyMode 639210502Ssyrinxwlan_channel_flags_to_snmp_phy(uint32_t cflags) 640210502Ssyrinx{ 641210502Ssyrinx /* XXX: recheck */ 642210502Ssyrinx if ((cflags & IEEE80211_CHAN_A) != 0) 643210502Ssyrinx return (WlanIfPhyMode_dot11a); 644210502Ssyrinx if ((cflags & IEEE80211_CHAN_B) != 0) 645210502Ssyrinx return (WlanIfPhyMode_dot11b); 646210502Ssyrinx if ((cflags & IEEE80211_CHAN_G) != 0 || 647210502Ssyrinx (cflags & IEEE80211_CHAN_PUREG) != 0) 648210502Ssyrinx return (WlanIfPhyMode_dot11g); 649210502Ssyrinx if ((cflags & IEEE80211_CHAN_FHSS) != 0) 650210502Ssyrinx return (WlanIfPhyMode_fh); 651210502Ssyrinx if ((cflags & IEEE80211_CHAN_TURBO) != 0 && 652210502Ssyrinx (cflags & IEEE80211_CHAN_A) != 0) 653210502Ssyrinx return (WlanIfPhyMode_turboA); 654210502Ssyrinx if ((cflags & IEEE80211_CHAN_TURBO) != 0 && 655210502Ssyrinx (cflags & IEEE80211_CHAN_G) != 0) 656210502Ssyrinx return (WlanIfPhyMode_turboG); 657210502Ssyrinx if ((cflags & IEEE80211_CHAN_STURBO) != 0) 658210502Ssyrinx return (WlanIfPhyMode_sturboA); 659210502Ssyrinx if ((cflags & IEEE80211_CHAN_HALF) != 0) 660210502Ssyrinx return (WlanIfPhyMode_ofdmHalf); 661210502Ssyrinx if ((cflags & IEEE80211_CHAN_QUARTER) != 0) 662210502Ssyrinx return (WlanIfPhyMode_ofdmQuarter); 663210502Ssyrinx 664210502Ssyrinx return (WlanIfPhyMode_auto); 665210502Ssyrinx} 666210502Ssyrinx 667210502Ssyrinxint 668210502Ssyrinxwlan_get_roam_params(struct wlan_iface *wif) 669210502Ssyrinx{ 670210502Ssyrinx int val = 0; 671210502Ssyrinx size_t argsize; 672210502Ssyrinx 673210502Ssyrinx argsize = sizeof(struct ieee80211_roamparams_req); 674210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_ROAM, &val, 675210502Ssyrinx &wif->roamparams, &argsize, 0) < 0) 676210502Ssyrinx return (-1); 677210502Ssyrinx 678210502Ssyrinx return (0); 679210502Ssyrinx} 680210502Ssyrinx 681210502Ssyrinxint 682210502Ssyrinxwlan_get_tx_params(struct wlan_iface *wif) 683210502Ssyrinx{ 684210502Ssyrinx int val = 0; 685210502Ssyrinx size_t argsize; 686210502Ssyrinx 687210502Ssyrinx /* 688210502Ssyrinx * XXX: Reset IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA 689210502Ssyrinx * and IEEE80211_MODE_11NG modes. 690210502Ssyrinx */ 691210502Ssyrinx argsize = sizeof(struct ieee80211_txparams_req); 692210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val, 693210502Ssyrinx &wif->txparams, &argsize, 0) < 0) 694210502Ssyrinx return (-1); 695210502Ssyrinx 696210502Ssyrinx return (0); 697210502Ssyrinx} 698210502Ssyrinx 699210502Ssyrinxint 700210502Ssyrinxwlan_set_tx_params(struct wlan_iface *wif, int32_t pmode __unused) 701210502Ssyrinx{ 702210502Ssyrinx int val = 0; 703210502Ssyrinx size_t argsize; 704210502Ssyrinx 705210502Ssyrinx /* 706210502Ssyrinx * XXX: Set IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA 707210502Ssyrinx * and IEEE80211_MODE_11NG modes. 708210502Ssyrinx */ 709210502Ssyrinx argsize = sizeof(struct ieee80211_txparams_req); 710210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val, 711210502Ssyrinx &wif->txparams, &argsize, 1) < 0) 712210502Ssyrinx return (-1); 713210502Ssyrinx 714210502Ssyrinx return (0); 715210502Ssyrinx} 716210502Ssyrinx 717210502Ssyrinxint 718210502Ssyrinxwlan_clone_create(struct wlan_iface *wif) 719210502Ssyrinx{ 720210502Ssyrinx struct ifreq ifr; 721210502Ssyrinx struct ieee80211_clone_params wcp; 722210502Ssyrinx static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 723210502Ssyrinx 724210502Ssyrinx memset(&wcp, 0, sizeof(wcp)); 725210502Ssyrinx memset(&ifr, 0, sizeof(ifr)); 726210502Ssyrinx 727210502Ssyrinx /* Sanity checks. */ 728210502Ssyrinx if (wif == NULL || wif->pname[0] == '\0' || wif->mode > WLAN_IFMODE_MAX) 729210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 730210502Ssyrinx 731210502Ssyrinx if (wif->mode == WlanIfaceOperatingModeType_wds && 732210502Ssyrinx memcmp(wif->dbssid, zerobssid, IEEE80211_ADDR_LEN) == 0) 733210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 734210502Ssyrinx 735210502Ssyrinx strlcpy(wcp.icp_parent, wif->pname, IFNAMSIZ); 736210502Ssyrinx if ((wif->flags & WlanIfaceFlagsType_uniqueBssid) != 0) 737210502Ssyrinx wcp.icp_flags |= IEEE80211_CLONE_BSSID; 738210502Ssyrinx if ((wif->flags & WlanIfaceFlagsType_noBeacons) != 0) 739210502Ssyrinx wcp.icp_flags |= IEEE80211_CLONE_NOBEACONS; 740210502Ssyrinx if (wif->mode == WlanIfaceOperatingModeType_wds && 741210502Ssyrinx (wif->flags & WlanIfaceFlagsType_wdsLegacy) != 0) 742210502Ssyrinx wcp.icp_flags |= IEEE80211_CLONE_WDSLEGACY; 743210502Ssyrinx 744210502Ssyrinx switch (wif->mode) { 745210502Ssyrinx case WlanIfaceOperatingModeType_ibss: 746210502Ssyrinx wcp.icp_opmode = IEEE80211_M_IBSS; 747210502Ssyrinx break; 748210502Ssyrinx case WlanIfaceOperatingModeType_station: 749210502Ssyrinx wcp.icp_opmode = IEEE80211_M_STA; 750210502Ssyrinx break; 751210502Ssyrinx case WlanIfaceOperatingModeType_wds: 752210502Ssyrinx wcp.icp_opmode = IEEE80211_M_WDS; 753210502Ssyrinx break; 754210502Ssyrinx case WlanIfaceOperatingModeType_adhocDemo: 755210502Ssyrinx wcp.icp_opmode = IEEE80211_M_AHDEMO; 756210502Ssyrinx break; 757210502Ssyrinx case WlanIfaceOperatingModeType_hostAp: 758210502Ssyrinx wcp.icp_opmode = IEEE80211_M_HOSTAP; 759210502Ssyrinx break; 760210502Ssyrinx case WlanIfaceOperatingModeType_monitor: 761210502Ssyrinx wcp.icp_opmode = IEEE80211_M_MONITOR; 762210502Ssyrinx break; 763210502Ssyrinx case WlanIfaceOperatingModeType_meshPoint: 764210502Ssyrinx wcp.icp_opmode = IEEE80211_M_MBSS; 765210502Ssyrinx break; 766210502Ssyrinx case WlanIfaceOperatingModeType_tdma: 767210502Ssyrinx wcp.icp_opmode = IEEE80211_M_AHDEMO; 768210502Ssyrinx wcp.icp_flags |= IEEE80211_CLONE_TDMA; 769210502Ssyrinx break; 770210502Ssyrinx } 771210502Ssyrinx 772210502Ssyrinx memcpy(wcp.icp_bssid, wif->dbssid, IEEE80211_ADDR_LEN); 773210502Ssyrinx if (memcmp(wif->dlmac, zerobssid, IEEE80211_ADDR_LEN) != 0) { 774210502Ssyrinx memcpy(wcp.icp_macaddr, wif->dlmac, IEEE80211_ADDR_LEN); 775210502Ssyrinx wcp.icp_flags |= IEEE80211_CLONE_MACADDR; 776210502Ssyrinx } 777210502Ssyrinx 778210502Ssyrinx strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ); 779210502Ssyrinx ifr.ifr_data = (caddr_t) &wcp; 780210502Ssyrinx 781210502Ssyrinx if (ioctl(sock, SIOCIFCREATE2, (caddr_t) &ifr) < 0) { 782210502Ssyrinx syslog(LOG_ERR, "wlan clone create: ioctl(SIOCIFCREATE2) " 783210502Ssyrinx "failed: %s", strerror(errno)); 784210502Ssyrinx return (SNMP_ERR_GENERR); 785210502Ssyrinx } 786210502Ssyrinx 787210502Ssyrinx return (SNMP_ERR_NOERROR); 788210502Ssyrinx} 789210502Ssyrinx 790210502Ssyrinxint 791210502Ssyrinxwlan_clone_destroy(struct wlan_iface *wif) 792210502Ssyrinx{ 793210502Ssyrinx struct ifreq ifr; 794210502Ssyrinx 795210502Ssyrinx if (wif == NULL) 796210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 797210502Ssyrinx 798210502Ssyrinx memset(&ifr, 0, sizeof(ifr)); 799210502Ssyrinx strcpy(ifr.ifr_name, wif->wname); 800210502Ssyrinx 801210502Ssyrinx if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) { 802210502Ssyrinx syslog(LOG_ERR, "wlan clone destroy: ioctl(SIOCIFDESTROY) " 803210502Ssyrinx "failed: %s", strerror(errno)); 804210502Ssyrinx return (SNMP_ERR_GENERR); 805210502Ssyrinx } 806210502Ssyrinx 807210502Ssyrinx return (SNMP_ERR_NOERROR); 808210502Ssyrinx} 809210502Ssyrinx 810210502Ssyrinxstatic int 811210502Ssyrinxwlan_config_snmp2ioctl(int which) 812210502Ssyrinx{ 813210502Ssyrinx int op; 814210502Ssyrinx 815210502Ssyrinx switch (which) { 816210502Ssyrinx case LEAF_wlanIfacePacketBurst: 817210502Ssyrinx op = IEEE80211_IOC_BURST; 818210502Ssyrinx break; 819210502Ssyrinx case LEAF_wlanIfaceCountryCode: 820210502Ssyrinx op = IEEE80211_IOC_REGDOMAIN; 821210502Ssyrinx break; 822210502Ssyrinx case LEAF_wlanIfaceRegDomain: 823210502Ssyrinx op = IEEE80211_IOC_REGDOMAIN; 824210502Ssyrinx break; 825210502Ssyrinx case LEAF_wlanIfaceDesiredSsid: 826210502Ssyrinx op = IEEE80211_IOC_SSID; 827210502Ssyrinx break; 828210502Ssyrinx case LEAF_wlanIfaceDesiredChannel: 829210502Ssyrinx op = IEEE80211_IOC_CURCHAN; 830210502Ssyrinx break; 831210502Ssyrinx case LEAF_wlanIfaceDynamicFreqSelection: 832210502Ssyrinx op = IEEE80211_IOC_DFS; 833210502Ssyrinx break; 834210502Ssyrinx case LEAF_wlanIfaceFastFrames: 835210502Ssyrinx op = IEEE80211_IOC_FF; 836210502Ssyrinx break; 837210502Ssyrinx case LEAF_wlanIfaceDturbo: 838210502Ssyrinx op = IEEE80211_IOC_TURBOP; 839210502Ssyrinx break; 840210502Ssyrinx case LEAF_wlanIfaceTxPower: 841210502Ssyrinx op = IEEE80211_IOC_TXPOWER; 842210502Ssyrinx break; 843210502Ssyrinx case LEAF_wlanIfaceFragmentThreshold: 844210502Ssyrinx op = IEEE80211_IOC_FRAGTHRESHOLD; 845210502Ssyrinx break; 846210502Ssyrinx case LEAF_wlanIfaceRTSThreshold: 847210502Ssyrinx op = IEEE80211_IOC_RTSTHRESHOLD; 848210502Ssyrinx break; 849210502Ssyrinx case LEAF_wlanIfaceWlanPrivacySubscribe: 850210502Ssyrinx op = IEEE80211_IOC_WPS; 851210502Ssyrinx break; 852210502Ssyrinx case LEAF_wlanIfaceBgScan: 853210502Ssyrinx op = IEEE80211_IOC_BGSCAN; 854210502Ssyrinx break; 855210502Ssyrinx case LEAF_wlanIfaceBgScanIdle: 856210502Ssyrinx op = IEEE80211_IOC_BGSCAN_IDLE; 857210502Ssyrinx break; 858210502Ssyrinx case LEAF_wlanIfaceBgScanInterval: 859210502Ssyrinx op = IEEE80211_IOC_BGSCAN_INTERVAL; 860210502Ssyrinx break; 861210502Ssyrinx case LEAF_wlanIfaceBeaconMissedThreshold: 862210502Ssyrinx op = IEEE80211_IOC_BMISSTHRESHOLD; 863210502Ssyrinx break; 864210502Ssyrinx case LEAF_wlanIfaceDesiredBssid: 865210502Ssyrinx op = IEEE80211_IOC_BSSID; 866210502Ssyrinx break; 867210502Ssyrinx case LEAF_wlanIfaceRoamingMode: 868210502Ssyrinx op = IEEE80211_IOC_ROAMING; 869210502Ssyrinx break; 870210502Ssyrinx case LEAF_wlanIfaceDot11d: 871210502Ssyrinx op = IEEE80211_IOC_DOTD; 872210502Ssyrinx break; 873210502Ssyrinx case LEAF_wlanIfaceDot11h: 874210502Ssyrinx op = IEEE80211_IOC_DOTH; 875210502Ssyrinx break; 876210502Ssyrinx case LEAF_wlanIfaceDynamicWds: 877210502Ssyrinx op = IEEE80211_IOC_DWDS; 878210502Ssyrinx break; 879210502Ssyrinx case LEAF_wlanIfacePowerSave: 880210502Ssyrinx op = IEEE80211_IOC_POWERSAVE; 881210502Ssyrinx break; 882210502Ssyrinx case LEAF_wlanIfaceApBridge: 883210502Ssyrinx op = IEEE80211_IOC_APBRIDGE; 884210502Ssyrinx break; 885210502Ssyrinx case LEAF_wlanIfaceBeaconInterval: 886210502Ssyrinx op = IEEE80211_IOC_BEACON_INTERVAL; 887210502Ssyrinx break; 888210502Ssyrinx case LEAF_wlanIfaceDtimPeriod: 889210502Ssyrinx op = IEEE80211_IOC_DTIM_PERIOD; 890210502Ssyrinx break; 891210502Ssyrinx case LEAF_wlanIfaceHideSsid: 892210502Ssyrinx op = IEEE80211_IOC_HIDESSID; 893210502Ssyrinx break; 894210502Ssyrinx case LEAF_wlanIfaceInactivityProccess: 895210502Ssyrinx op = IEEE80211_IOC_INACTIVITY; 896210502Ssyrinx break; 897210502Ssyrinx case LEAF_wlanIfaceDot11gProtMode: 898210502Ssyrinx op = IEEE80211_IOC_PROTMODE; 899210502Ssyrinx break; 900210502Ssyrinx case LEAF_wlanIfaceDot11gPureMode: 901210502Ssyrinx op = IEEE80211_IOC_PUREG; 902210502Ssyrinx break; 903210502Ssyrinx case LEAF_wlanIfaceDot11nPureMode: 904210502Ssyrinx op = IEEE80211_IOC_PUREN; 905210502Ssyrinx break; 906210502Ssyrinx case LEAF_wlanIfaceDot11nAmpdu: 907210502Ssyrinx op = IEEE80211_IOC_AMPDU; 908210502Ssyrinx break; 909210502Ssyrinx case LEAF_wlanIfaceDot11nAmpduDensity: 910210502Ssyrinx op = IEEE80211_IOC_AMPDU_DENSITY; 911210502Ssyrinx break; 912210502Ssyrinx case LEAF_wlanIfaceDot11nAmpduLimit: 913210502Ssyrinx op = IEEE80211_IOC_AMPDU_LIMIT; 914210502Ssyrinx break; 915210502Ssyrinx case LEAF_wlanIfaceDot11nAmsdu: 916210502Ssyrinx op = IEEE80211_IOC_AMSDU; 917210502Ssyrinx break; 918210502Ssyrinx case LEAF_wlanIfaceDot11nAmsduLimit: 919210502Ssyrinx op = IEEE80211_IOC_AMSDU_LIMIT; 920210502Ssyrinx break; 921210502Ssyrinx case LEAF_wlanIfaceDot11nHighThroughput: 922210502Ssyrinx op = IEEE80211_IOC_HTCONF; 923210502Ssyrinx break; 924210502Ssyrinx case LEAF_wlanIfaceDot11nHTCompatible: 925210502Ssyrinx op = IEEE80211_IOC_HTCOMPAT; 926210502Ssyrinx break; 927210502Ssyrinx case LEAF_wlanIfaceDot11nHTProtMode: 928210502Ssyrinx op = IEEE80211_IOC_HTPROTMODE; 929210502Ssyrinx break; 930210502Ssyrinx case LEAF_wlanIfaceDot11nRIFS: 931210502Ssyrinx op = IEEE80211_IOC_RIFS; 932210502Ssyrinx break; 933210502Ssyrinx case LEAF_wlanIfaceDot11nShortGI: 934210502Ssyrinx op = IEEE80211_IOC_SHORTGI; 935210502Ssyrinx break; 936210502Ssyrinx case LEAF_wlanIfaceDot11nSMPSMode: 937210502Ssyrinx op = IEEE80211_IOC_SMPS; 938210502Ssyrinx break; 939210502Ssyrinx case LEAF_wlanIfaceTdmaSlot: 940210502Ssyrinx op = IEEE80211_IOC_TDMA_SLOT; 941210502Ssyrinx break; 942210502Ssyrinx case LEAF_wlanIfaceTdmaSlotCount: 943210502Ssyrinx op = IEEE80211_IOC_TDMA_SLOTCNT; 944210502Ssyrinx break; 945210502Ssyrinx case LEAF_wlanIfaceTdmaSlotLength: 946210502Ssyrinx op = IEEE80211_IOC_TDMA_SLOTLEN; 947210502Ssyrinx break; 948210502Ssyrinx case LEAF_wlanIfaceTdmaBeaconInterval: 949210502Ssyrinx op = IEEE80211_IOC_TDMA_BINTERVAL; 950210502Ssyrinx break; 951210502Ssyrinx default: 952210502Ssyrinx op = -1; 953210502Ssyrinx } 954210502Ssyrinx 955210502Ssyrinx return (op); 956210502Ssyrinx} 957210502Ssyrinx 958210502Ssyrinxstatic enum WlanRegDomainCode 959210502Ssyrinxwlan_regdomain_to_snmp(int which) 960210502Ssyrinx{ 961210502Ssyrinx enum WlanRegDomainCode reg_domain; 962210502Ssyrinx 963210502Ssyrinx switch (which) { 964210502Ssyrinx case SKU_FCC: 965210502Ssyrinx reg_domain = WlanRegDomainCode_fcc; 966210502Ssyrinx break; 967210502Ssyrinx case SKU_CA: 968210502Ssyrinx reg_domain = WlanRegDomainCode_ca; 969210502Ssyrinx break; 970210502Ssyrinx case SKU_ETSI: 971210502Ssyrinx reg_domain = WlanRegDomainCode_etsi; 972210502Ssyrinx break; 973210502Ssyrinx case SKU_ETSI2: 974210502Ssyrinx reg_domain = WlanRegDomainCode_etsi2; 975210502Ssyrinx break; 976210502Ssyrinx case SKU_ETSI3: 977210502Ssyrinx reg_domain = WlanRegDomainCode_etsi3; 978210502Ssyrinx break; 979210502Ssyrinx case SKU_FCC3: 980210502Ssyrinx reg_domain = WlanRegDomainCode_fcc3; 981210502Ssyrinx break; 982210502Ssyrinx case SKU_JAPAN: 983210502Ssyrinx reg_domain = WlanRegDomainCode_japan; 984210502Ssyrinx break; 985210502Ssyrinx case SKU_KOREA: 986210502Ssyrinx reg_domain = WlanRegDomainCode_korea; 987210502Ssyrinx break; 988210502Ssyrinx case SKU_APAC: 989210502Ssyrinx reg_domain = WlanRegDomainCode_apac; 990210502Ssyrinx break; 991210502Ssyrinx case SKU_APAC2: 992210502Ssyrinx reg_domain = WlanRegDomainCode_apac2; 993210502Ssyrinx break; 994210502Ssyrinx case SKU_APAC3: 995210502Ssyrinx reg_domain = WlanRegDomainCode_apac3; 996210502Ssyrinx break; 997210502Ssyrinx case SKU_ROW: 998210502Ssyrinx reg_domain = WlanRegDomainCode_row; 999210502Ssyrinx break; 1000210502Ssyrinx case SKU_NONE: 1001210502Ssyrinx reg_domain = WlanRegDomainCode_none; 1002210502Ssyrinx break; 1003210502Ssyrinx case SKU_DEBUG: 1004210502Ssyrinx reg_domain = WlanRegDomainCode_debug; 1005210502Ssyrinx break; 1006210502Ssyrinx case SKU_SR9: 1007210502Ssyrinx reg_domain = WlanRegDomainCode_sr9; 1008210502Ssyrinx break; 1009210502Ssyrinx case SKU_XR9: 1010210502Ssyrinx reg_domain = WlanRegDomainCode_xr9; 1011210502Ssyrinx break; 1012210502Ssyrinx case SKU_GZ901: 1013210502Ssyrinx reg_domain = WlanRegDomainCode_gz901; 1014210502Ssyrinx break; 1015210502Ssyrinx case 0: 1016210502Ssyrinx reg_domain = WlanRegDomainCode_none; 1017210502Ssyrinx break; 1018210502Ssyrinx default: 1019210502Ssyrinx syslog(LOG_ERR, "unknown regdomain (0x%x) ", which); 1020210502Ssyrinx reg_domain = WlanRegDomainCode_none; 1021210502Ssyrinx break; 1022210502Ssyrinx } 1023210502Ssyrinx 1024210502Ssyrinx return (reg_domain); 1025210502Ssyrinx} 1026210502Ssyrinx 1027210502Ssyrinxstatic int 1028210502Ssyrinxwlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain) 1029210502Ssyrinx{ 1030210502Ssyrinx int which; 1031210502Ssyrinx 1032210502Ssyrinx switch (regdomain) { 1033210502Ssyrinx case WlanRegDomainCode_fcc: 1034210502Ssyrinx which = SKU_FCC; 1035210502Ssyrinx break; 1036210502Ssyrinx case WlanRegDomainCode_ca: 1037210502Ssyrinx which = SKU_CA; 1038210502Ssyrinx break; 1039210502Ssyrinx case WlanRegDomainCode_etsi: 1040210502Ssyrinx which = SKU_ETSI; 1041210502Ssyrinx break; 1042210502Ssyrinx case WlanRegDomainCode_etsi2: 1043210502Ssyrinx which = SKU_ETSI2; 1044210502Ssyrinx break; 1045210502Ssyrinx case WlanRegDomainCode_etsi3: 1046210502Ssyrinx which = SKU_ETSI3; 1047210502Ssyrinx break; 1048210502Ssyrinx case WlanRegDomainCode_fcc3: 1049210502Ssyrinx which = SKU_FCC3; 1050210502Ssyrinx break; 1051210502Ssyrinx case WlanRegDomainCode_japan: 1052210502Ssyrinx which = SKU_JAPAN; 1053210502Ssyrinx break; 1054210502Ssyrinx case WlanRegDomainCode_korea: 1055210502Ssyrinx which = SKU_KOREA; 1056210502Ssyrinx break; 1057210502Ssyrinx case WlanRegDomainCode_apac: 1058210502Ssyrinx which = SKU_APAC; 1059210502Ssyrinx break; 1060210502Ssyrinx case WlanRegDomainCode_apac2: 1061210502Ssyrinx which = SKU_APAC2; 1062210502Ssyrinx break; 1063210502Ssyrinx case WlanRegDomainCode_apac3: 1064210502Ssyrinx which = SKU_APAC3; 1065210502Ssyrinx break; 1066210502Ssyrinx case WlanRegDomainCode_row: 1067210502Ssyrinx which = SKU_ROW; 1068210502Ssyrinx break; 1069210502Ssyrinx case WlanRegDomainCode_none: 1070210502Ssyrinx which = SKU_NONE; 1071210502Ssyrinx break; 1072210502Ssyrinx case WlanRegDomainCode_debug: 1073210502Ssyrinx which = SKU_DEBUG; 1074210502Ssyrinx break; 1075210502Ssyrinx case WlanRegDomainCode_sr9: 1076210502Ssyrinx which = SKU_SR9; 1077210502Ssyrinx break; 1078210502Ssyrinx case WlanRegDomainCode_xr9: 1079210502Ssyrinx which = SKU_XR9; 1080210502Ssyrinx break; 1081210502Ssyrinx case WlanRegDomainCode_gz901: 1082210502Ssyrinx which = SKU_GZ901; 1083210502Ssyrinx break; 1084210502Ssyrinx default: 1085210502Ssyrinx syslog(LOG_ERR, "unknown snmp regdomain (0x%x) ", regdomain); 1086210502Ssyrinx which = SKU_NONE; 1087210502Ssyrinx break; 1088210502Ssyrinx } 1089210502Ssyrinx 1090210502Ssyrinx return (which); 1091210502Ssyrinx} 1092210502Ssyrinx 1093210502Ssyrinxstatic int 1094210502Ssyrinxwlan_config_get_country(struct wlan_iface *wif) 1095210502Ssyrinx{ 1096210502Ssyrinx int val = 0; 1097210502Ssyrinx size_t argsize; 1098210502Ssyrinx struct ieee80211_regdomain regdomain; 1099210502Ssyrinx 1100210502Ssyrinx memset(®domain, 0, sizeof(regdomain)); 1101210502Ssyrinx argsize = sizeof(regdomain); 1102210502Ssyrinx 1103210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, ®domain, 1104210502Ssyrinx &argsize, 0) < 0) 1105210502Ssyrinx return (-1); 1106210502Ssyrinx 1107210502Ssyrinx wif->reg_domain = wlan_regdomain_to_snmp(regdomain.regdomain); 1108210502Ssyrinx wif->country_code[0] = regdomain.isocc[0]; 1109210502Ssyrinx wif->country_code[1] = regdomain.isocc[1]; 1110210502Ssyrinx wif->country_code[2] = regdomain.location; 1111210502Ssyrinx 1112210502Ssyrinx return (0); 1113210502Ssyrinx} 1114210502Ssyrinx 1115210502Ssyrinxstatic int 1116210502Ssyrinxwlan_config_set_country(struct wlan_iface *wif, char *ccode, int rdomain) 1117210502Ssyrinx{ 1118210502Ssyrinx int val = 0, txpowermax; 1119210502Ssyrinx uint32_t i; 1120210502Ssyrinx size_t argsize = 0; 1121210502Ssyrinx struct ieee80211_regdomain_req *regdomain; 1122210502Ssyrinx 1123210502Ssyrinx if (wlan_get_channel_list(wif) < 0) 1124210502Ssyrinx return (-1); 1125210502Ssyrinx 1126210502Ssyrinx if (wif->nchannels == 0) { 1127210502Ssyrinx syslog(LOG_ERR, "iface %s - set regdomain failed", wif->wname); 1128210502Ssyrinx return (-1); 1129210502Ssyrinx } 1130210502Ssyrinx 1131210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPOWMAX, &txpowermax, 0, 1132210502Ssyrinx &argsize, 0) < 0) 1133210502Ssyrinx return (-1); 1134210502Ssyrinx 1135210502Ssyrinx regdomain = malloc(IEEE80211_REGDOMAIN_SIZE(wif->nchannels)); 1136210502Ssyrinx if (regdomain == NULL) 1137210502Ssyrinx return (-1); 1138210502Ssyrinx memset(regdomain, 0, IEEE80211_REGDOMAIN_SIZE(wif->nchannels)); 1139210502Ssyrinx argsize = IEEE80211_REGDOMAIN_SIZE(wif->nchannels); 1140210502Ssyrinx 1141210502Ssyrinx /* XXX: recheck with how this is done by ifconfig(8) */ 1142210502Ssyrinx regdomain->rd.regdomain = wlan_snmp_to_regdomain(rdomain); 1143210502Ssyrinx regdomain->rd.isocc[0] = ccode[0]; 1144210502Ssyrinx regdomain->rd.isocc[1] = ccode[1]; 1145210502Ssyrinx regdomain->rd.location = ccode[2]; 1146210502Ssyrinx 1147210502Ssyrinx /* XXX: fill the channel list properly */ 1148210502Ssyrinx regdomain->chaninfo.ic_nchans = wif->nchannels; 1149210502Ssyrinx memcpy(regdomain->chaninfo.ic_chans, wif->chanlist, 1150210502Ssyrinx wif->nchannels * sizeof(struct ieee80211_channel)); 1151210502Ssyrinx for (i = 0; i < wif->nchannels; i++) 1152210502Ssyrinx regdomain->chaninfo.ic_chans[i].ic_maxregpower = txpowermax; 1153210502Ssyrinx 1154210502Ssyrinx wif->state = wlanIfaceState_down; 1155210502Ssyrinx if (wlan_config_state(wif, 1) < 0 || 1156210502Ssyrinx wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, regdomain, 1157210502Ssyrinx &argsize, 1) < 0) { 1158210502Ssyrinx free(regdomain); 1159210502Ssyrinx return (-1); 1160210502Ssyrinx } 1161210502Ssyrinx 1162210502Ssyrinx wif->state = wlanIfaceState_up; 1163210502Ssyrinx (void)wlan_config_state(wif, 1); 1164210502Ssyrinx wif->reg_domain = wlan_regdomain_to_snmp(regdomain->rd.regdomain); 1165210502Ssyrinx wif->country_code[0] = regdomain->rd.isocc[0]; 1166210502Ssyrinx wif->country_code[1] = regdomain->rd.isocc[1]; 1167210502Ssyrinx wif->country_code[2] = regdomain->rd.location; 1168210502Ssyrinx free(regdomain); 1169210502Ssyrinx 1170210502Ssyrinx return (0); 1171210502Ssyrinx} 1172210502Ssyrinx 1173210502Ssyrinxint 1174210502Ssyrinxwlan_config_get_dssid(struct wlan_iface *wif) 1175210502Ssyrinx{ 1176210502Ssyrinx int val = -1; 1177210502Ssyrinx size_t argsize = IEEE80211_NWID_LEN + 1; 1178210502Ssyrinx char ssid[IEEE80211_NWID_LEN + 1]; 1179210502Ssyrinx 1180210502Ssyrinx memset(ssid, 0, IEEE80211_NWID_LEN + 1); 1181210502Ssyrinx 1182210502Ssyrinx if (wlan_ioctl(wif->wname, 1183210502Ssyrinx (wif->mode == WlanIfaceOperatingModeType_meshPoint) ? 1184210502Ssyrinx IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid, 1185210502Ssyrinx &argsize, 0) < 0) 1186210502Ssyrinx return (-1); 1187210502Ssyrinx 1188210502Ssyrinx if (argsize > IEEE80211_NWID_LEN) 1189210502Ssyrinx argsize = IEEE80211_NWID_LEN; 1190210502Ssyrinx memcpy(wif->desired_ssid, ssid, argsize); 1191210502Ssyrinx wif->desired_ssid[argsize] = '\0'; 1192210502Ssyrinx 1193210502Ssyrinx return (0); 1194210502Ssyrinx} 1195210502Ssyrinx 1196210502Ssyrinxint 1197210502Ssyrinxwlan_config_set_dssid(struct wlan_iface *wif, char *ssid, int slen) 1198210502Ssyrinx{ 1199210502Ssyrinx int val = 0; 1200210502Ssyrinx size_t argsize = slen; 1201210502Ssyrinx 1202210502Ssyrinx if (wlan_ioctl(wif->wname, 1203210502Ssyrinx (wif->mode == WlanIfaceOperatingModeType_meshPoint) ? 1204210502Ssyrinx IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid, 1205210502Ssyrinx &argsize, 1) < 0) 1206210502Ssyrinx return (-1); 1207210502Ssyrinx 1208210502Ssyrinx if (argsize > IEEE80211_NWID_LEN) 1209210502Ssyrinx argsize = IEEE80211_NWID_LEN; 1210210502Ssyrinx memcpy(wif->desired_ssid, ssid, argsize); 1211210502Ssyrinx wif->desired_ssid[argsize] = '\0'; 1212210502Ssyrinx 1213210502Ssyrinx return (0); 1214210502Ssyrinx} 1215210502Ssyrinx 1216210502Ssyrinxstatic int 1217210502Ssyrinxwlan_config_get_dchannel(struct wlan_iface *wif) 1218210502Ssyrinx{ 1219210502Ssyrinx uint32_t i = 0; 1220210502Ssyrinx int val = 0; 1221210502Ssyrinx size_t argsize = sizeof(struct ieee80211_channel); 1222210502Ssyrinx struct ieee80211_channel chan; 1223210502Ssyrinx 1224210502Ssyrinx if (wlan_get_channel_list(wif) < 0) 1225210502Ssyrinx return (-1); 1226210502Ssyrinx 1227210502Ssyrinx memset(&chan, 0, sizeof(chan)); 1228210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan, 1229210502Ssyrinx &argsize, 0) < 0) 1230210502Ssyrinx return (-1); 1231210502Ssyrinx 1232210502Ssyrinx for (i = 0; i < wif->nchannels; i++) 1233210502Ssyrinx if (chan.ic_ieee == wif->chanlist[i].ic_ieee && 1234210502Ssyrinx chan.ic_flags == wif->chanlist[i].ic_flags) { 1235210502Ssyrinx wif->desired_channel = i + 1; 1236210502Ssyrinx break; 1237210502Ssyrinx } 1238210502Ssyrinx 1239210502Ssyrinx return (0); 1240210502Ssyrinx} 1241210502Ssyrinx 1242210502Ssyrinxstatic int 1243210502Ssyrinxwlan_config_set_dchannel(struct wlan_iface *wif, uint32_t dchannel) 1244210502Ssyrinx{ 1245210502Ssyrinx int val = 0; 1246210502Ssyrinx size_t argsize = sizeof(struct ieee80211_channel); 1247210502Ssyrinx struct ieee80211_channel chan; 1248210502Ssyrinx 1249210502Ssyrinx if (wlan_get_channel_list(wif) < 0) 1250210502Ssyrinx return (-1); 1251210502Ssyrinx 1252210502Ssyrinx if (dchannel > wif->nchannels) 1253210502Ssyrinx return (-1); 1254210502Ssyrinx 1255210502Ssyrinx memcpy(&chan, wif->chanlist + dchannel - 1, sizeof(chan)); 1256210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan, 1257210502Ssyrinx &argsize, 1) < 0) 1258210502Ssyrinx return (-1); 1259210502Ssyrinx 1260210502Ssyrinx wif->desired_channel = dchannel; 1261210502Ssyrinx 1262210502Ssyrinx return (0); 1263210502Ssyrinx} 1264210502Ssyrinx 1265210502Ssyrinxstatic int 1266210502Ssyrinxwlan_config_get_bssid(struct wlan_iface *wif) 1267210502Ssyrinx{ 1268210502Ssyrinx int val = 0; 1269210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 1270210502Ssyrinx char bssid[IEEE80211_ADDR_LEN]; 1271210502Ssyrinx 1272210502Ssyrinx memset(bssid, 0, IEEE80211_ADDR_LEN); 1273210502Ssyrinx 1274210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid, 1275210502Ssyrinx &argsize, 0) < 0 || argsize != IEEE80211_ADDR_LEN) 1276210502Ssyrinx return (-1); 1277210502Ssyrinx 1278210502Ssyrinx memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN); 1279210502Ssyrinx 1280210502Ssyrinx return (0); 1281210502Ssyrinx} 1282210502Ssyrinx 1283210502Ssyrinxstatic int 1284210502Ssyrinxwlan_config_set_bssid(struct wlan_iface *wif, uint8_t *bssid) 1285210502Ssyrinx{ 1286210502Ssyrinx int val = 0; 1287210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 1288210502Ssyrinx 1289210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid, 1290210502Ssyrinx &argsize, 1) < 0 || argsize != IEEE80211_ADDR_LEN) 1291210502Ssyrinx return (-1); 1292210502Ssyrinx 1293210502Ssyrinx memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN); 1294210502Ssyrinx 1295210502Ssyrinx return (0); 1296210502Ssyrinx} 1297210502Ssyrinx 1298210502Ssyrinx/* 1299210502Ssyrinx * Convert the value returned by the kernel to the appropriate SNMP 1300210502Ssyrinx * representation and set the corresponding interface member accordingly. 1301210502Ssyrinx */ 1302210502Ssyrinxstatic void 1303210502Ssyrinxwlan_config_set_snmp_intval(struct wlan_iface *wif, int op, int val) 1304210502Ssyrinx{ 1305210502Ssyrinx switch (op) { 1306210502Ssyrinx case IEEE80211_IOC_BURST: 1307210502Ssyrinx if (val == 0) 1308210502Ssyrinx wif->packet_burst = TruthValue_false; 1309210502Ssyrinx else 1310210502Ssyrinx wif->packet_burst = TruthValue_true; 1311210502Ssyrinx break; 1312210502Ssyrinx case IEEE80211_IOC_DFS: 1313210502Ssyrinx if (val == 0) 1314210502Ssyrinx wif->dyn_frequency = TruthValue_false; 1315210502Ssyrinx else 1316210502Ssyrinx wif->dyn_frequency = TruthValue_true; 1317210502Ssyrinx break; 1318210502Ssyrinx case IEEE80211_IOC_FF: 1319210502Ssyrinx if (val == 0) 1320210502Ssyrinx wif->fast_frames = TruthValue_false; 1321210502Ssyrinx else 1322210502Ssyrinx wif->fast_frames = TruthValue_true; 1323210502Ssyrinx break; 1324210502Ssyrinx case IEEE80211_IOC_TURBOP: 1325210502Ssyrinx if (val == 0) 1326210502Ssyrinx wif->dturbo = TruthValue_false; 1327210502Ssyrinx else 1328210502Ssyrinx wif->dturbo = TruthValue_true; 1329210502Ssyrinx break; 1330210502Ssyrinx case IEEE80211_IOC_TXPOWER: 1331210502Ssyrinx wif->tx_power = val / 2; 1332210502Ssyrinx break; 1333210502Ssyrinx case IEEE80211_IOC_FRAGTHRESHOLD: 1334210502Ssyrinx wif->frag_threshold = val; 1335210502Ssyrinx break; 1336210502Ssyrinx case IEEE80211_IOC_RTSTHRESHOLD: 1337210502Ssyrinx wif->rts_threshold = val; 1338210502Ssyrinx break; 1339210502Ssyrinx case IEEE80211_IOC_WPS: 1340210502Ssyrinx if (val == 0) 1341210502Ssyrinx wif->priv_subscribe = TruthValue_false; 1342210502Ssyrinx else 1343210502Ssyrinx wif->priv_subscribe = TruthValue_true; 1344210502Ssyrinx break; 1345210502Ssyrinx case IEEE80211_IOC_BGSCAN: 1346210502Ssyrinx if (val == 0) 1347210502Ssyrinx wif->bg_scan = TruthValue_false; 1348210502Ssyrinx else 1349210502Ssyrinx wif->bg_scan = TruthValue_true; 1350210502Ssyrinx break; 1351210502Ssyrinx case IEEE80211_IOC_BGSCAN_IDLE: 1352210502Ssyrinx wif->bg_scan_idle = val; 1353210502Ssyrinx break; 1354210502Ssyrinx case IEEE80211_IOC_BGSCAN_INTERVAL: 1355210502Ssyrinx wif->bg_scan_interval = val; 1356210502Ssyrinx break; 1357210502Ssyrinx case IEEE80211_IOC_BMISSTHRESHOLD: 1358210502Ssyrinx wif->beacons_missed = val; 1359210502Ssyrinx break; 1360210502Ssyrinx case IEEE80211_IOC_ROAMING: 1361210502Ssyrinx switch (val) { 1362210502Ssyrinx case IEEE80211_ROAMING_DEVICE: 1363210502Ssyrinx wif->roam_mode = wlanIfaceRoamingMode_device; 1364210502Ssyrinx break; 1365210502Ssyrinx case IEEE80211_ROAMING_MANUAL: 1366210502Ssyrinx wif->roam_mode = wlanIfaceRoamingMode_manual; 1367210502Ssyrinx break; 1368210502Ssyrinx case IEEE80211_ROAMING_AUTO: 1369210502Ssyrinx /* FALTHROUGH */ 1370210502Ssyrinx default: 1371210502Ssyrinx wif->roam_mode = wlanIfaceRoamingMode_auto; 1372210502Ssyrinx break; 1373210502Ssyrinx } 1374210502Ssyrinx break; 1375210502Ssyrinx case IEEE80211_IOC_DOTD: 1376210502Ssyrinx if (val == 0) 1377210502Ssyrinx wif->dot11d = TruthValue_false; 1378210502Ssyrinx else 1379210502Ssyrinx wif->dot11d = TruthValue_true; 1380210502Ssyrinx break; 1381210502Ssyrinx case IEEE80211_IOC_DOTH: 1382210502Ssyrinx if (val == 0) 1383210502Ssyrinx wif->dot11h = TruthValue_false; 1384210502Ssyrinx else 1385210502Ssyrinx wif->dot11h = TruthValue_true; 1386210502Ssyrinx break; 1387210502Ssyrinx case IEEE80211_IOC_DWDS: 1388210502Ssyrinx if (val == 0) 1389210502Ssyrinx wif->dynamic_wds = TruthValue_false; 1390210502Ssyrinx else 1391210502Ssyrinx wif->dynamic_wds = TruthValue_true; 1392210502Ssyrinx break; 1393210502Ssyrinx case IEEE80211_IOC_POWERSAVE: 1394210502Ssyrinx if (val == 0) 1395210502Ssyrinx wif->power_save = TruthValue_false; 1396210502Ssyrinx else 1397210502Ssyrinx wif->power_save = TruthValue_true; 1398210502Ssyrinx break; 1399210502Ssyrinx case IEEE80211_IOC_APBRIDGE: 1400210502Ssyrinx if (val == 0) 1401210502Ssyrinx wif->ap_bridge = TruthValue_false; 1402210502Ssyrinx else 1403210502Ssyrinx wif->ap_bridge = TruthValue_true; 1404210502Ssyrinx break; 1405210502Ssyrinx case IEEE80211_IOC_BEACON_INTERVAL: 1406210502Ssyrinx wif->beacon_interval = val; 1407210502Ssyrinx break; 1408210502Ssyrinx case IEEE80211_IOC_DTIM_PERIOD: 1409210502Ssyrinx wif->dtim_period = val; 1410210502Ssyrinx break; 1411210502Ssyrinx case IEEE80211_IOC_HIDESSID: 1412210502Ssyrinx if (val == 0) 1413210502Ssyrinx wif->hide_ssid = TruthValue_false; 1414210502Ssyrinx else 1415210502Ssyrinx wif->hide_ssid = TruthValue_true; 1416210502Ssyrinx break; 1417210502Ssyrinx case IEEE80211_IOC_INACTIVITY: 1418210502Ssyrinx if (val == 0) 1419210502Ssyrinx wif->inact_process = TruthValue_false; 1420210502Ssyrinx else 1421210502Ssyrinx wif->inact_process = TruthValue_true; 1422210502Ssyrinx break; 1423210502Ssyrinx case IEEE80211_IOC_PROTMODE: 1424210502Ssyrinx switch (val) { 1425210502Ssyrinx case IEEE80211_PROTMODE_CTS: 1426210502Ssyrinx wif->do11g_protect = wlanIfaceDot11gProtMode_cts; 1427210502Ssyrinx break; 1428210502Ssyrinx case IEEE80211_PROTMODE_RTSCTS: 1429210502Ssyrinx wif->do11g_protect = wlanIfaceDot11gProtMode_rtscts; 1430210502Ssyrinx break; 1431210502Ssyrinx case IEEE80211_PROTMODE_OFF: 1432210502Ssyrinx /* FALLTHROUGH */ 1433210502Ssyrinx default: 1434210502Ssyrinx wif->do11g_protect = wlanIfaceDot11gProtMode_off; 1435210502Ssyrinx break; 1436210502Ssyrinx } 1437210502Ssyrinx break; 1438210502Ssyrinx case IEEE80211_IOC_PUREG: 1439210502Ssyrinx if (val == 0) 1440210502Ssyrinx wif->dot11g_pure = TruthValue_false; 1441210502Ssyrinx else 1442210502Ssyrinx wif->dot11g_pure = TruthValue_true; 1443210502Ssyrinx break; 1444210502Ssyrinx case IEEE80211_IOC_PUREN: 1445210502Ssyrinx if (val == 0) 1446210502Ssyrinx wif->dot11n_pure = TruthValue_false; 1447210502Ssyrinx else 1448210502Ssyrinx wif->dot11n_pure = TruthValue_true; 1449210502Ssyrinx break; 1450210502Ssyrinx case IEEE80211_IOC_AMPDU: 1451210502Ssyrinx switch (val) { 1452210502Ssyrinx case 0: 1453210502Ssyrinx wif->ampdu = WlanIfaceDot11nPduType_disabled; 1454210502Ssyrinx break; 1455210502Ssyrinx case 1: 1456210502Ssyrinx wif->ampdu = WlanIfaceDot11nPduType_txOnly; 1457210502Ssyrinx break; 1458210502Ssyrinx case 2: 1459210502Ssyrinx wif->ampdu = WlanIfaceDot11nPduType_rxOnly; 1460210502Ssyrinx break; 1461210502Ssyrinx case 3: 1462210502Ssyrinx /* FALLTHROUGH */ 1463210502Ssyrinx default: 1464210502Ssyrinx wif->ampdu = WlanIfaceDot11nPduType_txAndRx; 1465210502Ssyrinx break; 1466210502Ssyrinx } 1467210502Ssyrinx break; 1468210502Ssyrinx case IEEE80211_IOC_AMPDU_DENSITY: 1469210502Ssyrinx switch (val) { 1470210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_025: 1471210502Ssyrinx wif->ampdu_density = 25; 1472210502Ssyrinx break; 1473210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_05: 1474210502Ssyrinx wif->ampdu_density = 50; 1475210502Ssyrinx break; 1476210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_1: 1477210502Ssyrinx wif->ampdu_density = 100; 1478210502Ssyrinx break; 1479210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_2: 1480210502Ssyrinx wif->ampdu_density = 200; 1481210502Ssyrinx break; 1482210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_4: 1483210502Ssyrinx wif->ampdu_density = 400; 1484210502Ssyrinx break; 1485210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_8: 1486210502Ssyrinx wif->ampdu_density = 800; 1487210502Ssyrinx break; 1488210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_16: 1489210502Ssyrinx wif->ampdu_density = 1600; 1490210502Ssyrinx break; 1491210502Ssyrinx case IEEE80211_HTCAP_MPDUDENSITY_NA: 1492210502Ssyrinx default: 1493210502Ssyrinx wif->ampdu_density = 0; 1494210502Ssyrinx break; 1495210502Ssyrinx } 1496210502Ssyrinx break; 1497210502Ssyrinx case IEEE80211_IOC_AMPDU_LIMIT: 1498210502Ssyrinx switch (val) { 1499210502Ssyrinx case IEEE80211_HTCAP_MAXRXAMPDU_8K: 1500210502Ssyrinx wif->ampdu_limit = 8192; 1501210502Ssyrinx break; 1502210502Ssyrinx case IEEE80211_HTCAP_MAXRXAMPDU_16K: 1503210502Ssyrinx wif->ampdu_limit = 16384; 1504210502Ssyrinx break; 1505210502Ssyrinx case IEEE80211_HTCAP_MAXRXAMPDU_32K: 1506210502Ssyrinx wif->ampdu_limit = 32768; 1507210502Ssyrinx break; 1508210502Ssyrinx case IEEE80211_HTCAP_MAXRXAMPDU_64K: 1509210502Ssyrinx default: 1510210502Ssyrinx wif->ampdu_limit = 65536; 1511210502Ssyrinx break; 1512210502Ssyrinx } 1513210502Ssyrinx break; 1514210502Ssyrinx case IEEE80211_IOC_AMSDU: 1515210502Ssyrinx switch (val) { 1516210502Ssyrinx case 0: 1517210502Ssyrinx wif->amsdu = WlanIfaceDot11nPduType_disabled; 1518210502Ssyrinx break; 1519210502Ssyrinx case 1: 1520210502Ssyrinx wif->amsdu = WlanIfaceDot11nPduType_txOnly; 1521210502Ssyrinx break; 1522210502Ssyrinx case 3: 1523210502Ssyrinx wif->amsdu = WlanIfaceDot11nPduType_txAndRx; 1524210502Ssyrinx break; 1525210502Ssyrinx case 2: 1526210502Ssyrinx default: 1527210502Ssyrinx /* FALLTHROUGH */ 1528210502Ssyrinx wif->amsdu = WlanIfaceDot11nPduType_rxOnly; 1529210502Ssyrinx break; 1530210502Ssyrinx } 1531210502Ssyrinx break; 1532210502Ssyrinx case IEEE80211_IOC_AMSDU_LIMIT: 1533210502Ssyrinx wif->amsdu_limit = val; 1534210502Ssyrinx break; 1535210502Ssyrinx case IEEE80211_IOC_HTCONF: 1536210502Ssyrinx if (val == 0) /* XXX */ 1537210502Ssyrinx wif->ht_enabled = TruthValue_false; 1538210502Ssyrinx else 1539210502Ssyrinx wif->ht_enabled = TruthValue_true; 1540210502Ssyrinx break; 1541210502Ssyrinx case IEEE80211_IOC_HTCOMPAT: 1542210502Ssyrinx if (val == 0) 1543210502Ssyrinx wif->ht_compatible = TruthValue_false; 1544210502Ssyrinx else 1545210502Ssyrinx wif->ht_compatible = TruthValue_true; 1546210502Ssyrinx break; 1547210502Ssyrinx case IEEE80211_IOC_HTPROTMODE: 1548210502Ssyrinx if (val == IEEE80211_PROTMODE_RTSCTS) 1549210502Ssyrinx wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_rts; 1550210502Ssyrinx else 1551210502Ssyrinx wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_off; 1552210502Ssyrinx break; 1553210502Ssyrinx case IEEE80211_IOC_RIFS: 1554210502Ssyrinx if (val == 0) 1555210502Ssyrinx wif->rifs = TruthValue_false; 1556210502Ssyrinx else 1557210502Ssyrinx wif->rifs = TruthValue_true; 1558210502Ssyrinx break; 1559210502Ssyrinx case IEEE80211_IOC_SHORTGI: 1560210502Ssyrinx if (val == 0) 1561210502Ssyrinx wif->short_gi = TruthValue_false; 1562210502Ssyrinx else 1563210502Ssyrinx wif->short_gi = TruthValue_true; 1564210502Ssyrinx break; 1565210502Ssyrinx case IEEE80211_IOC_SMPS: 1566210502Ssyrinx switch (val) { 1567210502Ssyrinx case IEEE80211_HTCAP_SMPS_DYNAMIC: 1568210502Ssyrinx wif->smps_mode = wlanIfaceDot11nSMPSMode_dynamic; 1569210502Ssyrinx break; 1570210502Ssyrinx case IEEE80211_HTCAP_SMPS_ENA: 1571210502Ssyrinx wif->smps_mode = wlanIfaceDot11nSMPSMode_static; 1572210502Ssyrinx break; 1573210502Ssyrinx case IEEE80211_HTCAP_SMPS_OFF: 1574210502Ssyrinx /* FALLTHROUGH */ 1575210502Ssyrinx default: 1576210502Ssyrinx wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled; 1577210502Ssyrinx break; 1578210502Ssyrinx } 1579210502Ssyrinx break; 1580210502Ssyrinx case IEEE80211_IOC_TDMA_SLOT: 1581210502Ssyrinx wif->tdma_slot = val; 1582210502Ssyrinx break; 1583210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTCNT: 1584210502Ssyrinx wif->tdma_slot_count = val; 1585210502Ssyrinx break; 1586210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTLEN: 1587210502Ssyrinx wif->tdma_slot_length = val; 1588210502Ssyrinx break; 1589210502Ssyrinx case IEEE80211_IOC_TDMA_BINTERVAL: 1590210502Ssyrinx wif->tdma_binterval = val; 1591210502Ssyrinx break; 1592210502Ssyrinx default: 1593210502Ssyrinx break; 1594210502Ssyrinx } 1595210502Ssyrinx} 1596210502Ssyrinx 1597210502Ssyrinx/* 1598210502Ssyrinx * Convert an SNMP value to the kernel equivalent and also do sanity check 1599210502Ssyrinx * for each specific type. 1600210502Ssyrinx */ 1601210502Ssyrinxstatic int 1602210502Ssyrinxwlan_config_snmp2value(int which, int sval, int *value) 1603210502Ssyrinx{ 1604210502Ssyrinx *value = 0; 1605210502Ssyrinx 1606210502Ssyrinx switch (which) { 1607210502Ssyrinx case IEEE80211_IOC_BURST: 1608210502Ssyrinx case IEEE80211_IOC_DFS: 1609210502Ssyrinx case IEEE80211_IOC_FF: 1610210502Ssyrinx case IEEE80211_IOC_TURBOP: 1611210502Ssyrinx case IEEE80211_IOC_WPS: 1612210502Ssyrinx case IEEE80211_IOC_BGSCAN: 1613210502Ssyrinx case IEEE80211_IOC_DOTD: 1614210502Ssyrinx case IEEE80211_IOC_DOTH: 1615210502Ssyrinx case IEEE80211_IOC_DWDS: 1616210502Ssyrinx case IEEE80211_IOC_POWERSAVE: 1617210502Ssyrinx case IEEE80211_IOC_APBRIDGE: 1618210502Ssyrinx case IEEE80211_IOC_HIDESSID: 1619210502Ssyrinx case IEEE80211_IOC_INACTIVITY: 1620210502Ssyrinx case IEEE80211_IOC_PUREG: 1621210502Ssyrinx case IEEE80211_IOC_PUREN: 1622210502Ssyrinx case IEEE80211_IOC_HTCONF: 1623210502Ssyrinx case IEEE80211_IOC_HTCOMPAT: 1624210502Ssyrinx case IEEE80211_IOC_RIFS: 1625210502Ssyrinx if (sval == TruthValue_true) 1626210502Ssyrinx *value = 1; 1627210502Ssyrinx else if (sval != TruthValue_false) 1628210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1629210502Ssyrinx break; 1630210502Ssyrinx case IEEE80211_IOC_REGDOMAIN: 1631210502Ssyrinx break; 1632210502Ssyrinx case IEEE80211_IOC_SSID: 1633210502Ssyrinx break; 1634210502Ssyrinx case IEEE80211_IOC_CURCHAN: 1635210502Ssyrinx break; 1636210502Ssyrinx case IEEE80211_IOC_TXPOWER: 1637210502Ssyrinx *value = sval * 2; 1638210502Ssyrinx break; 1639210502Ssyrinx case IEEE80211_IOC_FRAGTHRESHOLD: 1640210502Ssyrinx if (sval < IEEE80211_FRAG_MIN || sval > IEEE80211_FRAG_MAX) 1641210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1642210502Ssyrinx *value = sval; 1643210502Ssyrinx break; 1644210502Ssyrinx case IEEE80211_IOC_RTSTHRESHOLD: 1645210502Ssyrinx if (sval < IEEE80211_RTS_MIN || sval > IEEE80211_RTS_MAX) 1646210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1647210502Ssyrinx *value = sval; 1648210502Ssyrinx break; 1649210502Ssyrinx case IEEE80211_IOC_BGSCAN_IDLE: 1650210502Ssyrinx if (sval < WLAN_BGSCAN_IDLE_MIN) 1651210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1652210502Ssyrinx *value = sval; 1653210502Ssyrinx break; 1654210502Ssyrinx case IEEE80211_IOC_BGSCAN_INTERVAL: 1655210502Ssyrinx if (sval < WLAN_SCAN_VALID_MIN) 1656210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1657210502Ssyrinx *value = sval; 1658210502Ssyrinx break; 1659210502Ssyrinx case IEEE80211_IOC_BMISSTHRESHOLD: 1660210502Ssyrinx if (sval < IEEE80211_HWBMISS_MIN || sval > IEEE80211_HWBMISS_MAX) 1661210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1662210502Ssyrinx *value = sval; 1663210502Ssyrinx break; 1664210502Ssyrinx case IEEE80211_IOC_BSSID: 1665210502Ssyrinx break; 1666210502Ssyrinx case IEEE80211_IOC_ROAMING: 1667210502Ssyrinx switch (sval) { 1668210502Ssyrinx case wlanIfaceRoamingMode_device: 1669210502Ssyrinx *value = IEEE80211_ROAMING_DEVICE; 1670210502Ssyrinx break; 1671210502Ssyrinx case wlanIfaceRoamingMode_manual: 1672210502Ssyrinx *value = IEEE80211_ROAMING_MANUAL; 1673210502Ssyrinx break; 1674210502Ssyrinx case wlanIfaceRoamingMode_auto: 1675210502Ssyrinx *value = IEEE80211_ROAMING_AUTO; 1676210502Ssyrinx break; 1677210502Ssyrinx default: 1678210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1679210502Ssyrinx } 1680210502Ssyrinx break; 1681210502Ssyrinx case IEEE80211_IOC_BEACON_INTERVAL: 1682210502Ssyrinx if (sval < IEEE80211_BINTVAL_MIN || sval > IEEE80211_BINTVAL_MAX) 1683210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1684210502Ssyrinx *value = sval; 1685210502Ssyrinx break; 1686210502Ssyrinx case IEEE80211_IOC_DTIM_PERIOD: 1687210502Ssyrinx if (sval < IEEE80211_DTIM_MIN || sval > IEEE80211_DTIM_MAX) 1688210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1689210502Ssyrinx *value = sval; 1690210502Ssyrinx break; 1691210502Ssyrinx case IEEE80211_IOC_PROTMODE: 1692210502Ssyrinx switch (sval) { 1693210502Ssyrinx case wlanIfaceDot11gProtMode_cts: 1694210502Ssyrinx *value = IEEE80211_PROTMODE_CTS; 1695210502Ssyrinx break; 1696210502Ssyrinx case wlanIfaceDot11gProtMode_rtscts: 1697210502Ssyrinx *value = IEEE80211_PROTMODE_RTSCTS; 1698210502Ssyrinx break; 1699210502Ssyrinx case wlanIfaceDot11gProtMode_off: 1700210502Ssyrinx *value = IEEE80211_PROTMODE_OFF; 1701210502Ssyrinx break; 1702210502Ssyrinx default: 1703210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1704210502Ssyrinx } 1705210502Ssyrinx break; 1706210502Ssyrinx case IEEE80211_IOC_AMPDU: 1707210502Ssyrinx switch (sval) { 1708210502Ssyrinx case WlanIfaceDot11nPduType_disabled: 1709210502Ssyrinx break; 1710210502Ssyrinx case WlanIfaceDot11nPduType_txOnly: 1711210502Ssyrinx *value = 1; 1712210502Ssyrinx break; 1713210502Ssyrinx case WlanIfaceDot11nPduType_rxOnly: 1714210502Ssyrinx *value = 2; 1715210502Ssyrinx break; 1716210502Ssyrinx case WlanIfaceDot11nPduType_txAndRx: 1717210502Ssyrinx *value = 3; 1718210502Ssyrinx break; 1719210502Ssyrinx default: 1720210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1721210502Ssyrinx } 1722210502Ssyrinx break; 1723210502Ssyrinx case IEEE80211_IOC_AMPDU_DENSITY: 1724210502Ssyrinx switch (sval) { 1725210502Ssyrinx case 0: 1726210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_NA; 1727210502Ssyrinx break; 1728210502Ssyrinx case 25: 1729210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_025; 1730210502Ssyrinx break; 1731210502Ssyrinx case 50: 1732210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_05; 1733210502Ssyrinx break; 1734210502Ssyrinx case 100: 1735210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_1; 1736210502Ssyrinx break; 1737210502Ssyrinx case 200: 1738210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_2; 1739210502Ssyrinx break; 1740210502Ssyrinx case 400: 1741210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_4; 1742210502Ssyrinx break; 1743210502Ssyrinx case 800: 1744210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_8; 1745210502Ssyrinx break; 1746210502Ssyrinx case 1600: 1747210502Ssyrinx *value = IEEE80211_HTCAP_MPDUDENSITY_16; 1748210502Ssyrinx break; 1749210502Ssyrinx default: 1750210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1751210502Ssyrinx } 1752210502Ssyrinx break; 1753210502Ssyrinx case IEEE80211_IOC_AMPDU_LIMIT: 1754210502Ssyrinx switch (sval) { 1755210502Ssyrinx case 8192: 1756210502Ssyrinx *value = IEEE80211_HTCAP_MAXRXAMPDU_8K; 1757210502Ssyrinx break; 1758210502Ssyrinx case 16384: 1759210502Ssyrinx *value = IEEE80211_HTCAP_MAXRXAMPDU_16K; 1760210502Ssyrinx break; 1761210502Ssyrinx case 32768: 1762210502Ssyrinx *value = IEEE80211_HTCAP_MAXRXAMPDU_32K; 1763210502Ssyrinx break; 1764210502Ssyrinx case 65536: 1765210502Ssyrinx *value = IEEE80211_HTCAP_MAXRXAMPDU_64K; 1766210502Ssyrinx break; 1767210502Ssyrinx default: 1768210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1769210502Ssyrinx } 1770210502Ssyrinx break; 1771210502Ssyrinx case IEEE80211_IOC_AMSDU: 1772210502Ssyrinx switch (sval) { 1773210502Ssyrinx case WlanIfaceDot11nPduType_disabled: 1774210502Ssyrinx break; 1775210502Ssyrinx case WlanIfaceDot11nPduType_txOnly: 1776210502Ssyrinx *value = 1; 1777210502Ssyrinx break; 1778210502Ssyrinx case WlanIfaceDot11nPduType_rxOnly: 1779210502Ssyrinx *value = 2; 1780210502Ssyrinx break; 1781210502Ssyrinx case WlanIfaceDot11nPduType_txAndRx: 1782210502Ssyrinx *value = 3; 1783210502Ssyrinx break; 1784210502Ssyrinx default: 1785210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1786210502Ssyrinx } 1787210502Ssyrinx break; 1788210502Ssyrinx case IEEE80211_IOC_AMSDU_LIMIT: 1789210502Ssyrinx if (sval == 3839 || sval == 0) 1790210502Ssyrinx *value = IEEE80211_HTCAP_MAXAMSDU_3839; 1791210502Ssyrinx else if (sval == 7935) 1792210502Ssyrinx *value = IEEE80211_HTCAP_MAXAMSDU_7935; 1793210502Ssyrinx else 1794210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1795210502Ssyrinx break; 1796210502Ssyrinx case IEEE80211_IOC_HTPROTMODE: 1797210502Ssyrinx switch (sval) { 1798210502Ssyrinx case wlanIfaceDot11nHTProtMode_rts: 1799210502Ssyrinx *value = IEEE80211_PROTMODE_RTSCTS; 1800210502Ssyrinx break; 1801210502Ssyrinx case wlanIfaceDot11nHTProtMode_off: 1802210502Ssyrinx break; 1803210502Ssyrinx default: 1804210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1805210502Ssyrinx } 1806210502Ssyrinx break; 1807210502Ssyrinx case IEEE80211_IOC_SHORTGI: 1808210502Ssyrinx if (sval == TruthValue_true) 1809210502Ssyrinx *value = IEEE80211_HTCAP_SHORTGI20 | 1810210502Ssyrinx IEEE80211_HTCAP_SHORTGI40; 1811210502Ssyrinx else if (sval != TruthValue_false) 1812210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1813210502Ssyrinx break; 1814210502Ssyrinx case IEEE80211_IOC_SMPS: 1815210502Ssyrinx switch (sval) { 1816210502Ssyrinx case wlanIfaceDot11nSMPSMode_disabled: 1817210502Ssyrinx *value = IEEE80211_HTCAP_SMPS_OFF; 1818210502Ssyrinx break; 1819210502Ssyrinx case wlanIfaceDot11nSMPSMode_static: 1820210502Ssyrinx *value = IEEE80211_HTCAP_SMPS_ENA; 1821210502Ssyrinx break; 1822210502Ssyrinx case wlanIfaceDot11nSMPSMode_dynamic: 1823210502Ssyrinx *value = IEEE80211_HTCAP_SMPS_DYNAMIC; 1824210502Ssyrinx break; 1825210502Ssyrinx default: 1826210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1827210502Ssyrinx } 1828210502Ssyrinx break; 1829210502Ssyrinx case IEEE80211_IOC_TDMA_SLOT: 1830210502Ssyrinx if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */ 1831210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1832210502Ssyrinx *value = sval; 1833210502Ssyrinx break; 1834210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTCNT: 1835210502Ssyrinx if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */ 1836210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1837210502Ssyrinx *value = sval; 1838210502Ssyrinx break; 1839210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTLEN: 1840210502Ssyrinx if (sval < 2*100 || sval > 0xfffff) /* XXX */ 1841210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1842210502Ssyrinx *value = sval; 1843210502Ssyrinx break; 1844210502Ssyrinx case IEEE80211_IOC_TDMA_BINTERVAL: 1845210502Ssyrinx if (sval < 1) /* XXX */ 1846210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1847210502Ssyrinx *value = sval; 1848210502Ssyrinx break; 1849210502Ssyrinx default: 1850210502Ssyrinx return (SNMP_ERR_INCONS_VALUE); 1851210502Ssyrinx } 1852210502Ssyrinx 1853210502Ssyrinx return (SNMP_ERR_NOERROR); 1854210502Ssyrinx} 1855210502Ssyrinx 1856210502Ssyrinx/* 1857210502Ssyrinx * Sanity checks for the wlanIfaceConfigTable. 1858210502Ssyrinx */ 1859210502Ssyrinxstatic int 1860210502Ssyrinxwlan_config_check(struct wlan_iface *wif, int op) 1861210502Ssyrinx{ 1862210502Ssyrinx switch (op) { 1863210502Ssyrinx case IEEE80211_IOC_BURST: 1864210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_burst)) == 0) { 1865210502Ssyrinx wif->packet_burst = TruthValue_false; 1866210502Ssyrinx return (-1); 1867210502Ssyrinx } 1868210502Ssyrinx break; 1869210502Ssyrinx case IEEE80211_IOC_DFS: 1870210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_dfs)) == 0) { 1871210502Ssyrinx wif->dyn_frequency = TruthValue_false; 1872210502Ssyrinx return (-1); 1873210502Ssyrinx } 1874210502Ssyrinx break; 1875210502Ssyrinx case IEEE80211_IOC_FF: 1876210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_athFastFrames)) 1877210502Ssyrinx == 0) { 1878210502Ssyrinx wif->fast_frames = TruthValue_false; 1879210502Ssyrinx return (-1); 1880210502Ssyrinx } 1881210502Ssyrinx break; 1882210502Ssyrinx case IEEE80211_IOC_TURBOP: 1883210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_athTurbo)) == 0) { 1884210502Ssyrinx wif->dturbo = TruthValue_false; 1885210502Ssyrinx return (-1); 1886210502Ssyrinx } 1887210502Ssyrinx break; 1888210502Ssyrinx case IEEE80211_IOC_TXPOWER: 1889210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_txPmgt)) == 0) { 1890210502Ssyrinx wif->tx_power = 0; 1891210502Ssyrinx return (-1); 1892210502Ssyrinx } 1893210502Ssyrinx break; 1894210502Ssyrinx case IEEE80211_IOC_FRAGTHRESHOLD: 1895210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_txFrag)) == 0) { 1896210502Ssyrinx wif->frag_threshold = IEEE80211_FRAG_MAX; 1897210502Ssyrinx return (-1); 1898210502Ssyrinx } 1899210502Ssyrinx break; 1900210502Ssyrinx case IEEE80211_IOC_DWDS: 1901210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_wds)) == 0) { 1902210502Ssyrinx wif->dynamic_wds = TruthValue_false; 1903210502Ssyrinx return (-1); 1904210502Ssyrinx } 1905210502Ssyrinx break; 1906210502Ssyrinx case IEEE80211_IOC_POWERSAVE: 1907210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_pmgt)) == 0) { 1908210502Ssyrinx wif->power_save = TruthValue_false; 1909210502Ssyrinx return (-1); 1910210502Ssyrinx } 1911210502Ssyrinx break; 1912210502Ssyrinx case IEEE80211_IOC_BEACON_INTERVAL: 1913210502Ssyrinx if (wif->mode != WlanIfaceOperatingModeType_hostAp && 1914210502Ssyrinx wif->mode != WlanIfaceOperatingModeType_meshPoint && 1915210502Ssyrinx wif->mode != WlanIfaceOperatingModeType_ibss) { 1916210502Ssyrinx wif->beacon_interval = 100; /* XXX */ 1917210502Ssyrinx return (-1); 1918210502Ssyrinx } 1919210502Ssyrinx break; 1920210502Ssyrinx case IEEE80211_IOC_DTIM_PERIOD: 1921210502Ssyrinx if (wif->mode != WlanIfaceOperatingModeType_hostAp && 1922210502Ssyrinx wif->mode != WlanIfaceOperatingModeType_meshPoint && 1923210502Ssyrinx wif->mode != WlanIfaceOperatingModeType_ibss) { 1924210502Ssyrinx wif->dtim_period = 1; /* XXX */ 1925210502Ssyrinx return (-1); 1926210502Ssyrinx } 1927210502Ssyrinx break; 1928210502Ssyrinx case IEEE80211_IOC_PUREN: 1929210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_htcHt)) == 0) { 1930210502Ssyrinx wif->dot11n_pure = TruthValue_false; 1931210502Ssyrinx return (-1); 1932210502Ssyrinx } 1933210502Ssyrinx break; 1934210502Ssyrinx case IEEE80211_IOC_AMPDU: 1935210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmpdu)) == 0) { 1936210502Ssyrinx wif->ampdu = WlanIfaceDot11nPduType_disabled; 1937210502Ssyrinx return (-1); 1938210502Ssyrinx } 1939210502Ssyrinx break; 1940210502Ssyrinx case IEEE80211_IOC_AMSDU: 1941210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmsdu)) == 0) { 1942210502Ssyrinx wif->amsdu = WlanIfaceDot11nPduType_disabled; 1943210502Ssyrinx return (-1); 1944210502Ssyrinx } 1945210502Ssyrinx break; 1946210502Ssyrinx case IEEE80211_IOC_RIFS: 1947210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_htcRifs)) == 0) { 1948210502Ssyrinx wif->rifs = TruthValue_false; 1949210502Ssyrinx return (-1); 1950210502Ssyrinx } 1951210502Ssyrinx break; 1952210502Ssyrinx case IEEE80211_IOC_SHORTGI: 1953210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_shortGi20 | 1954210502Ssyrinx 0x1 << WlanHTCaps_shortGi40)) == 0) { 1955210502Ssyrinx wif->short_gi = TruthValue_false; 1956210502Ssyrinx return (-1); 1957210502Ssyrinx } 1958210502Ssyrinx break; 1959210502Ssyrinx case IEEE80211_IOC_SMPS: 1960210502Ssyrinx if ((wif->htcaps & (0x1 << WlanHTCaps_htcSmps)) == 0) { 1961210502Ssyrinx wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled; 1962210502Ssyrinx return (-1); 1963210502Ssyrinx } 1964210502Ssyrinx break; 1965210502Ssyrinx case IEEE80211_IOC_TDMA_SLOT: 1966210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1967210502Ssyrinx wif->tdma_slot = 0; 1968210502Ssyrinx return (-1); 1969210502Ssyrinx } 1970210502Ssyrinx break; 1971210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTCNT: 1972210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1973210502Ssyrinx wif->tdma_slot_count = 0; 1974210502Ssyrinx return (-1); 1975210502Ssyrinx } 1976210502Ssyrinx break; 1977210502Ssyrinx case IEEE80211_IOC_TDMA_SLOTLEN: 1978210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1979210502Ssyrinx wif->tdma_slot_length = 0; 1980210502Ssyrinx return (-1); 1981210502Ssyrinx } 1982210502Ssyrinx break; 1983210502Ssyrinx case IEEE80211_IOC_TDMA_BINTERVAL: 1984210502Ssyrinx if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1985210502Ssyrinx wif->tdma_binterval = 0; 1986210502Ssyrinx return (-1); 1987210502Ssyrinx } 1988210502Ssyrinx break; 1989210502Ssyrinx default: 1990210502Ssyrinx break; 1991210502Ssyrinx } 1992210502Ssyrinx 1993210502Ssyrinx return (0); 1994210502Ssyrinx} 1995210502Ssyrinx 1996210502Ssyrinxstatic int 1997210502Ssyrinxwlan_config_get_intval(struct wlan_iface *wif, int op) 1998210502Ssyrinx{ 1999210502Ssyrinx int val = 0; 2000210502Ssyrinx size_t argsize = 0; 2001210502Ssyrinx 2002210502Ssyrinx if (wlan_config_check(wif, op) < 0) 2003210502Ssyrinx return (0); 2004210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0) 2005210502Ssyrinx return (-1); 2006210502Ssyrinx wlan_config_set_snmp_intval(wif, op, val); 2007210502Ssyrinx 2008210502Ssyrinx return (0); 2009210502Ssyrinx} 2010210502Ssyrinx 2011210502Ssyrinxstatic int 2012210502Ssyrinxwlan_config_set_intval(struct wlan_iface *wif, int op, int sval) 2013210502Ssyrinx{ 2014210502Ssyrinx size_t argsize = 0; 2015210502Ssyrinx int val; 2016210502Ssyrinx 2017210502Ssyrinx if (wlan_config_check(wif, op) < 0) 2018210502Ssyrinx return (-1); 2019210502Ssyrinx if (wlan_config_snmp2value(op, sval, &val) != SNMP_ERR_NOERROR) 2020210502Ssyrinx return (-1); 2021210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0) 2022210502Ssyrinx return (-1); 2023210502Ssyrinx wlan_config_set_snmp_intval(wif, op, val); 2024210502Ssyrinx 2025210502Ssyrinx return (0); 2026210502Ssyrinx} 2027210502Ssyrinx 2028210502Ssyrinxint 2029210502Ssyrinxwlan_config_get_ioctl(struct wlan_iface *wif, int which) 2030210502Ssyrinx{ 2031210502Ssyrinx int op; 2032210502Ssyrinx 2033210502Ssyrinx switch (which) { 2034210502Ssyrinx case LEAF_wlanIfaceCountryCode: 2035210502Ssyrinx /* FALLTHROUGH */ 2036210502Ssyrinx case LEAF_wlanIfaceRegDomain: 2037210502Ssyrinx return (wlan_config_get_country(wif)); 2038210502Ssyrinx case LEAF_wlanIfaceDesiredSsid: 2039210502Ssyrinx return (wlan_config_get_dssid(wif)); 2040210502Ssyrinx case LEAF_wlanIfaceDesiredChannel: 2041210502Ssyrinx return (wlan_config_get_dchannel(wif)); 2042210502Ssyrinx case LEAF_wlanIfaceDesiredBssid: 2043210502Ssyrinx return (wlan_config_get_bssid(wif)); 2044210502Ssyrinx default: 2045210502Ssyrinx op = wlan_config_snmp2ioctl(which); 2046210502Ssyrinx return (wlan_config_get_intval(wif, op)); 2047210502Ssyrinx } 2048210502Ssyrinx 2049210502Ssyrinx return (-1); 2050210502Ssyrinx} 2051210502Ssyrinx 2052210502Ssyrinxint 2053210502Ssyrinxwlan_config_set_ioctl(struct wlan_iface *wif, int which, int val, 2054210502Ssyrinx char *strval, int len) 2055210502Ssyrinx{ 2056210502Ssyrinx int op; 2057210502Ssyrinx 2058210502Ssyrinx switch (which) { 2059210502Ssyrinx case LEAF_wlanIfaceCountryCode: 2060210502Ssyrinx return (wlan_config_set_country(wif, strval, 2061210502Ssyrinx wif->reg_domain)); 2062210502Ssyrinx case LEAF_wlanIfaceRegDomain: 2063210502Ssyrinx return (wlan_config_set_country(wif, wif->country_code, 2064210502Ssyrinx val)); 2065210502Ssyrinx case LEAF_wlanIfaceDesiredSsid: 2066210502Ssyrinx return (wlan_config_set_dssid(wif, strval, len)); 2067210502Ssyrinx case LEAF_wlanIfaceDesiredChannel: 2068210502Ssyrinx return (wlan_config_set_dchannel(wif, val)); 2069210502Ssyrinx case LEAF_wlanIfaceDesiredBssid: 2070210502Ssyrinx return (wlan_config_set_bssid(wif, strval)); 2071210502Ssyrinx default: 2072210502Ssyrinx op = wlan_config_snmp2ioctl(which); 2073210502Ssyrinx return (wlan_config_set_intval(wif, op, val)); 2074210502Ssyrinx } 2075210502Ssyrinx 2076210502Ssyrinx return (-1); 2077210502Ssyrinx} 2078210502Ssyrinx 2079210502Ssyrinxstatic uint32_t 2080210502Ssyrinxwlan_snmp_to_scan_flags(int flags) 2081210502Ssyrinx{ 2082210502Ssyrinx int sr_flags = 0; 2083210502Ssyrinx 2084210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_noSelection)) != 0) 2085210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_NOPICK; 2086210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_activeScan)) != 0) 2087210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_ACTIVE; 2088210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_pickFirst)) != 0) 2089210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_PICK1ST; 2090210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_backgroundScan)) != 0) 2091210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_BGSCAN; 2092210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_once)) != 0) 2093210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_ONCE; 2094210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_noBroadcast)) != 0) 2095210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_NOBCAST; 2096210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_noAutoSequencing)) != 0) 2097210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_NOJOIN; 2098210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_flushCashe)) != 0) 2099210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_FLUSH; 2100210502Ssyrinx if ((flags & (0x1 << WlanScanFlagsType_chechCashe)) != 0) 2101210502Ssyrinx sr_flags |= IEEE80211_IOC_SCAN_CHECK; 2102210502Ssyrinx 2103210502Ssyrinx return (sr_flags); 2104210502Ssyrinx} 2105210502Ssyrinx 2106210502Ssyrinxint 2107210502Ssyrinxwlan_set_scan_config(struct wlan_iface *wif) 2108210502Ssyrinx{ 2109210502Ssyrinx int val = 0; 2110210502Ssyrinx size_t argsize; 2111210502Ssyrinx struct ieee80211_scan_req sr; 2112210502Ssyrinx 2113210502Ssyrinx 2114210502Ssyrinx memset(&sr, 0, sizeof(sr)); 2115210502Ssyrinx argsize = sizeof(struct ieee80211_scan_req); 2116210502Ssyrinx sr.sr_flags = wlan_snmp_to_scan_flags(wif->scan_flags); 2117210502Ssyrinx sr.sr_flags |= IEEE80211_IOC_SCAN_BGSCAN; 2118210502Ssyrinx sr.sr_duration = wif->scan_duration; 2119210502Ssyrinx sr.sr_mindwell = wif->scan_mindwell; 2120210502Ssyrinx sr.sr_maxdwell = wif->scan_maxdwell; 2121210502Ssyrinx sr.sr_nssid = 0; 2122210502Ssyrinx 2123210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_REQ, 2124210502Ssyrinx &val, &sr, &argsize, 1) < 0) 2125210502Ssyrinx return (-1); 2126210502Ssyrinx 2127210502Ssyrinx wif->scan_status = wlanScanConfigStatus_running; 2128210502Ssyrinx return (0); 2129210502Ssyrinx} 2130210502Ssyrinx 2131210502Ssyrinxstatic uint32_t 2132210502Ssyrinxwlan_peercaps_to_snmp(uint32_t pcaps) 2133210502Ssyrinx{ 2134210502Ssyrinx uint32_t scaps = 0; 2135210502Ssyrinx 2136210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_ESS) != 0) 2137210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_ess); 2138210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_IBSS) != 0) 2139210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_ibss); 2140210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_CF_POLLABLE) != 0) 2141210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollable); 2142210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_CF_POLLREQ) != 0) 2143210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollRequest); 2144210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_PRIVACY) != 0) 2145210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_privacy); 2146210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_SHORT_PREAMBLE) != 0) 2147210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_shortPreamble); 2148210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_PBCC) != 0) 2149210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_pbcc); 2150210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_CHNL_AGILITY) != 0) 2151210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_channelAgility); 2152210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_SHORT_SLOTTIME) != 0) 2153210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_shortSlotTime); 2154210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_RSN) != 0) 2155210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_rsn); 2156210502Ssyrinx if ((pcaps & IEEE80211_CAPINFO_DSSSOFDM) != 0) 2157210502Ssyrinx scaps |= (0x1 << WlanPeerCapabilityFlags_dsssofdm); 2158210502Ssyrinx 2159210502Ssyrinx return (scaps); 2160210502Ssyrinx} 2161210502Ssyrinx 2162210502Ssyrinxstatic int 2163210502Ssyrinxwlan_add_new_scan_result(struct wlan_iface *wif, 2164210502Ssyrinx const struct ieee80211req_scan_result *isr, uint8_t *ssid) 2165210502Ssyrinx{ 2166210502Ssyrinx struct wlan_scan_result *sr; 2167210502Ssyrinx 2168210502Ssyrinx if ((sr = wlan_scan_new_result(ssid, isr->isr_bssid)) == NULL) 2169210502Ssyrinx return (-1); 2170210502Ssyrinx 2171210502Ssyrinx sr->opchannel = wlan_channel_flags_to_snmp_phy(isr->isr_flags); 2172210502Ssyrinx sr->rssi = isr->isr_rssi; 2173210502Ssyrinx sr->frequency = isr->isr_freq; 2174210502Ssyrinx sr->noise = isr->isr_noise; 2175210502Ssyrinx sr->bintval = isr->isr_intval; 2176210502Ssyrinx sr->capinfo = wlan_peercaps_to_snmp(isr->isr_capinfo); 2177210502Ssyrinx 2178210502Ssyrinx if (wlan_scan_add_result(wif, sr) < 0) { 2179210502Ssyrinx wlan_scan_free_result(sr); 2180210502Ssyrinx return (-1); 2181210502Ssyrinx } 2182210502Ssyrinx 2183210502Ssyrinx return (0); 2184210502Ssyrinx} 2185210502Ssyrinx 2186210502Ssyrinxint 2187210502Ssyrinxwlan_get_scan_results(struct wlan_iface *wif) 2188210502Ssyrinx{ 2189210502Ssyrinx int ssidlen, val = 0; 2190210502Ssyrinx uint8_t buf[24 * 1024]; 2191210502Ssyrinx size_t argsize; 2192210502Ssyrinx const uint8_t *cp, *idp; 2193210502Ssyrinx uint8_t ssid[IEEE80211_NWID_LEN + 1]; 2194210502Ssyrinx struct ieee80211req_scan_result isr; 2195210502Ssyrinx 2196210502Ssyrinx argsize = sizeof(buf); 2197210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_RESULTS, &val, &buf, 2198210502Ssyrinx &argsize, 0) < 0) 2199210502Ssyrinx return (-1); 2200210502Ssyrinx 2201210502Ssyrinx if (argsize < sizeof(struct ieee80211req_scan_result)) 2202210502Ssyrinx return (0); 2203210502Ssyrinx 2204210502Ssyrinx cp = buf; 2205210502Ssyrinx do { 2206210502Ssyrinx memcpy(&isr, cp, sizeof(struct ieee80211req_scan_result)); 2207210502Ssyrinx memset(ssid, 0, IEEE80211_NWID_LEN + 1); 2208210502Ssyrinx 2209210502Ssyrinx if (isr.isr_meshid_len) { 2210210502Ssyrinx idp = cp + isr.isr_ie_off + isr.isr_ssid_len; 2211210502Ssyrinx ssidlen = isr.isr_meshid_len; 2212210502Ssyrinx } else { 2213210502Ssyrinx idp = cp + isr.isr_ie_off; 2214210502Ssyrinx ssidlen = isr.isr_ssid_len; 2215210502Ssyrinx } 2216210502Ssyrinx if (ssidlen > IEEE80211_NWID_LEN) 2217210502Ssyrinx ssidlen = IEEE80211_NWID_LEN; 2218210502Ssyrinx memcpy(ssid, idp, ssidlen); 2219210502Ssyrinx ssid[IEEE80211_NWID_LEN] = '\0'; 2220210502Ssyrinx (void)wlan_add_new_scan_result(wif, &isr, ssid); 2221210502Ssyrinx cp += isr.isr_len; 2222210502Ssyrinx argsize -= isr.isr_len; 2223210502Ssyrinx } while (argsize >= sizeof(struct ieee80211req_scan_result)); 2224210502Ssyrinx 2225210502Ssyrinx return (0); 2226210502Ssyrinx} 2227210502Ssyrinx 2228210502Ssyrinxint 2229210502Ssyrinxwlan_get_stats(struct wlan_iface *wif) 2230210502Ssyrinx{ 2231210502Ssyrinx struct ifreq ifr; 2232210502Ssyrinx 2233210502Ssyrinx memset(&ifr, 0, sizeof(struct ifreq)); 2234210502Ssyrinx strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ); 2235210502Ssyrinx 2236210502Ssyrinx ifr.ifr_data = (caddr_t) &wif->stats; 2237210502Ssyrinx 2238210502Ssyrinx if (ioctl(sock, SIOCG80211STATS, &ifr) < 0) { 2239210502Ssyrinx syslog(LOG_ERR, "iface %s - ioctl(SIOCG80211STATS) failed: %s", 2240210502Ssyrinx wif->wname, strerror(errno)); 2241210502Ssyrinx return (-1); 2242210502Ssyrinx } 2243210502Ssyrinx 2244210502Ssyrinx return (0); 2245210502Ssyrinx} 2246210502Ssyrinx 2247210502Ssyrinxint 2248210502Ssyrinxwlan_get_wepmode(struct wlan_iface *wif) 2249210502Ssyrinx{ 2250210502Ssyrinx int val = 0; 2251210502Ssyrinx size_t argsize = 0; 2252210502Ssyrinx 2253210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL, 2254210502Ssyrinx &argsize, 0) < 0 || val == IEEE80211_WEP_NOSUP) { 2255210502Ssyrinx wif->wepsupported = 0; /* XXX */ 2256210502Ssyrinx wif->wepmode = wlanWepMode_off; 2257210502Ssyrinx wif->weptxkey = 0; 2258210502Ssyrinx return (-1); 2259210502Ssyrinx } 2260210502Ssyrinx 2261210502Ssyrinx wif->wepsupported = 1; 2262210502Ssyrinx 2263210502Ssyrinx switch (val) { 2264210502Ssyrinx case IEEE80211_WEP_ON: 2265210502Ssyrinx wif->wepmode = wlanWepMode_on; 2266210502Ssyrinx break; 2267210502Ssyrinx case IEEE80211_WEP_MIXED: 2268210502Ssyrinx wif->wepmode = wlanWepMode_mixed; 2269210502Ssyrinx break; 2270210502Ssyrinx case IEEE80211_WEP_OFF: 2271210502Ssyrinx /* FALLTHROUGH */ 2272210502Ssyrinx default: 2273210502Ssyrinx wif->wepmode = wlanWepMode_off; 2274210502Ssyrinx break; 2275210502Ssyrinx } 2276210502Ssyrinx 2277210502Ssyrinx return (0); 2278210502Ssyrinx} 2279210502Ssyrinx 2280210502Ssyrinxint 2281210502Ssyrinxwlan_set_wepmode(struct wlan_iface *wif) 2282210502Ssyrinx{ 2283210502Ssyrinx int val; 2284210502Ssyrinx size_t argsize = 0; 2285210502Ssyrinx 2286210502Ssyrinx if (!wif->wepsupported) 2287210502Ssyrinx return (-1); 2288210502Ssyrinx 2289210502Ssyrinx switch (wif->wepmode) { 2290210502Ssyrinx case wlanWepMode_off: 2291210502Ssyrinx val = IEEE80211_WEP_OFF; 2292210502Ssyrinx break; 2293210502Ssyrinx case wlanWepMode_on: 2294210502Ssyrinx val = IEEE80211_WEP_ON; 2295210502Ssyrinx break; 2296210502Ssyrinx case wlanWepMode_mixed: 2297210502Ssyrinx val = IEEE80211_WEP_MIXED; 2298210502Ssyrinx break; 2299210502Ssyrinx default: 2300210502Ssyrinx return (-1); 2301210502Ssyrinx } 2302210502Ssyrinx 2303210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL, 2304210502Ssyrinx &argsize, 1) < 0) 2305210502Ssyrinx return (-1); 2306210502Ssyrinx 2307210502Ssyrinx return (0); 2308210502Ssyrinx} 2309210502Ssyrinx 2310210502Ssyrinxint 2311210502Ssyrinxwlan_get_weptxkey(struct wlan_iface *wif) 2312210502Ssyrinx{ 2313210502Ssyrinx int val; 2314210502Ssyrinx size_t argsize = 0; 2315210502Ssyrinx 2316210502Ssyrinx if (!wif->wepsupported) 2317210502Ssyrinx return (0); 2318210502Ssyrinx 2319210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL, 2320210502Ssyrinx &argsize, 0) < 0) 2321210502Ssyrinx return (-1); 2322210502Ssyrinx 2323210502Ssyrinx if (val == IEEE80211_KEYIX_NONE) 2324210502Ssyrinx wif->weptxkey = 0; 2325210502Ssyrinx else 2326210502Ssyrinx wif->weptxkey = val + 1; 2327210502Ssyrinx 2328210502Ssyrinx return (0); 2329210502Ssyrinx} 2330210502Ssyrinx 2331210502Ssyrinxint 2332210502Ssyrinxwlan_set_weptxkey(struct wlan_iface *wif) 2333210502Ssyrinx{ 2334210502Ssyrinx int val; 2335210502Ssyrinx size_t argsize = 0; 2336210502Ssyrinx 2337210502Ssyrinx if (!wif->wepsupported) 2338210502Ssyrinx return (0); 2339210502Ssyrinx 2340210502Ssyrinx if (wif->weptxkey >= IEEE80211_WEP_NKID) 2341210502Ssyrinx return (-1); 2342210502Ssyrinx 2343210502Ssyrinx if (wif->weptxkey == 0) 2344210502Ssyrinx val = IEEE80211_KEYIX_NONE; 2345210502Ssyrinx else 2346210502Ssyrinx val = wif->weptxkey - 1; 2347210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL, 2348210502Ssyrinx &argsize, 1) < 0) 2349210502Ssyrinx return (-1); 2350210502Ssyrinx 2351210502Ssyrinx return (0); 2352210502Ssyrinx} 2353210502Ssyrinx 2354210502Ssyrinxint 2355210502Ssyrinxwlan_get_wepkeys(struct wlan_iface *wif __unused) 2356210502Ssyrinx{ 2357210502Ssyrinx /* XXX: should they be visible via SNMP */ 2358210502Ssyrinx return (0); 2359210502Ssyrinx} 2360210502Ssyrinx 2361210502Ssyrinxint 2362210502Ssyrinxwlan_set_wepkeys(struct wlan_iface *wif __unused) 2363210502Ssyrinx{ 2364210502Ssyrinx /* XXX: should they be configurable via SNMP */ 2365210502Ssyrinx return (0); 2366210502Ssyrinx} 2367210502Ssyrinx 2368210502Ssyrinxint 2369210502Ssyrinxwlan_get_mac_policy(struct wlan_iface *wif) 2370210502Ssyrinx{ 2371210502Ssyrinx int val = IEEE80211_MACCMD_POLICY; 2372210502Ssyrinx size_t argsize = 0; 2373210502Ssyrinx struct ieee80211req ireq; 2374210502Ssyrinx 2375210502Ssyrinx memset(&ireq, 0, sizeof(struct ieee80211req)); 2376210502Ssyrinx strlcpy(ireq.i_name, wif->wname, IFNAMSIZ); 2377210502Ssyrinx ireq.i_type = IEEE80211_IOC_MACCMD; 2378210502Ssyrinx ireq.i_val = IEEE80211_MACCMD_POLICY; 2379210502Ssyrinx 2380210502Ssyrinx if (ioctl(sock, SIOCG80211, &ireq) < 0) { 2381210502Ssyrinx if (errno != EINVAL) { 2382210502Ssyrinx syslog(LOG_ERR, "iface %s - get param: ioctl(%d) " 2383210502Ssyrinx "failed: %s", wif->wname, ireq.i_type, 2384210502Ssyrinx strerror(errno)); 2385210502Ssyrinx wif->macsupported = 0; 2386210502Ssyrinx return (-1); 2387210502Ssyrinx } else { 2388210502Ssyrinx wif->macsupported = 1; 2389210502Ssyrinx wif->mac_policy = wlanMACAccessControlPolicy_open; 2390210502Ssyrinx return (0); 2391210502Ssyrinx } 2392310901Sngie 2393210502Ssyrinx } 2394210502Ssyrinx 2395210502Ssyrinx wif->macsupported = 1; 2396210502Ssyrinx 2397210502Ssyrinx switch (val) { 2398210502Ssyrinx case IEEE80211_MACCMD_POLICY_ALLOW: 2399210502Ssyrinx wif->mac_policy = wlanMACAccessControlPolicy_allow; 2400210502Ssyrinx break; 2401210502Ssyrinx case IEEE80211_MACCMD_POLICY_DENY: 2402210502Ssyrinx wif->mac_policy = wlanMACAccessControlPolicy_deny; 2403210502Ssyrinx break; 2404210502Ssyrinx case IEEE80211_MACCMD_POLICY_RADIUS: 2405210502Ssyrinx wif->mac_policy = wlanMACAccessControlPolicy_radius; 2406210502Ssyrinx break; 2407210502Ssyrinx case IEEE80211_MACCMD_POLICY_OPEN: 2408210502Ssyrinx /* FALLTHROUGH */ 2409210502Ssyrinx default: 2410210502Ssyrinx wif->mac_policy = wlanMACAccessControlPolicy_open; 2411210502Ssyrinx break; 2412210502Ssyrinx } 2413210502Ssyrinx 2414210502Ssyrinx argsize = 0; 2415210502Ssyrinx val = IEEE80211_MACCMD_LIST; 2416210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2417210502Ssyrinx &argsize, 0) < 0) 2418210502Ssyrinx return (-1); 2419210502Ssyrinx 2420210502Ssyrinx wif->mac_nacls = argsize / sizeof(struct ieee80211req_maclist *); 2421210502Ssyrinx return (0); 2422210502Ssyrinx} 2423210502Ssyrinx 2424210502Ssyrinxint 2425210502Ssyrinxwlan_set_mac_policy(struct wlan_iface *wif) 2426210502Ssyrinx{ 2427210502Ssyrinx int val; 2428210502Ssyrinx size_t argsize = 0; 2429210502Ssyrinx 2430210502Ssyrinx if (!wif->macsupported) 2431210502Ssyrinx return (-1); 2432210502Ssyrinx 2433210502Ssyrinx switch (wif->mac_policy) { 2434210502Ssyrinx case wlanMACAccessControlPolicy_allow: 2435210502Ssyrinx val = IEEE80211_MACCMD_POLICY_ALLOW; 2436210502Ssyrinx break; 2437210502Ssyrinx case wlanMACAccessControlPolicy_deny: 2438210502Ssyrinx val = IEEE80211_MACCMD_POLICY_DENY; 2439210502Ssyrinx break; 2440210502Ssyrinx case wlanMACAccessControlPolicy_radius: 2441210502Ssyrinx val = IEEE80211_MACCMD_POLICY_RADIUS; 2442210502Ssyrinx break; 2443210502Ssyrinx case wlanMACAccessControlPolicy_open: 2444210502Ssyrinx val = IEEE80211_MACCMD_POLICY_OPEN; 2445210502Ssyrinx break; 2446210502Ssyrinx default: 2447210502Ssyrinx return (-1); 2448210502Ssyrinx } 2449210502Ssyrinx 2450210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2451210502Ssyrinx &argsize, 1) < 0) 2452210502Ssyrinx return (-1); 2453210502Ssyrinx 2454210502Ssyrinx return (0); 2455210502Ssyrinx} 2456210502Ssyrinx 2457210502Ssyrinxint 2458210502Ssyrinxwlan_flush_mac_mac(struct wlan_iface *wif) 2459210502Ssyrinx{ 2460210502Ssyrinx int val = IEEE80211_MACCMD_FLUSH; 2461210502Ssyrinx size_t argsize = 0; 2462210502Ssyrinx 2463210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2464210502Ssyrinx &argsize, 1) < 0) 2465210502Ssyrinx return (-1); 2466210502Ssyrinx 2467210502Ssyrinx return (0); 2468210502Ssyrinx} 2469210502Ssyrinx 2470210502Ssyrinxstatic int 2471210502Ssyrinxwlan_add_mac_macinfo(struct wlan_iface *wif, 2472210502Ssyrinx const struct ieee80211req_maclist *ml) 2473210502Ssyrinx{ 2474210502Ssyrinx struct wlan_mac_mac *mmac; 2475210502Ssyrinx 2476210502Ssyrinx if ((mmac = wlan_mac_new_mac(ml->ml_macaddr)) == NULL) 2477210502Ssyrinx return (-1); 2478210502Ssyrinx 2479210502Ssyrinx mmac->mac_status = RowStatus_active; 2480210502Ssyrinx if (wlan_mac_add_mac(wif, mmac) < 0) { 2481210502Ssyrinx wlan_mac_free_mac(mmac); 2482210502Ssyrinx return (-1); 2483210502Ssyrinx } 2484210502Ssyrinx 2485210502Ssyrinx return (0); 2486210502Ssyrinx} 2487210502Ssyrinx 2488210502Ssyrinxint 2489210502Ssyrinxwlan_get_mac_acl_macs(struct wlan_iface *wif) 2490210502Ssyrinx{ 2491210502Ssyrinx int i, nacls, val = IEEE80211_MACCMD_LIST; 2492210502Ssyrinx size_t argsize = 0; 2493210502Ssyrinx uint8_t *data; 2494210502Ssyrinx struct ieee80211req ireq; 2495210502Ssyrinx const struct ieee80211req_maclist *acllist; 2496210502Ssyrinx 2497210502Ssyrinx if (wif->mac_policy == wlanMACAccessControlPolicy_radius) { 2498210502Ssyrinx wif->mac_nacls = 0; 2499210502Ssyrinx return (0); 2500210502Ssyrinx } 2501210502Ssyrinx 2502210502Ssyrinx memset(&ireq, 0, sizeof(struct ieee80211req)); 2503210502Ssyrinx strlcpy(ireq.i_name, wif->wname, IFNAMSIZ); 2504210502Ssyrinx ireq.i_type = IEEE80211_IOC_MACCMD; 2505210502Ssyrinx ireq.i_val = IEEE80211_MACCMD_LIST; 2506210502Ssyrinx 2507210502Ssyrinx 2508210502Ssyrinx if (ioctl(sock, SIOCG80211, &ireq) < 0) { 2509210502Ssyrinx if (errno != EINVAL) { 2510210502Ssyrinx syslog(LOG_ERR, "iface %s - get param: ioctl(%d) " 2511210502Ssyrinx "failed: %s", wif->wname, ireq.i_type, 2512210502Ssyrinx strerror(errno)); 2513210502Ssyrinx wif->macsupported = 0; 2514210502Ssyrinx return (-1); 2515210502Ssyrinx } 2516210502Ssyrinx } 2517210502Ssyrinx 2518210502Ssyrinx if (argsize == 0) { 2519210502Ssyrinx wif->mac_nacls = 0; 2520210502Ssyrinx return (0); 2521210502Ssyrinx } 2522210502Ssyrinx 2523210502Ssyrinx if ((data = (uint8_t *)malloc(argsize)) == NULL) 2524210502Ssyrinx return (-1); 2525210502Ssyrinx 2526210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, data, 2527210502Ssyrinx &argsize, 0) < 0) 2528210502Ssyrinx return (-1); 2529210502Ssyrinx 2530210502Ssyrinx nacls = argsize / sizeof(*acllist); 2531210502Ssyrinx acllist = (struct ieee80211req_maclist *) data; 2532210502Ssyrinx for (i = 0; i < nacls; i++) 2533210502Ssyrinx (void)wlan_add_mac_macinfo(wif, acllist + i); 2534210502Ssyrinx 2535210502Ssyrinx wif->mac_nacls = nacls; 2536210502Ssyrinx return (0); 2537210502Ssyrinx} 2538210502Ssyrinx 2539210502Ssyrinxint 2540210502Ssyrinxwlan_add_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac) 2541210502Ssyrinx{ 2542210502Ssyrinx int val = 0; 2543210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 2544210502Ssyrinx struct ieee80211req_mlme mlme; 2545210502Ssyrinx 2546210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_ADDMAC, &val, 2547210502Ssyrinx mmac->mac, &argsize, 1) < 0) 2548210502Ssyrinx return (-1); 2549210502Ssyrinx 2550210502Ssyrinx mmac->mac_status = RowStatus_active; 2551210502Ssyrinx 2552210502Ssyrinx /* If policy is deny, try to kick the station just in case. */ 2553210502Ssyrinx if (wif->mac_policy != wlanMACAccessControlPolicy_deny) 2554210502Ssyrinx return (0); 2555210502Ssyrinx 2556210502Ssyrinx memset(&mlme, 0, sizeof(mlme)); 2557210502Ssyrinx mlme.im_op = IEEE80211_MLME_DEAUTH; 2558210502Ssyrinx mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 2559210502Ssyrinx memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN); 2560210502Ssyrinx argsize = sizeof(struct ieee80211req_mlme); 2561210502Ssyrinx 2562210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme, 2563210502Ssyrinx &argsize, 1) < 0 && errno != ENOENT) 2564210502Ssyrinx return (-1); 2565210502Ssyrinx 2566210502Ssyrinx return (0); 2567210502Ssyrinx} 2568210502Ssyrinx 2569210502Ssyrinxint 2570210502Ssyrinxwlan_del_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac) 2571210502Ssyrinx{ 2572210502Ssyrinx int val = 0; 2573210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 2574210502Ssyrinx struct ieee80211req_mlme mlme; 2575210502Ssyrinx 2576210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_DELMAC, &val, 2577210502Ssyrinx mmac->mac, &argsize, 1) < 0) 2578210502Ssyrinx return (-1); 2579210502Ssyrinx 2580210502Ssyrinx mmac->mac_status = RowStatus_active; 2581210502Ssyrinx 2582210502Ssyrinx /* If policy is allow, try to kick the station just in case. */ 2583210502Ssyrinx if (wif->mac_policy != wlanMACAccessControlPolicy_allow) 2584210502Ssyrinx return (0); 2585210502Ssyrinx 2586210502Ssyrinx memset(&mlme, 0, sizeof(mlme)); 2587210502Ssyrinx mlme.im_op = IEEE80211_MLME_DEAUTH; 2588210502Ssyrinx mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 2589210502Ssyrinx memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN); 2590210502Ssyrinx argsize = sizeof(struct ieee80211req_mlme); 2591210502Ssyrinx 2592210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme, 2593210502Ssyrinx &argsize, 1) < 0 && errno != ENOENT) 2594210502Ssyrinx return (-1); 2595210502Ssyrinx 2596210502Ssyrinx return (0); 2597210502Ssyrinx} 2598210502Ssyrinx 2599210502Ssyrinxint 2600210502Ssyrinxwlan_peer_set_vlan(struct wlan_iface *wif, struct wlan_peer *wip, int vlan) 2601210502Ssyrinx{ 2602210502Ssyrinx int val = 0; 2603210502Ssyrinx size_t argsize; 2604210502Ssyrinx struct ieee80211req_sta_vlan vreq; 2605210502Ssyrinx 2606210502Ssyrinx memcpy(vreq.sv_macaddr, wip->pmac, IEEE80211_ADDR_LEN); 2607210502Ssyrinx vreq.sv_vlan = vlan; 2608210502Ssyrinx argsize = sizeof(struct ieee80211req_sta_vlan); 2609210502Ssyrinx 2610210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_VLAN, 2611210502Ssyrinx &val, &vreq, &argsize, 1) < 0) 2612210502Ssyrinx return (-1); 2613210502Ssyrinx 2614210502Ssyrinx wip->vlan = vlan; 2615210502Ssyrinx 2616210502Ssyrinx return (0); 2617210502Ssyrinx} 2618210502Ssyrinx 2619210502Ssyrinx/* XXX */ 2620210502Ssyrinx#ifndef IEEE80211_NODE_AUTH 2621210502Ssyrinx#define IEEE80211_NODE_AUTH 0x000001 /* authorized for data */ 2622210502Ssyrinx#define IEEE80211_NODE_QOS 0x000002 /* QoS enabled */ 2623210502Ssyrinx#define IEEE80211_NODE_ERP 0x000004 /* ERP enabled */ 2624210502Ssyrinx#define IEEE80211_NODE_PWR_MGT 0x000010 /* power save mode enabled */ 2625210502Ssyrinx#define IEEE80211_NODE_AREF 0x000020 /* authentication ref held */ 2626210502Ssyrinx#define IEEE80211_NODE_HT 0x000040 /* HT enabled */ 2627210502Ssyrinx#define IEEE80211_NODE_HTCOMPAT 0x000080 /* HT setup w/ vendor OUI's */ 2628210502Ssyrinx#define IEEE80211_NODE_WPS 0x000100 /* WPS association */ 2629210502Ssyrinx#define IEEE80211_NODE_TSN 0x000200 /* TSN association */ 2630210502Ssyrinx#define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */ 2631210502Ssyrinx#define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */ 2632210502Ssyrinx#define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */ 2633210502Ssyrinx#define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */ 2634210502Ssyrinx#define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */ 2635210502Ssyrinx#define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */ 2636210502Ssyrinx#define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */ 2637210502Ssyrinx#define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */ 2638210502Ssyrinx#define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */ 2639210502Ssyrinx#define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */ 2640210502Ssyrinx#endif 2641210502Ssyrinx 2642210502Ssyrinxstatic uint32_t 2643210502Ssyrinxwlan_peerstate_to_snmp(uint32_t pstate) 2644210502Ssyrinx{ 2645210502Ssyrinx uint32_t sstate = 0; 2646210502Ssyrinx 2647210502Ssyrinx if ((pstate & IEEE80211_NODE_AUTH) != 0) 2648210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_authorizedForData); 2649210502Ssyrinx if ((pstate & IEEE80211_NODE_QOS) != 0) 2650210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_qosEnabled); 2651210502Ssyrinx if ((pstate & IEEE80211_NODE_ERP) != 0) 2652210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_erpEnabled); 2653210502Ssyrinx if ((pstate & IEEE80211_NODE_PWR_MGT) != 0) 2654210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_powerSaveMode); 2655210502Ssyrinx if ((pstate & IEEE80211_NODE_AREF) != 0) 2656210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_authRefHeld); 2657210502Ssyrinx if ((pstate & IEEE80211_NODE_HT) != 0) 2658210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_htEnabled); 2659210502Ssyrinx if ((pstate & IEEE80211_NODE_HTCOMPAT) != 0) 2660210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_htCompat); 2661210502Ssyrinx if ((pstate & IEEE80211_NODE_WPS) != 0) 2662210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_wpsAssoc); 2663210502Ssyrinx if ((pstate & IEEE80211_NODE_TSN) != 0) 2664210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_tsnAssoc); 2665210502Ssyrinx if ((pstate & IEEE80211_NODE_AMPDU_RX) != 0) 2666210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_ampduRx); 2667210502Ssyrinx if ((pstate & IEEE80211_NODE_AMPDU_TX) != 0) 2668210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_ampduTx); 2669210502Ssyrinx if ((pstate & IEEE80211_NODE_MIMO_PS) != 0) 2670210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_mimoPowerSave); 2671210502Ssyrinx if ((pstate & IEEE80211_NODE_MIMO_RTS) != 0) 2672210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_sendRts); 2673210502Ssyrinx if ((pstate & IEEE80211_NODE_RIFS) != 0) 2674210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_rifs); 2675210502Ssyrinx if ((pstate & IEEE80211_NODE_SGI20) != 0) 2676210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT20); 2677210502Ssyrinx if ((pstate & IEEE80211_NODE_SGI40) != 0) 2678210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT40); 2679210502Ssyrinx if ((pstate & IEEE80211_NODE_AMSDU_RX) != 0) 2680210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_amsduRx); 2681210502Ssyrinx if ((pstate & IEEE80211_NODE_AMSDU_TX) != 0) 2682210502Ssyrinx sstate |= (0x1 << WlanIfacePeerFlagsType_amsduTx); 2683210502Ssyrinx 2684210502Ssyrinx return (sstate); 2685210502Ssyrinx} 2686210502Ssyrinx 2687210502Ssyrinxstatic struct wlan_peer * 2688210502Ssyrinxwlan_add_peerinfo(const struct ieee80211req_sta_info *si) 2689210502Ssyrinx{ 2690210502Ssyrinx struct wlan_peer *wip; 2691210502Ssyrinx 2692210502Ssyrinx if ((wip = wlan_new_peer(si->isi_macaddr))== NULL) 2693210502Ssyrinx return (NULL); 2694210502Ssyrinx 2695210502Ssyrinx wip->associd = IEEE80211_AID(si->isi_associd); 2696210502Ssyrinx wip->vlan = si->isi_vlan; 2697210502Ssyrinx wip->frequency = si->isi_freq; 2698210502Ssyrinx wip->fflags = si->isi_flags; 2699210502Ssyrinx wip->txrate = si->isi_txrate; 2700210502Ssyrinx wip->rssi = si->isi_rssi; 2701210502Ssyrinx wip->idle = si->isi_inact; 2702210502Ssyrinx wip->txseqs = si->isi_txseqs[0]; /* XXX */ 2703210502Ssyrinx wip->rxseqs = si->isi_rxseqs[0]; /* XXX */ 2704210502Ssyrinx wip->txpower = si->isi_txpower; 2705210502Ssyrinx wip->capinfo = wlan_peercaps_to_snmp(si->isi_capinfo); 2706210502Ssyrinx wip->state = wlan_peerstate_to_snmp(si->isi_state); 2707210502Ssyrinx wip->local_id = si->isi_localid; 2708210502Ssyrinx wip->peer_id = si->isi_peerid; 2709210502Ssyrinx 2710210502Ssyrinx return (wip); 2711210502Ssyrinx} 2712210502Ssyrinx 2713210502Ssyrinxint 2714210502Ssyrinxwlan_get_peerinfo(struct wlan_iface *wif) 2715210502Ssyrinx{ 2716210502Ssyrinx union { 2717210502Ssyrinx struct ieee80211req_sta_req req; 2718210502Ssyrinx uint8_t buf[24 * 1024]; 2719210502Ssyrinx } u; 2720210502Ssyrinx const uint8_t *cp; 2721210502Ssyrinx int val = 0; 2722210502Ssyrinx size_t len; 2723210502Ssyrinx struct ieee80211req_sta_info si; 2724210502Ssyrinx struct wlan_peer *wip; 2725210502Ssyrinx 2726210502Ssyrinx /* Get all stations - broadcast address */ 2727210502Ssyrinx (void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN); 2728210502Ssyrinx len = sizeof(u); 2729210502Ssyrinx 2730210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_INFO, 2731210502Ssyrinx & val, &u, &len, 0) < 0) 2732210502Ssyrinx return (-1); 2733210502Ssyrinx 2734210502Ssyrinx if (len < sizeof(struct ieee80211req_sta_info)) 2735210502Ssyrinx return (-1); 2736210502Ssyrinx 2737210502Ssyrinx cp = (const uint8_t *) u.req.info; 2738210502Ssyrinx do { 2739210502Ssyrinx memcpy(&si, cp, sizeof(struct ieee80211req_sta_info)); 2740210502Ssyrinx if ((wip = wlan_add_peerinfo(&si)) != NULL && 2741210502Ssyrinx wlan_add_peer(wif, wip) < 0) 2742210502Ssyrinx wlan_free_peer(wip); 2743210502Ssyrinx cp += si.isi_len, len -= si.isi_len; 2744210502Ssyrinx } while (len >= sizeof(struct ieee80211req_sta_info)); 2745210502Ssyrinx 2746210502Ssyrinx return (0); 2747210502Ssyrinx} 2748210502Ssyrinx 2749210502Ssyrinx/************************************************************************ 2750210502Ssyrinx * Wireless MESH & HWMP sysctl config. 2751210502Ssyrinx */ 2752210502Ssyrinxconst char wlan_sysctl_name[] = "net.wlan."; 2753210502Ssyrinx 2754210502Ssyrinxstatic const char *wlan_sysctl[] = { 2755210502Ssyrinx "mesh.retrytimeout", 2756210502Ssyrinx "mesh.holdingtimeout", 2757210502Ssyrinx "mesh.confirmtimeout", 2758210502Ssyrinx "mesh.maxretries", 2759210502Ssyrinx "hwmp.targetonly", 2760210502Ssyrinx "hwmp.replyforward", 2761210502Ssyrinx "hwmp.pathlifetime", 2762210502Ssyrinx "hwmp.roottimeout", 2763210502Ssyrinx "hwmp.rootint", 2764210502Ssyrinx "hwmp.rannint", 2765210502Ssyrinx "hwmp.inact", 2766210502Ssyrinx}; 2767210502Ssyrinx 2768210502Ssyrinxint32_t 2769210502Ssyrinxwlan_do_sysctl(struct wlan_config *cfg, enum wlan_syscl which, int set) 2770210502Ssyrinx{ 2771210502Ssyrinx char mib_name[100]; 2772210502Ssyrinx int val, sval; 2773210502Ssyrinx size_t len, vlen; 2774210502Ssyrinx 2775210502Ssyrinx if (set) { 2776210502Ssyrinx vlen = sizeof(sval); 2777210502Ssyrinx switch (which) { 2778210502Ssyrinx case WLAN_MESH_RETRY_TO: 2779210502Ssyrinx sval = cfg->mesh_retryto; 2780210502Ssyrinx break; 2781210502Ssyrinx case WLAN_MESH_HOLDING_TO: 2782210502Ssyrinx sval = cfg->mesh_holdingto; 2783210502Ssyrinx break; 2784210502Ssyrinx case WLAN_MESH_CONFIRM_TO: 2785210502Ssyrinx sval = cfg->mesh_confirmto; 2786210502Ssyrinx break; 2787210502Ssyrinx case WLAN_MESH_MAX_RETRIES: 2788210502Ssyrinx sval = cfg->mesh_maxretries; 2789210502Ssyrinx break; 2790210502Ssyrinx case WLAN_HWMP_TARGET_ONLY: 2791210502Ssyrinx sval = cfg->hwmp_targetonly; 2792210502Ssyrinx break; 2793210502Ssyrinx case WLAN_HWMP_REPLY_FORWARD: 2794210502Ssyrinx sval = cfg->hwmp_replyforward; 2795210502Ssyrinx break; 2796210502Ssyrinx case WLAN_HWMP_PATH_LIFETIME: 2797210502Ssyrinx sval = cfg->hwmp_pathlifetime; 2798210502Ssyrinx break; 2799210502Ssyrinx case WLAN_HWMP_ROOT_TO: 2800210502Ssyrinx sval = cfg->hwmp_roottimeout; 2801210502Ssyrinx break; 2802210502Ssyrinx case WLAN_HWMP_ROOT_INT: 2803210502Ssyrinx sval = cfg->hwmp_rootint; 2804210502Ssyrinx break; 2805210502Ssyrinx case WLAN_HWMP_RANN_INT: 2806210502Ssyrinx sval = cfg->hwmp_rannint; 2807210502Ssyrinx break; 2808210502Ssyrinx case WLAN_HWMP_INACTIVITY_TO: 2809210502Ssyrinx sval = cfg->hwmp_inact; 2810210502Ssyrinx break; 2811210502Ssyrinx default: 2812210502Ssyrinx return (-1); 2813210502Ssyrinx } 2814210502Ssyrinx } else { 2815210502Ssyrinx if (which >= WLAN_SYSCTL_MAX) 2816210502Ssyrinx return (-1); 2817210502Ssyrinx vlen = 0; 2818210502Ssyrinx } 2819210502Ssyrinx 2820210502Ssyrinx strlcpy(mib_name, wlan_sysctl_name, sizeof(mib_name)); 2821210502Ssyrinx strlcat(mib_name, wlan_sysctl[which], sizeof(mib_name)); 2822210502Ssyrinx len = sizeof (val); 2823210502Ssyrinx 2824210502Ssyrinx if (sysctlbyname(mib_name, &val, &len, (set? &sval : NULL), vlen) < 0) { 2825210502Ssyrinx syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_name, 2826210502Ssyrinx strerror(errno)); 2827210502Ssyrinx return (-1); 2828210502Ssyrinx } 2829210502Ssyrinx 2830210502Ssyrinx switch (which) { 2831210502Ssyrinx case WLAN_MESH_RETRY_TO: 2832210502Ssyrinx cfg->mesh_retryto = val; 2833210502Ssyrinx break; 2834210502Ssyrinx case WLAN_MESH_HOLDING_TO: 2835210502Ssyrinx cfg->mesh_holdingto = val; 2836210502Ssyrinx break; 2837210502Ssyrinx case WLAN_MESH_CONFIRM_TO: 2838210502Ssyrinx cfg->mesh_confirmto = val; 2839210502Ssyrinx break; 2840210502Ssyrinx case WLAN_MESH_MAX_RETRIES: 2841210502Ssyrinx cfg->mesh_maxretries = val; 2842210502Ssyrinx break; 2843210502Ssyrinx case WLAN_HWMP_TARGET_ONLY: 2844210502Ssyrinx cfg->hwmp_targetonly = val; 2845210502Ssyrinx break; 2846210502Ssyrinx case WLAN_HWMP_REPLY_FORWARD: 2847210502Ssyrinx cfg->hwmp_replyforward = val; 2848210502Ssyrinx break; 2849210502Ssyrinx case WLAN_HWMP_PATH_LIFETIME: 2850210502Ssyrinx cfg->hwmp_pathlifetime = val; 2851210502Ssyrinx break; 2852210502Ssyrinx case WLAN_HWMP_ROOT_TO: 2853210502Ssyrinx cfg->hwmp_roottimeout = val; 2854210502Ssyrinx break; 2855210502Ssyrinx case WLAN_HWMP_ROOT_INT: 2856210502Ssyrinx cfg->hwmp_rootint = val; 2857210502Ssyrinx break; 2858210502Ssyrinx case WLAN_HWMP_RANN_INT: 2859210502Ssyrinx cfg->hwmp_rannint = val; 2860210502Ssyrinx break; 2861210502Ssyrinx case WLAN_HWMP_INACTIVITY_TO: 2862210502Ssyrinx cfg->hwmp_inact = val; 2863210502Ssyrinx break; 2864210502Ssyrinx default: 2865210502Ssyrinx /* NOTREACHED */ 2866210502Ssyrinx abort(); 2867210502Ssyrinx } 2868210502Ssyrinx 2869210502Ssyrinx return (0); 2870210502Ssyrinx} 2871210502Ssyrinx 2872210502Ssyrinxint 2873210502Ssyrinxwlan_mesh_config_get(struct wlan_iface *wif, int which) 2874210502Ssyrinx{ 2875210502Ssyrinx int op, val = 0; 2876210502Ssyrinx size_t argsize = 0; 2877210502Ssyrinx uint8_t data[32], *pd = NULL; 2878210502Ssyrinx 2879210502Ssyrinx switch (which) { 2880210502Ssyrinx case LEAF_wlanMeshTTL: 2881210502Ssyrinx op = IEEE80211_IOC_MESH_TTL; 2882210502Ssyrinx break; 2883210502Ssyrinx case LEAF_wlanMeshPeeringEnabled: 2884210502Ssyrinx op = IEEE80211_IOC_MESH_AP; 2885210502Ssyrinx break; 2886210502Ssyrinx case LEAF_wlanMeshForwardingEnabled: 2887210502Ssyrinx op = IEEE80211_IOC_MESH_FWRD; 2888210502Ssyrinx break; 2889210502Ssyrinx case LEAF_wlanMeshMetric: 2890210502Ssyrinx op = IEEE80211_IOC_MESH_PR_METRIC; 2891210502Ssyrinx pd = data; 2892210502Ssyrinx argsize = sizeof(data); 2893210502Ssyrinx break; 2894210502Ssyrinx case LEAF_wlanMeshPath: 2895210502Ssyrinx op = IEEE80211_IOC_MESH_PR_PATH; 2896210502Ssyrinx pd = data; 2897210502Ssyrinx argsize = sizeof(data); 2898210502Ssyrinx break; 2899210502Ssyrinx case LEAF_wlanMeshRoutesFlush: 2900210502Ssyrinx return (0); 2901210502Ssyrinx default: 2902210502Ssyrinx return (-1); 2903210502Ssyrinx } 2904210502Ssyrinx 2905210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 0) < 0) 2906210502Ssyrinx return (-1); 2907210502Ssyrinx 2908210502Ssyrinx switch (which) { 2909210502Ssyrinx case LEAF_wlanMeshTTL: 2910210502Ssyrinx wif->mesh_ttl = val; 2911210502Ssyrinx break; 2912210502Ssyrinx case LEAF_wlanMeshPeeringEnabled: 2913210502Ssyrinx if (val) 2914210502Ssyrinx wif->mesh_peering = wlanMeshPeeringEnabled_true; 2915210502Ssyrinx else 2916210502Ssyrinx wif->mesh_peering = wlanMeshPeeringEnabled_false; 2917210502Ssyrinx break; 2918210502Ssyrinx case LEAF_wlanMeshForwardingEnabled: 2919210502Ssyrinx if (val) 2920210502Ssyrinx wif->mesh_forwarding = wlanMeshForwardingEnabled_true; 2921210502Ssyrinx else 2922210502Ssyrinx wif->mesh_forwarding = wlanMeshForwardingEnabled_false; 2923210502Ssyrinx break; 2924210502Ssyrinx case LEAF_wlanMeshMetric: 2925210502Ssyrinx data[argsize] = '\0'; 2926210502Ssyrinx if (strcmp(data, "AIRTIME") == 0) 2927210502Ssyrinx wif->mesh_metric = wlanMeshMetric_airtime; 2928210502Ssyrinx else 2929210502Ssyrinx wif->mesh_metric = wlanMeshMetric_unknown; 2930210502Ssyrinx break; 2931210502Ssyrinx case LEAF_wlanMeshPath: 2932210502Ssyrinx data[argsize] = '\0'; 2933210502Ssyrinx if (strcmp(data, "HWMP") == 0) 2934210502Ssyrinx wif->mesh_path = wlanMeshPath_hwmp; 2935210502Ssyrinx else 2936210502Ssyrinx wif->mesh_path = wlanMeshPath_unknown; 2937210502Ssyrinx } 2938210502Ssyrinx 2939210502Ssyrinx return (0); 2940210502Ssyrinx} 2941210502Ssyrinx 2942210502Ssyrinxint 2943210502Ssyrinxwlan_mesh_config_set(struct wlan_iface *wif, int which) 2944210502Ssyrinx{ 2945210502Ssyrinx int op, val = 0; 2946210502Ssyrinx size_t argsize = 0; 2947210502Ssyrinx uint8_t data[32], *pd = NULL; 2948210502Ssyrinx 2949210502Ssyrinx switch (which) { 2950210502Ssyrinx case LEAF_wlanMeshTTL: 2951210502Ssyrinx op = IEEE80211_IOC_MESH_TTL; 2952210502Ssyrinx val = wif->mesh_ttl; 2953210502Ssyrinx break; 2954210502Ssyrinx case LEAF_wlanMeshPeeringEnabled: 2955210502Ssyrinx op = IEEE80211_IOC_MESH_AP; 2956210502Ssyrinx if (wif->mesh_peering == wlanMeshPeeringEnabled_true) 2957210502Ssyrinx val = 1; 2958210502Ssyrinx break; 2959210502Ssyrinx case LEAF_wlanMeshForwardingEnabled: 2960210502Ssyrinx if (wif->mesh_forwarding == wlanMeshForwardingEnabled_true) 2961210502Ssyrinx val = 1; 2962210502Ssyrinx op = IEEE80211_IOC_MESH_FWRD; 2963210502Ssyrinx break; 2964210502Ssyrinx case LEAF_wlanMeshMetric: 2965210502Ssyrinx op = IEEE80211_IOC_MESH_PR_METRIC; 2966210502Ssyrinx if (wif->mesh_metric == wlanMeshMetric_airtime) 2967210502Ssyrinx strcpy(data, "AIRTIME"); 2968210502Ssyrinx else 2969210502Ssyrinx return (-1); 2970210502Ssyrinx pd = data; 2971210502Ssyrinx argsize = sizeof(data); 2972210502Ssyrinx break; 2973210502Ssyrinx case LEAF_wlanMeshPath: 2974210502Ssyrinx op = IEEE80211_IOC_MESH_PR_PATH; 2975210502Ssyrinx if (wif->mesh_path == wlanMeshPath_hwmp) 2976210502Ssyrinx strcpy(data, "HWMP"); 2977210502Ssyrinx else 2978210502Ssyrinx return (-1); 2979210502Ssyrinx pd = data; 2980210502Ssyrinx argsize = sizeof(data); 2981210502Ssyrinx break; 2982210502Ssyrinx default: 2983210502Ssyrinx return (-1); 2984210502Ssyrinx } 2985210502Ssyrinx 2986210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 1) < 0) 2987210502Ssyrinx return (-1); 2988210502Ssyrinx 2989210502Ssyrinx return(0); 2990210502Ssyrinx} 2991210502Ssyrinx 2992210502Ssyrinxint 2993210502Ssyrinxwlan_mesh_flush_routes(struct wlan_iface *wif) 2994210502Ssyrinx{ 2995210502Ssyrinx int val = IEEE80211_MESH_RTCMD_FLUSH; 2996210502Ssyrinx size_t argsize = 0; 2997210502Ssyrinx 2998210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, NULL, 2999210502Ssyrinx &argsize, 1) < 0) 3000210502Ssyrinx return (-1); 3001210502Ssyrinx 3002210502Ssyrinx return (0); 3003210502Ssyrinx} 3004210502Ssyrinx 3005210502Ssyrinxint 3006210502Ssyrinxwlan_mesh_add_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr) 3007210502Ssyrinx{ 3008210502Ssyrinx int val = IEEE80211_MESH_RTCMD_ADD; 3009210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 3010210502Ssyrinx 3011210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, 3012210502Ssyrinx wmr->imroute.imr_dest, &argsize, 1) < 0) 3013210502Ssyrinx return (-1); 3014210502Ssyrinx 3015210502Ssyrinx wmr->mroute_status = RowStatus_active; 3016210502Ssyrinx 3017210502Ssyrinx return (0); 3018210502Ssyrinx} 3019210502Ssyrinx 3020210502Ssyrinxint 3021210502Ssyrinxwlan_mesh_del_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr) 3022210502Ssyrinx{ 3023210502Ssyrinx int val = IEEE80211_MESH_RTCMD_DELETE; 3024210502Ssyrinx size_t argsize = IEEE80211_ADDR_LEN; 3025210502Ssyrinx 3026210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, 3027210502Ssyrinx wmr->imroute.imr_dest, &argsize, 1) < 0) 3028210502Ssyrinx return (-1); 3029210502Ssyrinx 3030210502Ssyrinx wmr->mroute_status = RowStatus_destroy; 3031210502Ssyrinx 3032210502Ssyrinx return (0); 3033210502Ssyrinx} 3034210502Ssyrinx 3035210502Ssyrinxint 3036210502Ssyrinxwlan_mesh_get_routelist(struct wlan_iface *wif) 3037210502Ssyrinx{ 3038210502Ssyrinx int i, nroutes, val = IEEE80211_MESH_RTCMD_LIST; 3039210502Ssyrinx size_t argsize; 3040210502Ssyrinx struct ieee80211req_mesh_route routes[128]; 3041210502Ssyrinx struct ieee80211req_mesh_route *rt; 3042210502Ssyrinx struct wlan_mesh_route *wmr; 3043210502Ssyrinx 3044210502Ssyrinx argsize = sizeof(routes); 3045210502Ssyrinx if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, routes, 3046210502Ssyrinx &argsize, 0) < 0) /* XXX: ENOMEM? */ 3047210502Ssyrinx return (-1); 3048210502Ssyrinx 3049210502Ssyrinx nroutes = argsize / sizeof(*rt); 3050210502Ssyrinx for (i = 0; i < nroutes; i++) { 3051210502Ssyrinx rt = routes + i; 3052210502Ssyrinx if ((wmr = wlan_mesh_new_route(rt->imr_dest)) == NULL) 3053210502Ssyrinx return (-1); 3054210502Ssyrinx memcpy(&wmr->imroute, rt, sizeof(*rt)); 3055210502Ssyrinx wmr->mroute_status = RowStatus_active; 3056210502Ssyrinx if (wlan_mesh_add_rtentry(wif, wmr) < 0) 3057210502Ssyrinx wlan_mesh_free_route(wmr); 3058210502Ssyrinx } 3059210502Ssyrinx 3060210502Ssyrinx return (0); 3061210502Ssyrinx} 3062210502Ssyrinx 3063210502Ssyrinxint 3064210502Ssyrinxwlan_hwmp_config_get(struct wlan_iface *wif, int which) 3065210502Ssyrinx{ 3066210502Ssyrinx int op, val = 0; 3067210502Ssyrinx size_t argsize = 0; 3068210502Ssyrinx 3069210502Ssyrinx switch (which) { 3070210502Ssyrinx case LEAF_wlanHWMPRootMode: 3071210502Ssyrinx op = IEEE80211_IOC_HWMP_ROOTMODE; 3072210502Ssyrinx break; 3073210502Ssyrinx case LEAF_wlanHWMPMaxHops: 3074210502Ssyrinx op = IEEE80211_IOC_HWMP_MAXHOPS; 3075210502Ssyrinx break; 3076210502Ssyrinx default: 3077210502Ssyrinx return (-1); 3078210502Ssyrinx } 3079210502Ssyrinx 3080210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0) 3081210502Ssyrinx return (-1); 3082210502Ssyrinx 3083210502Ssyrinx switch (which) { 3084210502Ssyrinx case LEAF_wlanHWMPRootMode: 3085210502Ssyrinx switch (val) { 3086210502Ssyrinx case IEEE80211_HWMP_ROOTMODE_NORMAL: 3087210502Ssyrinx wif->hwmp_root_mode = wlanHWMPRootMode_normal; 3088210502Ssyrinx break; 3089210502Ssyrinx case IEEE80211_HWMP_ROOTMODE_PROACTIVE: 3090210502Ssyrinx wif->hwmp_root_mode = wlanHWMPRootMode_proactive; 3091210502Ssyrinx break; 3092210502Ssyrinx case IEEE80211_HWMP_ROOTMODE_RANN: 3093210502Ssyrinx wif->hwmp_root_mode = wlanHWMPRootMode_rann; 3094210502Ssyrinx break; 3095210502Ssyrinx case IEEE80211_HWMP_ROOTMODE_DISABLED: 3096210502Ssyrinx default: 3097210502Ssyrinx wif->hwmp_root_mode = wlanHWMPRootMode_disabled; 3098210502Ssyrinx break; 3099210502Ssyrinx } 3100210502Ssyrinx break; 3101210502Ssyrinx case LEAF_wlanHWMPMaxHops: 3102210502Ssyrinx wif->hwmp_max_hops = val; 3103210502Ssyrinx break; 3104210502Ssyrinx } 3105210502Ssyrinx 3106210502Ssyrinx return (0); 3107210502Ssyrinx} 3108210502Ssyrinx 3109210502Ssyrinxint 3110210502Ssyrinxwlan_hwmp_config_set(struct wlan_iface *wif, int which) 3111210502Ssyrinx{ 3112210502Ssyrinx int op, val = 0; 3113210502Ssyrinx size_t argsize = 0; 3114210502Ssyrinx 3115210502Ssyrinx switch (which) { 3116210502Ssyrinx case LEAF_wlanHWMPRootMode: 3117210502Ssyrinx op = IEEE80211_IOC_HWMP_ROOTMODE; 3118210502Ssyrinx switch (wif->hwmp_root_mode) { 3119210502Ssyrinx case wlanHWMPRootMode_disabled: 3120210502Ssyrinx val = IEEE80211_HWMP_ROOTMODE_DISABLED; 3121210502Ssyrinx break; 3122210502Ssyrinx case wlanHWMPRootMode_normal: 3123210502Ssyrinx val = IEEE80211_HWMP_ROOTMODE_NORMAL; 3124210502Ssyrinx break; 3125210502Ssyrinx case wlanHWMPRootMode_proactive: 3126210502Ssyrinx val = IEEE80211_HWMP_ROOTMODE_PROACTIVE; 3127210502Ssyrinx break; 3128210502Ssyrinx case wlanHWMPRootMode_rann: 3129210502Ssyrinx val = IEEE80211_HWMP_ROOTMODE_RANN; 3130210502Ssyrinx break; 3131210502Ssyrinx default: 3132210502Ssyrinx return (-1); 3133210502Ssyrinx } 3134210502Ssyrinx break; 3135210502Ssyrinx case LEAF_wlanHWMPMaxHops: 3136210502Ssyrinx op = IEEE80211_IOC_HWMP_MAXHOPS; 3137210502Ssyrinx val = wif->hwmp_max_hops; 3138210502Ssyrinx break; 3139210502Ssyrinx default: 3140210502Ssyrinx return (-1); 3141210502Ssyrinx } 3142210502Ssyrinx 3143210502Ssyrinx if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0) 3144210502Ssyrinx return (-1); 3145210502Ssyrinx 3146210502Ssyrinx return (0); 3147210502Ssyrinx} 3148