29 30/* 31 * IEEE 802.11 ioctl support (FreeBSD-specific) 32 */ 33 34#include "opt_inet.h" 35#include "opt_ipx.h" 36#include "opt_wlan.h" 37 38#include <sys/endian.h> 39#include <sys/param.h> 40#include <sys/kernel.h> 41#include <sys/priv.h> 42#include <sys/socket.h> 43#include <sys/sockio.h> 44#include <sys/systm.h> 45#include <sys/taskqueue.h> 46 47#include <net/if.h> 48#include <net/if_dl.h> 49#include <net/if_media.h> 50#include <net/ethernet.h> 51 52#ifdef INET 53#include <netinet/in.h> 54#include <netinet/if_ether.h> 55#endif 56 57#ifdef IPX 58#include <netipx/ipx.h> 59#include <netipx/ipx_if.h> 60#endif 61 62#include <net80211/ieee80211_var.h> 63#include <net80211/ieee80211_ioctl.h> 64#include <net80211/ieee80211_regdomain.h> 65#include <net80211/ieee80211_input.h> 66 67#define IS_UP_AUTO(_vap) \ 68 (IFNET_IS_UP_RUNNING(vap->iv_ifp) && \ 69 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO) 70 71static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 72static struct ieee80211_channel *findchannel(struct ieee80211com *, 73 int ieee, int mode); 74 75static __noinline int 76ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 77{ 78 struct ieee80211com *ic = vap->iv_ic; 79 struct ieee80211_node *ni; 80 struct ieee80211req_key ik; 81 struct ieee80211_key *wk; 82 const struct ieee80211_cipher *cip; 83 u_int kid; 84 int error; 85 86 if (ireq->i_len != sizeof(ik)) 87 return EINVAL; 88 error = copyin(ireq->i_data, &ik, sizeof(ik)); 89 if (error) 90 return error; 91 kid = ik.ik_keyix; 92 if (kid == IEEE80211_KEYIX_NONE) { 93 ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr); 94 if (ni == NULL) 95 return ENOENT; 96 wk = &ni->ni_ucastkey; 97 } else { 98 if (kid >= IEEE80211_WEP_NKID) 99 return EINVAL; 100 wk = &vap->iv_nw_keys[kid]; 101 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr); 102 ni = NULL; 103 } 104 cip = wk->wk_cipher; 105 ik.ik_type = cip->ic_cipher; 106 ik.ik_keylen = wk->wk_keylen; 107 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 108 if (wk->wk_keyix == vap->iv_def_txkey) 109 ik.ik_flags |= IEEE80211_KEY_DEFAULT; 110 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 111 /* NB: only root can read key data */ 112 ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID]; 113 ik.ik_keytsc = wk->wk_keytsc; 114 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen); 115 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) { 116 memcpy(ik.ik_keydata+wk->wk_keylen, 117 wk->wk_key + IEEE80211_KEYBUF_SIZE, 118 IEEE80211_MICBUF_SIZE); 119 ik.ik_keylen += IEEE80211_MICBUF_SIZE; 120 } 121 } else { 122 ik.ik_keyrsc = 0; 123 ik.ik_keytsc = 0; 124 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); 125 } 126 if (ni != NULL) 127 ieee80211_free_node(ni); 128 return copyout(&ik, ireq->i_data, sizeof(ik)); 129} 130 131static __noinline int 132ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) 133{ 134 struct ieee80211com *ic = vap->iv_ic; 135 136 if (sizeof(ic->ic_chan_active) < ireq->i_len) 137 ireq->i_len = sizeof(ic->ic_chan_active); 138 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 139} 140 141static __noinline int 142ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq) 143{ 144 struct ieee80211com *ic = vap->iv_ic; 145 int space; 146 147 space = __offsetof(struct ieee80211req_chaninfo, 148 ic_chans[ic->ic_nchans]); 149 if (space > ireq->i_len) 150 space = ireq->i_len; 151 /* XXX assumes compatible layout */ 152 return copyout(&ic->ic_nchans, ireq->i_data, space); 153} 154 155static __noinline int 156ieee80211_ioctl_getwpaie(struct ieee80211vap *vap, 157 struct ieee80211req *ireq, int req) 158{ 159 struct ieee80211_node *ni; 160 struct ieee80211req_wpaie2 wpaie; 161 int error; 162 163 if (ireq->i_len < IEEE80211_ADDR_LEN) 164 return EINVAL; 165 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 166 if (error != 0) 167 return error; 168 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr); 169 if (ni == NULL) 170 return ENOENT; 171 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 172 if (ni->ni_ies.wpa_ie != NULL) { 173 int ielen = ni->ni_ies.wpa_ie[1] + 2; 174 if (ielen > sizeof(wpaie.wpa_ie)) 175 ielen = sizeof(wpaie.wpa_ie); 176 memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen); 177 } 178 if (req == IEEE80211_IOC_WPAIE2) { 179 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie)); 180 if (ni->ni_ies.rsn_ie != NULL) { 181 int ielen = ni->ni_ies.rsn_ie[1] + 2; 182 if (ielen > sizeof(wpaie.rsn_ie)) 183 ielen = sizeof(wpaie.rsn_ie); 184 memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen); 185 } 186 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2)) 187 ireq->i_len = sizeof(struct ieee80211req_wpaie2); 188 } else { 189 /* compatibility op, may overwrite wpa ie */ 190 /* XXX check ic_flags? */ 191 if (ni->ni_ies.rsn_ie != NULL) { 192 int ielen = ni->ni_ies.rsn_ie[1] + 2; 193 if (ielen > sizeof(wpaie.wpa_ie)) 194 ielen = sizeof(wpaie.wpa_ie); 195 memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen); 196 } 197 if (ireq->i_len > sizeof(struct ieee80211req_wpaie)) 198 ireq->i_len = sizeof(struct ieee80211req_wpaie); 199 } 200 ieee80211_free_node(ni); 201 return copyout(&wpaie, ireq->i_data, ireq->i_len); 202} 203 204static __noinline int 205ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) 206{ 207 struct ieee80211_node *ni; 208 uint8_t macaddr[IEEE80211_ADDR_LEN]; 209 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 210 int error; 211 212 if (ireq->i_len < off) 213 return EINVAL; 214 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 215 if (error != 0) 216 return error; 217 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 218 if (ni == NULL) 219 return ENOENT; 220 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 221 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 222 /* NB: copy out only the statistics */ 223 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off, 224 ireq->i_len - off); 225 ieee80211_free_node(ni); 226 return error; 227} 228 229struct scanreq { 230 struct ieee80211req_scan_result *sr; 231 size_t space; 232}; 233 234static size_t 235scan_space(const struct ieee80211_scan_entry *se, int *ielen) 236{ 237 size_t len; 238 239 *ielen = se->se_ies.len; 240 /* 241 * NB: ie's can be no more than 255 bytes and the max 802.11 242 * packet is <3Kbytes so we are sure this doesn't overflow 243 * 16-bits; if this is a concern we can drop the ie's. 244 */ 245 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen; 246 return roundup(len, sizeof(uint32_t)); 247} 248 249static void 250get_scan_space(void *arg, const struct ieee80211_scan_entry *se) 251{ 252 struct scanreq *req = arg; 253 int ielen; 254 255 req->space += scan_space(se, &ielen); 256} 257 258static __noinline void 259get_scan_result(void *arg, const struct ieee80211_scan_entry *se) 260{ 261 struct scanreq *req = arg; 262 struct ieee80211req_scan_result *sr; 263 int ielen, len, nr, nxr; 264 uint8_t *cp; 265 266 len = scan_space(se, &ielen); 267 if (len > req->space) 268 return; 269 270 sr = req->sr; 271 KASSERT(len <= 65535 && ielen <= 65535, 272 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen)); 273 sr->isr_len = len; 274 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result); 275 sr->isr_ie_len = ielen; 276 sr->isr_freq = se->se_chan->ic_freq; 277 sr->isr_flags = se->se_chan->ic_flags; 278 sr->isr_rssi = se->se_rssi; 279 sr->isr_noise = se->se_noise; 280 sr->isr_intval = se->se_intval; 281 sr->isr_capinfo = se->se_capinfo; 282 sr->isr_erp = se->se_erp; 283 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 284 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 285 memcpy(sr->isr_rates, se->se_rates+2, nr); 286 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 287 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 288 sr->isr_nrates = nr + nxr; 289 290 sr->isr_ssid_len = se->se_ssid[1]; 291 cp = ((uint8_t *)sr) + sr->isr_ie_off; 292 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 293 294 if (ielen) { 295 cp += sr->isr_ssid_len; 296 memcpy(cp, se->se_ies.data, ielen); 297 } 298 299 req->space -= len; 300 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len); 301} 302 303static __noinline int 304ieee80211_ioctl_getscanresults(struct ieee80211vap *vap, 305 struct ieee80211req *ireq) 306{ 307 struct scanreq req; 308 int error; 309 310 if (ireq->i_len < sizeof(struct scanreq)) 311 return EFAULT; 312 313 error = 0; 314 req.space = 0; 315 ieee80211_scan_iterate(vap, get_scan_space, &req); 316 if (req.space > ireq->i_len) 317 req.space = ireq->i_len; 318 if (req.space > 0) { 319 size_t space; 320 void *p; 321 322 space = req.space; 323 /* XXX M_WAITOK after driver lock released */ 324 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO); 325 if (p == NULL) 326 return ENOMEM; 327 req.sr = p; 328 ieee80211_scan_iterate(vap, get_scan_result, &req); 329 ireq->i_len = space - req.space; 330 error = copyout(p, ireq->i_data, ireq->i_len); 331 free(p, M_TEMP); 332 } else 333 ireq->i_len = 0; 334 335 return error; 336} 337 338struct stainforeq { 339 struct ieee80211vap *vap; 340 struct ieee80211req_sta_info *si; 341 size_t space; 342}; 343 344static size_t 345sta_space(const struct ieee80211_node *ni, size_t *ielen) 346{ 347 *ielen = ni->ni_ies.len; 348 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, 349 sizeof(uint32_t)); 350} 351 352static void 353get_sta_space(void *arg, struct ieee80211_node *ni) 354{ 355 struct stainforeq *req = arg; 356 size_t ielen; 357 358 if (req->vap != ni->ni_vap) 359 return; 360 if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP && 361 ni->ni_associd == 0) /* only associated stations */ 362 return; 363 req->space += sta_space(ni, &ielen); 364} 365 366static __noinline void 367get_sta_info(void *arg, struct ieee80211_node *ni) 368{ 369 struct stainforeq *req = arg; 370 struct ieee80211vap *vap = ni->ni_vap; 371 struct ieee80211req_sta_info *si; 372 size_t ielen, len; 373 uint8_t *cp; 374 375 if (req->vap != ni->ni_vap) 376 return; 377 if (vap->iv_opmode == IEEE80211_M_HOSTAP && 378 ni->ni_associd == 0) /* only associated stations */ 379 return; 380 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 381 return; 382 len = sta_space(ni, &ielen); 383 if (len > req->space) 384 return; 385 si = req->si; 386 si->isi_len = len; 387 si->isi_ie_off = sizeof(struct ieee80211req_sta_info); 388 si->isi_ie_len = ielen; 389 si->isi_freq = ni->ni_chan->ic_freq; 390 si->isi_flags = ni->ni_chan->ic_flags; 391 si->isi_state = ni->ni_flags; 392 si->isi_authmode = ni->ni_authmode; 393 vap->iv_ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise); 394 vap->iv_ic->ic_node_getmimoinfo(ni, &si->isi_mimo); 395 si->isi_capinfo = ni->ni_capinfo; 396 si->isi_erp = ni->ni_erp; 397 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 398 si->isi_nrates = ni->ni_rates.rs_nrates; 399 if (si->isi_nrates > 15) 400 si->isi_nrates = 15; 401 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 402 si->isi_txrate = ni->ni_txrate; 403 if (si->isi_txrate & IEEE80211_RATE_MCS) { 404 const struct ieee80211_mcs_rates *mcs = 405 &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS]; 406 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { 407 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 408 si->isi_txmbps = mcs->ht40_rate_800ns; 409 else 410 si->isi_txmbps = mcs->ht40_rate_400ns; 411 } else { 412 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 413 si->isi_txmbps = mcs->ht20_rate_800ns; 414 else 415 si->isi_txmbps = mcs->ht20_rate_400ns; 416 } 417 } else 418 si->isi_txmbps = si->isi_txrate; 419 si->isi_associd = ni->ni_associd; 420 si->isi_txpower = ni->ni_txpower; 421 si->isi_vlan = ni->ni_vlan; 422 if (ni->ni_flags & IEEE80211_NODE_QOS) { 423 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 424 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 425 } else { 426 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID]; 427 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID]; 428 } 429 /* NB: leave all cases in case we relax ni_associd == 0 check */ 430 if (ieee80211_node_is_authorized(ni)) 431 si->isi_inact = vap->iv_inact_run; 432 else if (ni->ni_associd != 0 || 433 (vap->iv_opmode == IEEE80211_M_WDS && 434 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))) 435 si->isi_inact = vap->iv_inact_auth; 436 else 437 si->isi_inact = vap->iv_inact_init; 438 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 439 440 if (ielen) { 441 cp = ((uint8_t *)si) + si->isi_ie_off; 442 memcpy(cp, ni->ni_ies.data, ielen); 443 } 444 445 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len); 446 req->space -= len; 447} 448 449static __noinline int 450getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq, 451 struct ieee80211_node *ni, int off) 452{ 453 struct ieee80211com *ic = vap->iv_ic; 454 struct stainforeq req; 455 size_t space; 456 void *p; 457 int error; 458 459 error = 0; 460 req.space = 0; 461 req.vap = vap; 462 if (ni == NULL) 463 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); 464 else 465 get_sta_space(&req, ni); 466 if (req.space > ireq->i_len) 467 req.space = ireq->i_len; 468 if (req.space > 0) { 469 space = req.space; 470 /* XXX M_WAITOK after driver lock released */ 471 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO); 472 if (p == NULL) { 473 error = ENOMEM; 474 goto bad; 475 } 476 req.si = p; 477 if (ni == NULL) 478 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 479 else 480 get_sta_info(&req, ni); 481 ireq->i_len = space - req.space; 482 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len); 483 free(p, M_TEMP); 484 } else 485 ireq->i_len = 0; 486bad: 487 if (ni != NULL) 488 ieee80211_free_node(ni); 489 return error; 490} 491 492static __noinline int 493ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq) 494{ 495 uint8_t macaddr[IEEE80211_ADDR_LEN]; 496 const int off = __offsetof(struct ieee80211req_sta_req, info); 497 struct ieee80211_node *ni; 498 int error; 499 500 if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) 501 return EFAULT; 502 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 503 if (error != 0) 504 return error; 505 if (IEEE80211_ADDR_EQ(macaddr, vap->iv_ifp->if_broadcastaddr)) { 506 ni = NULL; 507 } else { 508 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 509 if (ni == NULL) 510 return ENOENT; 511 } 512 return getstainfo_common(vap, ireq, ni, off); 513} 514 515static __noinline int 516ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) 517{ 518 struct ieee80211_node *ni; 519 struct ieee80211req_sta_txpow txpow; 520 int error; 521 522 if (ireq->i_len != sizeof(txpow)) 523 return EINVAL; 524 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 525 if (error != 0) 526 return error; 527 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr); 528 if (ni == NULL) 529 return ENOENT; 530 txpow.it_txpow = ni->ni_txpower; 531 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 532 ieee80211_free_node(ni); 533 return error; 534} 535 536static __noinline int 537ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) 538{ 539 struct ieee80211com *ic = vap->iv_ic; 540 struct ieee80211_wme_state *wme = &ic->ic_wme; 541 struct wmeParams *wmep; 542 int ac; 543 544 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 545 return EINVAL; 546 547 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 548 if (ac >= WME_NUM_AC) 549 ac = WME_AC_BE; 550 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 551 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 552 else 553 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 554 switch (ireq->i_type) { 555 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 556 ireq->i_val = wmep->wmep_logcwmin; 557 break; 558 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 559 ireq->i_val = wmep->wmep_logcwmax; 560 break; 561 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 562 ireq->i_val = wmep->wmep_aifsn; 563 break; 564 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 565 ireq->i_val = wmep->wmep_txopLimit; 566 break; 567 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 568 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 569 ireq->i_val = wmep->wmep_acm; 570 break; 571 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 572 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 573 ireq->i_val = !wmep->wmep_noackPolicy; 574 break; 575 } 576 return 0; 577} 578 579static __noinline int 580ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) 581{ 582 const struct ieee80211_aclator *acl = vap->iv_acl; 583 584 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq)); 585} 586
| 29 30/* 31 * IEEE 802.11 ioctl support (FreeBSD-specific) 32 */ 33 34#include "opt_inet.h" 35#include "opt_ipx.h" 36#include "opt_wlan.h" 37 38#include <sys/endian.h> 39#include <sys/param.h> 40#include <sys/kernel.h> 41#include <sys/priv.h> 42#include <sys/socket.h> 43#include <sys/sockio.h> 44#include <sys/systm.h> 45#include <sys/taskqueue.h> 46 47#include <net/if.h> 48#include <net/if_dl.h> 49#include <net/if_media.h> 50#include <net/ethernet.h> 51 52#ifdef INET 53#include <netinet/in.h> 54#include <netinet/if_ether.h> 55#endif 56 57#ifdef IPX 58#include <netipx/ipx.h> 59#include <netipx/ipx_if.h> 60#endif 61 62#include <net80211/ieee80211_var.h> 63#include <net80211/ieee80211_ioctl.h> 64#include <net80211/ieee80211_regdomain.h> 65#include <net80211/ieee80211_input.h> 66 67#define IS_UP_AUTO(_vap) \ 68 (IFNET_IS_UP_RUNNING(vap->iv_ifp) && \ 69 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO) 70 71static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 72static struct ieee80211_channel *findchannel(struct ieee80211com *, 73 int ieee, int mode); 74 75static __noinline int 76ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 77{ 78 struct ieee80211com *ic = vap->iv_ic; 79 struct ieee80211_node *ni; 80 struct ieee80211req_key ik; 81 struct ieee80211_key *wk; 82 const struct ieee80211_cipher *cip; 83 u_int kid; 84 int error; 85 86 if (ireq->i_len != sizeof(ik)) 87 return EINVAL; 88 error = copyin(ireq->i_data, &ik, sizeof(ik)); 89 if (error) 90 return error; 91 kid = ik.ik_keyix; 92 if (kid == IEEE80211_KEYIX_NONE) { 93 ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr); 94 if (ni == NULL) 95 return ENOENT; 96 wk = &ni->ni_ucastkey; 97 } else { 98 if (kid >= IEEE80211_WEP_NKID) 99 return EINVAL; 100 wk = &vap->iv_nw_keys[kid]; 101 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr); 102 ni = NULL; 103 } 104 cip = wk->wk_cipher; 105 ik.ik_type = cip->ic_cipher; 106 ik.ik_keylen = wk->wk_keylen; 107 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 108 if (wk->wk_keyix == vap->iv_def_txkey) 109 ik.ik_flags |= IEEE80211_KEY_DEFAULT; 110 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 111 /* NB: only root can read key data */ 112 ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID]; 113 ik.ik_keytsc = wk->wk_keytsc; 114 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen); 115 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) { 116 memcpy(ik.ik_keydata+wk->wk_keylen, 117 wk->wk_key + IEEE80211_KEYBUF_SIZE, 118 IEEE80211_MICBUF_SIZE); 119 ik.ik_keylen += IEEE80211_MICBUF_SIZE; 120 } 121 } else { 122 ik.ik_keyrsc = 0; 123 ik.ik_keytsc = 0; 124 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); 125 } 126 if (ni != NULL) 127 ieee80211_free_node(ni); 128 return copyout(&ik, ireq->i_data, sizeof(ik)); 129} 130 131static __noinline int 132ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) 133{ 134 struct ieee80211com *ic = vap->iv_ic; 135 136 if (sizeof(ic->ic_chan_active) < ireq->i_len) 137 ireq->i_len = sizeof(ic->ic_chan_active); 138 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 139} 140 141static __noinline int 142ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq) 143{ 144 struct ieee80211com *ic = vap->iv_ic; 145 int space; 146 147 space = __offsetof(struct ieee80211req_chaninfo, 148 ic_chans[ic->ic_nchans]); 149 if (space > ireq->i_len) 150 space = ireq->i_len; 151 /* XXX assumes compatible layout */ 152 return copyout(&ic->ic_nchans, ireq->i_data, space); 153} 154 155static __noinline int 156ieee80211_ioctl_getwpaie(struct ieee80211vap *vap, 157 struct ieee80211req *ireq, int req) 158{ 159 struct ieee80211_node *ni; 160 struct ieee80211req_wpaie2 wpaie; 161 int error; 162 163 if (ireq->i_len < IEEE80211_ADDR_LEN) 164 return EINVAL; 165 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 166 if (error != 0) 167 return error; 168 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr); 169 if (ni == NULL) 170 return ENOENT; 171 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 172 if (ni->ni_ies.wpa_ie != NULL) { 173 int ielen = ni->ni_ies.wpa_ie[1] + 2; 174 if (ielen > sizeof(wpaie.wpa_ie)) 175 ielen = sizeof(wpaie.wpa_ie); 176 memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen); 177 } 178 if (req == IEEE80211_IOC_WPAIE2) { 179 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie)); 180 if (ni->ni_ies.rsn_ie != NULL) { 181 int ielen = ni->ni_ies.rsn_ie[1] + 2; 182 if (ielen > sizeof(wpaie.rsn_ie)) 183 ielen = sizeof(wpaie.rsn_ie); 184 memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen); 185 } 186 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2)) 187 ireq->i_len = sizeof(struct ieee80211req_wpaie2); 188 } else { 189 /* compatibility op, may overwrite wpa ie */ 190 /* XXX check ic_flags? */ 191 if (ni->ni_ies.rsn_ie != NULL) { 192 int ielen = ni->ni_ies.rsn_ie[1] + 2; 193 if (ielen > sizeof(wpaie.wpa_ie)) 194 ielen = sizeof(wpaie.wpa_ie); 195 memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen); 196 } 197 if (ireq->i_len > sizeof(struct ieee80211req_wpaie)) 198 ireq->i_len = sizeof(struct ieee80211req_wpaie); 199 } 200 ieee80211_free_node(ni); 201 return copyout(&wpaie, ireq->i_data, ireq->i_len); 202} 203 204static __noinline int 205ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) 206{ 207 struct ieee80211_node *ni; 208 uint8_t macaddr[IEEE80211_ADDR_LEN]; 209 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 210 int error; 211 212 if (ireq->i_len < off) 213 return EINVAL; 214 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 215 if (error != 0) 216 return error; 217 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 218 if (ni == NULL) 219 return ENOENT; 220 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 221 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 222 /* NB: copy out only the statistics */ 223 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off, 224 ireq->i_len - off); 225 ieee80211_free_node(ni); 226 return error; 227} 228 229struct scanreq { 230 struct ieee80211req_scan_result *sr; 231 size_t space; 232}; 233 234static size_t 235scan_space(const struct ieee80211_scan_entry *se, int *ielen) 236{ 237 size_t len; 238 239 *ielen = se->se_ies.len; 240 /* 241 * NB: ie's can be no more than 255 bytes and the max 802.11 242 * packet is <3Kbytes so we are sure this doesn't overflow 243 * 16-bits; if this is a concern we can drop the ie's. 244 */ 245 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen; 246 return roundup(len, sizeof(uint32_t)); 247} 248 249static void 250get_scan_space(void *arg, const struct ieee80211_scan_entry *se) 251{ 252 struct scanreq *req = arg; 253 int ielen; 254 255 req->space += scan_space(se, &ielen); 256} 257 258static __noinline void 259get_scan_result(void *arg, const struct ieee80211_scan_entry *se) 260{ 261 struct scanreq *req = arg; 262 struct ieee80211req_scan_result *sr; 263 int ielen, len, nr, nxr; 264 uint8_t *cp; 265 266 len = scan_space(se, &ielen); 267 if (len > req->space) 268 return; 269 270 sr = req->sr; 271 KASSERT(len <= 65535 && ielen <= 65535, 272 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen)); 273 sr->isr_len = len; 274 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result); 275 sr->isr_ie_len = ielen; 276 sr->isr_freq = se->se_chan->ic_freq; 277 sr->isr_flags = se->se_chan->ic_flags; 278 sr->isr_rssi = se->se_rssi; 279 sr->isr_noise = se->se_noise; 280 sr->isr_intval = se->se_intval; 281 sr->isr_capinfo = se->se_capinfo; 282 sr->isr_erp = se->se_erp; 283 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 284 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 285 memcpy(sr->isr_rates, se->se_rates+2, nr); 286 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 287 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 288 sr->isr_nrates = nr + nxr; 289 290 sr->isr_ssid_len = se->se_ssid[1]; 291 cp = ((uint8_t *)sr) + sr->isr_ie_off; 292 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 293 294 if (ielen) { 295 cp += sr->isr_ssid_len; 296 memcpy(cp, se->se_ies.data, ielen); 297 } 298 299 req->space -= len; 300 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len); 301} 302 303static __noinline int 304ieee80211_ioctl_getscanresults(struct ieee80211vap *vap, 305 struct ieee80211req *ireq) 306{ 307 struct scanreq req; 308 int error; 309 310 if (ireq->i_len < sizeof(struct scanreq)) 311 return EFAULT; 312 313 error = 0; 314 req.space = 0; 315 ieee80211_scan_iterate(vap, get_scan_space, &req); 316 if (req.space > ireq->i_len) 317 req.space = ireq->i_len; 318 if (req.space > 0) { 319 size_t space; 320 void *p; 321 322 space = req.space; 323 /* XXX M_WAITOK after driver lock released */ 324 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO); 325 if (p == NULL) 326 return ENOMEM; 327 req.sr = p; 328 ieee80211_scan_iterate(vap, get_scan_result, &req); 329 ireq->i_len = space - req.space; 330 error = copyout(p, ireq->i_data, ireq->i_len); 331 free(p, M_TEMP); 332 } else 333 ireq->i_len = 0; 334 335 return error; 336} 337 338struct stainforeq { 339 struct ieee80211vap *vap; 340 struct ieee80211req_sta_info *si; 341 size_t space; 342}; 343 344static size_t 345sta_space(const struct ieee80211_node *ni, size_t *ielen) 346{ 347 *ielen = ni->ni_ies.len; 348 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, 349 sizeof(uint32_t)); 350} 351 352static void 353get_sta_space(void *arg, struct ieee80211_node *ni) 354{ 355 struct stainforeq *req = arg; 356 size_t ielen; 357 358 if (req->vap != ni->ni_vap) 359 return; 360 if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP && 361 ni->ni_associd == 0) /* only associated stations */ 362 return; 363 req->space += sta_space(ni, &ielen); 364} 365 366static __noinline void 367get_sta_info(void *arg, struct ieee80211_node *ni) 368{ 369 struct stainforeq *req = arg; 370 struct ieee80211vap *vap = ni->ni_vap; 371 struct ieee80211req_sta_info *si; 372 size_t ielen, len; 373 uint8_t *cp; 374 375 if (req->vap != ni->ni_vap) 376 return; 377 if (vap->iv_opmode == IEEE80211_M_HOSTAP && 378 ni->ni_associd == 0) /* only associated stations */ 379 return; 380 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 381 return; 382 len = sta_space(ni, &ielen); 383 if (len > req->space) 384 return; 385 si = req->si; 386 si->isi_len = len; 387 si->isi_ie_off = sizeof(struct ieee80211req_sta_info); 388 si->isi_ie_len = ielen; 389 si->isi_freq = ni->ni_chan->ic_freq; 390 si->isi_flags = ni->ni_chan->ic_flags; 391 si->isi_state = ni->ni_flags; 392 si->isi_authmode = ni->ni_authmode; 393 vap->iv_ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise); 394 vap->iv_ic->ic_node_getmimoinfo(ni, &si->isi_mimo); 395 si->isi_capinfo = ni->ni_capinfo; 396 si->isi_erp = ni->ni_erp; 397 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 398 si->isi_nrates = ni->ni_rates.rs_nrates; 399 if (si->isi_nrates > 15) 400 si->isi_nrates = 15; 401 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 402 si->isi_txrate = ni->ni_txrate; 403 if (si->isi_txrate & IEEE80211_RATE_MCS) { 404 const struct ieee80211_mcs_rates *mcs = 405 &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS]; 406 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { 407 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 408 si->isi_txmbps = mcs->ht40_rate_800ns; 409 else 410 si->isi_txmbps = mcs->ht40_rate_400ns; 411 } else { 412 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 413 si->isi_txmbps = mcs->ht20_rate_800ns; 414 else 415 si->isi_txmbps = mcs->ht20_rate_400ns; 416 } 417 } else 418 si->isi_txmbps = si->isi_txrate; 419 si->isi_associd = ni->ni_associd; 420 si->isi_txpower = ni->ni_txpower; 421 si->isi_vlan = ni->ni_vlan; 422 if (ni->ni_flags & IEEE80211_NODE_QOS) { 423 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 424 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 425 } else { 426 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID]; 427 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID]; 428 } 429 /* NB: leave all cases in case we relax ni_associd == 0 check */ 430 if (ieee80211_node_is_authorized(ni)) 431 si->isi_inact = vap->iv_inact_run; 432 else if (ni->ni_associd != 0 || 433 (vap->iv_opmode == IEEE80211_M_WDS && 434 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))) 435 si->isi_inact = vap->iv_inact_auth; 436 else 437 si->isi_inact = vap->iv_inact_init; 438 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 439 440 if (ielen) { 441 cp = ((uint8_t *)si) + si->isi_ie_off; 442 memcpy(cp, ni->ni_ies.data, ielen); 443 } 444 445 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len); 446 req->space -= len; 447} 448 449static __noinline int 450getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq, 451 struct ieee80211_node *ni, int off) 452{ 453 struct ieee80211com *ic = vap->iv_ic; 454 struct stainforeq req; 455 size_t space; 456 void *p; 457 int error; 458 459 error = 0; 460 req.space = 0; 461 req.vap = vap; 462 if (ni == NULL) 463 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); 464 else 465 get_sta_space(&req, ni); 466 if (req.space > ireq->i_len) 467 req.space = ireq->i_len; 468 if (req.space > 0) { 469 space = req.space; 470 /* XXX M_WAITOK after driver lock released */ 471 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO); 472 if (p == NULL) { 473 error = ENOMEM; 474 goto bad; 475 } 476 req.si = p; 477 if (ni == NULL) 478 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 479 else 480 get_sta_info(&req, ni); 481 ireq->i_len = space - req.space; 482 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len); 483 free(p, M_TEMP); 484 } else 485 ireq->i_len = 0; 486bad: 487 if (ni != NULL) 488 ieee80211_free_node(ni); 489 return error; 490} 491 492static __noinline int 493ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq) 494{ 495 uint8_t macaddr[IEEE80211_ADDR_LEN]; 496 const int off = __offsetof(struct ieee80211req_sta_req, info); 497 struct ieee80211_node *ni; 498 int error; 499 500 if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) 501 return EFAULT; 502 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 503 if (error != 0) 504 return error; 505 if (IEEE80211_ADDR_EQ(macaddr, vap->iv_ifp->if_broadcastaddr)) { 506 ni = NULL; 507 } else { 508 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 509 if (ni == NULL) 510 return ENOENT; 511 } 512 return getstainfo_common(vap, ireq, ni, off); 513} 514 515static __noinline int 516ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) 517{ 518 struct ieee80211_node *ni; 519 struct ieee80211req_sta_txpow txpow; 520 int error; 521 522 if (ireq->i_len != sizeof(txpow)) 523 return EINVAL; 524 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 525 if (error != 0) 526 return error; 527 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr); 528 if (ni == NULL) 529 return ENOENT; 530 txpow.it_txpow = ni->ni_txpower; 531 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 532 ieee80211_free_node(ni); 533 return error; 534} 535 536static __noinline int 537ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) 538{ 539 struct ieee80211com *ic = vap->iv_ic; 540 struct ieee80211_wme_state *wme = &ic->ic_wme; 541 struct wmeParams *wmep; 542 int ac; 543 544 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 545 return EINVAL; 546 547 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 548 if (ac >= WME_NUM_AC) 549 ac = WME_AC_BE; 550 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 551 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 552 else 553 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 554 switch (ireq->i_type) { 555 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 556 ireq->i_val = wmep->wmep_logcwmin; 557 break; 558 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 559 ireq->i_val = wmep->wmep_logcwmax; 560 break; 561 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 562 ireq->i_val = wmep->wmep_aifsn; 563 break; 564 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 565 ireq->i_val = wmep->wmep_txopLimit; 566 break; 567 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 568 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 569 ireq->i_val = wmep->wmep_acm; 570 break; 571 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 572 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 573 ireq->i_val = !wmep->wmep_noackPolicy; 574 break; 575 } 576 return 0; 577} 578 579static __noinline int 580ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) 581{ 582 const struct ieee80211_aclator *acl = vap->iv_acl; 583 584 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq)); 585} 586
|
602static __noinline int 603ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq) 604{ 605 struct ieee80211com *ic = vap->iv_ic; 606 struct ieee80211_channel *c; 607 608 if (ireq->i_len != sizeof(struct ieee80211_channel)) 609 return EINVAL; 610 /* 611 * vap's may have different operating channels when HT is 612 * in use. When in RUN state report the vap-specific channel. 613 * Otherwise return curchan. 614 */ 615 if (vap->iv_state == IEEE80211_S_RUN) 616 c = vap->iv_bss->ni_chan; 617 else 618 c = ic->ic_curchan; 619 return copyout(c, ireq->i_data, sizeof(*c)); 620} 621 622static int 623getappie(const struct ieee80211_appie *aie, struct ieee80211req *ireq) 624{ 625 if (aie == NULL) 626 return EINVAL; 627 /* NB: truncate, caller can check length */ 628 if (ireq->i_len > aie->ie_len) 629 ireq->i_len = aie->ie_len; 630 return copyout(aie->ie_data, ireq->i_data, ireq->i_len); 631} 632 633static int 634ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq) 635{ 636 uint8_t fc0; 637 638 fc0 = ireq->i_val & 0xff; 639 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 640 return EINVAL; 641 /* NB: could check iv_opmode and reject but hardly worth the effort */ 642 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) { 643 case IEEE80211_FC0_SUBTYPE_BEACON: 644 return getappie(vap->iv_appie_beacon, ireq); 645 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 646 return getappie(vap->iv_appie_proberesp, ireq); 647 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 648 return getappie(vap->iv_appie_assocresp, ireq); 649 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 650 return getappie(vap->iv_appie_probereq, ireq); 651 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 652 return getappie(vap->iv_appie_assocreq, ireq); 653 case IEEE80211_FC0_SUBTYPE_BEACON|IEEE80211_FC0_SUBTYPE_PROBE_RESP: 654 return getappie(vap->iv_appie_wpa, ireq); 655 } 656 return EINVAL; 657} 658 659static __noinline int 660ieee80211_ioctl_getregdomain(struct ieee80211vap *vap, 661 const struct ieee80211req *ireq) 662{ 663 struct ieee80211com *ic = vap->iv_ic; 664 665 if (ireq->i_len != sizeof(ic->ic_regdomain)) 666 return EINVAL; 667 return copyout(&ic->ic_regdomain, ireq->i_data, 668 sizeof(ic->ic_regdomain)); 669} 670 671static __noinline int 672ieee80211_ioctl_getroam(struct ieee80211vap *vap, 673 const struct ieee80211req *ireq) 674{ 675 size_t len = ireq->i_len; 676 /* NB: accept short requests for backwards compat */ 677 if (len > sizeof(vap->iv_roamparms)) 678 len = sizeof(vap->iv_roamparms); 679 return copyout(vap->iv_roamparms, ireq->i_data, len); 680} 681 682static __noinline int 683ieee80211_ioctl_gettxparams(struct ieee80211vap *vap, 684 const struct ieee80211req *ireq) 685{ 686 size_t len = ireq->i_len; 687 /* NB: accept short requests for backwards compat */ 688 if (len > sizeof(vap->iv_txparms)) 689 len = sizeof(vap->iv_txparms); 690 return copyout(vap->iv_txparms, ireq->i_data, len); 691} 692 693static __noinline int 694ieee80211_ioctl_getdevcaps(struct ieee80211com *ic, 695 const struct ieee80211req *ireq) 696{ 697 struct ieee80211_devcaps_req *dc; 698 struct ieee80211req_chaninfo *ci; 699 int maxchans, error; 700 701 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) / 702 sizeof(struct ieee80211_channel)); 703 /* NB: require 1 so we know ic_nchans is accessible */ 704 if (maxchans < 1) 705 return EINVAL; 706 /* constrain max request size, 2K channels is ~24Kbytes */ 707 if (maxchans > 2048) 708 maxchans = 2048; 709 dc = (struct ieee80211_devcaps_req *) 710 malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO); 711 if (dc == NULL) 712 return ENOMEM; 713 dc->dc_drivercaps = ic->ic_caps; 714 dc->dc_cryptocaps = ic->ic_cryptocaps; 715 dc->dc_htcaps = ic->ic_htcaps; 716 ci = &dc->dc_chaninfo; 717 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans); 718 KASSERT(ci->ic_nchans <= maxchans, 719 ("nchans %d maxchans %d", ci->ic_nchans, maxchans)); 720 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans); 721 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc)); 722 free(dc, M_TEMP); 723 return error; 724} 725 726static __noinline int 727ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) 728{ 729 struct ieee80211_node *ni; 730 struct ieee80211req_sta_vlan vlan; 731 int error; 732 733 if (ireq->i_len != sizeof(vlan)) 734 return EINVAL; 735 error = copyin(ireq->i_data, &vlan, sizeof(vlan)); 736 if (error != 0) 737 return error; 738 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) { 739 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 740 vlan.sv_macaddr); 741 if (ni == NULL) 742 return ENOENT; 743 } else 744 ni = ieee80211_ref_node(vap->iv_bss); 745 vlan.sv_vlan = ni->ni_vlan; 746 error = copyout(&vlan, ireq->i_data, sizeof(vlan)); 747 ieee80211_free_node(ni); 748 return error; 749} 750 751/* 752 * Dummy ioctl get handler so the linker set is defined. 753 */ 754static int 755dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq) 756{ 757 return ENOSYS; 758} 759IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get); 760 761static int 762ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq) 763{ 764 ieee80211_ioctl_getfunc * const *get; 765 int error; 766 767 SET_FOREACH(get, ieee80211_ioctl_getset) { 768 error = (*get)(vap, ireq); 769 if (error != ENOSYS) 770 return error; 771 } 772 return EINVAL; 773} 774 775/* 776 * When building the kernel with -O2 on the i386 architecture, gcc 777 * seems to want to inline this function into ieee80211_ioctl() 778 * (which is the only routine that calls it). When this happens, 779 * ieee80211_ioctl() ends up consuming an additional 2K of stack 780 * space. (Exactly why it needs so much is unclear.) The problem 781 * is that it's possible for ieee80211_ioctl() to invoke other 782 * routines (including driver init functions) which could then find 783 * themselves perilously close to exhausting the stack. 784 * 785 * To avoid this, we deliberately prevent gcc from inlining this 786 * routine. Another way to avoid this is to use less agressive 787 * optimization when compiling this file (i.e. -O instead of -O2) 788 * but special-casing the compilation of this one module in the 789 * build system would be awkward. 790 */ 791static __noinline int 792ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, 793 struct ieee80211req *ireq) 794{ 795#define MS(_v, _f) (((_v) & _f) >> _f##_S) 796 struct ieee80211com *ic = vap->iv_ic; 797 u_int kid, len; 798 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 799 char tmpssid[IEEE80211_NWID_LEN]; 800 int error = 0; 801 802 switch (ireq->i_type) { 803 case IEEE80211_IOC_SSID: 804 switch (vap->iv_state) { 805 case IEEE80211_S_INIT: 806 case IEEE80211_S_SCAN: 807 ireq->i_len = vap->iv_des_ssid[0].len; 808 memcpy(tmpssid, vap->iv_des_ssid[0].ssid, ireq->i_len); 809 break; 810 default: 811 ireq->i_len = vap->iv_bss->ni_esslen; 812 memcpy(tmpssid, vap->iv_bss->ni_essid, ireq->i_len); 813 break; 814 } 815 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 816 break; 817 case IEEE80211_IOC_NUMSSIDS: 818 ireq->i_val = 1; 819 break; 820 case IEEE80211_IOC_WEP: 821 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) 822 ireq->i_val = IEEE80211_WEP_OFF; 823 else if (vap->iv_flags & IEEE80211_F_DROPUNENC) 824 ireq->i_val = IEEE80211_WEP_ON; 825 else 826 ireq->i_val = IEEE80211_WEP_MIXED; 827 break; 828 case IEEE80211_IOC_WEPKEY: 829 kid = (u_int) ireq->i_val; 830 if (kid >= IEEE80211_WEP_NKID) 831 return EINVAL; 832 len = (u_int) vap->iv_nw_keys[kid].wk_keylen; 833 /* NB: only root can read WEP keys */ 834 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 835 bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len); 836 } else { 837 bzero(tmpkey, len); 838 } 839 ireq->i_len = len; 840 error = copyout(tmpkey, ireq->i_data, len); 841 break; 842 case IEEE80211_IOC_NUMWEPKEYS: 843 ireq->i_val = IEEE80211_WEP_NKID; 844 break; 845 case IEEE80211_IOC_WEPTXKEY: 846 ireq->i_val = vap->iv_def_txkey; 847 break; 848 case IEEE80211_IOC_AUTHMODE: 849 if (vap->iv_flags & IEEE80211_F_WPA) 850 ireq->i_val = IEEE80211_AUTH_WPA; 851 else 852 ireq->i_val = vap->iv_bss->ni_authmode; 853 break; 854 case IEEE80211_IOC_CHANNEL: 855 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan); 856 break; 857 case IEEE80211_IOC_POWERSAVE: 858 if (vap->iv_flags & IEEE80211_F_PMGTON) 859 ireq->i_val = IEEE80211_POWERSAVE_ON; 860 else 861 ireq->i_val = IEEE80211_POWERSAVE_OFF; 862 break; 863 case IEEE80211_IOC_POWERSAVESLEEP: 864 ireq->i_val = ic->ic_lintval; 865 break; 866 case IEEE80211_IOC_RTSTHRESHOLD: 867 ireq->i_val = vap->iv_rtsthreshold; 868 break; 869 case IEEE80211_IOC_PROTMODE: 870 ireq->i_val = ic->ic_protmode; 871 break; 872 case IEEE80211_IOC_TXPOWER: 873 /* 874 * Tx power limit is the min of max regulatory 875 * power, any user-set limit, and the max the 876 * radio can do. 877 */ 878 ireq->i_val = 2*ic->ic_curchan->ic_maxregpower; 879 if (ireq->i_val > ic->ic_txpowlimit) 880 ireq->i_val = ic->ic_txpowlimit; 881 if (ireq->i_val > ic->ic_curchan->ic_maxpower) 882 ireq->i_val = ic->ic_curchan->ic_maxpower; 883 break; 884 case IEEE80211_IOC_WPA: 885 switch (vap->iv_flags & IEEE80211_F_WPA) { 886 case IEEE80211_F_WPA1: 887 ireq->i_val = 1; 888 break; 889 case IEEE80211_F_WPA2: 890 ireq->i_val = 2; 891 break; 892 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2: 893 ireq->i_val = 3; 894 break; 895 default: 896 ireq->i_val = 0; 897 break; 898 } 899 break; 900 case IEEE80211_IOC_CHANLIST: 901 error = ieee80211_ioctl_getchanlist(vap, ireq); 902 break; 903 case IEEE80211_IOC_ROAMING: 904 ireq->i_val = vap->iv_roaming; 905 break; 906 case IEEE80211_IOC_PRIVACY: 907 ireq->i_val = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0; 908 break; 909 case IEEE80211_IOC_DROPUNENCRYPTED: 910 ireq->i_val = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0; 911 break; 912 case IEEE80211_IOC_COUNTERMEASURES: 913 ireq->i_val = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0; 914 break; 915 case IEEE80211_IOC_WME: 916 ireq->i_val = (vap->iv_flags & IEEE80211_F_WME) != 0; 917 break; 918 case IEEE80211_IOC_HIDESSID: 919 ireq->i_val = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0; 920 break; 921 case IEEE80211_IOC_APBRIDGE: 922 ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0; 923 break; 924 case IEEE80211_IOC_WPAKEY: 925 error = ieee80211_ioctl_getkey(vap, ireq); 926 break; 927 case IEEE80211_IOC_CHANINFO: 928 error = ieee80211_ioctl_getchaninfo(vap, ireq); 929 break; 930 case IEEE80211_IOC_BSSID: 931 if (ireq->i_len != IEEE80211_ADDR_LEN) 932 return EINVAL; 933 error = copyout(vap->iv_state == IEEE80211_S_RUN ? 934 vap->iv_bss->ni_bssid : 935 vap->iv_des_bssid, 936 ireq->i_data, ireq->i_len); 937 break; 938 case IEEE80211_IOC_WPAIE: 939 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type); 940 break; 941 case IEEE80211_IOC_WPAIE2: 942 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type); 943 break; 944 case IEEE80211_IOC_SCAN_RESULTS: 945 error = ieee80211_ioctl_getscanresults(vap, ireq); 946 break; 947 case IEEE80211_IOC_STA_STATS: 948 error = ieee80211_ioctl_getstastats(vap, ireq); 949 break; 950 case IEEE80211_IOC_TXPOWMAX: 951 ireq->i_val = vap->iv_bss->ni_txpower; 952 break; 953 case IEEE80211_IOC_STA_TXPOW: 954 error = ieee80211_ioctl_getstatxpow(vap, ireq); 955 break; 956 case IEEE80211_IOC_STA_INFO: 957 error = ieee80211_ioctl_getstainfo(vap, ireq); 958 break; 959 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 960 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 961 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 962 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 963 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 964 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 965 error = ieee80211_ioctl_getwmeparam(vap, ireq); 966 break; 967 case IEEE80211_IOC_DTIM_PERIOD: 968 ireq->i_val = vap->iv_dtim_period; 969 break; 970 case IEEE80211_IOC_BEACON_INTERVAL: 971 /* NB: get from ic_bss for station mode */ 972 ireq->i_val = vap->iv_bss->ni_intval; 973 break; 974 case IEEE80211_IOC_PUREG: 975 ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0; 976 break;
| 587static __noinline int 588ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq) 589{ 590 struct ieee80211com *ic = vap->iv_ic; 591 struct ieee80211_channel *c; 592 593 if (ireq->i_len != sizeof(struct ieee80211_channel)) 594 return EINVAL; 595 /* 596 * vap's may have different operating channels when HT is 597 * in use. When in RUN state report the vap-specific channel. 598 * Otherwise return curchan. 599 */ 600 if (vap->iv_state == IEEE80211_S_RUN) 601 c = vap->iv_bss->ni_chan; 602 else 603 c = ic->ic_curchan; 604 return copyout(c, ireq->i_data, sizeof(*c)); 605} 606 607static int 608getappie(const struct ieee80211_appie *aie, struct ieee80211req *ireq) 609{ 610 if (aie == NULL) 611 return EINVAL; 612 /* NB: truncate, caller can check length */ 613 if (ireq->i_len > aie->ie_len) 614 ireq->i_len = aie->ie_len; 615 return copyout(aie->ie_data, ireq->i_data, ireq->i_len); 616} 617 618static int 619ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq) 620{ 621 uint8_t fc0; 622 623 fc0 = ireq->i_val & 0xff; 624 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 625 return EINVAL; 626 /* NB: could check iv_opmode and reject but hardly worth the effort */ 627 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) { 628 case IEEE80211_FC0_SUBTYPE_BEACON: 629 return getappie(vap->iv_appie_beacon, ireq); 630 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 631 return getappie(vap->iv_appie_proberesp, ireq); 632 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 633 return getappie(vap->iv_appie_assocresp, ireq); 634 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 635 return getappie(vap->iv_appie_probereq, ireq); 636 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 637 return getappie(vap->iv_appie_assocreq, ireq); 638 case IEEE80211_FC0_SUBTYPE_BEACON|IEEE80211_FC0_SUBTYPE_PROBE_RESP: 639 return getappie(vap->iv_appie_wpa, ireq); 640 } 641 return EINVAL; 642} 643 644static __noinline int 645ieee80211_ioctl_getregdomain(struct ieee80211vap *vap, 646 const struct ieee80211req *ireq) 647{ 648 struct ieee80211com *ic = vap->iv_ic; 649 650 if (ireq->i_len != sizeof(ic->ic_regdomain)) 651 return EINVAL; 652 return copyout(&ic->ic_regdomain, ireq->i_data, 653 sizeof(ic->ic_regdomain)); 654} 655 656static __noinline int 657ieee80211_ioctl_getroam(struct ieee80211vap *vap, 658 const struct ieee80211req *ireq) 659{ 660 size_t len = ireq->i_len; 661 /* NB: accept short requests for backwards compat */ 662 if (len > sizeof(vap->iv_roamparms)) 663 len = sizeof(vap->iv_roamparms); 664 return copyout(vap->iv_roamparms, ireq->i_data, len); 665} 666 667static __noinline int 668ieee80211_ioctl_gettxparams(struct ieee80211vap *vap, 669 const struct ieee80211req *ireq) 670{ 671 size_t len = ireq->i_len; 672 /* NB: accept short requests for backwards compat */ 673 if (len > sizeof(vap->iv_txparms)) 674 len = sizeof(vap->iv_txparms); 675 return copyout(vap->iv_txparms, ireq->i_data, len); 676} 677 678static __noinline int 679ieee80211_ioctl_getdevcaps(struct ieee80211com *ic, 680 const struct ieee80211req *ireq) 681{ 682 struct ieee80211_devcaps_req *dc; 683 struct ieee80211req_chaninfo *ci; 684 int maxchans, error; 685 686 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) / 687 sizeof(struct ieee80211_channel)); 688 /* NB: require 1 so we know ic_nchans is accessible */ 689 if (maxchans < 1) 690 return EINVAL; 691 /* constrain max request size, 2K channels is ~24Kbytes */ 692 if (maxchans > 2048) 693 maxchans = 2048; 694 dc = (struct ieee80211_devcaps_req *) 695 malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO); 696 if (dc == NULL) 697 return ENOMEM; 698 dc->dc_drivercaps = ic->ic_caps; 699 dc->dc_cryptocaps = ic->ic_cryptocaps; 700 dc->dc_htcaps = ic->ic_htcaps; 701 ci = &dc->dc_chaninfo; 702 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans); 703 KASSERT(ci->ic_nchans <= maxchans, 704 ("nchans %d maxchans %d", ci->ic_nchans, maxchans)); 705 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans); 706 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc)); 707 free(dc, M_TEMP); 708 return error; 709} 710 711static __noinline int 712ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) 713{ 714 struct ieee80211_node *ni; 715 struct ieee80211req_sta_vlan vlan; 716 int error; 717 718 if (ireq->i_len != sizeof(vlan)) 719 return EINVAL; 720 error = copyin(ireq->i_data, &vlan, sizeof(vlan)); 721 if (error != 0) 722 return error; 723 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) { 724 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 725 vlan.sv_macaddr); 726 if (ni == NULL) 727 return ENOENT; 728 } else 729 ni = ieee80211_ref_node(vap->iv_bss); 730 vlan.sv_vlan = ni->ni_vlan; 731 error = copyout(&vlan, ireq->i_data, sizeof(vlan)); 732 ieee80211_free_node(ni); 733 return error; 734} 735 736/* 737 * Dummy ioctl get handler so the linker set is defined. 738 */ 739static int 740dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq) 741{ 742 return ENOSYS; 743} 744IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get); 745 746static int 747ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq) 748{ 749 ieee80211_ioctl_getfunc * const *get; 750 int error; 751 752 SET_FOREACH(get, ieee80211_ioctl_getset) { 753 error = (*get)(vap, ireq); 754 if (error != ENOSYS) 755 return error; 756 } 757 return EINVAL; 758} 759 760/* 761 * When building the kernel with -O2 on the i386 architecture, gcc 762 * seems to want to inline this function into ieee80211_ioctl() 763 * (which is the only routine that calls it). When this happens, 764 * ieee80211_ioctl() ends up consuming an additional 2K of stack 765 * space. (Exactly why it needs so much is unclear.) The problem 766 * is that it's possible for ieee80211_ioctl() to invoke other 767 * routines (including driver init functions) which could then find 768 * themselves perilously close to exhausting the stack. 769 * 770 * To avoid this, we deliberately prevent gcc from inlining this 771 * routine. Another way to avoid this is to use less agressive 772 * optimization when compiling this file (i.e. -O instead of -O2) 773 * but special-casing the compilation of this one module in the 774 * build system would be awkward. 775 */ 776static __noinline int 777ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, 778 struct ieee80211req *ireq) 779{ 780#define MS(_v, _f) (((_v) & _f) >> _f##_S) 781 struct ieee80211com *ic = vap->iv_ic; 782 u_int kid, len; 783 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 784 char tmpssid[IEEE80211_NWID_LEN]; 785 int error = 0; 786 787 switch (ireq->i_type) { 788 case IEEE80211_IOC_SSID: 789 switch (vap->iv_state) { 790 case IEEE80211_S_INIT: 791 case IEEE80211_S_SCAN: 792 ireq->i_len = vap->iv_des_ssid[0].len; 793 memcpy(tmpssid, vap->iv_des_ssid[0].ssid, ireq->i_len); 794 break; 795 default: 796 ireq->i_len = vap->iv_bss->ni_esslen; 797 memcpy(tmpssid, vap->iv_bss->ni_essid, ireq->i_len); 798 break; 799 } 800 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 801 break; 802 case IEEE80211_IOC_NUMSSIDS: 803 ireq->i_val = 1; 804 break; 805 case IEEE80211_IOC_WEP: 806 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) 807 ireq->i_val = IEEE80211_WEP_OFF; 808 else if (vap->iv_flags & IEEE80211_F_DROPUNENC) 809 ireq->i_val = IEEE80211_WEP_ON; 810 else 811 ireq->i_val = IEEE80211_WEP_MIXED; 812 break; 813 case IEEE80211_IOC_WEPKEY: 814 kid = (u_int) ireq->i_val; 815 if (kid >= IEEE80211_WEP_NKID) 816 return EINVAL; 817 len = (u_int) vap->iv_nw_keys[kid].wk_keylen; 818 /* NB: only root can read WEP keys */ 819 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 820 bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len); 821 } else { 822 bzero(tmpkey, len); 823 } 824 ireq->i_len = len; 825 error = copyout(tmpkey, ireq->i_data, len); 826 break; 827 case IEEE80211_IOC_NUMWEPKEYS: 828 ireq->i_val = IEEE80211_WEP_NKID; 829 break; 830 case IEEE80211_IOC_WEPTXKEY: 831 ireq->i_val = vap->iv_def_txkey; 832 break; 833 case IEEE80211_IOC_AUTHMODE: 834 if (vap->iv_flags & IEEE80211_F_WPA) 835 ireq->i_val = IEEE80211_AUTH_WPA; 836 else 837 ireq->i_val = vap->iv_bss->ni_authmode; 838 break; 839 case IEEE80211_IOC_CHANNEL: 840 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan); 841 break; 842 case IEEE80211_IOC_POWERSAVE: 843 if (vap->iv_flags & IEEE80211_F_PMGTON) 844 ireq->i_val = IEEE80211_POWERSAVE_ON; 845 else 846 ireq->i_val = IEEE80211_POWERSAVE_OFF; 847 break; 848 case IEEE80211_IOC_POWERSAVESLEEP: 849 ireq->i_val = ic->ic_lintval; 850 break; 851 case IEEE80211_IOC_RTSTHRESHOLD: 852 ireq->i_val = vap->iv_rtsthreshold; 853 break; 854 case IEEE80211_IOC_PROTMODE: 855 ireq->i_val = ic->ic_protmode; 856 break; 857 case IEEE80211_IOC_TXPOWER: 858 /* 859 * Tx power limit is the min of max regulatory 860 * power, any user-set limit, and the max the 861 * radio can do. 862 */ 863 ireq->i_val = 2*ic->ic_curchan->ic_maxregpower; 864 if (ireq->i_val > ic->ic_txpowlimit) 865 ireq->i_val = ic->ic_txpowlimit; 866 if (ireq->i_val > ic->ic_curchan->ic_maxpower) 867 ireq->i_val = ic->ic_curchan->ic_maxpower; 868 break; 869 case IEEE80211_IOC_WPA: 870 switch (vap->iv_flags & IEEE80211_F_WPA) { 871 case IEEE80211_F_WPA1: 872 ireq->i_val = 1; 873 break; 874 case IEEE80211_F_WPA2: 875 ireq->i_val = 2; 876 break; 877 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2: 878 ireq->i_val = 3; 879 break; 880 default: 881 ireq->i_val = 0; 882 break; 883 } 884 break; 885 case IEEE80211_IOC_CHANLIST: 886 error = ieee80211_ioctl_getchanlist(vap, ireq); 887 break; 888 case IEEE80211_IOC_ROAMING: 889 ireq->i_val = vap->iv_roaming; 890 break; 891 case IEEE80211_IOC_PRIVACY: 892 ireq->i_val = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0; 893 break; 894 case IEEE80211_IOC_DROPUNENCRYPTED: 895 ireq->i_val = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0; 896 break; 897 case IEEE80211_IOC_COUNTERMEASURES: 898 ireq->i_val = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0; 899 break; 900 case IEEE80211_IOC_WME: 901 ireq->i_val = (vap->iv_flags & IEEE80211_F_WME) != 0; 902 break; 903 case IEEE80211_IOC_HIDESSID: 904 ireq->i_val = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0; 905 break; 906 case IEEE80211_IOC_APBRIDGE: 907 ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0; 908 break; 909 case IEEE80211_IOC_WPAKEY: 910 error = ieee80211_ioctl_getkey(vap, ireq); 911 break; 912 case IEEE80211_IOC_CHANINFO: 913 error = ieee80211_ioctl_getchaninfo(vap, ireq); 914 break; 915 case IEEE80211_IOC_BSSID: 916 if (ireq->i_len != IEEE80211_ADDR_LEN) 917 return EINVAL; 918 error = copyout(vap->iv_state == IEEE80211_S_RUN ? 919 vap->iv_bss->ni_bssid : 920 vap->iv_des_bssid, 921 ireq->i_data, ireq->i_len); 922 break; 923 case IEEE80211_IOC_WPAIE: 924 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type); 925 break; 926 case IEEE80211_IOC_WPAIE2: 927 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type); 928 break; 929 case IEEE80211_IOC_SCAN_RESULTS: 930 error = ieee80211_ioctl_getscanresults(vap, ireq); 931 break; 932 case IEEE80211_IOC_STA_STATS: 933 error = ieee80211_ioctl_getstastats(vap, ireq); 934 break; 935 case IEEE80211_IOC_TXPOWMAX: 936 ireq->i_val = vap->iv_bss->ni_txpower; 937 break; 938 case IEEE80211_IOC_STA_TXPOW: 939 error = ieee80211_ioctl_getstatxpow(vap, ireq); 940 break; 941 case IEEE80211_IOC_STA_INFO: 942 error = ieee80211_ioctl_getstainfo(vap, ireq); 943 break; 944 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 945 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 946 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 947 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 948 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 949 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 950 error = ieee80211_ioctl_getwmeparam(vap, ireq); 951 break; 952 case IEEE80211_IOC_DTIM_PERIOD: 953 ireq->i_val = vap->iv_dtim_period; 954 break; 955 case IEEE80211_IOC_BEACON_INTERVAL: 956 /* NB: get from ic_bss for station mode */ 957 ireq->i_val = vap->iv_bss->ni_intval; 958 break; 959 case IEEE80211_IOC_PUREG: 960 ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0; 961 break;
|
983 case IEEE80211_IOC_BGSCAN: 984 ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0; 985 break; 986 case IEEE80211_IOC_BGSCAN_IDLE: 987 ireq->i_val = vap->iv_bgscanidle*hz/1000; /* ms */ 988 break; 989 case IEEE80211_IOC_BGSCAN_INTERVAL: 990 ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */ 991 break; 992 case IEEE80211_IOC_SCANVALID: 993 ireq->i_val = vap->iv_scanvalid/hz; /* seconds */ 994 break; 995 case IEEE80211_IOC_FRAGTHRESHOLD: 996 ireq->i_val = vap->iv_fragthreshold; 997 break; 998 case IEEE80211_IOC_MACCMD: 999 error = ieee80211_ioctl_getmaccmd(vap, ireq); 1000 break; 1001 case IEEE80211_IOC_BURST: 1002 ireq->i_val = (vap->iv_flags & IEEE80211_F_BURST) != 0; 1003 break; 1004 case IEEE80211_IOC_BMISSTHRESHOLD: 1005 ireq->i_val = vap->iv_bmissthreshold; 1006 break; 1007 case IEEE80211_IOC_CURCHAN: 1008 error = ieee80211_ioctl_getcurchan(vap, ireq); 1009 break; 1010 case IEEE80211_IOC_SHORTGI: 1011 ireq->i_val = 0; 1012 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI20) 1013 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20; 1014 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI40) 1015 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40; 1016 break; 1017 case IEEE80211_IOC_AMPDU: 1018 ireq->i_val = 0; 1019 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_TX) 1020 ireq->i_val |= 1; 1021 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_RX) 1022 ireq->i_val |= 2; 1023 break; 1024 case IEEE80211_IOC_AMPDU_LIMIT: 1025 if (vap->iv_opmode == IEEE80211_M_HOSTAP) 1026 ireq->i_val = vap->iv_ampdu_rxmax; 1027 else if (vap->iv_state == IEEE80211_S_RUN) 1028 ireq->i_val = MS(vap->iv_bss->ni_htparam, 1029 IEEE80211_HTCAP_MAXRXAMPDU); 1030 else 1031 ireq->i_val = vap->iv_ampdu_limit; 1032 break; 1033 case IEEE80211_IOC_AMPDU_DENSITY: 1034 if (vap->iv_opmode == IEEE80211_M_STA && 1035 vap->iv_state == IEEE80211_S_RUN) 1036 ireq->i_val = MS(vap->iv_bss->ni_htparam, 1037 IEEE80211_HTCAP_MPDUDENSITY); 1038 else 1039 ireq->i_val = vap->iv_ampdu_density; 1040 break; 1041 case IEEE80211_IOC_AMSDU: 1042 ireq->i_val = 0; 1043 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_TX) 1044 ireq->i_val |= 1; 1045 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_RX) 1046 ireq->i_val |= 2; 1047 break; 1048 case IEEE80211_IOC_AMSDU_LIMIT: 1049 ireq->i_val = vap->iv_amsdu_limit; /* XXX truncation? */ 1050 break; 1051 case IEEE80211_IOC_PUREN: 1052 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_PUREN) != 0; 1053 break; 1054 case IEEE80211_IOC_DOTH: 1055 ireq->i_val = (vap->iv_flags & IEEE80211_F_DOTH) != 0; 1056 break; 1057 case IEEE80211_IOC_REGDOMAIN: 1058 error = ieee80211_ioctl_getregdomain(vap, ireq); 1059 break; 1060 case IEEE80211_IOC_ROAM: 1061 error = ieee80211_ioctl_getroam(vap, ireq); 1062 break; 1063 case IEEE80211_IOC_TXPARAMS: 1064 error = ieee80211_ioctl_gettxparams(vap, ireq); 1065 break; 1066 case IEEE80211_IOC_HTCOMPAT: 1067 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0; 1068 break; 1069 case IEEE80211_IOC_DWDS: 1070 ireq->i_val = (vap->iv_flags & IEEE80211_F_DWDS) != 0; 1071 break; 1072 case IEEE80211_IOC_INACTIVITY: 1073 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_INACT) != 0; 1074 break; 1075 case IEEE80211_IOC_APPIE: 1076 error = ieee80211_ioctl_getappie(vap, ireq); 1077 break; 1078 case IEEE80211_IOC_WPS: 1079 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_WPS) != 0; 1080 break; 1081 case IEEE80211_IOC_TSN: 1082 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_TSN) != 0; 1083 break; 1084 case IEEE80211_IOC_DFS: 1085 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DFS) != 0; 1086 break; 1087 case IEEE80211_IOC_DOTD: 1088 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DOTD) != 0; 1089 break; 1090 case IEEE80211_IOC_DEVCAPS: 1091 error = ieee80211_ioctl_getdevcaps(ic, ireq); 1092 break; 1093 case IEEE80211_IOC_HTPROTMODE: 1094 ireq->i_val = ic->ic_htprotmode; 1095 break; 1096 case IEEE80211_IOC_HTCONF: 1097 if (vap->iv_flags_ext & IEEE80211_FEXT_HT) { 1098 ireq->i_val = 1; 1099 if (vap->iv_flags_ext & IEEE80211_FEXT_USEHT40) 1100 ireq->i_val |= 2; 1101 } else 1102 ireq->i_val = 0; 1103 break; 1104 case IEEE80211_IOC_STA_VLAN: 1105 error = ieee80211_ioctl_getstavlan(vap, ireq); 1106 break; 1107 case IEEE80211_IOC_SMPS: 1108 if (vap->iv_opmode == IEEE80211_M_STA && 1109 vap->iv_state == IEEE80211_S_RUN) { 1110 if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS) 1111 ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC; 1112 else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS) 1113 ireq->i_val = IEEE80211_HTCAP_SMPS_ENA; 1114 else 1115 ireq->i_val = IEEE80211_HTCAP_SMPS_OFF; 1116 } else 1117 ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS; 1118 break; 1119 case IEEE80211_IOC_RIFS: 1120 if (vap->iv_opmode == IEEE80211_M_STA && 1121 vap->iv_state == IEEE80211_S_RUN) 1122 ireq->i_val = 1123 (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0; 1124 else 1125 ireq->i_val = 1126 (vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0; 1127 break; 1128 default: 1129 error = ieee80211_ioctl_getdefault(vap, ireq); 1130 break; 1131 } 1132 return error; 1133#undef MS 1134} 1135 1136static __noinline int 1137ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 1138{ 1139 struct ieee80211req_key ik; 1140 struct ieee80211_node *ni; 1141 struct ieee80211_key *wk; 1142 uint16_t kid; 1143 int error, i; 1144 1145 if (ireq->i_len != sizeof(ik)) 1146 return EINVAL; 1147 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1148 if (error) 1149 return error; 1150 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1151 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1152 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1153 return E2BIG; 1154 kid = ik.ik_keyix; 1155 if (kid == IEEE80211_KEYIX_NONE) { 1156 /* XXX unicast keys currently must be tx/rx */ 1157 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1158 return EINVAL; 1159 if (vap->iv_opmode == IEEE80211_M_STA) { 1160 ni = ieee80211_ref_node(vap->iv_bss); 1161 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) { 1162 ieee80211_free_node(ni); 1163 return EADDRNOTAVAIL; 1164 } 1165 } else { 1166 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 1167 ik.ik_macaddr); 1168 if (ni == NULL) 1169 return ENOENT; 1170 } 1171 wk = &ni->ni_ucastkey; 1172 } else { 1173 if (kid >= IEEE80211_WEP_NKID) 1174 return EINVAL; 1175 wk = &vap->iv_nw_keys[kid]; 1176 /* 1177 * Global slots start off w/o any assigned key index. 1178 * Force one here for consistency with IEEE80211_IOC_WEPKEY. 1179 */ 1180 if (wk->wk_keyix == IEEE80211_KEYIX_NONE) 1181 wk->wk_keyix = kid; 1182 ni = NULL; 1183 } 1184 error = 0; 1185 ieee80211_key_update_begin(vap); 1186 if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) { 1187 wk->wk_keylen = ik.ik_keylen; 1188 /* NB: MIC presence is implied by cipher type */ 1189 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1190 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1191 for (i = 0; i < IEEE80211_TID_SIZE; i++) 1192 wk->wk_keyrsc[i] = ik.ik_keyrsc; 1193 wk->wk_keytsc = 0; /* new key, reset */ 1194 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1195 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1196 IEEE80211_ADDR_COPY(wk->wk_macaddr, 1197 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr); 1198 if (!ieee80211_crypto_setkey(vap, wk)) 1199 error = EIO; 1200 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1201 vap->iv_def_txkey = kid; 1202 } else 1203 error = ENXIO; 1204 ieee80211_key_update_end(vap); 1205 if (ni != NULL) 1206 ieee80211_free_node(ni); 1207 return error; 1208} 1209 1210static __noinline int 1211ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 1212{ 1213 struct ieee80211req_del_key dk; 1214 int kid, error; 1215 1216 if (ireq->i_len != sizeof(dk)) 1217 return EINVAL; 1218 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1219 if (error) 1220 return error; 1221 kid = dk.idk_keyix; 1222 /* XXX uint8_t -> uint16_t */ 1223 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) { 1224 struct ieee80211_node *ni; 1225 1226 if (vap->iv_opmode == IEEE80211_M_STA) { 1227 ni = ieee80211_ref_node(vap->iv_bss); 1228 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1229 ieee80211_free_node(ni); 1230 return EADDRNOTAVAIL; 1231 } 1232 } else { 1233 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 1234 dk.idk_macaddr); 1235 if (ni == NULL) 1236 return ENOENT; 1237 } 1238 /* XXX error return */ 1239 ieee80211_node_delucastkey(ni); 1240 ieee80211_free_node(ni); 1241 } else { 1242 if (kid >= IEEE80211_WEP_NKID) 1243 return EINVAL; 1244 /* XXX error return */ 1245 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]); 1246 } 1247 return 0; 1248} 1249 1250struct mlmeop { 1251 struct ieee80211vap *vap; 1252 int op; 1253 int reason; 1254}; 1255 1256static void 1257mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], 1258 int op, int reason) 1259{ 1260#ifdef IEEE80211_DEBUG 1261 static const struct { 1262 int mask; 1263 const char *opstr; 1264 } ops[] = { 1265 { 0, "op#0" }, 1266 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1267 IEEE80211_MSG_ASSOC, "assoc" }, 1268 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1269 IEEE80211_MSG_ASSOC, "disassoc" }, 1270 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1271 IEEE80211_MSG_AUTH, "deauth" }, 1272 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1273 IEEE80211_MSG_AUTH, "authorize" }, 1274 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1275 IEEE80211_MSG_AUTH, "unauthorize" }, 1276 }; 1277 1278 if (op == IEEE80211_MLME_AUTH) { 1279 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL | 1280 IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac, 1281 "station authenticate %s via MLME (reason %d)", 1282 reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT", 1283 reason); 1284 } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) { 1285 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac, 1286 "unknown MLME request %d (reason %d)", op, reason); 1287 } else if (reason == IEEE80211_STATUS_SUCCESS) { 1288 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac, 1289 "station %s via MLME", ops[op].opstr); 1290 } else { 1291 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac, 1292 "station %s via MLME (reason %d)", ops[op].opstr, reason); 1293 } 1294#endif /* IEEE80211_DEBUG */ 1295} 1296 1297static void 1298domlme(void *arg, struct ieee80211_node *ni) 1299{ 1300 struct mlmeop *mop = arg; 1301 struct ieee80211vap *vap = ni->ni_vap; 1302 1303 if (vap != mop->vap) 1304 return; 1305 /* 1306 * NB: if ni_associd is zero then the node is already cleaned 1307 * up and we don't need to do this (we're safely holding a 1308 * reference but should otherwise not modify it's state). 1309 */ 1310 if (ni->ni_associd == 0) 1311 return; 1312 mlmedebug(vap, ni->ni_macaddr, mop->op, mop->reason); 1313 if (mop->op == IEEE80211_MLME_DEAUTH) { 1314 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, 1315 mop->reason); 1316 } else { 1317 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, 1318 mop->reason); 1319 } 1320 ieee80211_node_leave(ni); 1321} 1322 1323static int 1324setmlme_dropsta(struct ieee80211vap *vap, 1325 const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) 1326{ 1327 struct ieee80211com *ic = vap->iv_ic; 1328 struct ieee80211_node_table *nt = &ic->ic_sta; 1329 struct ieee80211_node *ni; 1330 int error = 0; 1331 1332 /* NB: the broadcast address means do 'em all */ 1333 if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) { 1334 IEEE80211_NODE_LOCK(nt); 1335 ni = ieee80211_find_node_locked(nt, mac); 1336 if (ni != NULL) { 1337 domlme(mlmeop, ni); 1338 ieee80211_free_node(ni); 1339 } else 1340 error = ENOENT; 1341 IEEE80211_NODE_UNLOCK(nt); 1342 } else { 1343 ieee80211_iterate_nodes(nt, domlme, mlmeop); 1344 } 1345 return error; 1346} 1347 1348static __noinline int 1349setmlme_common(struct ieee80211vap *vap, int op, 1350 const uint8_t mac[IEEE80211_ADDR_LEN], int reason) 1351{ 1352 struct ieee80211com *ic = vap->iv_ic; 1353 struct ieee80211_node_table *nt = &ic->ic_sta; 1354 struct ieee80211_node *ni; 1355 struct mlmeop mlmeop; 1356 int error; 1357 1358 error = 0; 1359 switch (op) { 1360 case IEEE80211_MLME_DISASSOC: 1361 case IEEE80211_MLME_DEAUTH: 1362 switch (vap->iv_opmode) { 1363 case IEEE80211_M_STA: 1364 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason); 1365 /* XXX not quite right */ 1366 ieee80211_new_state(vap, IEEE80211_S_INIT, reason); 1367 break; 1368 case IEEE80211_M_HOSTAP: 1369 mlmeop.vap = vap; 1370 mlmeop.op = op; 1371 mlmeop.reason = reason; 1372 error = setmlme_dropsta(vap, mac, &mlmeop); 1373 break; 1374 case IEEE80211_M_WDS: 1375 /* XXX user app should send raw frame? */ 1376 if (op != IEEE80211_MLME_DEAUTH) { 1377 error = EINVAL; 1378 break; 1379 } 1380#if 0 1381 /* XXX accept any address, simplifies user code */ 1382 if (!IEEE80211_ADDR_EQ(mac, vap->iv_bss->ni_macaddr)) { 1383 error = EINVAL; 1384 break; 1385 } 1386#endif 1387 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason); 1388 ni = ieee80211_ref_node(vap->iv_bss); 1389 IEEE80211_SEND_MGMT(ni, 1390 IEEE80211_FC0_SUBTYPE_DEAUTH, reason); 1391 ieee80211_free_node(ni); 1392 break; 1393 default: 1394 error = EINVAL; 1395 break; 1396 } 1397 break; 1398 case IEEE80211_MLME_AUTHORIZE: 1399 case IEEE80211_MLME_UNAUTHORIZE: 1400 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 1401 vap->iv_opmode != IEEE80211_M_WDS) { 1402 error = EINVAL; 1403 break; 1404 } 1405 IEEE80211_NODE_LOCK(nt); 1406 ni = ieee80211_find_vap_node_locked(nt, vap, mac); 1407 if (ni != NULL) { 1408 mlmedebug(vap, mac, op, reason); 1409 if (op == IEEE80211_MLME_AUTHORIZE) 1410 ieee80211_node_authorize(ni); 1411 else 1412 ieee80211_node_unauthorize(ni); 1413 ieee80211_free_node(ni); 1414 } else 1415 error = ENOENT; 1416 IEEE80211_NODE_UNLOCK(nt); 1417 break; 1418 case IEEE80211_MLME_AUTH: 1419 if (vap->iv_opmode != IEEE80211_M_HOSTAP) { 1420 error = EINVAL; 1421 break; 1422 } 1423 IEEE80211_NODE_LOCK(nt); 1424 ni = ieee80211_find_vap_node_locked(nt, vap, mac); 1425 if (ni != NULL) { 1426 mlmedebug(vap, mac, op, reason); 1427 if (reason == IEEE80211_STATUS_SUCCESS) { 1428 IEEE80211_SEND_MGMT(ni, 1429 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1430 /* 1431 * For shared key auth, just continue the 1432 * exchange. Otherwise when 802.1x is not in 1433 * use mark the port authorized at this point 1434 * so traffic can flow. 1435 */ 1436 if (ni->ni_authmode != IEEE80211_AUTH_8021X && 1437 ni->ni_challenge == NULL) 1438 ieee80211_node_authorize(ni); 1439 } else { 1440 vap->iv_stats.is_rx_acl++; 1441 ieee80211_send_error(ni, ni->ni_macaddr, 1442 IEEE80211_FC0_SUBTYPE_AUTH, 2|(reason<<16)); 1443 ieee80211_node_leave(ni); 1444 } 1445 ieee80211_free_node(ni); 1446 } else 1447 error = ENOENT; 1448 IEEE80211_NODE_UNLOCK(nt); 1449 break; 1450 default: 1451 error = EINVAL; 1452 break; 1453 } 1454 return error; 1455} 1456 1457struct scanlookup { 1458 const uint8_t *mac; 1459 int esslen; 1460 const uint8_t *essid; 1461 const struct ieee80211_scan_entry *se; 1462}; 1463 1464/* 1465 * Match mac address and any ssid. 1466 */ 1467static void 1468mlmelookup(void *arg, const struct ieee80211_scan_entry *se) 1469{ 1470 struct scanlookup *look = arg; 1471 1472 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) 1473 return; 1474 if (look->esslen != 0) { 1475 if (se->se_ssid[1] != look->esslen) 1476 return; 1477 if (memcmp(look->essid, se->se_ssid+2, look->esslen)) 1478 return; 1479 } 1480 look->se = se; 1481} 1482 1483static __noinline int 1484setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], 1485 int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN]) 1486{ 1487 struct scanlookup lookup; 1488 1489 /* XXX ibss/ahdemo */ 1490 if (vap->iv_opmode != IEEE80211_M_STA) 1491 return EINVAL; 1492 1493 /* NB: this is racey if roaming is !manual */ 1494 lookup.se = NULL; 1495 lookup.mac = mac; 1496 lookup.esslen = ssid_len; 1497 lookup.essid = ssid; 1498 ieee80211_scan_iterate(vap, mlmelookup, &lookup); 1499 if (lookup.se == NULL) 1500 return ENOENT; 1501 mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0); 1502 if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se)) 1503 return EIO; /* XXX unique but could be better */ 1504 return 0; 1505} 1506 1507static __noinline int 1508ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq) 1509{ 1510 struct ieee80211req_mlme mlme; 1511 int error; 1512 1513 if (ireq->i_len != sizeof(mlme)) 1514 return EINVAL; 1515 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1516 if (error) 1517 return error; 1518 if (mlme.im_op == IEEE80211_MLME_ASSOC) 1519 return setmlme_assoc(vap, mlme.im_macaddr, 1520 vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid); 1521 else 1522 return setmlme_common(vap, mlme.im_op, 1523 mlme.im_macaddr, mlme.im_reason); 1524} 1525 1526static __noinline int 1527ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq) 1528{ 1529 uint8_t mac[IEEE80211_ADDR_LEN]; 1530 const struct ieee80211_aclator *acl = vap->iv_acl; 1531 int error; 1532 1533 if (ireq->i_len != sizeof(mac)) 1534 return EINVAL; 1535 error = copyin(ireq->i_data, mac, ireq->i_len); 1536 if (error) 1537 return error; 1538 if (acl == NULL) { 1539 acl = ieee80211_aclator_get("mac"); 1540 if (acl == NULL || !acl->iac_attach(vap)) 1541 return EINVAL; 1542 vap->iv_acl = acl; 1543 } 1544 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1545 acl->iac_add(vap, mac); 1546 else 1547 acl->iac_remove(vap, mac); 1548 return 0; 1549} 1550 1551static __noinline int 1552ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) 1553{ 1554 const struct ieee80211_aclator *acl = vap->iv_acl; 1555 1556 switch (ireq->i_val) { 1557 case IEEE80211_MACCMD_POLICY_OPEN: 1558 case IEEE80211_MACCMD_POLICY_ALLOW: 1559 case IEEE80211_MACCMD_POLICY_DENY: 1560 case IEEE80211_MACCMD_POLICY_RADIUS: 1561 if (acl == NULL) { 1562 acl = ieee80211_aclator_get("mac"); 1563 if (acl == NULL || !acl->iac_attach(vap)) 1564 return EINVAL; 1565 vap->iv_acl = acl; 1566 } 1567 acl->iac_setpolicy(vap, ireq->i_val); 1568 break; 1569 case IEEE80211_MACCMD_FLUSH: 1570 if (acl != NULL) 1571 acl->iac_flush(vap); 1572 /* NB: silently ignore when not in use */ 1573 break; 1574 case IEEE80211_MACCMD_DETACH: 1575 if (acl != NULL) { 1576 vap->iv_acl = NULL; 1577 acl->iac_detach(vap); 1578 } 1579 break; 1580 default: 1581 if (acl == NULL) 1582 return EINVAL; 1583 else 1584 return acl->iac_setioctl(vap, ireq); 1585 } 1586 return 0; 1587} 1588 1589static __noinline int 1590ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) 1591{ 1592 struct ieee80211com *ic = vap->iv_ic; 1593 uint8_t *chanlist, *list; 1594 int i, nchan, maxchan, error; 1595 1596 if (ireq->i_len > sizeof(ic->ic_chan_active)) 1597 ireq->i_len = sizeof(ic->ic_chan_active); 1598 list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP, 1599 M_NOWAIT | M_ZERO); 1600 if (list == NULL) 1601 return ENOMEM; 1602 error = copyin(ireq->i_data, list, ireq->i_len); 1603 if (error) 1604 return error; 1605 nchan = 0; 1606 chanlist = list + ireq->i_len; /* NB: zero'd already */ 1607 maxchan = ireq->i_len * NBBY; 1608 for (i = 0; i < ic->ic_nchans; i++) { 1609 const struct ieee80211_channel *c = &ic->ic_channels[i]; 1610 /* 1611 * Calculate the intersection of the user list and the 1612 * available channels so users can do things like specify 1613 * 1-255 to get all available channels. 1614 */ 1615 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) { 1616 setbit(chanlist, c->ic_ieee); 1617 nchan++; 1618 } 1619 } 1620 if (nchan == 0) 1621 return EINVAL; 1622 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ 1623 isclr(chanlist, ic->ic_bsschan->ic_ieee)) 1624 ic->ic_bsschan = IEEE80211_CHAN_ANYC; 1625 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES); 1626 ieee80211_scan_flush(vap); 1627 free(list, M_TEMP); 1628 return ENETRESET; 1629} 1630 1631static __noinline int 1632ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) 1633{ 1634 struct ieee80211_node *ni; 1635 uint8_t macaddr[IEEE80211_ADDR_LEN]; 1636 int error; 1637 1638 /* 1639 * NB: we could copyin ieee80211req_sta_stats so apps 1640 * could make selective changes but that's overkill; 1641 * just clear all stats for now. 1642 */ 1643 if (ireq->i_len < IEEE80211_ADDR_LEN) 1644 return EINVAL; 1645 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1646 if (error != 0) 1647 return error; 1648 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 1649 if (ni == NULL) 1650 return ENOENT; 1651 /* XXX require ni_vap == vap? */ 1652 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats)); 1653 ieee80211_free_node(ni); 1654 return 0; 1655} 1656 1657static __noinline int 1658ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) 1659{ 1660 struct ieee80211_node *ni; 1661 struct ieee80211req_sta_txpow txpow; 1662 int error; 1663 1664 if (ireq->i_len != sizeof(txpow)) 1665 return EINVAL; 1666 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1667 if (error != 0) 1668 return error; 1669 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr); 1670 if (ni == NULL) 1671 return ENOENT; 1672 ni->ni_txpower = txpow.it_txpow; 1673 ieee80211_free_node(ni); 1674 return error; 1675} 1676 1677static __noinline int 1678ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) 1679{ 1680 struct ieee80211com *ic = vap->iv_ic; 1681 struct ieee80211_wme_state *wme = &ic->ic_wme; 1682 struct wmeParams *wmep, *chanp; 1683 int isbss, ac; 1684 1685 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1686 return EOPNOTSUPP; 1687 1688 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1689 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1690 if (ac >= WME_NUM_AC) 1691 ac = WME_AC_BE; 1692 if (isbss) { 1693 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1694 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1695 } else { 1696 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1697 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1698 } 1699 switch (ireq->i_type) { 1700 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1701 if (isbss) { 1702 wmep->wmep_logcwmin = ireq->i_val; 1703 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1704 chanp->wmep_logcwmin = ireq->i_val; 1705 } else { 1706 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1707 ireq->i_val; 1708 } 1709 break; 1710 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1711 if (isbss) { 1712 wmep->wmep_logcwmax = ireq->i_val; 1713 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1714 chanp->wmep_logcwmax = ireq->i_val; 1715 } else { 1716 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1717 ireq->i_val; 1718 } 1719 break; 1720 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1721 if (isbss) { 1722 wmep->wmep_aifsn = ireq->i_val; 1723 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1724 chanp->wmep_aifsn = ireq->i_val; 1725 } else { 1726 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1727 } 1728 break; 1729 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1730 if (isbss) { 1731 wmep->wmep_txopLimit = ireq->i_val; 1732 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1733 chanp->wmep_txopLimit = ireq->i_val; 1734 } else { 1735 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1736 ireq->i_val; 1737 } 1738 break; 1739 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1740 wmep->wmep_acm = ireq->i_val; 1741 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1742 chanp->wmep_acm = ireq->i_val; 1743 break; 1744 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1745 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1746 (ireq->i_val) == 0; 1747 break; 1748 } 1749 ieee80211_wme_updateparams(vap); 1750 return 0; 1751} 1752 1753static int 1754find11gchannel(struct ieee80211com *ic, int start, int freq) 1755{ 1756 const struct ieee80211_channel *c; 1757 int i; 1758 1759 for (i = start+1; i < ic->ic_nchans; i++) { 1760 c = &ic->ic_channels[i]; 1761 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1762 return 1; 1763 } 1764 /* NB: should not be needed but in case things are mis-sorted */ 1765 for (i = 0; i < start; i++) { 1766 c = &ic->ic_channels[i]; 1767 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1768 return 1; 1769 } 1770 return 0; 1771} 1772 1773static struct ieee80211_channel * 1774findchannel(struct ieee80211com *ic, int ieee, int mode) 1775{ 1776 static const u_int chanflags[IEEE80211_MODE_MAX] = { 1777 [IEEE80211_MODE_AUTO] = 0, 1778 [IEEE80211_MODE_11A] = IEEE80211_CHAN_A, 1779 [IEEE80211_MODE_11B] = IEEE80211_CHAN_B, 1780 [IEEE80211_MODE_11G] = IEEE80211_CHAN_G, 1781 [IEEE80211_MODE_FH] = IEEE80211_CHAN_FHSS, 1782 [IEEE80211_MODE_TURBO_A] = IEEE80211_CHAN_108A, 1783 [IEEE80211_MODE_TURBO_G] = IEEE80211_CHAN_108G, 1784 [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_STURBO, 1785 [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF, 1786 [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER, 1787 /* NB: handled specially below */ 1788 [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A, 1789 [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G, 1790 }; 1791 u_int modeflags; 1792 int i; 1793 1794 modeflags = chanflags[mode]; 1795 for (i = 0; i < ic->ic_nchans; i++) { 1796 struct ieee80211_channel *c = &ic->ic_channels[i]; 1797 1798 if (c->ic_ieee != ieee) 1799 continue; 1800 if (mode == IEEE80211_MODE_AUTO) { 1801 /* ignore turbo channels for autoselect */ 1802 if (IEEE80211_IS_CHAN_TURBO(c)) 1803 continue; 1804 /* 1805 * XXX special-case 11b/g channels so we 1806 * always select the g channel if both 1807 * are present. 1808 * XXX prefer HT to non-HT? 1809 */ 1810 if (!IEEE80211_IS_CHAN_B(c) || 1811 !find11gchannel(ic, i, c->ic_freq)) 1812 return c; 1813 } else { 1814 /* must check HT specially */ 1815 if ((mode == IEEE80211_MODE_11NA || 1816 mode == IEEE80211_MODE_11NG) && 1817 !IEEE80211_IS_CHAN_HT(c)) 1818 continue; 1819 if ((c->ic_flags & modeflags) == modeflags) 1820 return c; 1821 } 1822 } 1823 return NULL; 1824} 1825 1826/* 1827 * Check the specified against any desired mode (aka netband). 1828 * This is only used (presently) when operating in hostap mode 1829 * to enforce consistency. 1830 */ 1831static int 1832check_mode_consistency(const struct ieee80211_channel *c, int mode) 1833{ 1834 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel")); 1835 1836 switch (mode) { 1837 case IEEE80211_MODE_11B: 1838 return (IEEE80211_IS_CHAN_B(c)); 1839 case IEEE80211_MODE_11G: 1840 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c)); 1841 case IEEE80211_MODE_11A: 1842 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c)); 1843 case IEEE80211_MODE_STURBO_A: 1844 return (IEEE80211_IS_CHAN_STURBO(c)); 1845 case IEEE80211_MODE_11NA: 1846 return (IEEE80211_IS_CHAN_HTA(c)); 1847 case IEEE80211_MODE_11NG: 1848 return (IEEE80211_IS_CHAN_HTG(c)); 1849 } 1850 return 1; 1851 1852} 1853 1854/* 1855 * Common code to set the current channel. If the device 1856 * is up and running this may result in an immediate channel 1857 * change or a kick of the state machine. 1858 */ 1859static int 1860setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c) 1861{ 1862 struct ieee80211com *ic = vap->iv_ic; 1863 int error; 1864 1865 if (c != IEEE80211_CHAN_ANYC) { 1866 if (IEEE80211_IS_CHAN_RADAR(c)) 1867 return EBUSY; /* XXX better code? */ 1868 if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 1869 if (IEEE80211_IS_CHAN_NOHOSTAP(c)) 1870 return EINVAL; 1871 if (!check_mode_consistency(c, vap->iv_des_mode)) 1872 return EINVAL; 1873 } else if (vap->iv_opmode == IEEE80211_M_IBSS) { 1874 if (IEEE80211_IS_CHAN_NOADHOC(c)) 1875 return EINVAL; 1876 } 1877 if (vap->iv_state == IEEE80211_S_RUN && 1878 vap->iv_bss->ni_chan == c) 1879 return 0; /* NB: nothing to do */ 1880 } 1881 vap->iv_des_chan = c; 1882 1883 error = 0; 1884 if (vap->iv_opmode == IEEE80211_M_MONITOR && 1885 vap->iv_des_chan != IEEE80211_CHAN_ANYC) { 1886 /* 1887 * Monitor mode can switch directly. 1888 */ 1889 if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) { 1890 /* XXX need state machine for other vap's to follow */ 1891 ieee80211_setcurchan(ic, vap->iv_des_chan); 1892 vap->iv_bss->ni_chan = ic->ic_curchan; 1893 } else 1894 ic->ic_curchan = vap->iv_des_chan; 1895 } else { 1896 /* 1897 * Need to go through the state machine in case we 1898 * need to reassociate or the like. The state machine 1899 * will pickup the desired channel and avoid scanning. 1900 */ 1901 if (IS_UP_AUTO(vap)) 1902 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 1903 else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) { 1904 /* 1905 * When not up+running and a real channel has 1906 * been specified fix the current channel so 1907 * there is immediate feedback; e.g. via ifconfig. 1908 */ 1909 ic->ic_curchan = vap->iv_des_chan; 1910 } 1911 } 1912 return error; 1913} 1914 1915/* 1916 * Old api for setting the current channel; this is 1917 * deprecated because channel numbers are ambiguous. 1918 */ 1919static __noinline int 1920ieee80211_ioctl_setchannel(struct ieee80211vap *vap, 1921 const struct ieee80211req *ireq) 1922{ 1923 struct ieee80211com *ic = vap->iv_ic; 1924 struct ieee80211_channel *c; 1925 1926 /* XXX 0xffff overflows 16-bit signed */ 1927 if (ireq->i_val == 0 || 1928 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) { 1929 c = IEEE80211_CHAN_ANYC; 1930 } else { 1931 struct ieee80211_channel *c2; 1932 1933 c = findchannel(ic, ireq->i_val, vap->iv_des_mode); 1934 if (c == NULL) { 1935 c = findchannel(ic, ireq->i_val, 1936 IEEE80211_MODE_AUTO); 1937 if (c == NULL) 1938 return EINVAL; 1939 } 1940 /* 1941 * Fine tune channel selection based on desired mode: 1942 * if 11b is requested, find the 11b version of any 1943 * 11g channel returned, 1944 * if static turbo, find the turbo version of any 1945 * 11a channel return, 1946 * if 11na is requested, find the ht version of any 1947 * 11a channel returned, 1948 * if 11ng is requested, find the ht version of any 1949 * 11g channel returned, 1950 * otherwise we should be ok with what we've got. 1951 */ 1952 switch (vap->iv_des_mode) { 1953 case IEEE80211_MODE_11B: 1954 if (IEEE80211_IS_CHAN_ANYG(c)) { 1955 c2 = findchannel(ic, ireq->i_val, 1956 IEEE80211_MODE_11B); 1957 /* NB: should not happen, =>'s 11g w/o 11b */ 1958 if (c2 != NULL) 1959 c = c2; 1960 } 1961 break; 1962 case IEEE80211_MODE_TURBO_A: 1963 if (IEEE80211_IS_CHAN_A(c)) { 1964 c2 = findchannel(ic, ireq->i_val, 1965 IEEE80211_MODE_TURBO_A); 1966 if (c2 != NULL) 1967 c = c2; 1968 } 1969 break; 1970 case IEEE80211_MODE_11NA: 1971 if (IEEE80211_IS_CHAN_A(c)) { 1972 c2 = findchannel(ic, ireq->i_val, 1973 IEEE80211_MODE_11NA); 1974 if (c2 != NULL) 1975 c = c2; 1976 } 1977 break; 1978 case IEEE80211_MODE_11NG: 1979 if (IEEE80211_IS_CHAN_ANYG(c)) { 1980 c2 = findchannel(ic, ireq->i_val, 1981 IEEE80211_MODE_11NG); 1982 if (c2 != NULL) 1983 c = c2; 1984 } 1985 break; 1986 default: /* NB: no static turboG */ 1987 break; 1988 } 1989 } 1990 return setcurchan(vap, c); 1991} 1992 1993/* 1994 * New/current api for setting the current channel; a complete 1995 * channel description is provide so there is no ambiguity in 1996 * identifying the channel. 1997 */ 1998static __noinline int 1999ieee80211_ioctl_setcurchan(struct ieee80211vap *vap, 2000 const struct ieee80211req *ireq) 2001{ 2002 struct ieee80211com *ic = vap->iv_ic; 2003 struct ieee80211_channel chan, *c; 2004 int error; 2005 2006 if (ireq->i_len != sizeof(chan)) 2007 return EINVAL; 2008 error = copyin(ireq->i_data, &chan, sizeof(chan)); 2009 if (error != 0) 2010 return error; 2011 /* XXX 0xffff overflows 16-bit signed */ 2012 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { 2013 c = IEEE80211_CHAN_ANYC; 2014 } else { 2015 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); 2016 if (c == NULL) 2017 return EINVAL; 2018 } 2019 return setcurchan(vap, c); 2020} 2021 2022static __noinline int 2023ieee80211_ioctl_setregdomain(struct ieee80211vap *vap, 2024 const struct ieee80211req *ireq) 2025{ 2026 struct ieee80211_regdomain_req *reg; 2027 int nchans, error; 2028 2029 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) / 2030 sizeof(struct ieee80211_channel)); 2031 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) { 2032 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2033 "%s: bad # chans, i_len %d nchans %d\n", __func__, 2034 ireq->i_len, nchans); 2035 return EINVAL; 2036 } 2037 reg = (struct ieee80211_regdomain_req *) 2038 malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT); 2039 if (reg == NULL) { 2040 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2041 "%s: no memory, nchans %d\n", __func__, nchans); 2042 return ENOMEM; 2043 } 2044 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans)); 2045 if (error == 0) { 2046 /* NB: validate inline channel count against storage size */ 2047 if (reg->chaninfo.ic_nchans != nchans) { 2048 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2049 "%s: chan cnt mismatch, %d != %d\n", __func__, 2050 reg->chaninfo.ic_nchans, nchans); 2051 error = EINVAL; 2052 } else 2053 error = ieee80211_setregdomain(vap, reg); 2054 } 2055 free(reg, M_TEMP); 2056 2057 return (error == 0 ? ENETRESET : error); 2058} 2059 2060static int 2061ieee80211_ioctl_setroam(struct ieee80211vap *vap, 2062 const struct ieee80211req *ireq) 2063{ 2064 if (ireq->i_len != sizeof(vap->iv_roamparms)) 2065 return EINVAL; 2066 /* XXX validate params */ 2067 /* XXX? ENETRESET to push to device? */ 2068 return copyin(ireq->i_data, vap->iv_roamparms, 2069 sizeof(vap->iv_roamparms)); 2070} 2071 2072static int 2073checkrate(const struct ieee80211_rateset *rs, int rate) 2074{ 2075 int i; 2076 2077 if (rate == IEEE80211_FIXED_RATE_NONE) 2078 return 1; 2079 for (i = 0; i < rs->rs_nrates; i++) 2080 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate) 2081 return 1; 2082 return 0; 2083} 2084 2085static int 2086checkmcs(int mcs) 2087{ 2088 if (mcs == IEEE80211_FIXED_RATE_NONE) 2089 return 1; 2090 if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */ 2091 return 0; 2092 return (mcs & 0x7f) <= 15; /* XXX could search ht rate set */ 2093} 2094 2095static __noinline int 2096ieee80211_ioctl_settxparams(struct ieee80211vap *vap, 2097 const struct ieee80211req *ireq) 2098{ 2099 struct ieee80211com *ic = vap->iv_ic; 2100 struct ieee80211_txparams_req parms; /* XXX stack use? */ 2101 struct ieee80211_txparam *src, *dst; 2102 const struct ieee80211_rateset *rs; 2103 int error, mode, changed, is11n, nmodes; 2104 2105 /* NB: accept short requests for backwards compat */ 2106 if (ireq->i_len > sizeof(parms)) 2107 return EINVAL; 2108 error = copyin(ireq->i_data, &parms, ireq->i_len); 2109 if (error != 0) 2110 return error; 2111 nmodes = ireq->i_len / sizeof(struct ieee80211_txparam); 2112 changed = 0; 2113 /* validate parameters and check if anything changed */ 2114 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) { 2115 if (isclr(ic->ic_modecaps, mode)) 2116 continue; 2117 src = &parms.params[mode]; 2118 dst = &vap->iv_txparms[mode]; 2119 rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */ 2120 is11n = (mode == IEEE80211_MODE_11NA || 2121 mode == IEEE80211_MODE_11NG); 2122 if (src->ucastrate != dst->ucastrate) { 2123 if (!checkrate(rs, src->ucastrate) && 2124 (!is11n || !checkmcs(src->ucastrate))) 2125 return EINVAL; 2126 changed++; 2127 } 2128 if (src->mcastrate != dst->mcastrate) { 2129 if (!checkrate(rs, src->mcastrate) && 2130 (!is11n || !checkmcs(src->mcastrate))) 2131 return EINVAL; 2132 changed++; 2133 } 2134 if (src->mgmtrate != dst->mgmtrate) { 2135 if (!checkrate(rs, src->mgmtrate) && 2136 (!is11n || !checkmcs(src->mgmtrate))) 2137 return EINVAL; 2138 changed++; 2139 } 2140 if (src->maxretry != dst->maxretry) /* NB: no bounds */ 2141 changed++; 2142 } 2143 if (changed) { 2144 /* 2145 * Copy new parameters in place and notify the 2146 * driver so it can push state to the device. 2147 */ 2148 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) { 2149 if (isset(ic->ic_modecaps, mode)) 2150 vap->iv_txparms[mode] = parms.params[mode]; 2151 } 2152 /* XXX could be more intelligent, 2153 e.g. don't reset if setting not being used */ 2154 return ENETRESET; 2155 } 2156 return 0; 2157} 2158 2159/* 2160 * Application Information Element support. 2161 */ 2162static int 2163setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq) 2164{ 2165 struct ieee80211_appie *app = *aie; 2166 struct ieee80211_appie *napp; 2167 int error; 2168 2169 if (ireq->i_len == 0) { /* delete any existing ie */ 2170 if (app != NULL) { 2171 *aie = NULL; /* XXX racey */ 2172 free(app, M_80211_NODE_IE); 2173 } 2174 return 0; 2175 } 2176 if (!(2 <= ireq->i_len && ireq->i_len <= IEEE80211_MAX_APPIE)) 2177 return EINVAL; 2178 /* 2179 * Allocate a new appie structure and copy in the user data. 2180 * When done swap in the new structure. Note that we do not 2181 * guard against users holding a ref to the old structure; 2182 * this must be handled outside this code. 2183 * 2184 * XXX bad bad bad 2185 */ 2186 napp = (struct ieee80211_appie *) malloc( 2187 sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT); 2188 if (napp == NULL) 2189 return ENOMEM; 2190 /* XXX holding ic lock */ 2191 error = copyin(ireq->i_data, napp->ie_data, ireq->i_len); 2192 if (error) { 2193 free(napp, M_80211_NODE_IE); 2194 return error; 2195 } 2196 napp->ie_len = ireq->i_len; 2197 *aie = napp; 2198 if (app != NULL) 2199 free(app, M_80211_NODE_IE); 2200 return 0; 2201} 2202 2203static void 2204setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space) 2205{ 2206 /* validate data is present as best we can */ 2207 if (space == 0 || 2+ie[1] > space) 2208 return; 2209 if (ie[0] == IEEE80211_ELEMID_VENDOR) 2210 vap->iv_wpa_ie = ie; 2211 else if (ie[0] == IEEE80211_ELEMID_RSN) 2212 vap->iv_rsn_ie = ie; 2213} 2214 2215static __noinline int 2216ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap, 2217 const struct ieee80211req *ireq, int fc0) 2218{ 2219 int error; 2220 2221 IEEE80211_LOCK_ASSERT(vap->iv_ic); 2222 2223 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) { 2224 case IEEE80211_FC0_SUBTYPE_BEACON: 2225 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2226 vap->iv_opmode != IEEE80211_M_IBSS) { 2227 error = EINVAL; 2228 break; 2229 } 2230 error = setappie(&vap->iv_appie_beacon, ireq); 2231 if (error == 0) 2232 ieee80211_beacon_notify(vap, IEEE80211_BEACON_APPIE); 2233 break; 2234 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 2235 error = setappie(&vap->iv_appie_proberesp, ireq); 2236 break; 2237 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 2238 if (vap->iv_opmode == IEEE80211_M_HOSTAP) 2239 error = setappie(&vap->iv_appie_assocresp, ireq); 2240 else 2241 error = EINVAL; 2242 break; 2243 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 2244 error = setappie(&vap->iv_appie_probereq, ireq); 2245 break; 2246 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 2247 if (vap->iv_opmode == IEEE80211_M_STA) 2248 error = setappie(&vap->iv_appie_assocreq, ireq); 2249 else 2250 error = EINVAL; 2251 break; 2252 case (IEEE80211_APPIE_WPA & IEEE80211_FC0_SUBTYPE_MASK): 2253 error = setappie(&vap->iv_appie_wpa, ireq); 2254 if (error == 0) { 2255 /* 2256 * Must split single blob of data into separate 2257 * WPA and RSN ie's because they go in different 2258 * locations in the mgt frames. 2259 * XXX use IEEE80211_IOC_WPA2 so user code does split 2260 */ 2261 vap->iv_wpa_ie = NULL; 2262 vap->iv_rsn_ie = NULL; 2263 if (vap->iv_appie_wpa != NULL) { 2264 struct ieee80211_appie *appie = 2265 vap->iv_appie_wpa; 2266 uint8_t *data = appie->ie_data; 2267 2268 /* XXX ie length validate is painful, cheat */ 2269 setwparsnie(vap, data, appie->ie_len); 2270 setwparsnie(vap, data + 2 + data[1], 2271 appie->ie_len - (2 + data[1])); 2272 } 2273 if (vap->iv_opmode == IEEE80211_M_HOSTAP || 2274 vap->iv_opmode == IEEE80211_M_IBSS) { 2275 /* 2276 * Must rebuild beacon frame as the update 2277 * mechanism doesn't handle WPA/RSN ie's. 2278 * Could extend it but it doesn't normally 2279 * change; this is just to deal with hostapd 2280 * plumbing the ie after the interface is up. 2281 */ 2282 error = ENETRESET; 2283 } 2284 } 2285 break; 2286 default: 2287 error = EINVAL; 2288 break; 2289 } 2290 return error; 2291} 2292 2293static __noinline int 2294ieee80211_ioctl_setappie(struct ieee80211vap *vap, 2295 const struct ieee80211req *ireq) 2296{ 2297 struct ieee80211com *ic = vap->iv_ic; 2298 int error; 2299 uint8_t fc0; 2300 2301 fc0 = ireq->i_val & 0xff; 2302 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 2303 return EINVAL; 2304 /* NB: could check iv_opmode and reject but hardly worth the effort */ 2305 IEEE80211_LOCK(ic); 2306 error = ieee80211_ioctl_setappie_locked(vap, ireq, fc0); 2307 IEEE80211_UNLOCK(ic); 2308 return error; 2309} 2310 2311static __noinline int 2312ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) 2313{ 2314 struct ieee80211com *ic = vap->iv_ic; 2315 struct ieee80211_chanswitch_req csr; 2316 struct ieee80211_channel *c; 2317 int error; 2318 2319 if (ireq->i_len != sizeof(csr)) 2320 return EINVAL; 2321 error = copyin(ireq->i_data, &csr, sizeof(csr)); 2322 if (error != 0) 2323 return error; 2324 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0) 2325 return EINVAL; 2326 c = ieee80211_find_channel(ic, 2327 csr.csa_chan.ic_freq, csr.csa_chan.ic_flags); 2328 if (c == NULL) 2329 return ENOENT; 2330 IEEE80211_LOCK(ic); 2331 if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) 2332 ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count); 2333 else 2334 error = EBUSY; 2335 IEEE80211_UNLOCK(ic); 2336 return error; 2337} 2338 2339static __noinline int 2340ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) 2341{ 2342#define IEEE80211_IOC_SCAN_FLAGS \ 2343 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \ 2344 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \ 2345 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \ 2346 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \ 2347 IEEE80211_IOC_SCAN_CHECK) 2348 struct ieee80211com *ic = vap->iv_ic; 2349 struct ieee80211_scan_req sr; /* XXX off stack? */ 2350 int error, i; 2351 2352 /* NB: parent must be running */ 2353 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2354 return ENXIO; 2355 2356 if (ireq->i_len != sizeof(sr)) 2357 return EINVAL; 2358 error = copyin(ireq->i_data, &sr, sizeof(sr)); 2359 if (error != 0) 2360 return error; 2361 /* convert duration */ 2362 if (sr.sr_duration == IEEE80211_IOC_SCAN_FOREVER) 2363 sr.sr_duration = IEEE80211_SCAN_FOREVER; 2364 else { 2365 if (sr.sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN || 2366 sr.sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX) 2367 return EINVAL; 2368 sr.sr_duration = msecs_to_ticks(sr.sr_duration); 2369 if (sr.sr_duration < 1) 2370 sr.sr_duration = 1; 2371 } 2372 /* convert min/max channel dwell */ 2373 if (sr.sr_mindwell != 0) { 2374 sr.sr_mindwell = msecs_to_ticks(sr.sr_mindwell); 2375 if (sr.sr_mindwell < 1) 2376 sr.sr_mindwell = 1; 2377 } 2378 if (sr.sr_maxdwell != 0) { 2379 sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell); 2380 if (sr.sr_maxdwell < 1) 2381 sr.sr_maxdwell = 1; 2382 } 2383 /* NB: silently reduce ssid count to what is supported */ 2384 if (sr.sr_nssid > IEEE80211_SCAN_MAX_SSID) 2385 sr.sr_nssid = IEEE80211_SCAN_MAX_SSID; 2386 for (i = 0; i < sr.sr_nssid; i++) 2387 if (sr.sr_ssid[i].len > IEEE80211_NWID_LEN) 2388 return EINVAL; 2389 /* cleanse flags just in case, could reject if invalid flags */ 2390 sr.sr_flags &= IEEE80211_IOC_SCAN_FLAGS; 2391 /* 2392 * Add an implicit NOPICK if the vap is not marked UP. This 2393 * allows applications to scan without joining a bss (or picking 2394 * a channel and setting up a bss) and without forcing manual 2395 * roaming mode--you just need to mark the parent device UP. 2396 */ 2397 if ((vap->iv_ifp->if_flags & IFF_UP) == 0) 2398 sr.sr_flags |= IEEE80211_IOC_SCAN_NOPICK; 2399 2400 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2401 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n", 2402 __func__, sr.sr_flags, 2403 (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "", 2404 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, sr.sr_nssid); 2405 /* 2406 * If we are in INIT state then the driver has never had a chance 2407 * to setup hardware state to do a scan; we must use the state 2408 * machine to get us up to the SCAN state but once we reach SCAN 2409 * state we then want to use the supplied params. Stash the 2410 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the 2411 * state machines will recognize this and use the stashed params 2412 * to issue the scan request. 2413 * 2414 * Otherwise just invoke the scan machinery directly. 2415 */ 2416 IEEE80211_LOCK(ic); 2417 if (vap->iv_state == IEEE80211_S_INIT) { 2418 /* NB: clobbers previous settings */ 2419 vap->iv_scanreq_flags = sr.sr_flags; 2420 vap->iv_scanreq_duration = sr.sr_duration; 2421 vap->iv_scanreq_nssid = sr.sr_nssid; 2422 for (i = 0; i < sr.sr_nssid; i++) { 2423 vap->iv_scanreq_ssid[i].len = sr.sr_ssid[i].len; 2424 memcpy(vap->iv_scanreq_ssid[i].ssid, sr.sr_ssid[i].ssid, 2425 sr.sr_ssid[i].len); 2426 } 2427 vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ; 2428 IEEE80211_UNLOCK(ic); 2429 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 2430 } else { 2431 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ; 2432 IEEE80211_UNLOCK(ic); 2433 /* XXX neeed error return codes */ 2434 if (sr.sr_flags & IEEE80211_IOC_SCAN_CHECK) { 2435 (void) ieee80211_check_scan(vap, sr.sr_flags, 2436 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, 2437 sr.sr_nssid, 2438 /* NB: cheat, we assume structures are compatible */ 2439 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); 2440 } else { 2441 (void) ieee80211_start_scan(vap, sr.sr_flags, 2442 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, 2443 sr.sr_nssid, 2444 /* NB: cheat, we assume structures are compatible */ 2445 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); 2446 } 2447 } 2448 return error; 2449#undef IEEE80211_IOC_SCAN_FLAGS 2450} 2451 2452static __noinline int 2453ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) 2454{ 2455 struct ieee80211_node *ni; 2456 struct ieee80211req_sta_vlan vlan; 2457 int error; 2458 2459 if (ireq->i_len != sizeof(vlan)) 2460 return EINVAL; 2461 error = copyin(ireq->i_data, &vlan, sizeof(vlan)); 2462 if (error != 0) 2463 return error; 2464 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) { 2465 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 2466 vlan.sv_macaddr); 2467 if (ni == NULL) 2468 return ENOENT; 2469 } else 2470 ni = ieee80211_ref_node(vap->iv_bss); 2471 ni->ni_vlan = vlan.sv_vlan; 2472 ieee80211_free_node(ni); 2473 return error; 2474} 2475 2476static int 2477isvap11g(const struct ieee80211vap *vap) 2478{ 2479 const struct ieee80211_node *bss = vap->iv_bss; 2480 return bss->ni_chan != IEEE80211_CHAN_ANYC && 2481 IEEE80211_IS_CHAN_ANYG(bss->ni_chan); 2482} 2483 2484static int 2485isvapht(const struct ieee80211vap *vap) 2486{ 2487 const struct ieee80211_node *bss = vap->iv_bss; 2488 return bss->ni_chan != IEEE80211_CHAN_ANYC && 2489 IEEE80211_IS_CHAN_HT(bss->ni_chan); 2490} 2491 2492/* 2493 * Dummy ioctl set handler so the linker set is defined. 2494 */ 2495static int 2496dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq) 2497{ 2498 return ENOSYS; 2499} 2500IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set); 2501 2502static int 2503ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq) 2504{ 2505 ieee80211_ioctl_setfunc * const *set; 2506 int error; 2507 2508 SET_FOREACH(set, ieee80211_ioctl_setset) { 2509 error = (*set)(vap, ireq); 2510 if (error != ENOSYS) 2511 return error; 2512 } 2513 return EINVAL; 2514} 2515 2516static __noinline int 2517ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq) 2518{ 2519 struct ieee80211com *ic = vap->iv_ic; 2520 int error; 2521 const struct ieee80211_authenticator *auth; 2522 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 2523 char tmpssid[IEEE80211_NWID_LEN]; 2524 uint8_t tmpbssid[IEEE80211_ADDR_LEN]; 2525 struct ieee80211_key *k; 2526 u_int kid; 2527 uint32_t flags; 2528 2529 error = 0; 2530 switch (ireq->i_type) { 2531 case IEEE80211_IOC_SSID: 2532 if (ireq->i_val != 0 || 2533 ireq->i_len > IEEE80211_NWID_LEN) 2534 return EINVAL; 2535 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 2536 if (error) 2537 break; 2538 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); 2539 vap->iv_des_ssid[0].len = ireq->i_len; 2540 memcpy(vap->iv_des_ssid[0].ssid, tmpssid, ireq->i_len); 2541 vap->iv_des_nssid = (ireq->i_len > 0); 2542 error = ENETRESET; 2543 break; 2544 case IEEE80211_IOC_WEP: 2545 switch (ireq->i_val) { 2546 case IEEE80211_WEP_OFF: 2547 vap->iv_flags &= ~IEEE80211_F_PRIVACY; 2548 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2549 break; 2550 case IEEE80211_WEP_ON: 2551 vap->iv_flags |= IEEE80211_F_PRIVACY; 2552 vap->iv_flags |= IEEE80211_F_DROPUNENC; 2553 break; 2554 case IEEE80211_WEP_MIXED: 2555 vap->iv_flags |= IEEE80211_F_PRIVACY; 2556 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2557 break; 2558 } 2559 error = ENETRESET; 2560 break; 2561 case IEEE80211_IOC_WEPKEY: 2562 kid = (u_int) ireq->i_val; 2563 if (kid >= IEEE80211_WEP_NKID) 2564 return EINVAL; 2565 k = &vap->iv_nw_keys[kid]; 2566 if (ireq->i_len == 0) { 2567 /* zero-len =>'s delete any existing key */ 2568 (void) ieee80211_crypto_delkey(vap, k); 2569 break; 2570 } 2571 if (ireq->i_len > sizeof(tmpkey)) 2572 return EINVAL; 2573 memset(tmpkey, 0, sizeof(tmpkey)); 2574 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 2575 if (error) 2576 break; 2577 ieee80211_key_update_begin(vap); 2578 k->wk_keyix = kid; /* NB: force fixed key id */ 2579 if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP, 2580 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2581 k->wk_keylen = ireq->i_len; 2582 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 2583 IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr); 2584 if (!ieee80211_crypto_setkey(vap, k)) 2585 error = EINVAL; 2586 } else 2587 error = EINVAL; 2588 ieee80211_key_update_end(vap); 2589 break; 2590 case IEEE80211_IOC_WEPTXKEY: 2591 kid = (u_int) ireq->i_val; 2592 if (kid >= IEEE80211_WEP_NKID && 2593 (uint16_t) kid != IEEE80211_KEYIX_NONE) 2594 return EINVAL; 2595 vap->iv_def_txkey = kid; 2596 break; 2597 case IEEE80211_IOC_AUTHMODE: 2598 switch (ireq->i_val) { 2599 case IEEE80211_AUTH_WPA: 2600 case IEEE80211_AUTH_8021X: /* 802.1x */ 2601 case IEEE80211_AUTH_OPEN: /* open */ 2602 case IEEE80211_AUTH_SHARED: /* shared-key */ 2603 case IEEE80211_AUTH_AUTO: /* auto */ 2604 auth = ieee80211_authenticator_get(ireq->i_val); 2605 if (auth == NULL) 2606 return EINVAL; 2607 break; 2608 default: 2609 return EINVAL; 2610 } 2611 switch (ireq->i_val) { 2612 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 2613 vap->iv_flags |= IEEE80211_F_PRIVACY; 2614 ireq->i_val = IEEE80211_AUTH_8021X; 2615 break; 2616 case IEEE80211_AUTH_OPEN: /* open */ 2617 vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 2618 break; 2619 case IEEE80211_AUTH_SHARED: /* shared-key */ 2620 case IEEE80211_AUTH_8021X: /* 802.1x */ 2621 vap->iv_flags &= ~IEEE80211_F_WPA; 2622 /* both require a key so mark the PRIVACY capability */ 2623 vap->iv_flags |= IEEE80211_F_PRIVACY; 2624 break; 2625 case IEEE80211_AUTH_AUTO: /* auto */ 2626 vap->iv_flags &= ~IEEE80211_F_WPA; 2627 /* XXX PRIVACY handling? */ 2628 /* XXX what's the right way to do this? */ 2629 break; 2630 } 2631 /* NB: authenticator attach/detach happens on state change */ 2632 vap->iv_bss->ni_authmode = ireq->i_val; 2633 /* XXX mixed/mode/usage? */ 2634 vap->iv_auth = auth; 2635 error = ENETRESET; 2636 break; 2637 case IEEE80211_IOC_CHANNEL: 2638 error = ieee80211_ioctl_setchannel(vap, ireq); 2639 break; 2640 case IEEE80211_IOC_POWERSAVE: 2641 switch (ireq->i_val) { 2642 case IEEE80211_POWERSAVE_OFF: 2643 if (vap->iv_flags & IEEE80211_F_PMGTON) { 2644 ieee80211_syncflag(vap, -IEEE80211_F_PMGTON); 2645 error = ERESTART; 2646 } 2647 break; 2648 case IEEE80211_POWERSAVE_ON: 2649 if ((vap->iv_caps & IEEE80211_C_PMGT) == 0) 2650 error = EOPNOTSUPP; 2651 else if ((vap->iv_flags & IEEE80211_F_PMGTON) == 0) { 2652 ieee80211_syncflag(vap, IEEE80211_F_PMGTON); 2653 error = ERESTART; 2654 } 2655 break; 2656 default: 2657 error = EINVAL; 2658 break; 2659 } 2660 break; 2661 case IEEE80211_IOC_POWERSAVESLEEP: 2662 if (ireq->i_val < 0) 2663 return EINVAL; 2664 ic->ic_lintval = ireq->i_val; 2665 error = ERESTART; 2666 break; 2667 case IEEE80211_IOC_RTSTHRESHOLD: 2668 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2669 ireq->i_val <= IEEE80211_RTS_MAX)) 2670 return EINVAL; 2671 vap->iv_rtsthreshold = ireq->i_val; 2672 error = ERESTART; 2673 break; 2674 case IEEE80211_IOC_PROTMODE: 2675 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2676 return EINVAL; 2677 ic->ic_protmode = ireq->i_val; 2678 /* NB: if not operating in 11g this can wait */ 2679 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2680 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2681 error = ERESTART; 2682 break; 2683 case IEEE80211_IOC_TXPOWER: 2684 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2685 return EOPNOTSUPP; 2686 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val && 2687 ireq->i_val <= IEEE80211_TXPOWER_MAX)) 2688 return EINVAL; 2689 ic->ic_txpowlimit = ireq->i_val; 2690 error = ERESTART; 2691 break; 2692 case IEEE80211_IOC_ROAMING: 2693 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2694 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2695 return EINVAL; 2696 vap->iv_roaming = ireq->i_val; 2697 /* XXXX reset? */ 2698 break; 2699 case IEEE80211_IOC_PRIVACY: 2700 if (ireq->i_val) { 2701 /* XXX check for key state? */ 2702 vap->iv_flags |= IEEE80211_F_PRIVACY; 2703 } else 2704 vap->iv_flags &= ~IEEE80211_F_PRIVACY; 2705 /* XXX ERESTART? */ 2706 break; 2707 case IEEE80211_IOC_DROPUNENCRYPTED: 2708 if (ireq->i_val) 2709 vap->iv_flags |= IEEE80211_F_DROPUNENC; 2710 else 2711 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2712 /* XXX ERESTART? */ 2713 break; 2714 case IEEE80211_IOC_WPAKEY: 2715 error = ieee80211_ioctl_setkey(vap, ireq); 2716 break; 2717 case IEEE80211_IOC_DELKEY: 2718 error = ieee80211_ioctl_delkey(vap, ireq); 2719 break; 2720 case IEEE80211_IOC_MLME: 2721 error = ieee80211_ioctl_setmlme(vap, ireq); 2722 break; 2723 case IEEE80211_IOC_COUNTERMEASURES: 2724 if (ireq->i_val) { 2725 if ((vap->iv_flags & IEEE80211_F_WPA) == 0) 2726 return EOPNOTSUPP; 2727 vap->iv_flags |= IEEE80211_F_COUNTERM; 2728 } else 2729 vap->iv_flags &= ~IEEE80211_F_COUNTERM; 2730 /* XXX ERESTART? */ 2731 break; 2732 case IEEE80211_IOC_WPA: 2733 if (ireq->i_val > 3) 2734 return EINVAL; 2735 /* XXX verify ciphers available */ 2736 flags = vap->iv_flags & ~IEEE80211_F_WPA; 2737 switch (ireq->i_val) { 2738 case 1: 2739 if (!(vap->iv_caps & IEEE80211_C_WPA1)) 2740 return EOPNOTSUPP; 2741 flags |= IEEE80211_F_WPA1; 2742 break; 2743 case 2: 2744 if (!(vap->iv_caps & IEEE80211_C_WPA2)) 2745 return EOPNOTSUPP; 2746 flags |= IEEE80211_F_WPA2; 2747 break; 2748 case 3: 2749 if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA) 2750 return EOPNOTSUPP; 2751 flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2752 break; 2753 default: /* Can't set any -> error */ 2754 return EOPNOTSUPP; 2755 } 2756 vap->iv_flags = flags; 2757 error = ERESTART; /* NB: can change beacon frame */ 2758 break; 2759 case IEEE80211_IOC_WME: 2760 if (ireq->i_val) { 2761 if ((vap->iv_caps & IEEE80211_C_WME) == 0) 2762 return EOPNOTSUPP; 2763 ieee80211_syncflag(vap, IEEE80211_F_WME); 2764 } else 2765 ieee80211_syncflag(vap, -IEEE80211_F_WME); 2766 error = ERESTART; /* NB: can change beacon frame */ 2767 break; 2768 case IEEE80211_IOC_HIDESSID: 2769 if (ireq->i_val) 2770 vap->iv_flags |= IEEE80211_F_HIDESSID; 2771 else 2772 vap->iv_flags &= ~IEEE80211_F_HIDESSID; 2773 error = ERESTART; /* XXX ENETRESET? */ 2774 break; 2775 case IEEE80211_IOC_APBRIDGE: 2776 if (ireq->i_val == 0) 2777 vap->iv_flags |= IEEE80211_F_NOBRIDGE; 2778 else 2779 vap->iv_flags &= ~IEEE80211_F_NOBRIDGE; 2780 break; 2781 case IEEE80211_IOC_BSSID: 2782 if (ireq->i_len != sizeof(tmpbssid)) 2783 return EINVAL; 2784 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2785 if (error) 2786 break; 2787 IEEE80211_ADDR_COPY(vap->iv_des_bssid, tmpbssid); 2788 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid)) 2789 vap->iv_flags &= ~IEEE80211_F_DESBSSID; 2790 else 2791 vap->iv_flags |= IEEE80211_F_DESBSSID; 2792 error = ENETRESET; 2793 break; 2794 case IEEE80211_IOC_CHANLIST: 2795 error = ieee80211_ioctl_setchanlist(vap, ireq); 2796 break; 2797#define OLD_IEEE80211_IOC_SCAN_REQ 23 2798#ifdef OLD_IEEE80211_IOC_SCAN_REQ 2799 case OLD_IEEE80211_IOC_SCAN_REQ: 2800 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2801 "%s: active scan request\n", __func__); 2802 /* 2803 * If we are in INIT state then the driver has never 2804 * had a chance to setup hardware state to do a scan; 2805 * use the state machine to get us up the SCAN state. 2806 * Otherwise just invoke the scan machinery to start 2807 * a one-time scan. 2808 */ 2809 if (vap->iv_state == IEEE80211_S_INIT) 2810 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 2811 else 2812 (void) ieee80211_start_scan(vap, 2813 IEEE80211_SCAN_ACTIVE | 2814 IEEE80211_SCAN_NOPICK | 2815 IEEE80211_SCAN_ONCE, 2816 IEEE80211_SCAN_FOREVER, 0, 0, 2817 /* XXX use ioctl params */ 2818 vap->iv_des_nssid, vap->iv_des_ssid); 2819 break; 2820#endif /* OLD_IEEE80211_IOC_SCAN_REQ */ 2821 case IEEE80211_IOC_SCAN_REQ: 2822 error = ieee80211_ioctl_scanreq(vap, ireq); 2823 break; 2824 case IEEE80211_IOC_SCAN_CANCEL: 2825 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2826 "%s: cancel scan\n", __func__); 2827 ieee80211_cancel_scan(vap); 2828 break; 2829 case IEEE80211_IOC_HTCONF: 2830 if (ireq->i_val & 1) 2831 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_HT); 2832 else 2833 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_HT); 2834 if (ireq->i_val & 2) 2835 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_USEHT40); 2836 else 2837 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_USEHT40); 2838 error = ENETRESET; 2839 break; 2840 case IEEE80211_IOC_ADDMAC: 2841 case IEEE80211_IOC_DELMAC: 2842 error = ieee80211_ioctl_macmac(vap, ireq); 2843 break; 2844 case IEEE80211_IOC_MACCMD: 2845 error = ieee80211_ioctl_setmaccmd(vap, ireq); 2846 break; 2847 case IEEE80211_IOC_STA_STATS: 2848 error = ieee80211_ioctl_setstastats(vap, ireq); 2849 break; 2850 case IEEE80211_IOC_STA_TXPOW: 2851 error = ieee80211_ioctl_setstatxpow(vap, ireq); 2852 break; 2853 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2854 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2855 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2856 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2857 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2858 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2859 error = ieee80211_ioctl_setwmeparam(vap, ireq); 2860 break; 2861 case IEEE80211_IOC_DTIM_PERIOD: 2862 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2863 vap->iv_opmode != IEEE80211_M_IBSS) 2864 return EINVAL; 2865 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2866 ireq->i_val <= IEEE80211_DTIM_MAX) { 2867 vap->iv_dtim_period = ireq->i_val; 2868 error = ENETRESET; /* requires restart */ 2869 } else 2870 error = EINVAL; 2871 break; 2872 case IEEE80211_IOC_BEACON_INTERVAL: 2873 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2874 vap->iv_opmode != IEEE80211_M_IBSS) 2875 return EINVAL; 2876 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2877 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2878 ic->ic_bintval = ireq->i_val; 2879 error = ENETRESET; /* requires restart */ 2880 } else 2881 error = EINVAL; 2882 break; 2883 case IEEE80211_IOC_PUREG: 2884 if (ireq->i_val) 2885 vap->iv_flags |= IEEE80211_F_PUREG; 2886 else 2887 vap->iv_flags &= ~IEEE80211_F_PUREG; 2888 /* NB: reset only if we're operating on an 11g channel */ 2889 if (isvap11g(vap)) 2890 error = ENETRESET; 2891 break;
| 962 case IEEE80211_IOC_BGSCAN: 963 ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0; 964 break; 965 case IEEE80211_IOC_BGSCAN_IDLE: 966 ireq->i_val = vap->iv_bgscanidle*hz/1000; /* ms */ 967 break; 968 case IEEE80211_IOC_BGSCAN_INTERVAL: 969 ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */ 970 break; 971 case IEEE80211_IOC_SCANVALID: 972 ireq->i_val = vap->iv_scanvalid/hz; /* seconds */ 973 break; 974 case IEEE80211_IOC_FRAGTHRESHOLD: 975 ireq->i_val = vap->iv_fragthreshold; 976 break; 977 case IEEE80211_IOC_MACCMD: 978 error = ieee80211_ioctl_getmaccmd(vap, ireq); 979 break; 980 case IEEE80211_IOC_BURST: 981 ireq->i_val = (vap->iv_flags & IEEE80211_F_BURST) != 0; 982 break; 983 case IEEE80211_IOC_BMISSTHRESHOLD: 984 ireq->i_val = vap->iv_bmissthreshold; 985 break; 986 case IEEE80211_IOC_CURCHAN: 987 error = ieee80211_ioctl_getcurchan(vap, ireq); 988 break; 989 case IEEE80211_IOC_SHORTGI: 990 ireq->i_val = 0; 991 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI20) 992 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20; 993 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI40) 994 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40; 995 break; 996 case IEEE80211_IOC_AMPDU: 997 ireq->i_val = 0; 998 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_TX) 999 ireq->i_val |= 1; 1000 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_RX) 1001 ireq->i_val |= 2; 1002 break; 1003 case IEEE80211_IOC_AMPDU_LIMIT: 1004 if (vap->iv_opmode == IEEE80211_M_HOSTAP) 1005 ireq->i_val = vap->iv_ampdu_rxmax; 1006 else if (vap->iv_state == IEEE80211_S_RUN) 1007 ireq->i_val = MS(vap->iv_bss->ni_htparam, 1008 IEEE80211_HTCAP_MAXRXAMPDU); 1009 else 1010 ireq->i_val = vap->iv_ampdu_limit; 1011 break; 1012 case IEEE80211_IOC_AMPDU_DENSITY: 1013 if (vap->iv_opmode == IEEE80211_M_STA && 1014 vap->iv_state == IEEE80211_S_RUN) 1015 ireq->i_val = MS(vap->iv_bss->ni_htparam, 1016 IEEE80211_HTCAP_MPDUDENSITY); 1017 else 1018 ireq->i_val = vap->iv_ampdu_density; 1019 break; 1020 case IEEE80211_IOC_AMSDU: 1021 ireq->i_val = 0; 1022 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_TX) 1023 ireq->i_val |= 1; 1024 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_RX) 1025 ireq->i_val |= 2; 1026 break; 1027 case IEEE80211_IOC_AMSDU_LIMIT: 1028 ireq->i_val = vap->iv_amsdu_limit; /* XXX truncation? */ 1029 break; 1030 case IEEE80211_IOC_PUREN: 1031 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_PUREN) != 0; 1032 break; 1033 case IEEE80211_IOC_DOTH: 1034 ireq->i_val = (vap->iv_flags & IEEE80211_F_DOTH) != 0; 1035 break; 1036 case IEEE80211_IOC_REGDOMAIN: 1037 error = ieee80211_ioctl_getregdomain(vap, ireq); 1038 break; 1039 case IEEE80211_IOC_ROAM: 1040 error = ieee80211_ioctl_getroam(vap, ireq); 1041 break; 1042 case IEEE80211_IOC_TXPARAMS: 1043 error = ieee80211_ioctl_gettxparams(vap, ireq); 1044 break; 1045 case IEEE80211_IOC_HTCOMPAT: 1046 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0; 1047 break; 1048 case IEEE80211_IOC_DWDS: 1049 ireq->i_val = (vap->iv_flags & IEEE80211_F_DWDS) != 0; 1050 break; 1051 case IEEE80211_IOC_INACTIVITY: 1052 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_INACT) != 0; 1053 break; 1054 case IEEE80211_IOC_APPIE: 1055 error = ieee80211_ioctl_getappie(vap, ireq); 1056 break; 1057 case IEEE80211_IOC_WPS: 1058 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_WPS) != 0; 1059 break; 1060 case IEEE80211_IOC_TSN: 1061 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_TSN) != 0; 1062 break; 1063 case IEEE80211_IOC_DFS: 1064 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DFS) != 0; 1065 break; 1066 case IEEE80211_IOC_DOTD: 1067 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DOTD) != 0; 1068 break; 1069 case IEEE80211_IOC_DEVCAPS: 1070 error = ieee80211_ioctl_getdevcaps(ic, ireq); 1071 break; 1072 case IEEE80211_IOC_HTPROTMODE: 1073 ireq->i_val = ic->ic_htprotmode; 1074 break; 1075 case IEEE80211_IOC_HTCONF: 1076 if (vap->iv_flags_ext & IEEE80211_FEXT_HT) { 1077 ireq->i_val = 1; 1078 if (vap->iv_flags_ext & IEEE80211_FEXT_USEHT40) 1079 ireq->i_val |= 2; 1080 } else 1081 ireq->i_val = 0; 1082 break; 1083 case IEEE80211_IOC_STA_VLAN: 1084 error = ieee80211_ioctl_getstavlan(vap, ireq); 1085 break; 1086 case IEEE80211_IOC_SMPS: 1087 if (vap->iv_opmode == IEEE80211_M_STA && 1088 vap->iv_state == IEEE80211_S_RUN) { 1089 if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS) 1090 ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC; 1091 else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS) 1092 ireq->i_val = IEEE80211_HTCAP_SMPS_ENA; 1093 else 1094 ireq->i_val = IEEE80211_HTCAP_SMPS_OFF; 1095 } else 1096 ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS; 1097 break; 1098 case IEEE80211_IOC_RIFS: 1099 if (vap->iv_opmode == IEEE80211_M_STA && 1100 vap->iv_state == IEEE80211_S_RUN) 1101 ireq->i_val = 1102 (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0; 1103 else 1104 ireq->i_val = 1105 (vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0; 1106 break; 1107 default: 1108 error = ieee80211_ioctl_getdefault(vap, ireq); 1109 break; 1110 } 1111 return error; 1112#undef MS 1113} 1114 1115static __noinline int 1116ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 1117{ 1118 struct ieee80211req_key ik; 1119 struct ieee80211_node *ni; 1120 struct ieee80211_key *wk; 1121 uint16_t kid; 1122 int error, i; 1123 1124 if (ireq->i_len != sizeof(ik)) 1125 return EINVAL; 1126 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1127 if (error) 1128 return error; 1129 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1130 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1131 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1132 return E2BIG; 1133 kid = ik.ik_keyix; 1134 if (kid == IEEE80211_KEYIX_NONE) { 1135 /* XXX unicast keys currently must be tx/rx */ 1136 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1137 return EINVAL; 1138 if (vap->iv_opmode == IEEE80211_M_STA) { 1139 ni = ieee80211_ref_node(vap->iv_bss); 1140 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) { 1141 ieee80211_free_node(ni); 1142 return EADDRNOTAVAIL; 1143 } 1144 } else { 1145 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 1146 ik.ik_macaddr); 1147 if (ni == NULL) 1148 return ENOENT; 1149 } 1150 wk = &ni->ni_ucastkey; 1151 } else { 1152 if (kid >= IEEE80211_WEP_NKID) 1153 return EINVAL; 1154 wk = &vap->iv_nw_keys[kid]; 1155 /* 1156 * Global slots start off w/o any assigned key index. 1157 * Force one here for consistency with IEEE80211_IOC_WEPKEY. 1158 */ 1159 if (wk->wk_keyix == IEEE80211_KEYIX_NONE) 1160 wk->wk_keyix = kid; 1161 ni = NULL; 1162 } 1163 error = 0; 1164 ieee80211_key_update_begin(vap); 1165 if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) { 1166 wk->wk_keylen = ik.ik_keylen; 1167 /* NB: MIC presence is implied by cipher type */ 1168 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1169 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1170 for (i = 0; i < IEEE80211_TID_SIZE; i++) 1171 wk->wk_keyrsc[i] = ik.ik_keyrsc; 1172 wk->wk_keytsc = 0; /* new key, reset */ 1173 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1174 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1175 IEEE80211_ADDR_COPY(wk->wk_macaddr, 1176 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr); 1177 if (!ieee80211_crypto_setkey(vap, wk)) 1178 error = EIO; 1179 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1180 vap->iv_def_txkey = kid; 1181 } else 1182 error = ENXIO; 1183 ieee80211_key_update_end(vap); 1184 if (ni != NULL) 1185 ieee80211_free_node(ni); 1186 return error; 1187} 1188 1189static __noinline int 1190ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 1191{ 1192 struct ieee80211req_del_key dk; 1193 int kid, error; 1194 1195 if (ireq->i_len != sizeof(dk)) 1196 return EINVAL; 1197 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1198 if (error) 1199 return error; 1200 kid = dk.idk_keyix; 1201 /* XXX uint8_t -> uint16_t */ 1202 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) { 1203 struct ieee80211_node *ni; 1204 1205 if (vap->iv_opmode == IEEE80211_M_STA) { 1206 ni = ieee80211_ref_node(vap->iv_bss); 1207 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1208 ieee80211_free_node(ni); 1209 return EADDRNOTAVAIL; 1210 } 1211 } else { 1212 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 1213 dk.idk_macaddr); 1214 if (ni == NULL) 1215 return ENOENT; 1216 } 1217 /* XXX error return */ 1218 ieee80211_node_delucastkey(ni); 1219 ieee80211_free_node(ni); 1220 } else { 1221 if (kid >= IEEE80211_WEP_NKID) 1222 return EINVAL; 1223 /* XXX error return */ 1224 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]); 1225 } 1226 return 0; 1227} 1228 1229struct mlmeop { 1230 struct ieee80211vap *vap; 1231 int op; 1232 int reason; 1233}; 1234 1235static void 1236mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], 1237 int op, int reason) 1238{ 1239#ifdef IEEE80211_DEBUG 1240 static const struct { 1241 int mask; 1242 const char *opstr; 1243 } ops[] = { 1244 { 0, "op#0" }, 1245 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1246 IEEE80211_MSG_ASSOC, "assoc" }, 1247 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1248 IEEE80211_MSG_ASSOC, "disassoc" }, 1249 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1250 IEEE80211_MSG_AUTH, "deauth" }, 1251 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1252 IEEE80211_MSG_AUTH, "authorize" }, 1253 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE | 1254 IEEE80211_MSG_AUTH, "unauthorize" }, 1255 }; 1256 1257 if (op == IEEE80211_MLME_AUTH) { 1258 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL | 1259 IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac, 1260 "station authenticate %s via MLME (reason %d)", 1261 reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT", 1262 reason); 1263 } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) { 1264 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac, 1265 "unknown MLME request %d (reason %d)", op, reason); 1266 } else if (reason == IEEE80211_STATUS_SUCCESS) { 1267 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac, 1268 "station %s via MLME", ops[op].opstr); 1269 } else { 1270 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac, 1271 "station %s via MLME (reason %d)", ops[op].opstr, reason); 1272 } 1273#endif /* IEEE80211_DEBUG */ 1274} 1275 1276static void 1277domlme(void *arg, struct ieee80211_node *ni) 1278{ 1279 struct mlmeop *mop = arg; 1280 struct ieee80211vap *vap = ni->ni_vap; 1281 1282 if (vap != mop->vap) 1283 return; 1284 /* 1285 * NB: if ni_associd is zero then the node is already cleaned 1286 * up and we don't need to do this (we're safely holding a 1287 * reference but should otherwise not modify it's state). 1288 */ 1289 if (ni->ni_associd == 0) 1290 return; 1291 mlmedebug(vap, ni->ni_macaddr, mop->op, mop->reason); 1292 if (mop->op == IEEE80211_MLME_DEAUTH) { 1293 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, 1294 mop->reason); 1295 } else { 1296 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, 1297 mop->reason); 1298 } 1299 ieee80211_node_leave(ni); 1300} 1301 1302static int 1303setmlme_dropsta(struct ieee80211vap *vap, 1304 const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) 1305{ 1306 struct ieee80211com *ic = vap->iv_ic; 1307 struct ieee80211_node_table *nt = &ic->ic_sta; 1308 struct ieee80211_node *ni; 1309 int error = 0; 1310 1311 /* NB: the broadcast address means do 'em all */ 1312 if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) { 1313 IEEE80211_NODE_LOCK(nt); 1314 ni = ieee80211_find_node_locked(nt, mac); 1315 if (ni != NULL) { 1316 domlme(mlmeop, ni); 1317 ieee80211_free_node(ni); 1318 } else 1319 error = ENOENT; 1320 IEEE80211_NODE_UNLOCK(nt); 1321 } else { 1322 ieee80211_iterate_nodes(nt, domlme, mlmeop); 1323 } 1324 return error; 1325} 1326 1327static __noinline int 1328setmlme_common(struct ieee80211vap *vap, int op, 1329 const uint8_t mac[IEEE80211_ADDR_LEN], int reason) 1330{ 1331 struct ieee80211com *ic = vap->iv_ic; 1332 struct ieee80211_node_table *nt = &ic->ic_sta; 1333 struct ieee80211_node *ni; 1334 struct mlmeop mlmeop; 1335 int error; 1336 1337 error = 0; 1338 switch (op) { 1339 case IEEE80211_MLME_DISASSOC: 1340 case IEEE80211_MLME_DEAUTH: 1341 switch (vap->iv_opmode) { 1342 case IEEE80211_M_STA: 1343 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason); 1344 /* XXX not quite right */ 1345 ieee80211_new_state(vap, IEEE80211_S_INIT, reason); 1346 break; 1347 case IEEE80211_M_HOSTAP: 1348 mlmeop.vap = vap; 1349 mlmeop.op = op; 1350 mlmeop.reason = reason; 1351 error = setmlme_dropsta(vap, mac, &mlmeop); 1352 break; 1353 case IEEE80211_M_WDS: 1354 /* XXX user app should send raw frame? */ 1355 if (op != IEEE80211_MLME_DEAUTH) { 1356 error = EINVAL; 1357 break; 1358 } 1359#if 0 1360 /* XXX accept any address, simplifies user code */ 1361 if (!IEEE80211_ADDR_EQ(mac, vap->iv_bss->ni_macaddr)) { 1362 error = EINVAL; 1363 break; 1364 } 1365#endif 1366 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason); 1367 ni = ieee80211_ref_node(vap->iv_bss); 1368 IEEE80211_SEND_MGMT(ni, 1369 IEEE80211_FC0_SUBTYPE_DEAUTH, reason); 1370 ieee80211_free_node(ni); 1371 break; 1372 default: 1373 error = EINVAL; 1374 break; 1375 } 1376 break; 1377 case IEEE80211_MLME_AUTHORIZE: 1378 case IEEE80211_MLME_UNAUTHORIZE: 1379 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 1380 vap->iv_opmode != IEEE80211_M_WDS) { 1381 error = EINVAL; 1382 break; 1383 } 1384 IEEE80211_NODE_LOCK(nt); 1385 ni = ieee80211_find_vap_node_locked(nt, vap, mac); 1386 if (ni != NULL) { 1387 mlmedebug(vap, mac, op, reason); 1388 if (op == IEEE80211_MLME_AUTHORIZE) 1389 ieee80211_node_authorize(ni); 1390 else 1391 ieee80211_node_unauthorize(ni); 1392 ieee80211_free_node(ni); 1393 } else 1394 error = ENOENT; 1395 IEEE80211_NODE_UNLOCK(nt); 1396 break; 1397 case IEEE80211_MLME_AUTH: 1398 if (vap->iv_opmode != IEEE80211_M_HOSTAP) { 1399 error = EINVAL; 1400 break; 1401 } 1402 IEEE80211_NODE_LOCK(nt); 1403 ni = ieee80211_find_vap_node_locked(nt, vap, mac); 1404 if (ni != NULL) { 1405 mlmedebug(vap, mac, op, reason); 1406 if (reason == IEEE80211_STATUS_SUCCESS) { 1407 IEEE80211_SEND_MGMT(ni, 1408 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1409 /* 1410 * For shared key auth, just continue the 1411 * exchange. Otherwise when 802.1x is not in 1412 * use mark the port authorized at this point 1413 * so traffic can flow. 1414 */ 1415 if (ni->ni_authmode != IEEE80211_AUTH_8021X && 1416 ni->ni_challenge == NULL) 1417 ieee80211_node_authorize(ni); 1418 } else { 1419 vap->iv_stats.is_rx_acl++; 1420 ieee80211_send_error(ni, ni->ni_macaddr, 1421 IEEE80211_FC0_SUBTYPE_AUTH, 2|(reason<<16)); 1422 ieee80211_node_leave(ni); 1423 } 1424 ieee80211_free_node(ni); 1425 } else 1426 error = ENOENT; 1427 IEEE80211_NODE_UNLOCK(nt); 1428 break; 1429 default: 1430 error = EINVAL; 1431 break; 1432 } 1433 return error; 1434} 1435 1436struct scanlookup { 1437 const uint8_t *mac; 1438 int esslen; 1439 const uint8_t *essid; 1440 const struct ieee80211_scan_entry *se; 1441}; 1442 1443/* 1444 * Match mac address and any ssid. 1445 */ 1446static void 1447mlmelookup(void *arg, const struct ieee80211_scan_entry *se) 1448{ 1449 struct scanlookup *look = arg; 1450 1451 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) 1452 return; 1453 if (look->esslen != 0) { 1454 if (se->se_ssid[1] != look->esslen) 1455 return; 1456 if (memcmp(look->essid, se->se_ssid+2, look->esslen)) 1457 return; 1458 } 1459 look->se = se; 1460} 1461 1462static __noinline int 1463setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], 1464 int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN]) 1465{ 1466 struct scanlookup lookup; 1467 1468 /* XXX ibss/ahdemo */ 1469 if (vap->iv_opmode != IEEE80211_M_STA) 1470 return EINVAL; 1471 1472 /* NB: this is racey if roaming is !manual */ 1473 lookup.se = NULL; 1474 lookup.mac = mac; 1475 lookup.esslen = ssid_len; 1476 lookup.essid = ssid; 1477 ieee80211_scan_iterate(vap, mlmelookup, &lookup); 1478 if (lookup.se == NULL) 1479 return ENOENT; 1480 mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0); 1481 if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se)) 1482 return EIO; /* XXX unique but could be better */ 1483 return 0; 1484} 1485 1486static __noinline int 1487ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq) 1488{ 1489 struct ieee80211req_mlme mlme; 1490 int error; 1491 1492 if (ireq->i_len != sizeof(mlme)) 1493 return EINVAL; 1494 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1495 if (error) 1496 return error; 1497 if (mlme.im_op == IEEE80211_MLME_ASSOC) 1498 return setmlme_assoc(vap, mlme.im_macaddr, 1499 vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid); 1500 else 1501 return setmlme_common(vap, mlme.im_op, 1502 mlme.im_macaddr, mlme.im_reason); 1503} 1504 1505static __noinline int 1506ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq) 1507{ 1508 uint8_t mac[IEEE80211_ADDR_LEN]; 1509 const struct ieee80211_aclator *acl = vap->iv_acl; 1510 int error; 1511 1512 if (ireq->i_len != sizeof(mac)) 1513 return EINVAL; 1514 error = copyin(ireq->i_data, mac, ireq->i_len); 1515 if (error) 1516 return error; 1517 if (acl == NULL) { 1518 acl = ieee80211_aclator_get("mac"); 1519 if (acl == NULL || !acl->iac_attach(vap)) 1520 return EINVAL; 1521 vap->iv_acl = acl; 1522 } 1523 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1524 acl->iac_add(vap, mac); 1525 else 1526 acl->iac_remove(vap, mac); 1527 return 0; 1528} 1529 1530static __noinline int 1531ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) 1532{ 1533 const struct ieee80211_aclator *acl = vap->iv_acl; 1534 1535 switch (ireq->i_val) { 1536 case IEEE80211_MACCMD_POLICY_OPEN: 1537 case IEEE80211_MACCMD_POLICY_ALLOW: 1538 case IEEE80211_MACCMD_POLICY_DENY: 1539 case IEEE80211_MACCMD_POLICY_RADIUS: 1540 if (acl == NULL) { 1541 acl = ieee80211_aclator_get("mac"); 1542 if (acl == NULL || !acl->iac_attach(vap)) 1543 return EINVAL; 1544 vap->iv_acl = acl; 1545 } 1546 acl->iac_setpolicy(vap, ireq->i_val); 1547 break; 1548 case IEEE80211_MACCMD_FLUSH: 1549 if (acl != NULL) 1550 acl->iac_flush(vap); 1551 /* NB: silently ignore when not in use */ 1552 break; 1553 case IEEE80211_MACCMD_DETACH: 1554 if (acl != NULL) { 1555 vap->iv_acl = NULL; 1556 acl->iac_detach(vap); 1557 } 1558 break; 1559 default: 1560 if (acl == NULL) 1561 return EINVAL; 1562 else 1563 return acl->iac_setioctl(vap, ireq); 1564 } 1565 return 0; 1566} 1567 1568static __noinline int 1569ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) 1570{ 1571 struct ieee80211com *ic = vap->iv_ic; 1572 uint8_t *chanlist, *list; 1573 int i, nchan, maxchan, error; 1574 1575 if (ireq->i_len > sizeof(ic->ic_chan_active)) 1576 ireq->i_len = sizeof(ic->ic_chan_active); 1577 list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP, 1578 M_NOWAIT | M_ZERO); 1579 if (list == NULL) 1580 return ENOMEM; 1581 error = copyin(ireq->i_data, list, ireq->i_len); 1582 if (error) 1583 return error; 1584 nchan = 0; 1585 chanlist = list + ireq->i_len; /* NB: zero'd already */ 1586 maxchan = ireq->i_len * NBBY; 1587 for (i = 0; i < ic->ic_nchans; i++) { 1588 const struct ieee80211_channel *c = &ic->ic_channels[i]; 1589 /* 1590 * Calculate the intersection of the user list and the 1591 * available channels so users can do things like specify 1592 * 1-255 to get all available channels. 1593 */ 1594 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) { 1595 setbit(chanlist, c->ic_ieee); 1596 nchan++; 1597 } 1598 } 1599 if (nchan == 0) 1600 return EINVAL; 1601 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ 1602 isclr(chanlist, ic->ic_bsschan->ic_ieee)) 1603 ic->ic_bsschan = IEEE80211_CHAN_ANYC; 1604 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES); 1605 ieee80211_scan_flush(vap); 1606 free(list, M_TEMP); 1607 return ENETRESET; 1608} 1609 1610static __noinline int 1611ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) 1612{ 1613 struct ieee80211_node *ni; 1614 uint8_t macaddr[IEEE80211_ADDR_LEN]; 1615 int error; 1616 1617 /* 1618 * NB: we could copyin ieee80211req_sta_stats so apps 1619 * could make selective changes but that's overkill; 1620 * just clear all stats for now. 1621 */ 1622 if (ireq->i_len < IEEE80211_ADDR_LEN) 1623 return EINVAL; 1624 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1625 if (error != 0) 1626 return error; 1627 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr); 1628 if (ni == NULL) 1629 return ENOENT; 1630 /* XXX require ni_vap == vap? */ 1631 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats)); 1632 ieee80211_free_node(ni); 1633 return 0; 1634} 1635 1636static __noinline int 1637ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) 1638{ 1639 struct ieee80211_node *ni; 1640 struct ieee80211req_sta_txpow txpow; 1641 int error; 1642 1643 if (ireq->i_len != sizeof(txpow)) 1644 return EINVAL; 1645 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1646 if (error != 0) 1647 return error; 1648 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr); 1649 if (ni == NULL) 1650 return ENOENT; 1651 ni->ni_txpower = txpow.it_txpow; 1652 ieee80211_free_node(ni); 1653 return error; 1654} 1655 1656static __noinline int 1657ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) 1658{ 1659 struct ieee80211com *ic = vap->iv_ic; 1660 struct ieee80211_wme_state *wme = &ic->ic_wme; 1661 struct wmeParams *wmep, *chanp; 1662 int isbss, ac; 1663 1664 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1665 return EOPNOTSUPP; 1666 1667 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1668 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1669 if (ac >= WME_NUM_AC) 1670 ac = WME_AC_BE; 1671 if (isbss) { 1672 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1673 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1674 } else { 1675 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1676 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1677 } 1678 switch (ireq->i_type) { 1679 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1680 if (isbss) { 1681 wmep->wmep_logcwmin = ireq->i_val; 1682 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1683 chanp->wmep_logcwmin = ireq->i_val; 1684 } else { 1685 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1686 ireq->i_val; 1687 } 1688 break; 1689 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1690 if (isbss) { 1691 wmep->wmep_logcwmax = ireq->i_val; 1692 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1693 chanp->wmep_logcwmax = ireq->i_val; 1694 } else { 1695 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1696 ireq->i_val; 1697 } 1698 break; 1699 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1700 if (isbss) { 1701 wmep->wmep_aifsn = ireq->i_val; 1702 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1703 chanp->wmep_aifsn = ireq->i_val; 1704 } else { 1705 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1706 } 1707 break; 1708 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1709 if (isbss) { 1710 wmep->wmep_txopLimit = ireq->i_val; 1711 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1712 chanp->wmep_txopLimit = ireq->i_val; 1713 } else { 1714 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1715 ireq->i_val; 1716 } 1717 break; 1718 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1719 wmep->wmep_acm = ireq->i_val; 1720 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1721 chanp->wmep_acm = ireq->i_val; 1722 break; 1723 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1724 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1725 (ireq->i_val) == 0; 1726 break; 1727 } 1728 ieee80211_wme_updateparams(vap); 1729 return 0; 1730} 1731 1732static int 1733find11gchannel(struct ieee80211com *ic, int start, int freq) 1734{ 1735 const struct ieee80211_channel *c; 1736 int i; 1737 1738 for (i = start+1; i < ic->ic_nchans; i++) { 1739 c = &ic->ic_channels[i]; 1740 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1741 return 1; 1742 } 1743 /* NB: should not be needed but in case things are mis-sorted */ 1744 for (i = 0; i < start; i++) { 1745 c = &ic->ic_channels[i]; 1746 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1747 return 1; 1748 } 1749 return 0; 1750} 1751 1752static struct ieee80211_channel * 1753findchannel(struct ieee80211com *ic, int ieee, int mode) 1754{ 1755 static const u_int chanflags[IEEE80211_MODE_MAX] = { 1756 [IEEE80211_MODE_AUTO] = 0, 1757 [IEEE80211_MODE_11A] = IEEE80211_CHAN_A, 1758 [IEEE80211_MODE_11B] = IEEE80211_CHAN_B, 1759 [IEEE80211_MODE_11G] = IEEE80211_CHAN_G, 1760 [IEEE80211_MODE_FH] = IEEE80211_CHAN_FHSS, 1761 [IEEE80211_MODE_TURBO_A] = IEEE80211_CHAN_108A, 1762 [IEEE80211_MODE_TURBO_G] = IEEE80211_CHAN_108G, 1763 [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_STURBO, 1764 [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF, 1765 [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER, 1766 /* NB: handled specially below */ 1767 [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A, 1768 [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G, 1769 }; 1770 u_int modeflags; 1771 int i; 1772 1773 modeflags = chanflags[mode]; 1774 for (i = 0; i < ic->ic_nchans; i++) { 1775 struct ieee80211_channel *c = &ic->ic_channels[i]; 1776 1777 if (c->ic_ieee != ieee) 1778 continue; 1779 if (mode == IEEE80211_MODE_AUTO) { 1780 /* ignore turbo channels for autoselect */ 1781 if (IEEE80211_IS_CHAN_TURBO(c)) 1782 continue; 1783 /* 1784 * XXX special-case 11b/g channels so we 1785 * always select the g channel if both 1786 * are present. 1787 * XXX prefer HT to non-HT? 1788 */ 1789 if (!IEEE80211_IS_CHAN_B(c) || 1790 !find11gchannel(ic, i, c->ic_freq)) 1791 return c; 1792 } else { 1793 /* must check HT specially */ 1794 if ((mode == IEEE80211_MODE_11NA || 1795 mode == IEEE80211_MODE_11NG) && 1796 !IEEE80211_IS_CHAN_HT(c)) 1797 continue; 1798 if ((c->ic_flags & modeflags) == modeflags) 1799 return c; 1800 } 1801 } 1802 return NULL; 1803} 1804 1805/* 1806 * Check the specified against any desired mode (aka netband). 1807 * This is only used (presently) when operating in hostap mode 1808 * to enforce consistency. 1809 */ 1810static int 1811check_mode_consistency(const struct ieee80211_channel *c, int mode) 1812{ 1813 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel")); 1814 1815 switch (mode) { 1816 case IEEE80211_MODE_11B: 1817 return (IEEE80211_IS_CHAN_B(c)); 1818 case IEEE80211_MODE_11G: 1819 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c)); 1820 case IEEE80211_MODE_11A: 1821 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c)); 1822 case IEEE80211_MODE_STURBO_A: 1823 return (IEEE80211_IS_CHAN_STURBO(c)); 1824 case IEEE80211_MODE_11NA: 1825 return (IEEE80211_IS_CHAN_HTA(c)); 1826 case IEEE80211_MODE_11NG: 1827 return (IEEE80211_IS_CHAN_HTG(c)); 1828 } 1829 return 1; 1830 1831} 1832 1833/* 1834 * Common code to set the current channel. If the device 1835 * is up and running this may result in an immediate channel 1836 * change or a kick of the state machine. 1837 */ 1838static int 1839setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c) 1840{ 1841 struct ieee80211com *ic = vap->iv_ic; 1842 int error; 1843 1844 if (c != IEEE80211_CHAN_ANYC) { 1845 if (IEEE80211_IS_CHAN_RADAR(c)) 1846 return EBUSY; /* XXX better code? */ 1847 if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 1848 if (IEEE80211_IS_CHAN_NOHOSTAP(c)) 1849 return EINVAL; 1850 if (!check_mode_consistency(c, vap->iv_des_mode)) 1851 return EINVAL; 1852 } else if (vap->iv_opmode == IEEE80211_M_IBSS) { 1853 if (IEEE80211_IS_CHAN_NOADHOC(c)) 1854 return EINVAL; 1855 } 1856 if (vap->iv_state == IEEE80211_S_RUN && 1857 vap->iv_bss->ni_chan == c) 1858 return 0; /* NB: nothing to do */ 1859 } 1860 vap->iv_des_chan = c; 1861 1862 error = 0; 1863 if (vap->iv_opmode == IEEE80211_M_MONITOR && 1864 vap->iv_des_chan != IEEE80211_CHAN_ANYC) { 1865 /* 1866 * Monitor mode can switch directly. 1867 */ 1868 if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) { 1869 /* XXX need state machine for other vap's to follow */ 1870 ieee80211_setcurchan(ic, vap->iv_des_chan); 1871 vap->iv_bss->ni_chan = ic->ic_curchan; 1872 } else 1873 ic->ic_curchan = vap->iv_des_chan; 1874 } else { 1875 /* 1876 * Need to go through the state machine in case we 1877 * need to reassociate or the like. The state machine 1878 * will pickup the desired channel and avoid scanning. 1879 */ 1880 if (IS_UP_AUTO(vap)) 1881 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 1882 else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) { 1883 /* 1884 * When not up+running and a real channel has 1885 * been specified fix the current channel so 1886 * there is immediate feedback; e.g. via ifconfig. 1887 */ 1888 ic->ic_curchan = vap->iv_des_chan; 1889 } 1890 } 1891 return error; 1892} 1893 1894/* 1895 * Old api for setting the current channel; this is 1896 * deprecated because channel numbers are ambiguous. 1897 */ 1898static __noinline int 1899ieee80211_ioctl_setchannel(struct ieee80211vap *vap, 1900 const struct ieee80211req *ireq) 1901{ 1902 struct ieee80211com *ic = vap->iv_ic; 1903 struct ieee80211_channel *c; 1904 1905 /* XXX 0xffff overflows 16-bit signed */ 1906 if (ireq->i_val == 0 || 1907 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) { 1908 c = IEEE80211_CHAN_ANYC; 1909 } else { 1910 struct ieee80211_channel *c2; 1911 1912 c = findchannel(ic, ireq->i_val, vap->iv_des_mode); 1913 if (c == NULL) { 1914 c = findchannel(ic, ireq->i_val, 1915 IEEE80211_MODE_AUTO); 1916 if (c == NULL) 1917 return EINVAL; 1918 } 1919 /* 1920 * Fine tune channel selection based on desired mode: 1921 * if 11b is requested, find the 11b version of any 1922 * 11g channel returned, 1923 * if static turbo, find the turbo version of any 1924 * 11a channel return, 1925 * if 11na is requested, find the ht version of any 1926 * 11a channel returned, 1927 * if 11ng is requested, find the ht version of any 1928 * 11g channel returned, 1929 * otherwise we should be ok with what we've got. 1930 */ 1931 switch (vap->iv_des_mode) { 1932 case IEEE80211_MODE_11B: 1933 if (IEEE80211_IS_CHAN_ANYG(c)) { 1934 c2 = findchannel(ic, ireq->i_val, 1935 IEEE80211_MODE_11B); 1936 /* NB: should not happen, =>'s 11g w/o 11b */ 1937 if (c2 != NULL) 1938 c = c2; 1939 } 1940 break; 1941 case IEEE80211_MODE_TURBO_A: 1942 if (IEEE80211_IS_CHAN_A(c)) { 1943 c2 = findchannel(ic, ireq->i_val, 1944 IEEE80211_MODE_TURBO_A); 1945 if (c2 != NULL) 1946 c = c2; 1947 } 1948 break; 1949 case IEEE80211_MODE_11NA: 1950 if (IEEE80211_IS_CHAN_A(c)) { 1951 c2 = findchannel(ic, ireq->i_val, 1952 IEEE80211_MODE_11NA); 1953 if (c2 != NULL) 1954 c = c2; 1955 } 1956 break; 1957 case IEEE80211_MODE_11NG: 1958 if (IEEE80211_IS_CHAN_ANYG(c)) { 1959 c2 = findchannel(ic, ireq->i_val, 1960 IEEE80211_MODE_11NG); 1961 if (c2 != NULL) 1962 c = c2; 1963 } 1964 break; 1965 default: /* NB: no static turboG */ 1966 break; 1967 } 1968 } 1969 return setcurchan(vap, c); 1970} 1971 1972/* 1973 * New/current api for setting the current channel; a complete 1974 * channel description is provide so there is no ambiguity in 1975 * identifying the channel. 1976 */ 1977static __noinline int 1978ieee80211_ioctl_setcurchan(struct ieee80211vap *vap, 1979 const struct ieee80211req *ireq) 1980{ 1981 struct ieee80211com *ic = vap->iv_ic; 1982 struct ieee80211_channel chan, *c; 1983 int error; 1984 1985 if (ireq->i_len != sizeof(chan)) 1986 return EINVAL; 1987 error = copyin(ireq->i_data, &chan, sizeof(chan)); 1988 if (error != 0) 1989 return error; 1990 /* XXX 0xffff overflows 16-bit signed */ 1991 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { 1992 c = IEEE80211_CHAN_ANYC; 1993 } else { 1994 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); 1995 if (c == NULL) 1996 return EINVAL; 1997 } 1998 return setcurchan(vap, c); 1999} 2000 2001static __noinline int 2002ieee80211_ioctl_setregdomain(struct ieee80211vap *vap, 2003 const struct ieee80211req *ireq) 2004{ 2005 struct ieee80211_regdomain_req *reg; 2006 int nchans, error; 2007 2008 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) / 2009 sizeof(struct ieee80211_channel)); 2010 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) { 2011 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2012 "%s: bad # chans, i_len %d nchans %d\n", __func__, 2013 ireq->i_len, nchans); 2014 return EINVAL; 2015 } 2016 reg = (struct ieee80211_regdomain_req *) 2017 malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT); 2018 if (reg == NULL) { 2019 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2020 "%s: no memory, nchans %d\n", __func__, nchans); 2021 return ENOMEM; 2022 } 2023 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans)); 2024 if (error == 0) { 2025 /* NB: validate inline channel count against storage size */ 2026 if (reg->chaninfo.ic_nchans != nchans) { 2027 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL, 2028 "%s: chan cnt mismatch, %d != %d\n", __func__, 2029 reg->chaninfo.ic_nchans, nchans); 2030 error = EINVAL; 2031 } else 2032 error = ieee80211_setregdomain(vap, reg); 2033 } 2034 free(reg, M_TEMP); 2035 2036 return (error == 0 ? ENETRESET : error); 2037} 2038 2039static int 2040ieee80211_ioctl_setroam(struct ieee80211vap *vap, 2041 const struct ieee80211req *ireq) 2042{ 2043 if (ireq->i_len != sizeof(vap->iv_roamparms)) 2044 return EINVAL; 2045 /* XXX validate params */ 2046 /* XXX? ENETRESET to push to device? */ 2047 return copyin(ireq->i_data, vap->iv_roamparms, 2048 sizeof(vap->iv_roamparms)); 2049} 2050 2051static int 2052checkrate(const struct ieee80211_rateset *rs, int rate) 2053{ 2054 int i; 2055 2056 if (rate == IEEE80211_FIXED_RATE_NONE) 2057 return 1; 2058 for (i = 0; i < rs->rs_nrates; i++) 2059 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate) 2060 return 1; 2061 return 0; 2062} 2063 2064static int 2065checkmcs(int mcs) 2066{ 2067 if (mcs == IEEE80211_FIXED_RATE_NONE) 2068 return 1; 2069 if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */ 2070 return 0; 2071 return (mcs & 0x7f) <= 15; /* XXX could search ht rate set */ 2072} 2073 2074static __noinline int 2075ieee80211_ioctl_settxparams(struct ieee80211vap *vap, 2076 const struct ieee80211req *ireq) 2077{ 2078 struct ieee80211com *ic = vap->iv_ic; 2079 struct ieee80211_txparams_req parms; /* XXX stack use? */ 2080 struct ieee80211_txparam *src, *dst; 2081 const struct ieee80211_rateset *rs; 2082 int error, mode, changed, is11n, nmodes; 2083 2084 /* NB: accept short requests for backwards compat */ 2085 if (ireq->i_len > sizeof(parms)) 2086 return EINVAL; 2087 error = copyin(ireq->i_data, &parms, ireq->i_len); 2088 if (error != 0) 2089 return error; 2090 nmodes = ireq->i_len / sizeof(struct ieee80211_txparam); 2091 changed = 0; 2092 /* validate parameters and check if anything changed */ 2093 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) { 2094 if (isclr(ic->ic_modecaps, mode)) 2095 continue; 2096 src = &parms.params[mode]; 2097 dst = &vap->iv_txparms[mode]; 2098 rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */ 2099 is11n = (mode == IEEE80211_MODE_11NA || 2100 mode == IEEE80211_MODE_11NG); 2101 if (src->ucastrate != dst->ucastrate) { 2102 if (!checkrate(rs, src->ucastrate) && 2103 (!is11n || !checkmcs(src->ucastrate))) 2104 return EINVAL; 2105 changed++; 2106 } 2107 if (src->mcastrate != dst->mcastrate) { 2108 if (!checkrate(rs, src->mcastrate) && 2109 (!is11n || !checkmcs(src->mcastrate))) 2110 return EINVAL; 2111 changed++; 2112 } 2113 if (src->mgmtrate != dst->mgmtrate) { 2114 if (!checkrate(rs, src->mgmtrate) && 2115 (!is11n || !checkmcs(src->mgmtrate))) 2116 return EINVAL; 2117 changed++; 2118 } 2119 if (src->maxretry != dst->maxretry) /* NB: no bounds */ 2120 changed++; 2121 } 2122 if (changed) { 2123 /* 2124 * Copy new parameters in place and notify the 2125 * driver so it can push state to the device. 2126 */ 2127 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) { 2128 if (isset(ic->ic_modecaps, mode)) 2129 vap->iv_txparms[mode] = parms.params[mode]; 2130 } 2131 /* XXX could be more intelligent, 2132 e.g. don't reset if setting not being used */ 2133 return ENETRESET; 2134 } 2135 return 0; 2136} 2137 2138/* 2139 * Application Information Element support. 2140 */ 2141static int 2142setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq) 2143{ 2144 struct ieee80211_appie *app = *aie; 2145 struct ieee80211_appie *napp; 2146 int error; 2147 2148 if (ireq->i_len == 0) { /* delete any existing ie */ 2149 if (app != NULL) { 2150 *aie = NULL; /* XXX racey */ 2151 free(app, M_80211_NODE_IE); 2152 } 2153 return 0; 2154 } 2155 if (!(2 <= ireq->i_len && ireq->i_len <= IEEE80211_MAX_APPIE)) 2156 return EINVAL; 2157 /* 2158 * Allocate a new appie structure and copy in the user data. 2159 * When done swap in the new structure. Note that we do not 2160 * guard against users holding a ref to the old structure; 2161 * this must be handled outside this code. 2162 * 2163 * XXX bad bad bad 2164 */ 2165 napp = (struct ieee80211_appie *) malloc( 2166 sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT); 2167 if (napp == NULL) 2168 return ENOMEM; 2169 /* XXX holding ic lock */ 2170 error = copyin(ireq->i_data, napp->ie_data, ireq->i_len); 2171 if (error) { 2172 free(napp, M_80211_NODE_IE); 2173 return error; 2174 } 2175 napp->ie_len = ireq->i_len; 2176 *aie = napp; 2177 if (app != NULL) 2178 free(app, M_80211_NODE_IE); 2179 return 0; 2180} 2181 2182static void 2183setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space) 2184{ 2185 /* validate data is present as best we can */ 2186 if (space == 0 || 2+ie[1] > space) 2187 return; 2188 if (ie[0] == IEEE80211_ELEMID_VENDOR) 2189 vap->iv_wpa_ie = ie; 2190 else if (ie[0] == IEEE80211_ELEMID_RSN) 2191 vap->iv_rsn_ie = ie; 2192} 2193 2194static __noinline int 2195ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap, 2196 const struct ieee80211req *ireq, int fc0) 2197{ 2198 int error; 2199 2200 IEEE80211_LOCK_ASSERT(vap->iv_ic); 2201 2202 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) { 2203 case IEEE80211_FC0_SUBTYPE_BEACON: 2204 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2205 vap->iv_opmode != IEEE80211_M_IBSS) { 2206 error = EINVAL; 2207 break; 2208 } 2209 error = setappie(&vap->iv_appie_beacon, ireq); 2210 if (error == 0) 2211 ieee80211_beacon_notify(vap, IEEE80211_BEACON_APPIE); 2212 break; 2213 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 2214 error = setappie(&vap->iv_appie_proberesp, ireq); 2215 break; 2216 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 2217 if (vap->iv_opmode == IEEE80211_M_HOSTAP) 2218 error = setappie(&vap->iv_appie_assocresp, ireq); 2219 else 2220 error = EINVAL; 2221 break; 2222 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 2223 error = setappie(&vap->iv_appie_probereq, ireq); 2224 break; 2225 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 2226 if (vap->iv_opmode == IEEE80211_M_STA) 2227 error = setappie(&vap->iv_appie_assocreq, ireq); 2228 else 2229 error = EINVAL; 2230 break; 2231 case (IEEE80211_APPIE_WPA & IEEE80211_FC0_SUBTYPE_MASK): 2232 error = setappie(&vap->iv_appie_wpa, ireq); 2233 if (error == 0) { 2234 /* 2235 * Must split single blob of data into separate 2236 * WPA and RSN ie's because they go in different 2237 * locations in the mgt frames. 2238 * XXX use IEEE80211_IOC_WPA2 so user code does split 2239 */ 2240 vap->iv_wpa_ie = NULL; 2241 vap->iv_rsn_ie = NULL; 2242 if (vap->iv_appie_wpa != NULL) { 2243 struct ieee80211_appie *appie = 2244 vap->iv_appie_wpa; 2245 uint8_t *data = appie->ie_data; 2246 2247 /* XXX ie length validate is painful, cheat */ 2248 setwparsnie(vap, data, appie->ie_len); 2249 setwparsnie(vap, data + 2 + data[1], 2250 appie->ie_len - (2 + data[1])); 2251 } 2252 if (vap->iv_opmode == IEEE80211_M_HOSTAP || 2253 vap->iv_opmode == IEEE80211_M_IBSS) { 2254 /* 2255 * Must rebuild beacon frame as the update 2256 * mechanism doesn't handle WPA/RSN ie's. 2257 * Could extend it but it doesn't normally 2258 * change; this is just to deal with hostapd 2259 * plumbing the ie after the interface is up. 2260 */ 2261 error = ENETRESET; 2262 } 2263 } 2264 break; 2265 default: 2266 error = EINVAL; 2267 break; 2268 } 2269 return error; 2270} 2271 2272static __noinline int 2273ieee80211_ioctl_setappie(struct ieee80211vap *vap, 2274 const struct ieee80211req *ireq) 2275{ 2276 struct ieee80211com *ic = vap->iv_ic; 2277 int error; 2278 uint8_t fc0; 2279 2280 fc0 = ireq->i_val & 0xff; 2281 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) 2282 return EINVAL; 2283 /* NB: could check iv_opmode and reject but hardly worth the effort */ 2284 IEEE80211_LOCK(ic); 2285 error = ieee80211_ioctl_setappie_locked(vap, ireq, fc0); 2286 IEEE80211_UNLOCK(ic); 2287 return error; 2288} 2289 2290static __noinline int 2291ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) 2292{ 2293 struct ieee80211com *ic = vap->iv_ic; 2294 struct ieee80211_chanswitch_req csr; 2295 struct ieee80211_channel *c; 2296 int error; 2297 2298 if (ireq->i_len != sizeof(csr)) 2299 return EINVAL; 2300 error = copyin(ireq->i_data, &csr, sizeof(csr)); 2301 if (error != 0) 2302 return error; 2303 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0) 2304 return EINVAL; 2305 c = ieee80211_find_channel(ic, 2306 csr.csa_chan.ic_freq, csr.csa_chan.ic_flags); 2307 if (c == NULL) 2308 return ENOENT; 2309 IEEE80211_LOCK(ic); 2310 if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) 2311 ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count); 2312 else 2313 error = EBUSY; 2314 IEEE80211_UNLOCK(ic); 2315 return error; 2316} 2317 2318static __noinline int 2319ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) 2320{ 2321#define IEEE80211_IOC_SCAN_FLAGS \ 2322 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \ 2323 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \ 2324 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \ 2325 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \ 2326 IEEE80211_IOC_SCAN_CHECK) 2327 struct ieee80211com *ic = vap->iv_ic; 2328 struct ieee80211_scan_req sr; /* XXX off stack? */ 2329 int error, i; 2330 2331 /* NB: parent must be running */ 2332 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2333 return ENXIO; 2334 2335 if (ireq->i_len != sizeof(sr)) 2336 return EINVAL; 2337 error = copyin(ireq->i_data, &sr, sizeof(sr)); 2338 if (error != 0) 2339 return error; 2340 /* convert duration */ 2341 if (sr.sr_duration == IEEE80211_IOC_SCAN_FOREVER) 2342 sr.sr_duration = IEEE80211_SCAN_FOREVER; 2343 else { 2344 if (sr.sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN || 2345 sr.sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX) 2346 return EINVAL; 2347 sr.sr_duration = msecs_to_ticks(sr.sr_duration); 2348 if (sr.sr_duration < 1) 2349 sr.sr_duration = 1; 2350 } 2351 /* convert min/max channel dwell */ 2352 if (sr.sr_mindwell != 0) { 2353 sr.sr_mindwell = msecs_to_ticks(sr.sr_mindwell); 2354 if (sr.sr_mindwell < 1) 2355 sr.sr_mindwell = 1; 2356 } 2357 if (sr.sr_maxdwell != 0) { 2358 sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell); 2359 if (sr.sr_maxdwell < 1) 2360 sr.sr_maxdwell = 1; 2361 } 2362 /* NB: silently reduce ssid count to what is supported */ 2363 if (sr.sr_nssid > IEEE80211_SCAN_MAX_SSID) 2364 sr.sr_nssid = IEEE80211_SCAN_MAX_SSID; 2365 for (i = 0; i < sr.sr_nssid; i++) 2366 if (sr.sr_ssid[i].len > IEEE80211_NWID_LEN) 2367 return EINVAL; 2368 /* cleanse flags just in case, could reject if invalid flags */ 2369 sr.sr_flags &= IEEE80211_IOC_SCAN_FLAGS; 2370 /* 2371 * Add an implicit NOPICK if the vap is not marked UP. This 2372 * allows applications to scan without joining a bss (or picking 2373 * a channel and setting up a bss) and without forcing manual 2374 * roaming mode--you just need to mark the parent device UP. 2375 */ 2376 if ((vap->iv_ifp->if_flags & IFF_UP) == 0) 2377 sr.sr_flags |= IEEE80211_IOC_SCAN_NOPICK; 2378 2379 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2380 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n", 2381 __func__, sr.sr_flags, 2382 (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "", 2383 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, sr.sr_nssid); 2384 /* 2385 * If we are in INIT state then the driver has never had a chance 2386 * to setup hardware state to do a scan; we must use the state 2387 * machine to get us up to the SCAN state but once we reach SCAN 2388 * state we then want to use the supplied params. Stash the 2389 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the 2390 * state machines will recognize this and use the stashed params 2391 * to issue the scan request. 2392 * 2393 * Otherwise just invoke the scan machinery directly. 2394 */ 2395 IEEE80211_LOCK(ic); 2396 if (vap->iv_state == IEEE80211_S_INIT) { 2397 /* NB: clobbers previous settings */ 2398 vap->iv_scanreq_flags = sr.sr_flags; 2399 vap->iv_scanreq_duration = sr.sr_duration; 2400 vap->iv_scanreq_nssid = sr.sr_nssid; 2401 for (i = 0; i < sr.sr_nssid; i++) { 2402 vap->iv_scanreq_ssid[i].len = sr.sr_ssid[i].len; 2403 memcpy(vap->iv_scanreq_ssid[i].ssid, sr.sr_ssid[i].ssid, 2404 sr.sr_ssid[i].len); 2405 } 2406 vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ; 2407 IEEE80211_UNLOCK(ic); 2408 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 2409 } else { 2410 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ; 2411 IEEE80211_UNLOCK(ic); 2412 /* XXX neeed error return codes */ 2413 if (sr.sr_flags & IEEE80211_IOC_SCAN_CHECK) { 2414 (void) ieee80211_check_scan(vap, sr.sr_flags, 2415 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, 2416 sr.sr_nssid, 2417 /* NB: cheat, we assume structures are compatible */ 2418 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); 2419 } else { 2420 (void) ieee80211_start_scan(vap, sr.sr_flags, 2421 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, 2422 sr.sr_nssid, 2423 /* NB: cheat, we assume structures are compatible */ 2424 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); 2425 } 2426 } 2427 return error; 2428#undef IEEE80211_IOC_SCAN_FLAGS 2429} 2430 2431static __noinline int 2432ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) 2433{ 2434 struct ieee80211_node *ni; 2435 struct ieee80211req_sta_vlan vlan; 2436 int error; 2437 2438 if (ireq->i_len != sizeof(vlan)) 2439 return EINVAL; 2440 error = copyin(ireq->i_data, &vlan, sizeof(vlan)); 2441 if (error != 0) 2442 return error; 2443 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) { 2444 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, 2445 vlan.sv_macaddr); 2446 if (ni == NULL) 2447 return ENOENT; 2448 } else 2449 ni = ieee80211_ref_node(vap->iv_bss); 2450 ni->ni_vlan = vlan.sv_vlan; 2451 ieee80211_free_node(ni); 2452 return error; 2453} 2454 2455static int 2456isvap11g(const struct ieee80211vap *vap) 2457{ 2458 const struct ieee80211_node *bss = vap->iv_bss; 2459 return bss->ni_chan != IEEE80211_CHAN_ANYC && 2460 IEEE80211_IS_CHAN_ANYG(bss->ni_chan); 2461} 2462 2463static int 2464isvapht(const struct ieee80211vap *vap) 2465{ 2466 const struct ieee80211_node *bss = vap->iv_bss; 2467 return bss->ni_chan != IEEE80211_CHAN_ANYC && 2468 IEEE80211_IS_CHAN_HT(bss->ni_chan); 2469} 2470 2471/* 2472 * Dummy ioctl set handler so the linker set is defined. 2473 */ 2474static int 2475dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq) 2476{ 2477 return ENOSYS; 2478} 2479IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set); 2480 2481static int 2482ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq) 2483{ 2484 ieee80211_ioctl_setfunc * const *set; 2485 int error; 2486 2487 SET_FOREACH(set, ieee80211_ioctl_setset) { 2488 error = (*set)(vap, ireq); 2489 if (error != ENOSYS) 2490 return error; 2491 } 2492 return EINVAL; 2493} 2494 2495static __noinline int 2496ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq) 2497{ 2498 struct ieee80211com *ic = vap->iv_ic; 2499 int error; 2500 const struct ieee80211_authenticator *auth; 2501 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 2502 char tmpssid[IEEE80211_NWID_LEN]; 2503 uint8_t tmpbssid[IEEE80211_ADDR_LEN]; 2504 struct ieee80211_key *k; 2505 u_int kid; 2506 uint32_t flags; 2507 2508 error = 0; 2509 switch (ireq->i_type) { 2510 case IEEE80211_IOC_SSID: 2511 if (ireq->i_val != 0 || 2512 ireq->i_len > IEEE80211_NWID_LEN) 2513 return EINVAL; 2514 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 2515 if (error) 2516 break; 2517 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); 2518 vap->iv_des_ssid[0].len = ireq->i_len; 2519 memcpy(vap->iv_des_ssid[0].ssid, tmpssid, ireq->i_len); 2520 vap->iv_des_nssid = (ireq->i_len > 0); 2521 error = ENETRESET; 2522 break; 2523 case IEEE80211_IOC_WEP: 2524 switch (ireq->i_val) { 2525 case IEEE80211_WEP_OFF: 2526 vap->iv_flags &= ~IEEE80211_F_PRIVACY; 2527 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2528 break; 2529 case IEEE80211_WEP_ON: 2530 vap->iv_flags |= IEEE80211_F_PRIVACY; 2531 vap->iv_flags |= IEEE80211_F_DROPUNENC; 2532 break; 2533 case IEEE80211_WEP_MIXED: 2534 vap->iv_flags |= IEEE80211_F_PRIVACY; 2535 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2536 break; 2537 } 2538 error = ENETRESET; 2539 break; 2540 case IEEE80211_IOC_WEPKEY: 2541 kid = (u_int) ireq->i_val; 2542 if (kid >= IEEE80211_WEP_NKID) 2543 return EINVAL; 2544 k = &vap->iv_nw_keys[kid]; 2545 if (ireq->i_len == 0) { 2546 /* zero-len =>'s delete any existing key */ 2547 (void) ieee80211_crypto_delkey(vap, k); 2548 break; 2549 } 2550 if (ireq->i_len > sizeof(tmpkey)) 2551 return EINVAL; 2552 memset(tmpkey, 0, sizeof(tmpkey)); 2553 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 2554 if (error) 2555 break; 2556 ieee80211_key_update_begin(vap); 2557 k->wk_keyix = kid; /* NB: force fixed key id */ 2558 if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP, 2559 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2560 k->wk_keylen = ireq->i_len; 2561 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 2562 IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr); 2563 if (!ieee80211_crypto_setkey(vap, k)) 2564 error = EINVAL; 2565 } else 2566 error = EINVAL; 2567 ieee80211_key_update_end(vap); 2568 break; 2569 case IEEE80211_IOC_WEPTXKEY: 2570 kid = (u_int) ireq->i_val; 2571 if (kid >= IEEE80211_WEP_NKID && 2572 (uint16_t) kid != IEEE80211_KEYIX_NONE) 2573 return EINVAL; 2574 vap->iv_def_txkey = kid; 2575 break; 2576 case IEEE80211_IOC_AUTHMODE: 2577 switch (ireq->i_val) { 2578 case IEEE80211_AUTH_WPA: 2579 case IEEE80211_AUTH_8021X: /* 802.1x */ 2580 case IEEE80211_AUTH_OPEN: /* open */ 2581 case IEEE80211_AUTH_SHARED: /* shared-key */ 2582 case IEEE80211_AUTH_AUTO: /* auto */ 2583 auth = ieee80211_authenticator_get(ireq->i_val); 2584 if (auth == NULL) 2585 return EINVAL; 2586 break; 2587 default: 2588 return EINVAL; 2589 } 2590 switch (ireq->i_val) { 2591 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 2592 vap->iv_flags |= IEEE80211_F_PRIVACY; 2593 ireq->i_val = IEEE80211_AUTH_8021X; 2594 break; 2595 case IEEE80211_AUTH_OPEN: /* open */ 2596 vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 2597 break; 2598 case IEEE80211_AUTH_SHARED: /* shared-key */ 2599 case IEEE80211_AUTH_8021X: /* 802.1x */ 2600 vap->iv_flags &= ~IEEE80211_F_WPA; 2601 /* both require a key so mark the PRIVACY capability */ 2602 vap->iv_flags |= IEEE80211_F_PRIVACY; 2603 break; 2604 case IEEE80211_AUTH_AUTO: /* auto */ 2605 vap->iv_flags &= ~IEEE80211_F_WPA; 2606 /* XXX PRIVACY handling? */ 2607 /* XXX what's the right way to do this? */ 2608 break; 2609 } 2610 /* NB: authenticator attach/detach happens on state change */ 2611 vap->iv_bss->ni_authmode = ireq->i_val; 2612 /* XXX mixed/mode/usage? */ 2613 vap->iv_auth = auth; 2614 error = ENETRESET; 2615 break; 2616 case IEEE80211_IOC_CHANNEL: 2617 error = ieee80211_ioctl_setchannel(vap, ireq); 2618 break; 2619 case IEEE80211_IOC_POWERSAVE: 2620 switch (ireq->i_val) { 2621 case IEEE80211_POWERSAVE_OFF: 2622 if (vap->iv_flags & IEEE80211_F_PMGTON) { 2623 ieee80211_syncflag(vap, -IEEE80211_F_PMGTON); 2624 error = ERESTART; 2625 } 2626 break; 2627 case IEEE80211_POWERSAVE_ON: 2628 if ((vap->iv_caps & IEEE80211_C_PMGT) == 0) 2629 error = EOPNOTSUPP; 2630 else if ((vap->iv_flags & IEEE80211_F_PMGTON) == 0) { 2631 ieee80211_syncflag(vap, IEEE80211_F_PMGTON); 2632 error = ERESTART; 2633 } 2634 break; 2635 default: 2636 error = EINVAL; 2637 break; 2638 } 2639 break; 2640 case IEEE80211_IOC_POWERSAVESLEEP: 2641 if (ireq->i_val < 0) 2642 return EINVAL; 2643 ic->ic_lintval = ireq->i_val; 2644 error = ERESTART; 2645 break; 2646 case IEEE80211_IOC_RTSTHRESHOLD: 2647 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2648 ireq->i_val <= IEEE80211_RTS_MAX)) 2649 return EINVAL; 2650 vap->iv_rtsthreshold = ireq->i_val; 2651 error = ERESTART; 2652 break; 2653 case IEEE80211_IOC_PROTMODE: 2654 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2655 return EINVAL; 2656 ic->ic_protmode = ireq->i_val; 2657 /* NB: if not operating in 11g this can wait */ 2658 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2659 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2660 error = ERESTART; 2661 break; 2662 case IEEE80211_IOC_TXPOWER: 2663 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2664 return EOPNOTSUPP; 2665 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val && 2666 ireq->i_val <= IEEE80211_TXPOWER_MAX)) 2667 return EINVAL; 2668 ic->ic_txpowlimit = ireq->i_val; 2669 error = ERESTART; 2670 break; 2671 case IEEE80211_IOC_ROAMING: 2672 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2673 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2674 return EINVAL; 2675 vap->iv_roaming = ireq->i_val; 2676 /* XXXX reset? */ 2677 break; 2678 case IEEE80211_IOC_PRIVACY: 2679 if (ireq->i_val) { 2680 /* XXX check for key state? */ 2681 vap->iv_flags |= IEEE80211_F_PRIVACY; 2682 } else 2683 vap->iv_flags &= ~IEEE80211_F_PRIVACY; 2684 /* XXX ERESTART? */ 2685 break; 2686 case IEEE80211_IOC_DROPUNENCRYPTED: 2687 if (ireq->i_val) 2688 vap->iv_flags |= IEEE80211_F_DROPUNENC; 2689 else 2690 vap->iv_flags &= ~IEEE80211_F_DROPUNENC; 2691 /* XXX ERESTART? */ 2692 break; 2693 case IEEE80211_IOC_WPAKEY: 2694 error = ieee80211_ioctl_setkey(vap, ireq); 2695 break; 2696 case IEEE80211_IOC_DELKEY: 2697 error = ieee80211_ioctl_delkey(vap, ireq); 2698 break; 2699 case IEEE80211_IOC_MLME: 2700 error = ieee80211_ioctl_setmlme(vap, ireq); 2701 break; 2702 case IEEE80211_IOC_COUNTERMEASURES: 2703 if (ireq->i_val) { 2704 if ((vap->iv_flags & IEEE80211_F_WPA) == 0) 2705 return EOPNOTSUPP; 2706 vap->iv_flags |= IEEE80211_F_COUNTERM; 2707 } else 2708 vap->iv_flags &= ~IEEE80211_F_COUNTERM; 2709 /* XXX ERESTART? */ 2710 break; 2711 case IEEE80211_IOC_WPA: 2712 if (ireq->i_val > 3) 2713 return EINVAL; 2714 /* XXX verify ciphers available */ 2715 flags = vap->iv_flags & ~IEEE80211_F_WPA; 2716 switch (ireq->i_val) { 2717 case 1: 2718 if (!(vap->iv_caps & IEEE80211_C_WPA1)) 2719 return EOPNOTSUPP; 2720 flags |= IEEE80211_F_WPA1; 2721 break; 2722 case 2: 2723 if (!(vap->iv_caps & IEEE80211_C_WPA2)) 2724 return EOPNOTSUPP; 2725 flags |= IEEE80211_F_WPA2; 2726 break; 2727 case 3: 2728 if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA) 2729 return EOPNOTSUPP; 2730 flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2731 break; 2732 default: /* Can't set any -> error */ 2733 return EOPNOTSUPP; 2734 } 2735 vap->iv_flags = flags; 2736 error = ERESTART; /* NB: can change beacon frame */ 2737 break; 2738 case IEEE80211_IOC_WME: 2739 if (ireq->i_val) { 2740 if ((vap->iv_caps & IEEE80211_C_WME) == 0) 2741 return EOPNOTSUPP; 2742 ieee80211_syncflag(vap, IEEE80211_F_WME); 2743 } else 2744 ieee80211_syncflag(vap, -IEEE80211_F_WME); 2745 error = ERESTART; /* NB: can change beacon frame */ 2746 break; 2747 case IEEE80211_IOC_HIDESSID: 2748 if (ireq->i_val) 2749 vap->iv_flags |= IEEE80211_F_HIDESSID; 2750 else 2751 vap->iv_flags &= ~IEEE80211_F_HIDESSID; 2752 error = ERESTART; /* XXX ENETRESET? */ 2753 break; 2754 case IEEE80211_IOC_APBRIDGE: 2755 if (ireq->i_val == 0) 2756 vap->iv_flags |= IEEE80211_F_NOBRIDGE; 2757 else 2758 vap->iv_flags &= ~IEEE80211_F_NOBRIDGE; 2759 break; 2760 case IEEE80211_IOC_BSSID: 2761 if (ireq->i_len != sizeof(tmpbssid)) 2762 return EINVAL; 2763 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2764 if (error) 2765 break; 2766 IEEE80211_ADDR_COPY(vap->iv_des_bssid, tmpbssid); 2767 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid)) 2768 vap->iv_flags &= ~IEEE80211_F_DESBSSID; 2769 else 2770 vap->iv_flags |= IEEE80211_F_DESBSSID; 2771 error = ENETRESET; 2772 break; 2773 case IEEE80211_IOC_CHANLIST: 2774 error = ieee80211_ioctl_setchanlist(vap, ireq); 2775 break; 2776#define OLD_IEEE80211_IOC_SCAN_REQ 23 2777#ifdef OLD_IEEE80211_IOC_SCAN_REQ 2778 case OLD_IEEE80211_IOC_SCAN_REQ: 2779 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2780 "%s: active scan request\n", __func__); 2781 /* 2782 * If we are in INIT state then the driver has never 2783 * had a chance to setup hardware state to do a scan; 2784 * use the state machine to get us up the SCAN state. 2785 * Otherwise just invoke the scan machinery to start 2786 * a one-time scan. 2787 */ 2788 if (vap->iv_state == IEEE80211_S_INIT) 2789 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 2790 else 2791 (void) ieee80211_start_scan(vap, 2792 IEEE80211_SCAN_ACTIVE | 2793 IEEE80211_SCAN_NOPICK | 2794 IEEE80211_SCAN_ONCE, 2795 IEEE80211_SCAN_FOREVER, 0, 0, 2796 /* XXX use ioctl params */ 2797 vap->iv_des_nssid, vap->iv_des_ssid); 2798 break; 2799#endif /* OLD_IEEE80211_IOC_SCAN_REQ */ 2800 case IEEE80211_IOC_SCAN_REQ: 2801 error = ieee80211_ioctl_scanreq(vap, ireq); 2802 break; 2803 case IEEE80211_IOC_SCAN_CANCEL: 2804 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 2805 "%s: cancel scan\n", __func__); 2806 ieee80211_cancel_scan(vap); 2807 break; 2808 case IEEE80211_IOC_HTCONF: 2809 if (ireq->i_val & 1) 2810 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_HT); 2811 else 2812 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_HT); 2813 if (ireq->i_val & 2) 2814 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_USEHT40); 2815 else 2816 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_USEHT40); 2817 error = ENETRESET; 2818 break; 2819 case IEEE80211_IOC_ADDMAC: 2820 case IEEE80211_IOC_DELMAC: 2821 error = ieee80211_ioctl_macmac(vap, ireq); 2822 break; 2823 case IEEE80211_IOC_MACCMD: 2824 error = ieee80211_ioctl_setmaccmd(vap, ireq); 2825 break; 2826 case IEEE80211_IOC_STA_STATS: 2827 error = ieee80211_ioctl_setstastats(vap, ireq); 2828 break; 2829 case IEEE80211_IOC_STA_TXPOW: 2830 error = ieee80211_ioctl_setstatxpow(vap, ireq); 2831 break; 2832 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2833 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2834 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2835 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2836 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2837 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2838 error = ieee80211_ioctl_setwmeparam(vap, ireq); 2839 break; 2840 case IEEE80211_IOC_DTIM_PERIOD: 2841 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2842 vap->iv_opmode != IEEE80211_M_IBSS) 2843 return EINVAL; 2844 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2845 ireq->i_val <= IEEE80211_DTIM_MAX) { 2846 vap->iv_dtim_period = ireq->i_val; 2847 error = ENETRESET; /* requires restart */ 2848 } else 2849 error = EINVAL; 2850 break; 2851 case IEEE80211_IOC_BEACON_INTERVAL: 2852 if (vap->iv_opmode != IEEE80211_M_HOSTAP && 2853 vap->iv_opmode != IEEE80211_M_IBSS) 2854 return EINVAL; 2855 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2856 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2857 ic->ic_bintval = ireq->i_val; 2858 error = ENETRESET; /* requires restart */ 2859 } else 2860 error = EINVAL; 2861 break; 2862 case IEEE80211_IOC_PUREG: 2863 if (ireq->i_val) 2864 vap->iv_flags |= IEEE80211_F_PUREG; 2865 else 2866 vap->iv_flags &= ~IEEE80211_F_PUREG; 2867 /* NB: reset only if we're operating on an 11g channel */ 2868 if (isvap11g(vap)) 2869 error = ENETRESET; 2870 break;
|