1 /*- 2 * Copyright (c) 2010 The FreeBSD Foundation 3 * All rights reserved. 4 5 * This software was developed by Shteryana Sotirova Shopova under 6 * sponsorship from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/ioctl.h> 33 #include <sys/param.h> 34 #include <sys/module.h> 35 #include <sys/linker.h> 36 #include <sys/socket.h> 37 #include <sys/sysctl.h> 38 39 #include <net/if.h> 40 #include <net/if_dl.h> 41 #include <net/if_media.h> 42 #include <net/if_mib.h> 43 #include <net/if_types.h> 44 #include <net80211/ieee80211.h> 45 #include <net80211/ieee80211_ioctl.h> 46 #include <net80211/ieee80211_regdomain.h> 47 48 #include <errno.h> 49 #include <ifaddrs.h> 50 #include <stdarg.h> 51 #include <stdlib.h> 52 #include <stdio.h> 53 #include <string.h> 54 #include <syslog.h> 55 56 #include <bsnmp/snmpmod.h> 57 #include <bsnmp/snmp_mibII.h> 58 59 #include "wlan_tree.h" 60 #include "wlan_snmp.h" 61 62 static int sock = -1; 63 64 static int wlan_ioctl(char *, uint16_t, int *, void *, size_t *, int); 65 static int wlan_kmod_load(const char *); 66 static uint32_t wlan_drivercaps_to_snmp(uint32_t); 67 static uint32_t wlan_cryptocaps_to_snmp(uint32_t); 68 static uint32_t wlan_htcaps_to_snmp(uint32_t); 69 static uint32_t wlan_peerstate_to_snmp(uint32_t); 70 static uint32_t wlan_peercaps_to_snmp(uint32_t ); 71 static uint32_t wlan_channel_flags_to_snmp_phy(uint32_t); 72 static uint32_t wlan_regdomain_to_snmp(int); 73 static uint32_t wlan_snmp_to_scan_flags(int); 74 static int wlan_config_snmp2ioctl(int); 75 static int wlan_snmp_to_regdomain(enum WlanRegDomainCode); 76 static int wlan_config_get_country(struct wlan_iface *); 77 static int wlan_config_set_country(struct wlan_iface *, char *, int); 78 static int wlan_config_get_dchannel(struct wlan_iface *wif); 79 static int wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t); 80 static int wlan_config_get_bssid(struct wlan_iface *); 81 static int wlan_config_set_bssid(struct wlan_iface *, uint8_t *); 82 static void wlan_config_set_snmp_intval(struct wlan_iface *, int, int); 83 static int wlan_config_snmp2value(int, int, int *); 84 static int wlan_config_check(struct wlan_iface *, int); 85 static int wlan_config_get_intval(struct wlan_iface *, int); 86 static int wlan_config_set_intval(struct wlan_iface *, int, int); 87 static int wlan_add_new_scan_result(struct wlan_iface *, 88 const struct ieee80211req_scan_result *, uint8_t *); 89 static int wlan_add_mac_macinfo(struct wlan_iface *, 90 const struct ieee80211req_maclist *); 91 static struct wlan_peer *wlan_add_peerinfo(const struct ieee80211req_sta_info *); 92 93 int 94 wlan_ioctl_init(void) 95 { 96 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 97 syslog(LOG_ERR, "cannot open socket : %s", strerror(errno)); 98 return (-1); 99 } 100 101 return (0); 102 } 103 /* 104 * Load the needed modules in kernel if not already there. 105 */ 106 enum wlan_kmodules { 107 WLAN_KMOD = 0, 108 WLAN_KMOD_ACL, 109 WLAN_KMOD_WEP, 110 WLAN_KMODS_MAX 111 }; 112 113 static const char *wmod_names[] = { 114 "wlan", 115 "wlan_wlan_acl", 116 "wlan_wep", 117 NULL 118 }; 119 120 static int 121 wlan_kmod_load(const char *modname) 122 { 123 int fileid, modid; 124 struct module_stat mstat; 125 126 mstat.version = sizeof(struct module_stat); 127 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 128 for (modid = kldfirstmod(fileid); modid > 0; 129 modid = modfnext(modid)) { 130 if (modstat(modid, &mstat) < 0) 131 continue; 132 if (strcmp(modname, mstat.name) == 0) 133 return (0); 134 } 135 } 136 137 /* Not present - load it. */ 138 if (kldload(modname) < 0) { 139 syslog(LOG_ERR, "failed to load %s kernel module - %s", modname, 140 strerror(errno)); 141 return (-1); 142 } 143 144 return (1); 145 } 146 147 int 148 wlan_kmodules_load(void) 149 { 150 if (wlan_kmod_load(wmod_names[WLAN_KMOD]) < 0) 151 return (-1); 152 153 if (wlan_kmod_load(wmod_names[WLAN_KMOD_ACL]) > 0) 154 syslog(LOG_NOTICE, "SNMP wlan loaded %s module", 155 wmod_names[WLAN_KMOD_ACL]); 156 157 if (wlan_kmod_load(wmod_names[WLAN_KMOD_WEP]) > 0) 158 syslog(LOG_NOTICE, "SNMP wlan loaded %s module", 159 wmod_names[WLAN_KMOD_WEP]); 160 161 return (0); 162 } 163 164 /* XXX: FIXME */ 165 static int 166 wlan_ioctl(char *wif_name, uint16_t req_type, int *val, void *arg, 167 size_t *argsize, int set) 168 { 169 struct ieee80211req ireq; 170 171 memset(&ireq, 0, sizeof(struct ieee80211req)); 172 strlcpy(ireq.i_name, wif_name, IFNAMSIZ); 173 174 ireq.i_type = req_type; 175 ireq.i_val = *val; 176 ireq.i_len = *argsize; 177 ireq.i_data = arg; 178 179 if (ioctl(sock, set ? SIOCS80211 : SIOCG80211, &ireq) < 0) { 180 syslog(LOG_ERR, "iface %s - %s param: ioctl(%d) " 181 "failed: %s", wif_name, set ? "set" : "get", 182 req_type, strerror(errno)); 183 return (-1); 184 } 185 186 *argsize = ireq.i_len; 187 *val = ireq.i_val; 188 189 return (0); 190 } 191 192 int 193 wlan_check_media(char *ifname) 194 { 195 struct ifmediareq ifmr; 196 197 memset(&ifmr, 0, sizeof(struct ifmediareq)); 198 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 199 200 if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0 || ifmr.ifm_count == 0) 201 return (0); /* Interface doesn't support SIOCGIFMEDIA. */ 202 203 if ((ifmr.ifm_status & IFM_AVALID) == 0) 204 return (0); 205 206 return (IFM_TYPE(ifmr.ifm_active)); 207 } 208 209 int 210 wlan_get_opmode(struct wlan_iface *wif) 211 { 212 struct ifmediareq ifmr; 213 214 memset(&ifmr, 0, sizeof(struct ifmediareq)); 215 strlcpy(ifmr.ifm_name, wif->wname, sizeof(ifmr.ifm_name)); 216 217 if (ioctl(sock, SIOCGIFMEDIA, &ifmr) < 0) { 218 if (errno == ENXIO) 219 return (-1); 220 wif->mode = WlanIfaceOperatingModeType_station; 221 return (0); 222 } 223 224 if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { 225 if (ifmr.ifm_current & IFM_FLAG0) 226 wif->mode = WlanIfaceOperatingModeType_adhocDemo; 227 else 228 wif->mode = WlanIfaceOperatingModeType_ibss; 229 } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 230 wif->mode = WlanIfaceOperatingModeType_hostAp; 231 else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 232 wif->mode = WlanIfaceOperatingModeType_monitor; 233 else if (ifmr.ifm_current & IFM_IEEE80211_MBSS) 234 wif->mode = WlanIfaceOperatingModeType_meshPoint; 235 else if (ifmr.ifm_current & IFM_IEEE80211_WDS) 236 wif->mode = WlanIfaceOperatingModeType_wds; 237 238 return (0); 239 } 240 241 int 242 wlan_config_state(struct wlan_iface *wif, uint8_t set) 243 { 244 int flags; 245 struct ifreq ifr; 246 247 memset(&ifr, 0, sizeof(ifr)); 248 strcpy(ifr.ifr_name, wif->wname); 249 250 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 251 syslog(LOG_ERR, "set %s status: ioctl(SIOCGIFFLAGS) " 252 "failed: %s", wif->wname, strerror(errno)); 253 return (-1); 254 } 255 256 if (set == 0) { 257 if ((ifr.ifr_flags & IFF_UP) != 0) 258 wif->state = wlanIfaceState_up; 259 else 260 wif->state = wlanIfaceState_down; 261 return (0); 262 } 263 264 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 265 266 if (wif->state == wlanIfaceState_up) 267 flags |= IFF_UP; 268 else 269 flags &= ~IFF_UP; 270 271 ifr.ifr_flags = flags & 0xffff; 272 ifr.ifr_flagshigh = flags >> 16; 273 if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 274 syslog(LOG_ERR, "set %s %s: ioctl(SIOCSIFFLAGS) failed: %s", 275 wif->wname, wif->state == wlanIfaceState_up?"up":"down", 276 strerror(errno)); 277 return (-1); 278 } 279 280 return (0); 281 } 282 283 int 284 wlan_get_local_addr(struct wlan_iface *wif) 285 { 286 int len; 287 char ifname[IFNAMSIZ]; 288 struct ifaddrs *ifap, *ifa; 289 struct sockaddr_dl sdl; 290 291 if (getifaddrs(&ifap) != 0) { 292 syslog(LOG_ERR, "wlan get mac: getifaddrs() failed - %s", 293 strerror(errno)); 294 return (-1); 295 } 296 297 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 298 if (ifa->ifa_addr->sa_family != AF_LINK) 299 continue; 300 memcpy(&sdl, ifa->ifa_addr, sizeof(struct sockaddr_dl)); 301 if (sdl.sdl_alen > IEEE80211_ADDR_LEN) 302 continue; 303 if ((len = sdl.sdl_nlen) >= IFNAMSIZ) 304 len = IFNAMSIZ - 1; 305 memcpy(ifname, sdl.sdl_data, len); 306 ifname[len] = '\0'; 307 if (strcmp(wif->wname, ifname) == 0) 308 break; 309 } 310 311 freeifaddrs(ifap); 312 return (0); 313 } 314 315 int 316 wlan_get_parent(struct wlan_iface *wif __unused) 317 { 318 /* XXX: There's no way to fetch this from the kernel. */ 319 return (0); 320 } 321 322 /* XXX */ 323 #define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */ 324 #define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */ 325 #define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */ 326 #define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/ 327 #define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */ 328 #define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */ 329 #define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ 330 #define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */ 331 #define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */ 332 #define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */ 333 #define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */ 334 #define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */ 335 #define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */ 336 #define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/ 337 #define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ 338 /* 0x7c0000 available */ 339 #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ 340 #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ 341 #define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ 342 #define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */ 343 #define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */ 344 #define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */ 345 /* 0x10000000 reserved */ 346 #define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */ 347 #define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */ 348 #define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */ 349 350 static uint32_t 351 wlan_drivercaps_to_snmp(uint32_t dcaps) 352 { 353 uint32_t scaps = 0; 354 355 if ((dcaps & IEEE80211_C_STA) != 0) 356 scaps |= (0x1 << WlanDriverCaps_station); 357 if ((dcaps & IEEE80211_C_8023ENCAP) != 0) 358 scaps |= (0x1 << WlanDriverCaps_ieee8023encap); 359 if ((dcaps & IEEE80211_C_FF) != 0) 360 scaps |= (0x1 << WlanDriverCaps_athFastFrames); 361 if ((dcaps & IEEE80211_C_TURBOP) != 0) 362 scaps |= (0x1 << WlanDriverCaps_athTurbo); 363 if ((dcaps & IEEE80211_C_IBSS) != 0) 364 scaps |= (0x1 << WlanDriverCaps_ibss); 365 if ((dcaps & IEEE80211_C_PMGT) != 0) 366 scaps |= (0x1 << WlanDriverCaps_pmgt); 367 if ((dcaps & IEEE80211_C_HOSTAP) != 0) 368 scaps |= (0x1 << WlanDriverCaps_hostAp); 369 if ((dcaps & IEEE80211_C_AHDEMO) != 0) 370 scaps |= (0x1 << WlanDriverCaps_ahDemo); 371 if ((dcaps & IEEE80211_C_SWRETRY) != 0) 372 scaps |= (0x1 << WlanDriverCaps_swRetry); 373 if ((dcaps & IEEE80211_C_TXPMGT) != 0) 374 scaps |= (0x1 << WlanDriverCaps_txPmgt); 375 if ((dcaps & IEEE80211_C_SHSLOT) != 0) 376 scaps |= (0x1 << WlanDriverCaps_shortSlot); 377 if ((dcaps & IEEE80211_C_SHPREAMBLE) != 0) 378 scaps |= (0x1 << WlanDriverCaps_shortPreamble); 379 if ((dcaps & IEEE80211_C_MONITOR) != 0) 380 scaps |= (0x1 << WlanDriverCaps_monitor); 381 if ((dcaps & IEEE80211_C_DFS) != 0) 382 scaps |= (0x1 << WlanDriverCaps_dfs); 383 if ((dcaps & IEEE80211_C_MBSS) != 0) 384 scaps |= (0x1 << WlanDriverCaps_mbss); 385 if ((dcaps & IEEE80211_C_WPA1) != 0) 386 scaps |= (0x1 << WlanDriverCaps_wpa1); 387 if ((dcaps & IEEE80211_C_WPA2) != 0) 388 scaps |= (0x1 << WlanDriverCaps_wpa2); 389 if ((dcaps & IEEE80211_C_BURST) != 0) 390 scaps |= (0x1 << WlanDriverCaps_burst); 391 if ((dcaps & IEEE80211_C_WME) != 0) 392 scaps |= (0x1 << WlanDriverCaps_wme); 393 if ((dcaps & IEEE80211_C_WDS) != 0) 394 scaps |= (0x1 << WlanDriverCaps_wds); 395 if ((dcaps & IEEE80211_C_BGSCAN) != 0) 396 scaps |= (0x1 << WlanDriverCaps_bgScan); 397 if ((dcaps & IEEE80211_C_TXFRAG) != 0) 398 scaps |= (0x1 << WlanDriverCaps_txFrag); 399 if ((dcaps & IEEE80211_C_TDMA) != 0) 400 scaps |= (0x1 << WlanDriverCaps_tdma); 401 402 return (scaps); 403 } 404 405 static uint32_t 406 wlan_cryptocaps_to_snmp(uint32_t ccaps) 407 { 408 uint32_t scaps = 0; 409 410 #if NOT_YET 411 if ((ccaps & IEEE80211_CRYPTO_WEP) != 0) 412 scaps |= (0x1 << wlanCryptoCaps_wep); 413 if ((ccaps & IEEE80211_CRYPTO_TKIP) != 0) 414 scaps |= (0x1 << wlanCryptoCaps_tkip); 415 if ((ccaps & IEEE80211_CRYPTO_AES_OCB) != 0) 416 scaps |= (0x1 << wlanCryptoCaps_aes); 417 if ((ccaps & IEEE80211_CRYPTO_AES_CCM) != 0) 418 scaps |= (0x1 << wlanCryptoCaps_aesCcm); 419 if ((ccaps & IEEE80211_CRYPTO_TKIPMIC) != 0) 420 scaps |= (0x1 << wlanCryptoCaps_tkipMic); 421 if ((ccaps & IEEE80211_CRYPTO_CKIP) != 0) 422 scaps |= (0x1 << wlanCryptoCaps_ckip); 423 #else /* !NOT_YET */ 424 scaps = ccaps; 425 #endif 426 return (scaps); 427 } 428 429 #define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */ 430 #define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */ 431 /* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */ 432 #define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */ 433 #define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/ 434 #define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */ 435 436 static uint32_t 437 wlan_htcaps_to_snmp(uint32_t hcaps) 438 { 439 uint32_t scaps = 0; 440 441 if ((hcaps & IEEE80211_HTCAP_LDPC) != 0) 442 scaps |= (0x1 << WlanHTCaps_ldpc); 443 if ((hcaps & IEEE80211_HTCAP_CHWIDTH40) != 0) 444 scaps |= (0x1 << WlanHTCaps_chwidth40); 445 if ((hcaps & IEEE80211_HTCAP_GREENFIELD) != 0) 446 scaps |= (0x1 << WlanHTCaps_greenField); 447 if ((hcaps & IEEE80211_HTCAP_SHORTGI20) != 0) 448 scaps |= (0x1 << WlanHTCaps_shortGi20); 449 if ((hcaps & IEEE80211_HTCAP_SHORTGI40) != 0) 450 scaps |= (0x1 << WlanHTCaps_shortGi40); 451 if ((hcaps & IEEE80211_HTCAP_TXSTBC) != 0) 452 scaps |= (0x1 << WlanHTCaps_txStbc); 453 if ((hcaps & IEEE80211_HTCAP_DELBA) != 0) 454 scaps |= (0x1 << WlanHTCaps_delba); 455 if ((hcaps & IEEE80211_HTCAP_MAXAMSDU_7935) != 0) 456 scaps |= (0x1 << WlanHTCaps_amsdu7935); 457 if ((hcaps & IEEE80211_HTCAP_DSSSCCK40) != 0) 458 scaps |= (0x1 << WlanHTCaps_dssscck40); 459 if ((hcaps & IEEE80211_HTCAP_PSMP) != 0) 460 scaps |= (0x1 << WlanHTCaps_psmp); 461 if ((hcaps & IEEE80211_HTCAP_40INTOLERANT) != 0) 462 scaps |= (0x1 << WlanHTCaps_fortyMHzIntolerant); 463 if ((hcaps & IEEE80211_HTCAP_LSIGTXOPPROT) != 0) 464 scaps |= (0x1 << WlanHTCaps_lsigTxOpProt); 465 if ((hcaps & IEEE80211_HTC_AMPDU) != 0) 466 scaps |= (0x1 << WlanHTCaps_htcAmpdu); 467 if ((hcaps & IEEE80211_HTC_AMSDU) != 0) 468 scaps |= (0x1 << WlanHTCaps_htcAmsdu); 469 if ((hcaps & IEEE80211_HTC_HT) != 0) 470 scaps |= (0x1 << WlanHTCaps_htcHt); 471 if ((hcaps & IEEE80211_HTC_SMPS) != 0) 472 scaps |= (0x1 << WlanHTCaps_htcSmps); 473 if ((hcaps & IEEE80211_HTC_RIFS) != 0) 474 scaps |= (0x1 << WlanHTCaps_htcRifs); 475 476 return (scaps); 477 } 478 479 /* XXX: Not here? */ 480 #define WLAN_SET_TDMA_OPMODE(w) do { \ 481 if ((w)->mode == WlanIfaceOperatingModeType_adhocDemo && \ 482 ((w)->drivercaps & WlanDriverCaps_tdma) != 0) \ 483 (w)->mode = WlanIfaceOperatingModeType_tdma; \ 484 } while (0) 485 int 486 wlan_get_driver_caps(struct wlan_iface *wif) 487 { 488 int val = 0; 489 size_t argsize; 490 struct ieee80211_devcaps_req dc; 491 492 memset(&dc, 0, sizeof(struct ieee80211_devcaps_req)); 493 argsize = sizeof(struct ieee80211_devcaps_req); 494 495 if (wlan_ioctl(wif->wname, IEEE80211_IOC_DEVCAPS, &val, &dc, 496 &argsize, 0) < 0) 497 return (-1); 498 499 wif->drivercaps = wlan_drivercaps_to_snmp(dc.dc_drivercaps); 500 wif->cryptocaps = wlan_cryptocaps_to_snmp(dc.dc_cryptocaps); 501 wif->htcaps = wlan_htcaps_to_snmp(dc.dc_htcaps); 502 503 WLAN_SET_TDMA_OPMODE(wif); 504 505 argsize = dc.dc_chaninfo.ic_nchans * sizeof(struct ieee80211_channel); 506 wif->chanlist = (struct ieee80211_channel *)malloc(argsize); 507 if (wif->chanlist == NULL) 508 return (0); 509 510 memcpy(wif->chanlist, dc.dc_chaninfo.ic_chans, argsize); 511 wif->nchannels = dc.dc_chaninfo.ic_nchans; 512 513 return (0); 514 } 515 516 uint8_t 517 wlan_channel_state_to_snmp(uint8_t cstate) 518 { 519 uint8_t cs = 0; 520 521 if ((cstate & IEEE80211_CHANSTATE_RADAR) != 0) 522 cs |= (0x1 << WlanIfaceChannelStateType_radar); 523 if ((cstate & IEEE80211_CHANSTATE_CACDONE) != 0) 524 cs |= (0x1 << WlanIfaceChannelStateType_cacDone); 525 if ((cstate & IEEE80211_CHANSTATE_CWINT) != 0) 526 cs |= (0x1 << WlanIfaceChannelStateType_interferenceDetected); 527 if ((cstate & IEEE80211_CHANSTATE_NORADAR) != 0) 528 cs |= (0x1 << WlanIfaceChannelStateType_radarClear); 529 530 return (cs); 531 } 532 533 uint32_t 534 wlan_channel_flags_to_snmp(uint32_t cflags) 535 { 536 uint32_t cf = 0; 537 538 if ((cflags & IEEE80211_CHAN_TURBO) != 0) 539 cf |= (0x1 << WlanIfaceChannelFlagsType_turbo); 540 if ((cflags & IEEE80211_CHAN_CCK) != 0) 541 cf |= (0x1 << WlanIfaceChannelFlagsType_cck); 542 if ((cflags & IEEE80211_CHAN_OFDM) != 0) 543 cf |= (0x1 << WlanIfaceChannelFlagsType_ofdm); 544 if ((cflags & IEEE80211_CHAN_2GHZ) != 0) 545 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum2Ghz); 546 if ((cflags & IEEE80211_CHAN_5GHZ) != 0) 547 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum5Ghz); 548 if ((cflags & IEEE80211_CHAN_PASSIVE) != 0) 549 cf |= (0x1 << WlanIfaceChannelFlagsType_passiveScan); 550 if ((cflags & IEEE80211_CHAN_DYN) != 0) 551 cf |= (0x1 << WlanIfaceChannelFlagsType_dynamicCckOfdm); 552 if ((cflags & IEEE80211_CHAN_GFSK) != 0) 553 cf |= (0x1 << WlanIfaceChannelFlagsType_gfsk); 554 if ((cflags & IEEE80211_CHAN_GSM) != 0) 555 cf |= (0x1 << WlanIfaceChannelFlagsType_spectrum900Mhz); 556 if ((cflags & IEEE80211_CHAN_STURBO) != 0) 557 cf |= (0x1 << WlanIfaceChannelFlagsType_dot11aStaticTurbo); 558 if ((cflags & IEEE80211_CHAN_HALF) != 0) 559 cf |= (0x1 << WlanIfaceChannelFlagsType_halfRate); 560 if ((cflags & IEEE80211_CHAN_QUARTER) != 0) 561 cf |= (0x1 << WlanIfaceChannelFlagsType_quarterRate); 562 if ((cflags & IEEE80211_CHAN_HT20) != 0) 563 cf |= (0x1 << WlanIfaceChannelFlagsType_ht20); 564 if ((cflags & IEEE80211_CHAN_HT40U) != 0) 565 cf |= (0x1 << WlanIfaceChannelFlagsType_ht40u); 566 if ((cflags & IEEE80211_CHAN_HT40D) != 0) 567 cf |= (0x1 << WlanIfaceChannelFlagsType_ht40d); 568 if ((cflags & IEEE80211_CHAN_DFS) != 0) 569 cf |= (0x1 << WlanIfaceChannelFlagsType_dfs); 570 if ((cflags & IEEE80211_CHAN_4MSXMIT) != 0) 571 cf |= (0x1 << WlanIfaceChannelFlagsType_xmit4ms); 572 if ((cflags & IEEE80211_CHAN_NOADHOC) != 0) 573 cf |= (0x1 << WlanIfaceChannelFlagsType_noAdhoc); 574 if ((cflags & IEEE80211_CHAN_NOHOSTAP) != 0) 575 cf |= (0x1 << WlanIfaceChannelFlagsType_noHostAp); 576 if ((cflags & IEEE80211_CHAN_11D) != 0) 577 cf |= (0x1 << WlanIfaceChannelFlagsType_dot11d); 578 579 return (cf); 580 } 581 582 /* XXX: */ 583 #define WLAN_SNMP_MAX_CHANS 256 584 int 585 wlan_get_channel_list(struct wlan_iface *wif) 586 { 587 int val = 0; 588 uint32_t i, nchans; 589 size_t argsize; 590 struct ieee80211req_chaninfo *chaninfo; 591 struct ieee80211req_chanlist active; 592 const struct ieee80211_channel *c; 593 594 argsize = sizeof(struct ieee80211req_chaninfo) + 595 sizeof(struct ieee80211_channel) * WLAN_SNMP_MAX_CHANS; 596 chaninfo = (struct ieee80211req_chaninfo *)malloc(argsize); 597 if (chaninfo == NULL) 598 return (-1); 599 600 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANINFO, &val, chaninfo, 601 &argsize, 0) < 0) 602 return (-1); 603 604 argsize = sizeof(active); 605 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CHANLIST, &val, &active, 606 &argsize, 0) < 0) 607 goto error; 608 609 for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) { 610 c = &chaninfo->ic_chans[i]; 611 if (!isset(active.ic_channels, c->ic_ieee)) 612 continue; 613 nchans++; 614 } 615 wif->chanlist = (struct ieee80211_channel *)reallocf(wif->chanlist, 616 nchans * sizeof(*c)); 617 if (wif->chanlist == NULL) 618 goto error; 619 wif->nchannels = nchans; 620 for (i = 0, nchans = 0; i < chaninfo->ic_nchans; i++) { 621 c = &chaninfo->ic_chans[i]; 622 if (!isset(active.ic_channels, c->ic_ieee)) 623 continue; 624 memcpy(wif->chanlist + nchans, c, sizeof (*c)); 625 nchans++; 626 } 627 628 free(chaninfo); 629 return (0); 630 error: 631 wif->nchannels = 0; 632 free(chaninfo); 633 return (-1); 634 } 635 636 static enum WlanIfPhyMode 637 wlan_channel_flags_to_snmp_phy(uint32_t cflags) 638 { 639 /* XXX: recheck */ 640 if ((cflags & IEEE80211_CHAN_A) != 0) 641 return (WlanIfPhyMode_dot11a); 642 if ((cflags & IEEE80211_CHAN_B) != 0) 643 return (WlanIfPhyMode_dot11b); 644 if ((cflags & IEEE80211_CHAN_G) != 0 || 645 (cflags & IEEE80211_CHAN_PUREG) != 0) 646 return (WlanIfPhyMode_dot11g); 647 if ((cflags & IEEE80211_CHAN_FHSS) != 0) 648 return (WlanIfPhyMode_fh); 649 if ((cflags & IEEE80211_CHAN_TURBO) != 0 && 650 (cflags & IEEE80211_CHAN_A) != 0) 651 return (WlanIfPhyMode_turboA); 652 if ((cflags & IEEE80211_CHAN_TURBO) != 0 && 653 (cflags & IEEE80211_CHAN_G) != 0) 654 return (WlanIfPhyMode_turboG); 655 if ((cflags & IEEE80211_CHAN_STURBO) != 0) 656 return (WlanIfPhyMode_sturboA); 657 if ((cflags & IEEE80211_CHAN_HALF) != 0) 658 return (WlanIfPhyMode_ofdmHalf); 659 if ((cflags & IEEE80211_CHAN_QUARTER) != 0) 660 return (WlanIfPhyMode_ofdmQuarter); 661 662 return (WlanIfPhyMode_auto); 663 } 664 665 int 666 wlan_get_roam_params(struct wlan_iface *wif) 667 { 668 int val = 0; 669 size_t argsize; 670 671 argsize = sizeof(struct ieee80211_roamparams_req); 672 if (wlan_ioctl(wif->wname, IEEE80211_IOC_ROAM, &val, 673 &wif->roamparams, &argsize, 0) < 0) 674 return (-1); 675 676 return (0); 677 } 678 679 int 680 wlan_get_tx_params(struct wlan_iface *wif) 681 { 682 int val = 0; 683 size_t argsize; 684 685 /* 686 * XXX: Reset IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA 687 * and IEEE80211_MODE_11NG modes. 688 */ 689 argsize = sizeof(struct ieee80211_txparams_req); 690 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val, 691 &wif->txparams, &argsize, 0) < 0) 692 return (-1); 693 694 return (0); 695 } 696 697 int 698 wlan_set_tx_params(struct wlan_iface *wif, int32_t pmode __unused) 699 { 700 int val = 0; 701 size_t argsize; 702 703 /* 704 * XXX: Set IEEE80211_RATE_MCS bit on IEEE80211_MODE_11NA 705 * and IEEE80211_MODE_11NG modes. 706 */ 707 argsize = sizeof(struct ieee80211_txparams_req); 708 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPARAMS, &val, 709 &wif->txparams, &argsize, 1) < 0) 710 return (-1); 711 712 return (0); 713 } 714 715 int 716 wlan_clone_create(struct wlan_iface *wif) 717 { 718 struct ifreq ifr; 719 struct ieee80211_clone_params wcp; 720 static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 721 722 memset(&wcp, 0, sizeof(wcp)); 723 memset(&ifr, 0, sizeof(ifr)); 724 725 /* Sanity checks. */ 726 if (wif == NULL || wif->pname[0] == '\0' || wif->mode > WLAN_IFMODE_MAX) 727 return (SNMP_ERR_INCONS_VALUE); 728 729 if (wif->mode == WlanIfaceOperatingModeType_wds && 730 memcmp(wif->dbssid, zerobssid, IEEE80211_ADDR_LEN) == 0) 731 return (SNMP_ERR_INCONS_VALUE); 732 733 strlcpy(wcp.icp_parent, wif->pname, IFNAMSIZ); 734 if ((wif->flags & WlanIfaceFlagsType_uniqueBssid) != 0) 735 wcp.icp_flags |= IEEE80211_CLONE_BSSID; 736 if ((wif->flags & WlanIfaceFlagsType_noBeacons) != 0) 737 wcp.icp_flags |= IEEE80211_CLONE_NOBEACONS; 738 if (wif->mode == WlanIfaceOperatingModeType_wds && 739 (wif->flags & WlanIfaceFlagsType_wdsLegacy) != 0) 740 wcp.icp_flags |= IEEE80211_CLONE_WDSLEGACY; 741 742 switch (wif->mode) { 743 case WlanIfaceOperatingModeType_ibss: 744 wcp.icp_opmode = IEEE80211_M_IBSS; 745 break; 746 case WlanIfaceOperatingModeType_station: 747 wcp.icp_opmode = IEEE80211_M_STA; 748 break; 749 case WlanIfaceOperatingModeType_wds: 750 wcp.icp_opmode = IEEE80211_M_WDS; 751 break; 752 case WlanIfaceOperatingModeType_adhocDemo: 753 wcp.icp_opmode = IEEE80211_M_AHDEMO; 754 break; 755 case WlanIfaceOperatingModeType_hostAp: 756 wcp.icp_opmode = IEEE80211_M_HOSTAP; 757 break; 758 case WlanIfaceOperatingModeType_monitor: 759 wcp.icp_opmode = IEEE80211_M_MONITOR; 760 break; 761 case WlanIfaceOperatingModeType_meshPoint: 762 wcp.icp_opmode = IEEE80211_M_MBSS; 763 break; 764 case WlanIfaceOperatingModeType_tdma: 765 wcp.icp_opmode = IEEE80211_M_AHDEMO; 766 wcp.icp_flags |= IEEE80211_CLONE_TDMA; 767 break; 768 } 769 770 memcpy(wcp.icp_bssid, wif->dbssid, IEEE80211_ADDR_LEN); 771 if (memcmp(wif->dlmac, zerobssid, IEEE80211_ADDR_LEN) != 0) { 772 memcpy(wcp.icp_macaddr, wif->dlmac, IEEE80211_ADDR_LEN); 773 wcp.icp_flags |= IEEE80211_CLONE_MACADDR; 774 } 775 776 strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ); 777 ifr.ifr_data = (caddr_t) &wcp; 778 779 if (ioctl(sock, SIOCIFCREATE2, (caddr_t) &ifr) < 0) { 780 syslog(LOG_ERR, "wlan clone create: ioctl(SIOCIFCREATE2) " 781 "failed: %s", strerror(errno)); 782 return (SNMP_ERR_GENERR); 783 } 784 785 return (SNMP_ERR_NOERROR); 786 } 787 788 int 789 wlan_clone_destroy(struct wlan_iface *wif) 790 { 791 struct ifreq ifr; 792 793 if (wif == NULL) 794 return (SNMP_ERR_INCONS_VALUE); 795 796 memset(&ifr, 0, sizeof(ifr)); 797 strcpy(ifr.ifr_name, wif->wname); 798 799 if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) { 800 syslog(LOG_ERR, "wlan clone destroy: ioctl(SIOCIFDESTROY) " 801 "failed: %s", strerror(errno)); 802 return (SNMP_ERR_GENERR); 803 } 804 805 return (SNMP_ERR_NOERROR); 806 } 807 808 static int 809 wlan_config_snmp2ioctl(int which) 810 { 811 int op; 812 813 switch (which) { 814 case LEAF_wlanIfacePacketBurst: 815 op = IEEE80211_IOC_BURST; 816 break; 817 case LEAF_wlanIfaceCountryCode: 818 op = IEEE80211_IOC_REGDOMAIN; 819 break; 820 case LEAF_wlanIfaceRegDomain: 821 op = IEEE80211_IOC_REGDOMAIN; 822 break; 823 case LEAF_wlanIfaceDesiredSsid: 824 op = IEEE80211_IOC_SSID; 825 break; 826 case LEAF_wlanIfaceDesiredChannel: 827 op = IEEE80211_IOC_CURCHAN; 828 break; 829 case LEAF_wlanIfaceDynamicFreqSelection: 830 op = IEEE80211_IOC_DFS; 831 break; 832 case LEAF_wlanIfaceFastFrames: 833 op = IEEE80211_IOC_FF; 834 break; 835 case LEAF_wlanIfaceDturbo: 836 op = IEEE80211_IOC_TURBOP; 837 break; 838 case LEAF_wlanIfaceTxPower: 839 op = IEEE80211_IOC_TXPOWER; 840 break; 841 case LEAF_wlanIfaceFragmentThreshold: 842 op = IEEE80211_IOC_FRAGTHRESHOLD; 843 break; 844 case LEAF_wlanIfaceRTSThreshold: 845 op = IEEE80211_IOC_RTSTHRESHOLD; 846 break; 847 case LEAF_wlanIfaceWlanPrivacySubscribe: 848 op = IEEE80211_IOC_WPS; 849 break; 850 case LEAF_wlanIfaceBgScan: 851 op = IEEE80211_IOC_BGSCAN; 852 break; 853 case LEAF_wlanIfaceBgScanIdle: 854 op = IEEE80211_IOC_BGSCAN_IDLE; 855 break; 856 case LEAF_wlanIfaceBgScanInterval: 857 op = IEEE80211_IOC_BGSCAN_INTERVAL; 858 break; 859 case LEAF_wlanIfaceBeaconMissedThreshold: 860 op = IEEE80211_IOC_BMISSTHRESHOLD; 861 break; 862 case LEAF_wlanIfaceDesiredBssid: 863 op = IEEE80211_IOC_BSSID; 864 break; 865 case LEAF_wlanIfaceRoamingMode: 866 op = IEEE80211_IOC_ROAMING; 867 break; 868 case LEAF_wlanIfaceDot11d: 869 op = IEEE80211_IOC_DOTD; 870 break; 871 case LEAF_wlanIfaceDot11h: 872 op = IEEE80211_IOC_DOTH; 873 break; 874 case LEAF_wlanIfaceDynamicWds: 875 op = IEEE80211_IOC_DWDS; 876 break; 877 case LEAF_wlanIfacePowerSave: 878 op = IEEE80211_IOC_POWERSAVE; 879 break; 880 case LEAF_wlanIfaceApBridge: 881 op = IEEE80211_IOC_APBRIDGE; 882 break; 883 case LEAF_wlanIfaceBeaconInterval: 884 op = IEEE80211_IOC_BEACON_INTERVAL; 885 break; 886 case LEAF_wlanIfaceDtimPeriod: 887 op = IEEE80211_IOC_DTIM_PERIOD; 888 break; 889 case LEAF_wlanIfaceHideSsid: 890 op = IEEE80211_IOC_HIDESSID; 891 break; 892 case LEAF_wlanIfaceInactivityProccess: 893 op = IEEE80211_IOC_INACTIVITY; 894 break; 895 case LEAF_wlanIfaceDot11gProtMode: 896 op = IEEE80211_IOC_PROTMODE; 897 break; 898 case LEAF_wlanIfaceDot11gPureMode: 899 op = IEEE80211_IOC_PUREG; 900 break; 901 case LEAF_wlanIfaceDot11nPureMode: 902 op = IEEE80211_IOC_PUREN; 903 break; 904 case LEAF_wlanIfaceDot11nAmpdu: 905 op = IEEE80211_IOC_AMPDU; 906 break; 907 case LEAF_wlanIfaceDot11nAmpduDensity: 908 op = IEEE80211_IOC_AMPDU_DENSITY; 909 break; 910 case LEAF_wlanIfaceDot11nAmpduLimit: 911 op = IEEE80211_IOC_AMPDU_LIMIT; 912 break; 913 case LEAF_wlanIfaceDot11nAmsdu: 914 op = IEEE80211_IOC_AMSDU; 915 break; 916 case LEAF_wlanIfaceDot11nAmsduLimit: 917 op = IEEE80211_IOC_AMSDU_LIMIT; 918 break; 919 case LEAF_wlanIfaceDot11nHighThroughput: 920 op = IEEE80211_IOC_HTCONF; 921 break; 922 case LEAF_wlanIfaceDot11nHTCompatible: 923 op = IEEE80211_IOC_HTCOMPAT; 924 break; 925 case LEAF_wlanIfaceDot11nHTProtMode: 926 op = IEEE80211_IOC_HTPROTMODE; 927 break; 928 case LEAF_wlanIfaceDot11nRIFS: 929 op = IEEE80211_IOC_RIFS; 930 break; 931 case LEAF_wlanIfaceDot11nShortGI: 932 op = IEEE80211_IOC_SHORTGI; 933 break; 934 case LEAF_wlanIfaceDot11nSMPSMode: 935 op = IEEE80211_IOC_SMPS; 936 break; 937 case LEAF_wlanIfaceTdmaSlot: 938 op = IEEE80211_IOC_TDMA_SLOT; 939 break; 940 case LEAF_wlanIfaceTdmaSlotCount: 941 op = IEEE80211_IOC_TDMA_SLOTCNT; 942 break; 943 case LEAF_wlanIfaceTdmaSlotLength: 944 op = IEEE80211_IOC_TDMA_SLOTLEN; 945 break; 946 case LEAF_wlanIfaceTdmaBeaconInterval: 947 op = IEEE80211_IOC_TDMA_BINTERVAL; 948 break; 949 default: 950 op = -1; 951 } 952 953 return (op); 954 } 955 956 static enum WlanRegDomainCode 957 wlan_regdomain_to_snmp(int which) 958 { 959 enum WlanRegDomainCode reg_domain; 960 961 switch (which) { 962 case SKU_FCC: 963 reg_domain = WlanRegDomainCode_fcc; 964 break; 965 case SKU_CA: 966 reg_domain = WlanRegDomainCode_ca; 967 break; 968 case SKU_ETSI: 969 reg_domain = WlanRegDomainCode_etsi; 970 break; 971 case SKU_ETSI2: 972 reg_domain = WlanRegDomainCode_etsi2; 973 break; 974 case SKU_ETSI3: 975 reg_domain = WlanRegDomainCode_etsi3; 976 break; 977 case SKU_FCC3: 978 reg_domain = WlanRegDomainCode_fcc3; 979 break; 980 case SKU_JAPAN: 981 reg_domain = WlanRegDomainCode_japan; 982 break; 983 case SKU_KOREA: 984 reg_domain = WlanRegDomainCode_korea; 985 break; 986 case SKU_APAC: 987 reg_domain = WlanRegDomainCode_apac; 988 break; 989 case SKU_APAC2: 990 reg_domain = WlanRegDomainCode_apac2; 991 break; 992 case SKU_APAC3: 993 reg_domain = WlanRegDomainCode_apac3; 994 break; 995 case SKU_ROW: 996 reg_domain = WlanRegDomainCode_row; 997 break; 998 case SKU_NONE: 999 reg_domain = WlanRegDomainCode_none; 1000 break; 1001 case SKU_DEBUG: 1002 reg_domain = WlanRegDomainCode_debug; 1003 break; 1004 case SKU_SR9: 1005 reg_domain = WlanRegDomainCode_sr9; 1006 break; 1007 case SKU_XR9: 1008 reg_domain = WlanRegDomainCode_xr9; 1009 break; 1010 case SKU_GZ901: 1011 reg_domain = WlanRegDomainCode_gz901; 1012 break; 1013 case 0: 1014 reg_domain = WlanRegDomainCode_none; 1015 break; 1016 default: 1017 syslog(LOG_ERR, "unknown regdomain (0x%x) ", which); 1018 reg_domain = WlanRegDomainCode_none; 1019 break; 1020 } 1021 1022 return (reg_domain); 1023 } 1024 1025 static int 1026 wlan_snmp_to_regdomain(enum WlanRegDomainCode regdomain) 1027 { 1028 int which; 1029 1030 switch (regdomain) { 1031 case WlanRegDomainCode_fcc: 1032 which = SKU_FCC; 1033 break; 1034 case WlanRegDomainCode_ca: 1035 which = SKU_CA; 1036 break; 1037 case WlanRegDomainCode_etsi: 1038 which = SKU_ETSI; 1039 break; 1040 case WlanRegDomainCode_etsi2: 1041 which = SKU_ETSI2; 1042 break; 1043 case WlanRegDomainCode_etsi3: 1044 which = SKU_ETSI3; 1045 break; 1046 case WlanRegDomainCode_fcc3: 1047 which = SKU_FCC3; 1048 break; 1049 case WlanRegDomainCode_japan: 1050 which = SKU_JAPAN; 1051 break; 1052 case WlanRegDomainCode_korea: 1053 which = SKU_KOREA; 1054 break; 1055 case WlanRegDomainCode_apac: 1056 which = SKU_APAC; 1057 break; 1058 case WlanRegDomainCode_apac2: 1059 which = SKU_APAC2; 1060 break; 1061 case WlanRegDomainCode_apac3: 1062 which = SKU_APAC3; 1063 break; 1064 case WlanRegDomainCode_row: 1065 which = SKU_ROW; 1066 break; 1067 case WlanRegDomainCode_none: 1068 which = SKU_NONE; 1069 break; 1070 case WlanRegDomainCode_debug: 1071 which = SKU_DEBUG; 1072 break; 1073 case WlanRegDomainCode_sr9: 1074 which = SKU_SR9; 1075 break; 1076 case WlanRegDomainCode_xr9: 1077 which = SKU_XR9; 1078 break; 1079 case WlanRegDomainCode_gz901: 1080 which = SKU_GZ901; 1081 break; 1082 default: 1083 syslog(LOG_ERR, "unknown snmp regdomain (0x%x) ", regdomain); 1084 which = SKU_NONE; 1085 break; 1086 } 1087 1088 return (which); 1089 } 1090 1091 static int 1092 wlan_config_get_country(struct wlan_iface *wif) 1093 { 1094 int val = 0; 1095 size_t argsize; 1096 struct ieee80211_regdomain regdomain; 1097 1098 memset(®domain, 0, sizeof(regdomain)); 1099 argsize = sizeof(regdomain); 1100 1101 if (wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, ®domain, 1102 &argsize, 0) < 0) 1103 return (-1); 1104 1105 wif->reg_domain = wlan_regdomain_to_snmp(regdomain.regdomain); 1106 wif->country_code[0] = regdomain.isocc[0]; 1107 wif->country_code[1] = regdomain.isocc[1]; 1108 wif->country_code[2] = regdomain.location; 1109 1110 return (0); 1111 } 1112 1113 static int 1114 wlan_config_set_country(struct wlan_iface *wif, char *ccode, int rdomain) 1115 { 1116 int val = 0, txpowermax; 1117 uint32_t i; 1118 size_t argsize = 0; 1119 struct ieee80211_regdomain_req *regdomain; 1120 1121 if (wlan_get_channel_list(wif) < 0) 1122 return (-1); 1123 1124 if (wif->nchannels == 0) { 1125 syslog(LOG_ERR, "iface %s - set regdomain failed", wif->wname); 1126 return (-1); 1127 } 1128 1129 if (wlan_ioctl(wif->wname, IEEE80211_IOC_TXPOWMAX, &txpowermax, 0, 1130 &argsize, 0) < 0) 1131 return (-1); 1132 1133 regdomain = malloc(IEEE80211_REGDOMAIN_SIZE(wif->nchannels)); 1134 if (regdomain == NULL) 1135 return (-1); 1136 memset(regdomain, 0, IEEE80211_REGDOMAIN_SIZE(wif->nchannels)); 1137 argsize = IEEE80211_REGDOMAIN_SIZE(wif->nchannels); 1138 1139 /* XXX: recheck with how this is done by ifconfig(8) */ 1140 regdomain->rd.regdomain = wlan_snmp_to_regdomain(rdomain); 1141 regdomain->rd.isocc[0] = ccode[0]; 1142 regdomain->rd.isocc[1] = ccode[1]; 1143 regdomain->rd.location = ccode[2]; 1144 1145 /* XXX: fill the channel list properly */ 1146 regdomain->chaninfo.ic_nchans = wif->nchannels; 1147 memcpy(regdomain->chaninfo.ic_chans, wif->chanlist, 1148 wif->nchannels * sizeof(struct ieee80211_channel)); 1149 for (i = 0; i < wif->nchannels; i++) 1150 regdomain->chaninfo.ic_chans[i].ic_maxregpower = txpowermax; 1151 1152 wif->state = wlanIfaceState_down; 1153 if (wlan_config_state(wif, 1) < 0 || 1154 wlan_ioctl(wif->wname, IEEE80211_IOC_REGDOMAIN, &val, regdomain, 1155 &argsize, 1) < 0) { 1156 free(regdomain); 1157 return (-1); 1158 } 1159 1160 wif->state = wlanIfaceState_up; 1161 (void)wlan_config_state(wif, 1); 1162 wif->reg_domain = wlan_regdomain_to_snmp(regdomain->rd.regdomain); 1163 wif->country_code[0] = regdomain->rd.isocc[0]; 1164 wif->country_code[1] = regdomain->rd.isocc[1]; 1165 wif->country_code[2] = regdomain->rd.location; 1166 free(regdomain); 1167 1168 return (0); 1169 } 1170 1171 int 1172 wlan_config_get_dssid(struct wlan_iface *wif) 1173 { 1174 int val = -1; 1175 size_t argsize = IEEE80211_NWID_LEN + 1; 1176 char ssid[IEEE80211_NWID_LEN + 1]; 1177 1178 memset(ssid, 0, IEEE80211_NWID_LEN + 1); 1179 1180 if (wlan_ioctl(wif->wname, 1181 (wif->mode == WlanIfaceOperatingModeType_meshPoint) ? 1182 IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid, 1183 &argsize, 0) < 0) 1184 return (-1); 1185 1186 if (argsize > IEEE80211_NWID_LEN) 1187 argsize = IEEE80211_NWID_LEN; 1188 memcpy(wif->desired_ssid, ssid, argsize); 1189 wif->desired_ssid[argsize] = '\0'; 1190 1191 return (0); 1192 } 1193 1194 int 1195 wlan_config_set_dssid(struct wlan_iface *wif, char *ssid, int slen) 1196 { 1197 int val = 0; 1198 size_t argsize = slen; 1199 1200 if (wlan_ioctl(wif->wname, 1201 (wif->mode == WlanIfaceOperatingModeType_meshPoint) ? 1202 IEEE80211_IOC_MESH_ID : IEEE80211_IOC_SSID, &val, ssid, 1203 &argsize, 1) < 0) 1204 return (-1); 1205 1206 if (argsize > IEEE80211_NWID_LEN) 1207 argsize = IEEE80211_NWID_LEN; 1208 memcpy(wif->desired_ssid, ssid, argsize); 1209 wif->desired_ssid[argsize] = '\0'; 1210 1211 return (0); 1212 } 1213 1214 static int 1215 wlan_config_get_dchannel(struct wlan_iface *wif) 1216 { 1217 uint32_t i = 0; 1218 int val = 0; 1219 size_t argsize = sizeof(struct ieee80211_channel); 1220 struct ieee80211_channel chan; 1221 1222 if (wlan_get_channel_list(wif) < 0) 1223 return (-1); 1224 1225 memset(&chan, 0, sizeof(chan)); 1226 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan, 1227 &argsize, 0) < 0) 1228 return (-1); 1229 1230 for (i = 0; i < wif->nchannels; i++) 1231 if (chan.ic_ieee == wif->chanlist[i].ic_ieee && 1232 chan.ic_flags == wif->chanlist[i].ic_flags) { 1233 wif->desired_channel = i + 1; 1234 break; 1235 } 1236 1237 return (0); 1238 } 1239 1240 static int 1241 wlan_config_set_dchannel(struct wlan_iface *wif, uint32_t dchannel) 1242 { 1243 int val = 0; 1244 size_t argsize = sizeof(struct ieee80211_channel); 1245 struct ieee80211_channel chan; 1246 1247 if (wlan_get_channel_list(wif) < 0) 1248 return (-1); 1249 1250 if (dchannel > wif->nchannels) 1251 return (-1); 1252 1253 memcpy(&chan, wif->chanlist + dchannel - 1, sizeof(chan)); 1254 if (wlan_ioctl(wif->wname, IEEE80211_IOC_CURCHAN, &val, &chan, 1255 &argsize, 1) < 0) 1256 return (-1); 1257 1258 wif->desired_channel = dchannel; 1259 1260 return (0); 1261 } 1262 1263 static int 1264 wlan_config_get_bssid(struct wlan_iface *wif) 1265 { 1266 int val = 0; 1267 size_t argsize = IEEE80211_ADDR_LEN; 1268 char bssid[IEEE80211_ADDR_LEN]; 1269 1270 memset(bssid, 0, IEEE80211_ADDR_LEN); 1271 1272 if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid, 1273 &argsize, 0) < 0 || argsize != IEEE80211_ADDR_LEN) 1274 return (-1); 1275 1276 memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN); 1277 1278 return (0); 1279 } 1280 1281 static int 1282 wlan_config_set_bssid(struct wlan_iface *wif, uint8_t *bssid) 1283 { 1284 int val = 0; 1285 size_t argsize = IEEE80211_ADDR_LEN; 1286 1287 if (wlan_ioctl(wif->wname, IEEE80211_IOC_BSSID, &val, bssid, 1288 &argsize, 1) < 0 || argsize != IEEE80211_ADDR_LEN) 1289 return (-1); 1290 1291 memcpy(wif->desired_bssid, bssid, IEEE80211_ADDR_LEN); 1292 1293 return (0); 1294 } 1295 1296 /* 1297 * Convert the value returned by the kernel to the appropriate SNMP 1298 * representation and set the corresponding interface member accordingly. 1299 */ 1300 static void 1301 wlan_config_set_snmp_intval(struct wlan_iface *wif, int op, int val) 1302 { 1303 switch (op) { 1304 case IEEE80211_IOC_BURST: 1305 if (val == 0) 1306 wif->packet_burst = TruthValue_false; 1307 else 1308 wif->packet_burst = TruthValue_true; 1309 break; 1310 case IEEE80211_IOC_DFS: 1311 if (val == 0) 1312 wif->dyn_frequency = TruthValue_false; 1313 else 1314 wif->dyn_frequency = TruthValue_true; 1315 break; 1316 case IEEE80211_IOC_FF: 1317 if (val == 0) 1318 wif->fast_frames = TruthValue_false; 1319 else 1320 wif->fast_frames = TruthValue_true; 1321 break; 1322 case IEEE80211_IOC_TURBOP: 1323 if (val == 0) 1324 wif->dturbo = TruthValue_false; 1325 else 1326 wif->dturbo = TruthValue_true; 1327 break; 1328 case IEEE80211_IOC_TXPOWER: 1329 wif->tx_power = val / 2; 1330 break; 1331 case IEEE80211_IOC_FRAGTHRESHOLD: 1332 wif->frag_threshold = val; 1333 break; 1334 case IEEE80211_IOC_RTSTHRESHOLD: 1335 wif->rts_threshold = val; 1336 break; 1337 case IEEE80211_IOC_WPS: 1338 if (val == 0) 1339 wif->priv_subscribe = TruthValue_false; 1340 else 1341 wif->priv_subscribe = TruthValue_true; 1342 break; 1343 case IEEE80211_IOC_BGSCAN: 1344 if (val == 0) 1345 wif->bg_scan = TruthValue_false; 1346 else 1347 wif->bg_scan = TruthValue_true; 1348 break; 1349 case IEEE80211_IOC_BGSCAN_IDLE: 1350 wif->bg_scan_idle = val; 1351 break; 1352 case IEEE80211_IOC_BGSCAN_INTERVAL: 1353 wif->bg_scan_interval = val; 1354 break; 1355 case IEEE80211_IOC_BMISSTHRESHOLD: 1356 wif->beacons_missed = val; 1357 break; 1358 case IEEE80211_IOC_ROAMING: 1359 switch (val) { 1360 case IEEE80211_ROAMING_DEVICE: 1361 wif->roam_mode = wlanIfaceRoamingMode_device; 1362 break; 1363 case IEEE80211_ROAMING_MANUAL: 1364 wif->roam_mode = wlanIfaceRoamingMode_manual; 1365 break; 1366 case IEEE80211_ROAMING_AUTO: 1367 /* FALTHROUGH */ 1368 default: 1369 wif->roam_mode = wlanIfaceRoamingMode_auto; 1370 break; 1371 } 1372 break; 1373 case IEEE80211_IOC_DOTD: 1374 if (val == 0) 1375 wif->dot11d = TruthValue_false; 1376 else 1377 wif->dot11d = TruthValue_true; 1378 break; 1379 case IEEE80211_IOC_DOTH: 1380 if (val == 0) 1381 wif->dot11h = TruthValue_false; 1382 else 1383 wif->dot11h = TruthValue_true; 1384 break; 1385 case IEEE80211_IOC_DWDS: 1386 if (val == 0) 1387 wif->dynamic_wds = TruthValue_false; 1388 else 1389 wif->dynamic_wds = TruthValue_true; 1390 break; 1391 case IEEE80211_IOC_POWERSAVE: 1392 if (val == 0) 1393 wif->power_save = TruthValue_false; 1394 else 1395 wif->power_save = TruthValue_true; 1396 break; 1397 case IEEE80211_IOC_APBRIDGE: 1398 if (val == 0) 1399 wif->ap_bridge = TruthValue_false; 1400 else 1401 wif->ap_bridge = TruthValue_true; 1402 break; 1403 case IEEE80211_IOC_BEACON_INTERVAL: 1404 wif->beacon_interval = val; 1405 break; 1406 case IEEE80211_IOC_DTIM_PERIOD: 1407 wif->dtim_period = val; 1408 break; 1409 case IEEE80211_IOC_HIDESSID: 1410 if (val == 0) 1411 wif->hide_ssid = TruthValue_false; 1412 else 1413 wif->hide_ssid = TruthValue_true; 1414 break; 1415 case IEEE80211_IOC_INACTIVITY: 1416 if (val == 0) 1417 wif->inact_process = TruthValue_false; 1418 else 1419 wif->inact_process = TruthValue_true; 1420 break; 1421 case IEEE80211_IOC_PROTMODE: 1422 switch (val) { 1423 case IEEE80211_PROTMODE_CTS: 1424 wif->do11g_protect = wlanIfaceDot11gProtMode_cts; 1425 break; 1426 case IEEE80211_PROTMODE_RTSCTS: 1427 wif->do11g_protect = wlanIfaceDot11gProtMode_rtscts; 1428 break; 1429 case IEEE80211_PROTMODE_OFF: 1430 /* FALLTHROUGH */ 1431 default: 1432 wif->do11g_protect = wlanIfaceDot11gProtMode_off; 1433 break; 1434 } 1435 break; 1436 case IEEE80211_IOC_PUREG: 1437 if (val == 0) 1438 wif->dot11g_pure = TruthValue_false; 1439 else 1440 wif->dot11g_pure = TruthValue_true; 1441 break; 1442 case IEEE80211_IOC_PUREN: 1443 if (val == 0) 1444 wif->dot11n_pure = TruthValue_false; 1445 else 1446 wif->dot11n_pure = TruthValue_true; 1447 break; 1448 case IEEE80211_IOC_AMPDU: 1449 switch (val) { 1450 case 0: 1451 wif->ampdu = WlanIfaceDot11nPduType_disabled; 1452 break; 1453 case 1: 1454 wif->ampdu = WlanIfaceDot11nPduType_txOnly; 1455 break; 1456 case 2: 1457 wif->ampdu = WlanIfaceDot11nPduType_rxOnly; 1458 break; 1459 case 3: 1460 /* FALLTHROUGH */ 1461 default: 1462 wif->ampdu = WlanIfaceDot11nPduType_txAndRx; 1463 break; 1464 } 1465 break; 1466 case IEEE80211_IOC_AMPDU_DENSITY: 1467 switch (val) { 1468 case IEEE80211_HTCAP_MPDUDENSITY_025: 1469 wif->ampdu_density = 25; 1470 break; 1471 case IEEE80211_HTCAP_MPDUDENSITY_05: 1472 wif->ampdu_density = 50; 1473 break; 1474 case IEEE80211_HTCAP_MPDUDENSITY_1: 1475 wif->ampdu_density = 100; 1476 break; 1477 case IEEE80211_HTCAP_MPDUDENSITY_2: 1478 wif->ampdu_density = 200; 1479 break; 1480 case IEEE80211_HTCAP_MPDUDENSITY_4: 1481 wif->ampdu_density = 400; 1482 break; 1483 case IEEE80211_HTCAP_MPDUDENSITY_8: 1484 wif->ampdu_density = 800; 1485 break; 1486 case IEEE80211_HTCAP_MPDUDENSITY_16: 1487 wif->ampdu_density = 1600; 1488 break; 1489 case IEEE80211_HTCAP_MPDUDENSITY_NA: 1490 default: 1491 wif->ampdu_density = 0; 1492 break; 1493 } 1494 break; 1495 case IEEE80211_IOC_AMPDU_LIMIT: 1496 switch (val) { 1497 case IEEE80211_HTCAP_MAXRXAMPDU_8K: 1498 wif->ampdu_limit = 8192; 1499 break; 1500 case IEEE80211_HTCAP_MAXRXAMPDU_16K: 1501 wif->ampdu_limit = 16384; 1502 break; 1503 case IEEE80211_HTCAP_MAXRXAMPDU_32K: 1504 wif->ampdu_limit = 32768; 1505 break; 1506 case IEEE80211_HTCAP_MAXRXAMPDU_64K: 1507 default: 1508 wif->ampdu_limit = 65536; 1509 break; 1510 } 1511 break; 1512 case IEEE80211_IOC_AMSDU: 1513 switch (val) { 1514 case 0: 1515 wif->amsdu = WlanIfaceDot11nPduType_disabled; 1516 break; 1517 case 1: 1518 wif->amsdu = WlanIfaceDot11nPduType_txOnly; 1519 break; 1520 case 3: 1521 wif->amsdu = WlanIfaceDot11nPduType_txAndRx; 1522 break; 1523 case 2: 1524 default: 1525 /* FALLTHROUGH */ 1526 wif->amsdu = WlanIfaceDot11nPduType_rxOnly; 1527 break; 1528 } 1529 break; 1530 case IEEE80211_IOC_AMSDU_LIMIT: 1531 wif->amsdu_limit = val; 1532 break; 1533 case IEEE80211_IOC_HTCONF: 1534 if (val == 0) /* XXX */ 1535 wif->ht_enabled = TruthValue_false; 1536 else 1537 wif->ht_enabled = TruthValue_true; 1538 break; 1539 case IEEE80211_IOC_HTCOMPAT: 1540 if (val == 0) 1541 wif->ht_compatible = TruthValue_false; 1542 else 1543 wif->ht_compatible = TruthValue_true; 1544 break; 1545 case IEEE80211_IOC_HTPROTMODE: 1546 if (val == IEEE80211_PROTMODE_RTSCTS) 1547 wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_rts; 1548 else 1549 wif->ht_prot_mode = wlanIfaceDot11nHTProtMode_off; 1550 break; 1551 case IEEE80211_IOC_RIFS: 1552 if (val == 0) 1553 wif->rifs = TruthValue_false; 1554 else 1555 wif->rifs = TruthValue_true; 1556 break; 1557 case IEEE80211_IOC_SHORTGI: 1558 if (val == 0) 1559 wif->short_gi = TruthValue_false; 1560 else 1561 wif->short_gi = TruthValue_true; 1562 break; 1563 case IEEE80211_IOC_SMPS: 1564 switch (val) { 1565 case IEEE80211_HTCAP_SMPS_DYNAMIC: 1566 wif->smps_mode = wlanIfaceDot11nSMPSMode_dynamic; 1567 break; 1568 case IEEE80211_HTCAP_SMPS_ENA: 1569 wif->smps_mode = wlanIfaceDot11nSMPSMode_static; 1570 break; 1571 case IEEE80211_HTCAP_SMPS_OFF: 1572 /* FALLTHROUGH */ 1573 default: 1574 wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled; 1575 break; 1576 } 1577 break; 1578 case IEEE80211_IOC_TDMA_SLOT: 1579 wif->tdma_slot = val; 1580 break; 1581 case IEEE80211_IOC_TDMA_SLOTCNT: 1582 wif->tdma_slot_count = val; 1583 break; 1584 case IEEE80211_IOC_TDMA_SLOTLEN: 1585 wif->tdma_slot_length = val; 1586 break; 1587 case IEEE80211_IOC_TDMA_BINTERVAL: 1588 wif->tdma_binterval = val; 1589 break; 1590 default: 1591 break; 1592 } 1593 } 1594 1595 /* 1596 * Convert an SNMP value to the kernel equivalent and also do sanity check 1597 * for each specific type. 1598 */ 1599 static int 1600 wlan_config_snmp2value(int which, int sval, int *value) 1601 { 1602 *value = 0; 1603 1604 switch (which) { 1605 case IEEE80211_IOC_BURST: 1606 case IEEE80211_IOC_DFS: 1607 case IEEE80211_IOC_FF: 1608 case IEEE80211_IOC_TURBOP: 1609 case IEEE80211_IOC_WPS: 1610 case IEEE80211_IOC_BGSCAN: 1611 case IEEE80211_IOC_DOTD: 1612 case IEEE80211_IOC_DOTH: 1613 case IEEE80211_IOC_DWDS: 1614 case IEEE80211_IOC_POWERSAVE: 1615 case IEEE80211_IOC_APBRIDGE: 1616 case IEEE80211_IOC_HIDESSID: 1617 case IEEE80211_IOC_INACTIVITY: 1618 case IEEE80211_IOC_PUREG: 1619 case IEEE80211_IOC_PUREN: 1620 case IEEE80211_IOC_HTCONF: 1621 case IEEE80211_IOC_HTCOMPAT: 1622 case IEEE80211_IOC_RIFS: 1623 if (sval == TruthValue_true) 1624 *value = 1; 1625 else if (sval != TruthValue_false) 1626 return (SNMP_ERR_INCONS_VALUE); 1627 break; 1628 case IEEE80211_IOC_REGDOMAIN: 1629 break; 1630 case IEEE80211_IOC_SSID: 1631 break; 1632 case IEEE80211_IOC_CURCHAN: 1633 break; 1634 case IEEE80211_IOC_TXPOWER: 1635 *value = sval * 2; 1636 break; 1637 case IEEE80211_IOC_FRAGTHRESHOLD: 1638 if (sval < IEEE80211_FRAG_MIN || sval > IEEE80211_FRAG_MAX) 1639 return (SNMP_ERR_INCONS_VALUE); 1640 *value = sval; 1641 break; 1642 case IEEE80211_IOC_RTSTHRESHOLD: 1643 if (sval < IEEE80211_RTS_MIN || sval > IEEE80211_RTS_MAX) 1644 return (SNMP_ERR_INCONS_VALUE); 1645 *value = sval; 1646 break; 1647 case IEEE80211_IOC_BGSCAN_IDLE: 1648 if (sval < WLAN_BGSCAN_IDLE_MIN) 1649 return (SNMP_ERR_INCONS_VALUE); 1650 *value = sval; 1651 break; 1652 case IEEE80211_IOC_BGSCAN_INTERVAL: 1653 if (sval < WLAN_SCAN_VALID_MIN) 1654 return (SNMP_ERR_INCONS_VALUE); 1655 *value = sval; 1656 break; 1657 case IEEE80211_IOC_BMISSTHRESHOLD: 1658 if (sval < IEEE80211_HWBMISS_MIN || sval > IEEE80211_HWBMISS_MAX) 1659 return (SNMP_ERR_INCONS_VALUE); 1660 *value = sval; 1661 break; 1662 case IEEE80211_IOC_BSSID: 1663 break; 1664 case IEEE80211_IOC_ROAMING: 1665 switch (sval) { 1666 case wlanIfaceRoamingMode_device: 1667 *value = IEEE80211_ROAMING_DEVICE; 1668 break; 1669 case wlanIfaceRoamingMode_manual: 1670 *value = IEEE80211_ROAMING_MANUAL; 1671 break; 1672 case wlanIfaceRoamingMode_auto: 1673 *value = IEEE80211_ROAMING_AUTO; 1674 break; 1675 default: 1676 return (SNMP_ERR_INCONS_VALUE); 1677 } 1678 break; 1679 case IEEE80211_IOC_BEACON_INTERVAL: 1680 if (sval < IEEE80211_BINTVAL_MIN || sval > IEEE80211_BINTVAL_MAX) 1681 return (SNMP_ERR_INCONS_VALUE); 1682 *value = sval; 1683 break; 1684 case IEEE80211_IOC_DTIM_PERIOD: 1685 if (sval < IEEE80211_DTIM_MIN || sval > IEEE80211_DTIM_MAX) 1686 return (SNMP_ERR_INCONS_VALUE); 1687 *value = sval; 1688 break; 1689 case IEEE80211_IOC_PROTMODE: 1690 switch (sval) { 1691 case wlanIfaceDot11gProtMode_cts: 1692 *value = IEEE80211_PROTMODE_CTS; 1693 break; 1694 case wlanIfaceDot11gProtMode_rtscts: 1695 *value = IEEE80211_PROTMODE_RTSCTS; 1696 break; 1697 case wlanIfaceDot11gProtMode_off: 1698 *value = IEEE80211_PROTMODE_OFF; 1699 break; 1700 default: 1701 return (SNMP_ERR_INCONS_VALUE); 1702 } 1703 break; 1704 case IEEE80211_IOC_AMPDU: 1705 switch (sval) { 1706 case WlanIfaceDot11nPduType_disabled: 1707 break; 1708 case WlanIfaceDot11nPduType_txOnly: 1709 *value = 1; 1710 break; 1711 case WlanIfaceDot11nPduType_rxOnly: 1712 *value = 2; 1713 break; 1714 case WlanIfaceDot11nPduType_txAndRx: 1715 *value = 3; 1716 break; 1717 default: 1718 return (SNMP_ERR_INCONS_VALUE); 1719 } 1720 break; 1721 case IEEE80211_IOC_AMPDU_DENSITY: 1722 switch (sval) { 1723 case 0: 1724 *value = IEEE80211_HTCAP_MPDUDENSITY_NA; 1725 break; 1726 case 25: 1727 *value = IEEE80211_HTCAP_MPDUDENSITY_025; 1728 break; 1729 case 50: 1730 *value = IEEE80211_HTCAP_MPDUDENSITY_05; 1731 break; 1732 case 100: 1733 *value = IEEE80211_HTCAP_MPDUDENSITY_1; 1734 break; 1735 case 200: 1736 *value = IEEE80211_HTCAP_MPDUDENSITY_2; 1737 break; 1738 case 400: 1739 *value = IEEE80211_HTCAP_MPDUDENSITY_4; 1740 break; 1741 case 800: 1742 *value = IEEE80211_HTCAP_MPDUDENSITY_8; 1743 break; 1744 case 1600: 1745 *value = IEEE80211_HTCAP_MPDUDENSITY_16; 1746 break; 1747 default: 1748 return (SNMP_ERR_INCONS_VALUE); 1749 } 1750 break; 1751 case IEEE80211_IOC_AMPDU_LIMIT: 1752 switch (sval) { 1753 case 8192: 1754 *value = IEEE80211_HTCAP_MAXRXAMPDU_8K; 1755 break; 1756 case 16384: 1757 *value = IEEE80211_HTCAP_MAXRXAMPDU_16K; 1758 break; 1759 case 32768: 1760 *value = IEEE80211_HTCAP_MAXRXAMPDU_32K; 1761 break; 1762 case 65536: 1763 *value = IEEE80211_HTCAP_MAXRXAMPDU_64K; 1764 break; 1765 default: 1766 return (SNMP_ERR_INCONS_VALUE); 1767 } 1768 break; 1769 case IEEE80211_IOC_AMSDU: 1770 switch (sval) { 1771 case WlanIfaceDot11nPduType_disabled: 1772 break; 1773 case WlanIfaceDot11nPduType_txOnly: 1774 *value = 1; 1775 break; 1776 case WlanIfaceDot11nPduType_rxOnly: 1777 *value = 2; 1778 break; 1779 case WlanIfaceDot11nPduType_txAndRx: 1780 *value = 3; 1781 break; 1782 default: 1783 return (SNMP_ERR_INCONS_VALUE); 1784 } 1785 break; 1786 case IEEE80211_IOC_AMSDU_LIMIT: 1787 if (sval == 3839 || sval == 0) 1788 *value = IEEE80211_HTCAP_MAXAMSDU_3839; 1789 else if (sval == 7935) 1790 *value = IEEE80211_HTCAP_MAXAMSDU_7935; 1791 else 1792 return (SNMP_ERR_INCONS_VALUE); 1793 break; 1794 case IEEE80211_IOC_HTPROTMODE: 1795 switch (sval) { 1796 case wlanIfaceDot11nHTProtMode_rts: 1797 *value = IEEE80211_PROTMODE_RTSCTS; 1798 break; 1799 case wlanIfaceDot11nHTProtMode_off: 1800 break; 1801 default: 1802 return (SNMP_ERR_INCONS_VALUE); 1803 } 1804 break; 1805 case IEEE80211_IOC_SHORTGI: 1806 if (sval == TruthValue_true) 1807 *value = IEEE80211_HTCAP_SHORTGI20 | 1808 IEEE80211_HTCAP_SHORTGI40; 1809 else if (sval != TruthValue_false) 1810 return (SNMP_ERR_INCONS_VALUE); 1811 break; 1812 case IEEE80211_IOC_SMPS: 1813 switch (sval) { 1814 case wlanIfaceDot11nSMPSMode_disabled: 1815 *value = IEEE80211_HTCAP_SMPS_OFF; 1816 break; 1817 case wlanIfaceDot11nSMPSMode_static: 1818 *value = IEEE80211_HTCAP_SMPS_ENA; 1819 break; 1820 case wlanIfaceDot11nSMPSMode_dynamic: 1821 *value = IEEE80211_HTCAP_SMPS_DYNAMIC; 1822 break; 1823 default: 1824 return (SNMP_ERR_INCONS_VALUE); 1825 } 1826 break; 1827 case IEEE80211_IOC_TDMA_SLOT: 1828 if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */ 1829 return (SNMP_ERR_INCONS_VALUE); 1830 *value = sval; 1831 break; 1832 case IEEE80211_IOC_TDMA_SLOTCNT: 1833 if (sval < 0 || sval > WLAN_TDMA_MAXSLOTS) /* XXX */ 1834 return (SNMP_ERR_INCONS_VALUE); 1835 *value = sval; 1836 break; 1837 case IEEE80211_IOC_TDMA_SLOTLEN: 1838 if (sval < 2*100 || sval > 0xfffff) /* XXX */ 1839 return (SNMP_ERR_INCONS_VALUE); 1840 *value = sval; 1841 break; 1842 case IEEE80211_IOC_TDMA_BINTERVAL: 1843 if (sval < 1) /* XXX */ 1844 return (SNMP_ERR_INCONS_VALUE); 1845 *value = sval; 1846 break; 1847 default: 1848 return (SNMP_ERR_INCONS_VALUE); 1849 } 1850 1851 return (SNMP_ERR_NOERROR); 1852 } 1853 1854 /* 1855 * Sanity checks for the wlanIfaceConfigTable. 1856 */ 1857 static int 1858 wlan_config_check(struct wlan_iface *wif, int op) 1859 { 1860 switch (op) { 1861 case IEEE80211_IOC_BURST: 1862 if ((wif->drivercaps & (0x1 << WlanDriverCaps_burst)) == 0) { 1863 wif->packet_burst = TruthValue_false; 1864 return (-1); 1865 } 1866 break; 1867 case IEEE80211_IOC_DFS: 1868 if ((wif->drivercaps & (0x1 << WlanDriverCaps_dfs)) == 0) { 1869 wif->dyn_frequency = TruthValue_false; 1870 return (-1); 1871 } 1872 break; 1873 case IEEE80211_IOC_FF: 1874 if ((wif->drivercaps & (0x1 << WlanDriverCaps_athFastFrames)) 1875 == 0) { 1876 wif->fast_frames = TruthValue_false; 1877 return (-1); 1878 } 1879 break; 1880 case IEEE80211_IOC_TURBOP: 1881 if ((wif->drivercaps & (0x1 << WlanDriverCaps_athTurbo)) == 0) { 1882 wif->dturbo = TruthValue_false; 1883 return (-1); 1884 } 1885 break; 1886 case IEEE80211_IOC_TXPOWER: 1887 if ((wif->drivercaps & (0x1 << WlanDriverCaps_txPmgt)) == 0) { 1888 wif->tx_power = 0; 1889 return (-1); 1890 } 1891 break; 1892 case IEEE80211_IOC_FRAGTHRESHOLD: 1893 if ((wif->drivercaps & (0x1 << WlanDriverCaps_txFrag)) == 0) { 1894 wif->frag_threshold = IEEE80211_FRAG_MAX; 1895 return (-1); 1896 } 1897 break; 1898 case IEEE80211_IOC_DWDS: 1899 if ((wif->drivercaps & (0x1 << WlanDriverCaps_wds)) == 0) { 1900 wif->dynamic_wds = TruthValue_false; 1901 return (-1); 1902 } 1903 break; 1904 case IEEE80211_IOC_POWERSAVE: 1905 if ((wif->drivercaps & (0x1 << WlanDriverCaps_pmgt)) == 0) { 1906 wif->power_save = TruthValue_false; 1907 return (-1); 1908 } 1909 break; 1910 case IEEE80211_IOC_BEACON_INTERVAL: 1911 if (wif->mode != WlanIfaceOperatingModeType_hostAp && 1912 wif->mode != WlanIfaceOperatingModeType_meshPoint && 1913 wif->mode != WlanIfaceOperatingModeType_ibss) { 1914 wif->beacon_interval = 100; /* XXX */ 1915 return (-1); 1916 } 1917 break; 1918 case IEEE80211_IOC_DTIM_PERIOD: 1919 if (wif->mode != WlanIfaceOperatingModeType_hostAp && 1920 wif->mode != WlanIfaceOperatingModeType_meshPoint && 1921 wif->mode != WlanIfaceOperatingModeType_ibss) { 1922 wif->dtim_period = 1; /* XXX */ 1923 return (-1); 1924 } 1925 break; 1926 case IEEE80211_IOC_PUREN: 1927 if ((wif->htcaps & (0x1 << WlanHTCaps_htcHt)) == 0) { 1928 wif->dot11n_pure = TruthValue_false; 1929 return (-1); 1930 } 1931 break; 1932 case IEEE80211_IOC_AMPDU: 1933 if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmpdu)) == 0) { 1934 wif->ampdu = WlanIfaceDot11nPduType_disabled; 1935 return (-1); 1936 } 1937 break; 1938 case IEEE80211_IOC_AMSDU: 1939 if ((wif->htcaps & (0x1 << WlanHTCaps_htcAmsdu)) == 0) { 1940 wif->amsdu = WlanIfaceDot11nPduType_disabled; 1941 return (-1); 1942 } 1943 break; 1944 case IEEE80211_IOC_RIFS: 1945 if ((wif->htcaps & (0x1 << WlanHTCaps_htcRifs)) == 0) { 1946 wif->rifs = TruthValue_false; 1947 return (-1); 1948 } 1949 break; 1950 case IEEE80211_IOC_SHORTGI: 1951 if ((wif->htcaps & (0x1 << WlanHTCaps_shortGi20 | 1952 0x1 << WlanHTCaps_shortGi40)) == 0) { 1953 wif->short_gi = TruthValue_false; 1954 return (-1); 1955 } 1956 break; 1957 case IEEE80211_IOC_SMPS: 1958 if ((wif->htcaps & (0x1 << WlanHTCaps_htcSmps)) == 0) { 1959 wif->smps_mode = wlanIfaceDot11nSMPSMode_disabled; 1960 return (-1); 1961 } 1962 break; 1963 case IEEE80211_IOC_TDMA_SLOT: 1964 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1965 wif->tdma_slot = 0; 1966 return (-1); 1967 } 1968 break; 1969 case IEEE80211_IOC_TDMA_SLOTCNT: 1970 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1971 wif->tdma_slot_count = 0; 1972 return (-1); 1973 } 1974 break; 1975 case IEEE80211_IOC_TDMA_SLOTLEN: 1976 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1977 wif->tdma_slot_length = 0; 1978 return (-1); 1979 } 1980 break; 1981 case IEEE80211_IOC_TDMA_BINTERVAL: 1982 if ((wif->drivercaps & (0x1 << WlanDriverCaps_tdma)) == 0) { 1983 wif->tdma_binterval = 0; 1984 return (-1); 1985 } 1986 break; 1987 default: 1988 break; 1989 } 1990 1991 return (0); 1992 } 1993 1994 static int 1995 wlan_config_get_intval(struct wlan_iface *wif, int op) 1996 { 1997 int val = 0; 1998 size_t argsize = 0; 1999 2000 if (wlan_config_check(wif, op) < 0) 2001 return (0); 2002 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0) 2003 return (-1); 2004 wlan_config_set_snmp_intval(wif, op, val); 2005 2006 return (0); 2007 } 2008 2009 static int 2010 wlan_config_set_intval(struct wlan_iface *wif, int op, int sval) 2011 { 2012 size_t argsize = 0; 2013 int val; 2014 2015 if (wlan_config_check(wif, op) < 0) 2016 return (-1); 2017 if (wlan_config_snmp2value(op, sval, &val) != SNMP_ERR_NOERROR) 2018 return (-1); 2019 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0) 2020 return (-1); 2021 wlan_config_set_snmp_intval(wif, op, val); 2022 2023 return (0); 2024 } 2025 2026 int 2027 wlan_config_get_ioctl(struct wlan_iface *wif, int which) 2028 { 2029 int op; 2030 2031 switch (which) { 2032 case LEAF_wlanIfaceCountryCode: 2033 /* FALLTHROUGH */ 2034 case LEAF_wlanIfaceRegDomain: 2035 return (wlan_config_get_country(wif)); 2036 case LEAF_wlanIfaceDesiredSsid: 2037 return (wlan_config_get_dssid(wif)); 2038 case LEAF_wlanIfaceDesiredChannel: 2039 return (wlan_config_get_dchannel(wif)); 2040 case LEAF_wlanIfaceDesiredBssid: 2041 return (wlan_config_get_bssid(wif)); 2042 default: 2043 op = wlan_config_snmp2ioctl(which); 2044 return (wlan_config_get_intval(wif, op)); 2045 } 2046 2047 return (-1); 2048 } 2049 2050 int 2051 wlan_config_set_ioctl(struct wlan_iface *wif, int which, int val, 2052 char *strval, int len) 2053 { 2054 int op; 2055 2056 switch (which) { 2057 case LEAF_wlanIfaceCountryCode: 2058 return (wlan_config_set_country(wif, strval, 2059 wif->reg_domain)); 2060 case LEAF_wlanIfaceRegDomain: 2061 return (wlan_config_set_country(wif, wif->country_code, 2062 val)); 2063 case LEAF_wlanIfaceDesiredSsid: 2064 return (wlan_config_set_dssid(wif, strval, len)); 2065 case LEAF_wlanIfaceDesiredChannel: 2066 return (wlan_config_set_dchannel(wif, val)); 2067 case LEAF_wlanIfaceDesiredBssid: 2068 return (wlan_config_set_bssid(wif, strval)); 2069 default: 2070 op = wlan_config_snmp2ioctl(which); 2071 return (wlan_config_set_intval(wif, op, val)); 2072 } 2073 2074 return (-1); 2075 } 2076 2077 static uint32_t 2078 wlan_snmp_to_scan_flags(int flags) 2079 { 2080 int sr_flags = 0; 2081 2082 if ((flags & (0x1 << WlanScanFlagsType_noSelection)) != 0) 2083 sr_flags |= IEEE80211_IOC_SCAN_NOPICK; 2084 if ((flags & (0x1 << WlanScanFlagsType_activeScan)) != 0) 2085 sr_flags |= IEEE80211_IOC_SCAN_ACTIVE; 2086 if ((flags & (0x1 << WlanScanFlagsType_pickFirst)) != 0) 2087 sr_flags |= IEEE80211_IOC_SCAN_PICK1ST; 2088 if ((flags & (0x1 << WlanScanFlagsType_backgroundScan)) != 0) 2089 sr_flags |= IEEE80211_IOC_SCAN_BGSCAN; 2090 if ((flags & (0x1 << WlanScanFlagsType_once)) != 0) 2091 sr_flags |= IEEE80211_IOC_SCAN_ONCE; 2092 if ((flags & (0x1 << WlanScanFlagsType_noBroadcast)) != 0) 2093 sr_flags |= IEEE80211_IOC_SCAN_NOBCAST; 2094 if ((flags & (0x1 << WlanScanFlagsType_noAutoSequencing)) != 0) 2095 sr_flags |= IEEE80211_IOC_SCAN_NOJOIN; 2096 if ((flags & (0x1 << WlanScanFlagsType_flushCashe)) != 0) 2097 sr_flags |= IEEE80211_IOC_SCAN_FLUSH; 2098 if ((flags & (0x1 << WlanScanFlagsType_chechCashe)) != 0) 2099 sr_flags |= IEEE80211_IOC_SCAN_CHECK; 2100 2101 return (sr_flags); 2102 } 2103 2104 int 2105 wlan_set_scan_config(struct wlan_iface *wif) 2106 { 2107 int val = 0; 2108 size_t argsize; 2109 struct ieee80211_scan_req sr; 2110 2111 2112 memset(&sr, 0, sizeof(sr)); 2113 argsize = sizeof(struct ieee80211_scan_req); 2114 sr.sr_flags = wlan_snmp_to_scan_flags(wif->scan_flags); 2115 sr.sr_flags |= IEEE80211_IOC_SCAN_BGSCAN; 2116 sr.sr_duration = wif->scan_duration; 2117 sr.sr_mindwell = wif->scan_mindwell; 2118 sr.sr_maxdwell = wif->scan_maxdwell; 2119 sr.sr_nssid = 0; 2120 2121 if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_REQ, 2122 &val, &sr, &argsize, 1) < 0) 2123 return (-1); 2124 2125 wif->scan_status = wlanScanConfigStatus_running; 2126 return (0); 2127 } 2128 2129 static uint32_t 2130 wlan_peercaps_to_snmp(uint32_t pcaps) 2131 { 2132 uint32_t scaps = 0; 2133 2134 if ((pcaps & IEEE80211_CAPINFO_ESS) != 0) 2135 scaps |= (0x1 << WlanPeerCapabilityFlags_ess); 2136 if ((pcaps & IEEE80211_CAPINFO_IBSS) != 0) 2137 scaps |= (0x1 << WlanPeerCapabilityFlags_ibss); 2138 if ((pcaps & IEEE80211_CAPINFO_CF_POLLABLE) != 0) 2139 scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollable); 2140 if ((pcaps & IEEE80211_CAPINFO_CF_POLLREQ) != 0) 2141 scaps |= (0x1 << WlanPeerCapabilityFlags_cfPollRequest); 2142 if ((pcaps & IEEE80211_CAPINFO_PRIVACY) != 0) 2143 scaps |= (0x1 << WlanPeerCapabilityFlags_privacy); 2144 if ((pcaps & IEEE80211_CAPINFO_SHORT_PREAMBLE) != 0) 2145 scaps |= (0x1 << WlanPeerCapabilityFlags_shortPreamble); 2146 if ((pcaps & IEEE80211_CAPINFO_PBCC) != 0) 2147 scaps |= (0x1 << WlanPeerCapabilityFlags_pbcc); 2148 if ((pcaps & IEEE80211_CAPINFO_CHNL_AGILITY) != 0) 2149 scaps |= (0x1 << WlanPeerCapabilityFlags_channelAgility); 2150 if ((pcaps & IEEE80211_CAPINFO_SHORT_SLOTTIME) != 0) 2151 scaps |= (0x1 << WlanPeerCapabilityFlags_shortSlotTime); 2152 if ((pcaps & IEEE80211_CAPINFO_RSN) != 0) 2153 scaps |= (0x1 << WlanPeerCapabilityFlags_rsn); 2154 if ((pcaps & IEEE80211_CAPINFO_DSSSOFDM) != 0) 2155 scaps |= (0x1 << WlanPeerCapabilityFlags_dsssofdm); 2156 2157 return (scaps); 2158 } 2159 2160 static int 2161 wlan_add_new_scan_result(struct wlan_iface *wif, 2162 const struct ieee80211req_scan_result *isr, uint8_t *ssid) 2163 { 2164 struct wlan_scan_result *sr; 2165 2166 if ((sr = wlan_scan_new_result(ssid, isr->isr_bssid)) == NULL) 2167 return (-1); 2168 2169 sr->opchannel = wlan_channel_flags_to_snmp_phy(isr->isr_flags); 2170 sr->rssi = isr->isr_rssi; 2171 sr->frequency = isr->isr_freq; 2172 sr->noise = isr->isr_noise; 2173 sr->bintval = isr->isr_intval; 2174 sr->capinfo = wlan_peercaps_to_snmp(isr->isr_capinfo); 2175 2176 if (wlan_scan_add_result(wif, sr) < 0) { 2177 wlan_scan_free_result(sr); 2178 return (-1); 2179 } 2180 2181 return (0); 2182 } 2183 2184 int 2185 wlan_get_scan_results(struct wlan_iface *wif) 2186 { 2187 int ssidlen, val = 0; 2188 uint8_t buf[24 * 1024]; 2189 size_t argsize; 2190 const uint8_t *cp, *idp; 2191 uint8_t ssid[IEEE80211_NWID_LEN + 1]; 2192 struct ieee80211req_scan_result isr; 2193 2194 argsize = sizeof(buf); 2195 if (wlan_ioctl(wif->wname, IEEE80211_IOC_SCAN_RESULTS, &val, &buf, 2196 &argsize, 0) < 0) 2197 return (-1); 2198 2199 if (argsize < sizeof(struct ieee80211req_scan_result)) 2200 return (0); 2201 2202 cp = buf; 2203 do { 2204 memcpy(&isr, cp, sizeof(struct ieee80211req_scan_result)); 2205 memset(ssid, 0, IEEE80211_NWID_LEN + 1); 2206 2207 if (isr.isr_meshid_len) { 2208 idp = cp + isr.isr_ie_off + isr.isr_ssid_len; 2209 ssidlen = isr.isr_meshid_len; 2210 } else { 2211 idp = cp + isr.isr_ie_off; 2212 ssidlen = isr.isr_ssid_len; 2213 } 2214 if (ssidlen > IEEE80211_NWID_LEN) 2215 ssidlen = IEEE80211_NWID_LEN; 2216 memcpy(ssid, idp, ssidlen); 2217 ssid[IEEE80211_NWID_LEN] = '\0'; 2218 (void)wlan_add_new_scan_result(wif, &isr, ssid); 2219 cp += isr.isr_len; 2220 argsize -= isr.isr_len; 2221 } while (argsize >= sizeof(struct ieee80211req_scan_result)); 2222 2223 return (0); 2224 } 2225 2226 int 2227 wlan_get_stats(struct wlan_iface *wif) 2228 { 2229 struct ifreq ifr; 2230 2231 memset(&ifr, 0, sizeof(struct ifreq)); 2232 strlcpy(ifr.ifr_name, wif->wname, IFNAMSIZ); 2233 2234 ifr.ifr_data = (caddr_t) &wif->stats; 2235 2236 if (ioctl(sock, SIOCG80211STATS, &ifr) < 0) { 2237 syslog(LOG_ERR, "iface %s - ioctl(SIOCG80211STATS) failed: %s", 2238 wif->wname, strerror(errno)); 2239 return (-1); 2240 } 2241 2242 return (0); 2243 } 2244 2245 int 2246 wlan_get_wepmode(struct wlan_iface *wif) 2247 { 2248 int val = 0; 2249 size_t argsize = 0; 2250 2251 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL, 2252 &argsize, 0) < 0 || val == IEEE80211_WEP_NOSUP) { 2253 wif->wepsupported = 0; /* XXX */ 2254 wif->wepmode = wlanWepMode_off; 2255 wif->weptxkey = 0; 2256 return (-1); 2257 } 2258 2259 wif->wepsupported = 1; 2260 2261 switch (val) { 2262 case IEEE80211_WEP_ON: 2263 wif->wepmode = wlanWepMode_on; 2264 break; 2265 case IEEE80211_WEP_MIXED: 2266 wif->wepmode = wlanWepMode_mixed; 2267 break; 2268 case IEEE80211_WEP_OFF: 2269 /* FALLTHROUGH */ 2270 default: 2271 wif->wepmode = wlanWepMode_off; 2272 break; 2273 } 2274 2275 return (0); 2276 } 2277 2278 int 2279 wlan_set_wepmode(struct wlan_iface *wif) 2280 { 2281 int val; 2282 size_t argsize = 0; 2283 2284 if (!wif->wepsupported) 2285 return (-1); 2286 2287 switch (wif->wepmode) { 2288 case wlanWepMode_off: 2289 val = IEEE80211_WEP_OFF; 2290 break; 2291 case wlanWepMode_on: 2292 val = IEEE80211_WEP_ON; 2293 break; 2294 case wlanWepMode_mixed: 2295 val = IEEE80211_WEP_MIXED; 2296 break; 2297 default: 2298 return (-1); 2299 } 2300 2301 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEP, &val, NULL, 2302 &argsize, 1) < 0) 2303 return (-1); 2304 2305 return (0); 2306 } 2307 2308 int 2309 wlan_get_weptxkey(struct wlan_iface *wif) 2310 { 2311 int val; 2312 size_t argsize = 0; 2313 2314 if (!wif->wepsupported) 2315 return (0); 2316 2317 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL, 2318 &argsize, 0) < 0) 2319 return (-1); 2320 2321 if (val == IEEE80211_KEYIX_NONE) 2322 wif->weptxkey = 0; 2323 else 2324 wif->weptxkey = val + 1; 2325 2326 return (0); 2327 } 2328 2329 int 2330 wlan_set_weptxkey(struct wlan_iface *wif) 2331 { 2332 int val; 2333 size_t argsize = 0; 2334 2335 if (!wif->wepsupported) 2336 return (0); 2337 2338 if (wif->weptxkey >= IEEE80211_WEP_NKID) 2339 return (-1); 2340 2341 if (wif->weptxkey == 0) 2342 val = IEEE80211_KEYIX_NONE; 2343 else 2344 val = wif->weptxkey - 1; 2345 if (wlan_ioctl(wif->wname, IEEE80211_IOC_WEPTXKEY, &val, NULL, 2346 &argsize, 1) < 0) 2347 return (-1); 2348 2349 return (0); 2350 } 2351 2352 int 2353 wlan_get_wepkeys(struct wlan_iface *wif __unused) 2354 { 2355 /* XXX: should they be visible via SNMP */ 2356 return (0); 2357 } 2358 2359 int 2360 wlan_set_wepkeys(struct wlan_iface *wif __unused) 2361 { 2362 /* XXX: should they be configurable via SNMP */ 2363 return (0); 2364 } 2365 2366 int 2367 wlan_get_mac_policy(struct wlan_iface *wif) 2368 { 2369 int val = IEEE80211_MACCMD_POLICY; 2370 size_t argsize = 0; 2371 struct ieee80211req ireq; 2372 2373 memset(&ireq, 0, sizeof(struct ieee80211req)); 2374 strlcpy(ireq.i_name, wif->wname, IFNAMSIZ); 2375 ireq.i_type = IEEE80211_IOC_MACCMD; 2376 ireq.i_val = IEEE80211_MACCMD_POLICY; 2377 2378 if (ioctl(sock, SIOCG80211, &ireq) < 0) { 2379 if (errno != EINVAL) { 2380 syslog(LOG_ERR, "iface %s - get param: ioctl(%d) " 2381 "failed: %s", wif->wname, ireq.i_type, 2382 strerror(errno)); 2383 wif->macsupported = 0; 2384 return (-1); 2385 } else { 2386 wif->macsupported = 1; 2387 wif->mac_policy = wlanMACAccessControlPolicy_open; 2388 return (0); 2389 } 2390 2391 } 2392 2393 wif->macsupported = 1; 2394 2395 switch (val) { 2396 case IEEE80211_MACCMD_POLICY_ALLOW: 2397 wif->mac_policy = wlanMACAccessControlPolicy_allow; 2398 break; 2399 case IEEE80211_MACCMD_POLICY_DENY: 2400 wif->mac_policy = wlanMACAccessControlPolicy_deny; 2401 break; 2402 case IEEE80211_MACCMD_POLICY_RADIUS: 2403 wif->mac_policy = wlanMACAccessControlPolicy_radius; 2404 break; 2405 case IEEE80211_MACCMD_POLICY_OPEN: 2406 /* FALLTHROUGH */ 2407 default: 2408 wif->mac_policy = wlanMACAccessControlPolicy_open; 2409 break; 2410 } 2411 2412 argsize = 0; 2413 val = IEEE80211_MACCMD_LIST; 2414 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2415 &argsize, 0) < 0) 2416 return (-1); 2417 2418 wif->mac_nacls = argsize / sizeof(struct ieee80211req_maclist *); 2419 return (0); 2420 } 2421 2422 int 2423 wlan_set_mac_policy(struct wlan_iface *wif) 2424 { 2425 int val; 2426 size_t argsize = 0; 2427 2428 if (!wif->macsupported) 2429 return (-1); 2430 2431 switch (wif->mac_policy) { 2432 case wlanMACAccessControlPolicy_allow: 2433 val = IEEE80211_MACCMD_POLICY_ALLOW; 2434 break; 2435 case wlanMACAccessControlPolicy_deny: 2436 val = IEEE80211_MACCMD_POLICY_DENY; 2437 break; 2438 case wlanMACAccessControlPolicy_radius: 2439 val = IEEE80211_MACCMD_POLICY_RADIUS; 2440 break; 2441 case wlanMACAccessControlPolicy_open: 2442 val = IEEE80211_MACCMD_POLICY_OPEN; 2443 break; 2444 default: 2445 return (-1); 2446 } 2447 2448 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2449 &argsize, 1) < 0) 2450 return (-1); 2451 2452 return (0); 2453 } 2454 2455 int 2456 wlan_flush_mac_mac(struct wlan_iface *wif) 2457 { 2458 int val = IEEE80211_MACCMD_FLUSH; 2459 size_t argsize = 0; 2460 2461 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, NULL, 2462 &argsize, 1) < 0) 2463 return (-1); 2464 2465 return (0); 2466 } 2467 2468 static int 2469 wlan_add_mac_macinfo(struct wlan_iface *wif, 2470 const struct ieee80211req_maclist *ml) 2471 { 2472 struct wlan_mac_mac *mmac; 2473 2474 if ((mmac = wlan_mac_new_mac(ml->ml_macaddr)) == NULL) 2475 return (-1); 2476 2477 mmac->mac_status = RowStatus_active; 2478 if (wlan_mac_add_mac(wif, mmac) < 0) { 2479 wlan_mac_free_mac(mmac); 2480 return (-1); 2481 } 2482 2483 return (0); 2484 } 2485 2486 int 2487 wlan_get_mac_acl_macs(struct wlan_iface *wif) 2488 { 2489 int i, nacls, val = IEEE80211_MACCMD_LIST; 2490 size_t argsize = 0; 2491 uint8_t *data; 2492 struct ieee80211req ireq; 2493 const struct ieee80211req_maclist *acllist; 2494 2495 if (wif->mac_policy == wlanMACAccessControlPolicy_radius) { 2496 wif->mac_nacls = 0; 2497 return (0); 2498 } 2499 2500 memset(&ireq, 0, sizeof(struct ieee80211req)); 2501 strlcpy(ireq.i_name, wif->wname, IFNAMSIZ); 2502 ireq.i_type = IEEE80211_IOC_MACCMD; 2503 ireq.i_val = IEEE80211_MACCMD_LIST; 2504 2505 2506 if (ioctl(sock, SIOCG80211, &ireq) < 0) { 2507 if (errno != EINVAL) { 2508 syslog(LOG_ERR, "iface %s - get param: ioctl(%d) " 2509 "failed: %s", wif->wname, ireq.i_type, 2510 strerror(errno)); 2511 wif->macsupported = 0; 2512 return (-1); 2513 } 2514 } 2515 2516 if (argsize == 0) { 2517 wif->mac_nacls = 0; 2518 return (0); 2519 } 2520 2521 if ((data = (uint8_t *)malloc(argsize)) == NULL) 2522 return (-1); 2523 2524 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MACCMD, &val, data, 2525 &argsize, 0) < 0) 2526 return (-1); 2527 2528 nacls = argsize / sizeof(*acllist); 2529 acllist = (struct ieee80211req_maclist *) data; 2530 for (i = 0; i < nacls; i++) 2531 (void)wlan_add_mac_macinfo(wif, acllist + i); 2532 2533 wif->mac_nacls = nacls; 2534 return (0); 2535 } 2536 2537 int 2538 wlan_add_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac) 2539 { 2540 int val = 0; 2541 size_t argsize = IEEE80211_ADDR_LEN; 2542 struct ieee80211req_mlme mlme; 2543 2544 if (wlan_ioctl(wif->wname, IEEE80211_IOC_ADDMAC, &val, 2545 mmac->mac, &argsize, 1) < 0) 2546 return (-1); 2547 2548 mmac->mac_status = RowStatus_active; 2549 2550 /* If policy is deny, try to kick the station just in case. */ 2551 if (wif->mac_policy != wlanMACAccessControlPolicy_deny) 2552 return (0); 2553 2554 memset(&mlme, 0, sizeof(mlme)); 2555 mlme.im_op = IEEE80211_MLME_DEAUTH; 2556 mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 2557 memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN); 2558 argsize = sizeof(struct ieee80211req_mlme); 2559 2560 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme, 2561 &argsize, 1) < 0 && errno != ENOENT) 2562 return (-1); 2563 2564 return (0); 2565 } 2566 2567 int 2568 wlan_del_mac_acl_mac(struct wlan_iface *wif, struct wlan_mac_mac *mmac) 2569 { 2570 int val = 0; 2571 size_t argsize = IEEE80211_ADDR_LEN; 2572 struct ieee80211req_mlme mlme; 2573 2574 if (wlan_ioctl(wif->wname, IEEE80211_IOC_DELMAC, &val, 2575 mmac->mac, &argsize, 1) < 0) 2576 return (-1); 2577 2578 mmac->mac_status = RowStatus_active; 2579 2580 /* If policy is allow, try to kick the station just in case. */ 2581 if (wif->mac_policy != wlanMACAccessControlPolicy_allow) 2582 return (0); 2583 2584 memset(&mlme, 0, sizeof(mlme)); 2585 mlme.im_op = IEEE80211_MLME_DEAUTH; 2586 mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 2587 memcpy(mlme.im_macaddr, mmac->mac, IEEE80211_ADDR_LEN); 2588 argsize = sizeof(struct ieee80211req_mlme); 2589 2590 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MLME, &val, &mlme, 2591 &argsize, 1) < 0 && errno != ENOENT) 2592 return (-1); 2593 2594 return (0); 2595 } 2596 2597 int 2598 wlan_peer_set_vlan(struct wlan_iface *wif, struct wlan_peer *wip, int vlan) 2599 { 2600 int val = 0; 2601 size_t argsize; 2602 struct ieee80211req_sta_vlan vreq; 2603 2604 memcpy(vreq.sv_macaddr, wip->pmac, IEEE80211_ADDR_LEN); 2605 vreq.sv_vlan = vlan; 2606 argsize = sizeof(struct ieee80211req_sta_vlan); 2607 2608 if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_VLAN, 2609 &val, &vreq, &argsize, 1) < 0) 2610 return (-1); 2611 2612 wip->vlan = vlan; 2613 2614 return (0); 2615 } 2616 2617 /* XXX */ 2618 #ifndef IEEE80211_NODE_AUTH 2619 #define IEEE80211_NODE_AUTH 0x000001 /* authorized for data */ 2620 #define IEEE80211_NODE_QOS 0x000002 /* QoS enabled */ 2621 #define IEEE80211_NODE_ERP 0x000004 /* ERP enabled */ 2622 #define IEEE80211_NODE_PWR_MGT 0x000010 /* power save mode enabled */ 2623 #define IEEE80211_NODE_AREF 0x000020 /* authentication ref held */ 2624 #define IEEE80211_NODE_HT 0x000040 /* HT enabled */ 2625 #define IEEE80211_NODE_HTCOMPAT 0x000080 /* HT setup w/ vendor OUI's */ 2626 #define IEEE80211_NODE_WPS 0x000100 /* WPS association */ 2627 #define IEEE80211_NODE_TSN 0x000200 /* TSN association */ 2628 #define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */ 2629 #define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */ 2630 #define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */ 2631 #define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */ 2632 #define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */ 2633 #define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */ 2634 #define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */ 2635 #define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */ 2636 #define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */ 2637 #define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */ 2638 #endif 2639 2640 static uint32_t 2641 wlan_peerstate_to_snmp(uint32_t pstate) 2642 { 2643 uint32_t sstate = 0; 2644 2645 if ((pstate & IEEE80211_NODE_AUTH) != 0) 2646 sstate |= (0x1 << WlanIfacePeerFlagsType_authorizedForData); 2647 if ((pstate & IEEE80211_NODE_QOS) != 0) 2648 sstate |= (0x1 << WlanIfacePeerFlagsType_qosEnabled); 2649 if ((pstate & IEEE80211_NODE_ERP) != 0) 2650 sstate |= (0x1 << WlanIfacePeerFlagsType_erpEnabled); 2651 if ((pstate & IEEE80211_NODE_PWR_MGT) != 0) 2652 sstate |= (0x1 << WlanIfacePeerFlagsType_powerSaveMode); 2653 if ((pstate & IEEE80211_NODE_AREF) != 0) 2654 sstate |= (0x1 << WlanIfacePeerFlagsType_authRefHeld); 2655 if ((pstate & IEEE80211_NODE_HT) != 0) 2656 sstate |= (0x1 << WlanIfacePeerFlagsType_htEnabled); 2657 if ((pstate & IEEE80211_NODE_HTCOMPAT) != 0) 2658 sstate |= (0x1 << WlanIfacePeerFlagsType_htCompat); 2659 if ((pstate & IEEE80211_NODE_WPS) != 0) 2660 sstate |= (0x1 << WlanIfacePeerFlagsType_wpsAssoc); 2661 if ((pstate & IEEE80211_NODE_TSN) != 0) 2662 sstate |= (0x1 << WlanIfacePeerFlagsType_tsnAssoc); 2663 if ((pstate & IEEE80211_NODE_AMPDU_RX) != 0) 2664 sstate |= (0x1 << WlanIfacePeerFlagsType_ampduRx); 2665 if ((pstate & IEEE80211_NODE_AMPDU_TX) != 0) 2666 sstate |= (0x1 << WlanIfacePeerFlagsType_ampduTx); 2667 if ((pstate & IEEE80211_NODE_MIMO_PS) != 0) 2668 sstate |= (0x1 << WlanIfacePeerFlagsType_mimoPowerSave); 2669 if ((pstate & IEEE80211_NODE_MIMO_RTS) != 0) 2670 sstate |= (0x1 << WlanIfacePeerFlagsType_sendRts); 2671 if ((pstate & IEEE80211_NODE_RIFS) != 0) 2672 sstate |= (0x1 << WlanIfacePeerFlagsType_rifs); 2673 if ((pstate & IEEE80211_NODE_SGI20) != 0) 2674 sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT20); 2675 if ((pstate & IEEE80211_NODE_SGI40) != 0) 2676 sstate |= (0x1 << WlanIfacePeerFlagsType_shortGiHT40); 2677 if ((pstate & IEEE80211_NODE_AMSDU_RX) != 0) 2678 sstate |= (0x1 << WlanIfacePeerFlagsType_amsduRx); 2679 if ((pstate & IEEE80211_NODE_AMSDU_TX) != 0) 2680 sstate |= (0x1 << WlanIfacePeerFlagsType_amsduTx); 2681 2682 return (sstate); 2683 } 2684 2685 static struct wlan_peer * 2686 wlan_add_peerinfo(const struct ieee80211req_sta_info *si) 2687 { 2688 struct wlan_peer *wip; 2689 2690 if ((wip = wlan_new_peer(si->isi_macaddr))== NULL) 2691 return (NULL); 2692 2693 wip->associd = IEEE80211_AID(si->isi_associd); 2694 wip->vlan = si->isi_vlan; 2695 wip->frequency = si->isi_freq; 2696 wip->fflags = si->isi_flags; 2697 wip->txrate = si->isi_txrate; 2698 wip->rssi = si->isi_rssi; 2699 wip->idle = si->isi_inact; 2700 wip->txseqs = si->isi_txseqs[0]; /* XXX */ 2701 wip->rxseqs = si->isi_rxseqs[0]; /* XXX */ 2702 wip->txpower = si->isi_txpower; 2703 wip->capinfo = wlan_peercaps_to_snmp(si->isi_capinfo); 2704 wip->state = wlan_peerstate_to_snmp(si->isi_state); 2705 wip->local_id = si->isi_localid; 2706 wip->peer_id = si->isi_peerid; 2707 2708 return (wip); 2709 } 2710 2711 int 2712 wlan_get_peerinfo(struct wlan_iface *wif) 2713 { 2714 union { 2715 struct ieee80211req_sta_req req; 2716 uint8_t buf[24 * 1024]; 2717 } u; 2718 const uint8_t *cp; 2719 int val = 0; 2720 size_t len; 2721 struct ieee80211req_sta_info si; 2722 struct wlan_peer *wip; 2723 2724 /* Get all stations - broadcast address */ 2725 (void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN); 2726 len = sizeof(u); 2727 2728 if (wlan_ioctl(wif->wname, IEEE80211_IOC_STA_INFO, 2729 & val, &u, &len, 0) < 0) 2730 return (-1); 2731 2732 if (len < sizeof(struct ieee80211req_sta_info)) 2733 return (-1); 2734 2735 cp = (const uint8_t *) u.req.info; 2736 do { 2737 memcpy(&si, cp, sizeof(struct ieee80211req_sta_info)); 2738 if ((wip = wlan_add_peerinfo(&si)) != NULL && 2739 wlan_add_peer(wif, wip) < 0) 2740 wlan_free_peer(wip); 2741 cp += si.isi_len, len -= si.isi_len; 2742 } while (len >= sizeof(struct ieee80211req_sta_info)); 2743 2744 return (0); 2745 } 2746 2747 /************************************************************************ 2748 * Wireless MESH & HWMP sysctl config. 2749 */ 2750 const char wlan_sysctl_name[] = "net.wlan."; 2751 2752 static const char *wlan_sysctl[] = { 2753 "mesh.retrytimeout", 2754 "mesh.holdingtimeout", 2755 "mesh.confirmtimeout", 2756 "mesh.maxretries", 2757 "hwmp.targetonly", 2758 "hwmp.replyforward", 2759 "hwmp.pathlifetime", 2760 "hwmp.roottimeout", 2761 "hwmp.rootint", 2762 "hwmp.rannint", 2763 "hwmp.inact", 2764 }; 2765 2766 int32_t 2767 wlan_do_sysctl(struct wlan_config *cfg, enum wlan_syscl which, int set) 2768 { 2769 char mib_name[100]; 2770 int val, sval; 2771 size_t len, vlen; 2772 2773 if (set) { 2774 vlen = sizeof(sval); 2775 switch (which) { 2776 case WLAN_MESH_RETRY_TO: 2777 sval = cfg->mesh_retryto; 2778 break; 2779 case WLAN_MESH_HOLDING_TO: 2780 sval = cfg->mesh_holdingto; 2781 break; 2782 case WLAN_MESH_CONFIRM_TO: 2783 sval = cfg->mesh_confirmto; 2784 break; 2785 case WLAN_MESH_MAX_RETRIES: 2786 sval = cfg->mesh_maxretries; 2787 break; 2788 case WLAN_HWMP_TARGET_ONLY: 2789 sval = cfg->hwmp_targetonly; 2790 break; 2791 case WLAN_HWMP_REPLY_FORWARD: 2792 sval = cfg->hwmp_replyforward; 2793 break; 2794 case WLAN_HWMP_PATH_LIFETIME: 2795 sval = cfg->hwmp_pathlifetime; 2796 break; 2797 case WLAN_HWMP_ROOT_TO: 2798 sval = cfg->hwmp_roottimeout; 2799 break; 2800 case WLAN_HWMP_ROOT_INT: 2801 sval = cfg->hwmp_rootint; 2802 break; 2803 case WLAN_HWMP_RANN_INT: 2804 sval = cfg->hwmp_rannint; 2805 break; 2806 case WLAN_HWMP_INACTIVITY_TO: 2807 sval = cfg->hwmp_inact; 2808 break; 2809 default: 2810 return (-1); 2811 } 2812 } else { 2813 if (which >= WLAN_SYSCTL_MAX) 2814 return (-1); 2815 vlen = 0; 2816 } 2817 2818 strlcpy(mib_name, wlan_sysctl_name, sizeof(mib_name)); 2819 strlcat(mib_name, wlan_sysctl[which], sizeof(mib_name)); 2820 len = sizeof (val); 2821 2822 if (sysctlbyname(mib_name, &val, &len, (set? &sval : NULL), vlen) < 0) { 2823 syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_name, 2824 strerror(errno)); 2825 return (-1); 2826 } 2827 2828 switch (which) { 2829 case WLAN_MESH_RETRY_TO: 2830 cfg->mesh_retryto = val; 2831 break; 2832 case WLAN_MESH_HOLDING_TO: 2833 cfg->mesh_holdingto = val; 2834 break; 2835 case WLAN_MESH_CONFIRM_TO: 2836 cfg->mesh_confirmto = val; 2837 break; 2838 case WLAN_MESH_MAX_RETRIES: 2839 cfg->mesh_maxretries = val; 2840 break; 2841 case WLAN_HWMP_TARGET_ONLY: 2842 cfg->hwmp_targetonly = val; 2843 break; 2844 case WLAN_HWMP_REPLY_FORWARD: 2845 cfg->hwmp_replyforward = val; 2846 break; 2847 case WLAN_HWMP_PATH_LIFETIME: 2848 cfg->hwmp_pathlifetime = val; 2849 break; 2850 case WLAN_HWMP_ROOT_TO: 2851 cfg->hwmp_roottimeout = val; 2852 break; 2853 case WLAN_HWMP_ROOT_INT: 2854 cfg->hwmp_rootint = val; 2855 break; 2856 case WLAN_HWMP_RANN_INT: 2857 cfg->hwmp_rannint = val; 2858 break; 2859 case WLAN_HWMP_INACTIVITY_TO: 2860 cfg->hwmp_inact = val; 2861 break; 2862 default: 2863 /* NOTREACHED */ 2864 abort(); 2865 } 2866 2867 return (0); 2868 } 2869 2870 int 2871 wlan_mesh_config_get(struct wlan_iface *wif, int which) 2872 { 2873 int op, val = 0; 2874 size_t argsize = 0; 2875 uint8_t data[32], *pd = NULL; 2876 2877 switch (which) { 2878 case LEAF_wlanMeshTTL: 2879 op = IEEE80211_IOC_MESH_TTL; 2880 break; 2881 case LEAF_wlanMeshPeeringEnabled: 2882 op = IEEE80211_IOC_MESH_AP; 2883 break; 2884 case LEAF_wlanMeshForwardingEnabled: 2885 op = IEEE80211_IOC_MESH_FWRD; 2886 break; 2887 case LEAF_wlanMeshMetric: 2888 op = IEEE80211_IOC_MESH_PR_METRIC; 2889 pd = data; 2890 argsize = sizeof(data); 2891 break; 2892 case LEAF_wlanMeshPath: 2893 op = IEEE80211_IOC_MESH_PR_PATH; 2894 pd = data; 2895 argsize = sizeof(data); 2896 break; 2897 case LEAF_wlanMeshRoutesFlush: 2898 return (0); 2899 default: 2900 return (-1); 2901 } 2902 2903 if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 0) < 0) 2904 return (-1); 2905 2906 switch (which) { 2907 case LEAF_wlanMeshTTL: 2908 wif->mesh_ttl = val; 2909 break; 2910 case LEAF_wlanMeshPeeringEnabled: 2911 if (val) 2912 wif->mesh_peering = wlanMeshPeeringEnabled_true; 2913 else 2914 wif->mesh_peering = wlanMeshPeeringEnabled_false; 2915 break; 2916 case LEAF_wlanMeshForwardingEnabled: 2917 if (val) 2918 wif->mesh_forwarding = wlanMeshForwardingEnabled_true; 2919 else 2920 wif->mesh_forwarding = wlanMeshForwardingEnabled_false; 2921 break; 2922 case LEAF_wlanMeshMetric: 2923 data[argsize] = '\0'; 2924 if (strcmp(data, "AIRTIME") == 0) 2925 wif->mesh_metric = wlanMeshMetric_airtime; 2926 else 2927 wif->mesh_metric = wlanMeshMetric_unknown; 2928 break; 2929 case LEAF_wlanMeshPath: 2930 data[argsize] = '\0'; 2931 if (strcmp(data, "HWMP") == 0) 2932 wif->mesh_path = wlanMeshPath_hwmp; 2933 else 2934 wif->mesh_path = wlanMeshPath_unknown; 2935 } 2936 2937 return (0); 2938 } 2939 2940 int 2941 wlan_mesh_config_set(struct wlan_iface *wif, int which) 2942 { 2943 int op, val = 0; 2944 size_t argsize = 0; 2945 uint8_t data[32], *pd = NULL; 2946 2947 switch (which) { 2948 case LEAF_wlanMeshTTL: 2949 op = IEEE80211_IOC_MESH_TTL; 2950 val = wif->mesh_ttl; 2951 break; 2952 case LEAF_wlanMeshPeeringEnabled: 2953 op = IEEE80211_IOC_MESH_AP; 2954 if (wif->mesh_peering == wlanMeshPeeringEnabled_true) 2955 val = 1; 2956 break; 2957 case LEAF_wlanMeshForwardingEnabled: 2958 if (wif->mesh_forwarding == wlanMeshForwardingEnabled_true) 2959 val = 1; 2960 op = IEEE80211_IOC_MESH_FWRD; 2961 break; 2962 case LEAF_wlanMeshMetric: 2963 op = IEEE80211_IOC_MESH_PR_METRIC; 2964 if (wif->mesh_metric == wlanMeshMetric_airtime) 2965 strcpy(data, "AIRTIME"); 2966 else 2967 return (-1); 2968 pd = data; 2969 argsize = sizeof(data); 2970 break; 2971 case LEAF_wlanMeshPath: 2972 op = IEEE80211_IOC_MESH_PR_PATH; 2973 if (wif->mesh_path == wlanMeshPath_hwmp) 2974 strcpy(data, "HWMP"); 2975 else 2976 return (-1); 2977 pd = data; 2978 argsize = sizeof(data); 2979 break; 2980 default: 2981 return (-1); 2982 } 2983 2984 if (wlan_ioctl(wif->wname, op, &val, pd, &argsize, 1) < 0) 2985 return (-1); 2986 2987 return(0); 2988 } 2989 2990 int 2991 wlan_mesh_flush_routes(struct wlan_iface *wif) 2992 { 2993 int val = IEEE80211_MESH_RTCMD_FLUSH; 2994 size_t argsize = 0; 2995 2996 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, NULL, 2997 &argsize, 1) < 0) 2998 return (-1); 2999 3000 return (0); 3001 } 3002 3003 int 3004 wlan_mesh_add_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr) 3005 { 3006 int val = IEEE80211_MESH_RTCMD_ADD; 3007 size_t argsize = IEEE80211_ADDR_LEN; 3008 3009 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, 3010 wmr->imroute.imr_dest, &argsize, 1) < 0) 3011 return (-1); 3012 3013 wmr->mroute_status = RowStatus_active; 3014 3015 return (0); 3016 } 3017 3018 int 3019 wlan_mesh_del_route(struct wlan_iface *wif, struct wlan_mesh_route *wmr) 3020 { 3021 int val = IEEE80211_MESH_RTCMD_DELETE; 3022 size_t argsize = IEEE80211_ADDR_LEN; 3023 3024 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, 3025 wmr->imroute.imr_dest, &argsize, 1) < 0) 3026 return (-1); 3027 3028 wmr->mroute_status = RowStatus_destroy; 3029 3030 return (0); 3031 } 3032 3033 int 3034 wlan_mesh_get_routelist(struct wlan_iface *wif) 3035 { 3036 int i, nroutes, val = IEEE80211_MESH_RTCMD_LIST; 3037 size_t argsize; 3038 struct ieee80211req_mesh_route routes[128]; 3039 struct ieee80211req_mesh_route *rt; 3040 struct wlan_mesh_route *wmr; 3041 3042 argsize = sizeof(routes); 3043 if (wlan_ioctl(wif->wname, IEEE80211_IOC_MESH_RTCMD, &val, routes, 3044 &argsize, 0) < 0) /* XXX: ENOMEM? */ 3045 return (-1); 3046 3047 nroutes = argsize / sizeof(*rt); 3048 for (i = 0; i < nroutes; i++) { 3049 rt = routes + i; 3050 if ((wmr = wlan_mesh_new_route(rt->imr_dest)) == NULL) 3051 return (-1); 3052 memcpy(&wmr->imroute, rt, sizeof(*rt)); 3053 wmr->mroute_status = RowStatus_active; 3054 if (wlan_mesh_add_rtentry(wif, wmr) < 0) 3055 wlan_mesh_free_route(wmr); 3056 } 3057 3058 return (0); 3059 } 3060 3061 int 3062 wlan_hwmp_config_get(struct wlan_iface *wif, int which) 3063 { 3064 int op, val = 0; 3065 size_t argsize = 0; 3066 3067 switch (which) { 3068 case LEAF_wlanHWMPRootMode: 3069 op = IEEE80211_IOC_HWMP_ROOTMODE; 3070 break; 3071 case LEAF_wlanHWMPMaxHops: 3072 op = IEEE80211_IOC_HWMP_MAXHOPS; 3073 break; 3074 default: 3075 return (-1); 3076 } 3077 3078 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 0) < 0) 3079 return (-1); 3080 3081 switch (which) { 3082 case LEAF_wlanHWMPRootMode: 3083 switch (val) { 3084 case IEEE80211_HWMP_ROOTMODE_NORMAL: 3085 wif->hwmp_root_mode = wlanHWMPRootMode_normal; 3086 break; 3087 case IEEE80211_HWMP_ROOTMODE_PROACTIVE: 3088 wif->hwmp_root_mode = wlanHWMPRootMode_proactive; 3089 break; 3090 case IEEE80211_HWMP_ROOTMODE_RANN: 3091 wif->hwmp_root_mode = wlanHWMPRootMode_rann; 3092 break; 3093 case IEEE80211_HWMP_ROOTMODE_DISABLED: 3094 default: 3095 wif->hwmp_root_mode = wlanHWMPRootMode_disabled; 3096 break; 3097 } 3098 break; 3099 case LEAF_wlanHWMPMaxHops: 3100 wif->hwmp_max_hops = val; 3101 break; 3102 } 3103 3104 return (0); 3105 } 3106 3107 int 3108 wlan_hwmp_config_set(struct wlan_iface *wif, int which) 3109 { 3110 int op, val = 0; 3111 size_t argsize = 0; 3112 3113 switch (which) { 3114 case LEAF_wlanHWMPRootMode: 3115 op = IEEE80211_IOC_HWMP_ROOTMODE; 3116 switch (wif->hwmp_root_mode) { 3117 case wlanHWMPRootMode_disabled: 3118 val = IEEE80211_HWMP_ROOTMODE_DISABLED; 3119 break; 3120 case wlanHWMPRootMode_normal: 3121 val = IEEE80211_HWMP_ROOTMODE_NORMAL; 3122 break; 3123 case wlanHWMPRootMode_proactive: 3124 val = IEEE80211_HWMP_ROOTMODE_PROACTIVE; 3125 break; 3126 case wlanHWMPRootMode_rann: 3127 val = IEEE80211_HWMP_ROOTMODE_RANN; 3128 break; 3129 default: 3130 return (-1); 3131 } 3132 break; 3133 case LEAF_wlanHWMPMaxHops: 3134 op = IEEE80211_IOC_HWMP_MAXHOPS; 3135 val = wif->hwmp_max_hops; 3136 break; 3137 default: 3138 return (-1); 3139 } 3140 3141 if (wlan_ioctl(wif->wname, op, &val, NULL, &argsize, 1) < 0) 3142 return (-1); 3143 3144 return (0); 3145 } 3146