1 /*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include "opt_compat.h" 31 32 /* 33 * IEEE 802.11 ioctl support (FreeBSD-specific) 34 */ 35 36 #include "opt_inet.h" 37 #include "opt_ipx.h" 38 39 #include <sys/endian.h> 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/priv.h> 43 #include <sys/socket.h> 44 #include <sys/sockio.h> 45 #include <sys/systm.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 65 #define IS_UP(_ic) \ 66 (((_ic)->ic_ifp->if_flags & IFF_UP) && \ 67 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING)) 68 #define IS_UP_AUTO(_ic) \ 69 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO) 70 #define RESCAN 1 71 72 static struct ieee80211_channel *findchannel(struct ieee80211com *, 73 int ieee, int mode); 74 75 static int 76 cap2cipher(int flag) 77 { 78 switch (flag) { 79 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP; 80 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB; 81 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM; 82 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP; 83 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP; 84 } 85 return -1; 86 } 87 88 static int 89 ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq) 90 { 91 struct ieee80211_node *ni; 92 struct ieee80211req_key ik; 93 struct ieee80211_key *wk; 94 const struct ieee80211_cipher *cip; 95 u_int kid; 96 int error; 97 98 if (ireq->i_len != sizeof(ik)) 99 return EINVAL; 100 error = copyin(ireq->i_data, &ik, sizeof(ik)); 101 if (error) 102 return error; 103 kid = ik.ik_keyix; 104 if (kid == IEEE80211_KEYIX_NONE) { 105 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr); 106 if (ni == NULL) 107 return EINVAL; /* XXX */ 108 wk = &ni->ni_ucastkey; 109 } else { 110 if (kid >= IEEE80211_WEP_NKID) 111 return EINVAL; 112 wk = &ic->ic_nw_keys[kid]; 113 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr); 114 ni = NULL; 115 } 116 cip = wk->wk_cipher; 117 ik.ik_type = cip->ic_cipher; 118 ik.ik_keylen = wk->wk_keylen; 119 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 120 if (wk->wk_keyix == ic->ic_def_txkey) 121 ik.ik_flags |= IEEE80211_KEY_DEFAULT; 122 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 123 /* NB: only root can read key data */ 124 ik.ik_keyrsc = wk->wk_keyrsc; 125 ik.ik_keytsc = wk->wk_keytsc; 126 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen); 127 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) { 128 memcpy(ik.ik_keydata+wk->wk_keylen, 129 wk->wk_key + IEEE80211_KEYBUF_SIZE, 130 IEEE80211_MICBUF_SIZE); 131 ik.ik_keylen += IEEE80211_MICBUF_SIZE; 132 } 133 } else { 134 ik.ik_keyrsc = 0; 135 ik.ik_keytsc = 0; 136 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); 137 } 138 if (ni != NULL) 139 ieee80211_free_node(ni); 140 return copyout(&ik, ireq->i_data, sizeof(ik)); 141 } 142 143 static int 144 ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 145 { 146 147 if (sizeof(ic->ic_chan_active) < ireq->i_len) 148 ireq->i_len = sizeof(ic->ic_chan_active); 149 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 150 } 151 152 static int 153 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) 154 { 155 int space; 156 157 space = __offsetof(struct ieee80211req_chaninfo, 158 ic_chans[ic->ic_nchans]); 159 if (space > ireq->i_len) 160 space = ireq->i_len; 161 /* XXX assumes compatible layout */ 162 return copyout(&ic->ic_nchans, ireq->i_data, space); 163 } 164 165 static int 166 ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req) 167 { 168 struct ieee80211_node *ni; 169 struct ieee80211req_wpaie2 wpaie; 170 int error; 171 172 if (ireq->i_len < IEEE80211_ADDR_LEN) 173 return EINVAL; 174 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 175 if (error != 0) 176 return error; 177 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr); 178 if (ni == NULL) 179 return ENOENT; /* XXX */ 180 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 181 if (ni->ni_wpa_ie != NULL) { 182 int ielen = ni->ni_wpa_ie[1] + 2; 183 if (ielen > sizeof(wpaie.wpa_ie)) 184 ielen = sizeof(wpaie.wpa_ie); 185 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); 186 } 187 if (req == IEEE80211_IOC_WPAIE2) { 188 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie)); 189 if (ni->ni_rsn_ie != NULL) { 190 int ielen = ni->ni_rsn_ie[1] + 2; 191 if (ielen > sizeof(wpaie.rsn_ie)) 192 ielen = sizeof(wpaie.rsn_ie); 193 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen); 194 } 195 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2)) 196 ireq->i_len = sizeof(struct ieee80211req_wpaie2); 197 } else { 198 /* compatibility op, may overwrite wpa ie */ 199 /* XXX check ic_flags? */ 200 if (ni->ni_rsn_ie != NULL) { 201 int ielen = ni->ni_rsn_ie[1] + 2; 202 if (ielen > sizeof(wpaie.wpa_ie)) 203 ielen = sizeof(wpaie.wpa_ie); 204 memcpy(wpaie.wpa_ie, ni->ni_rsn_ie, ielen); 205 } 206 if (ireq->i_len > sizeof(struct ieee80211req_wpaie)) 207 ireq->i_len = sizeof(struct ieee80211req_wpaie); 208 } 209 ieee80211_free_node(ni); 210 return copyout(&wpaie, ireq->i_data, ireq->i_len); 211 } 212 213 static int 214 ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 215 { 216 struct ieee80211_node *ni; 217 uint8_t macaddr[IEEE80211_ADDR_LEN]; 218 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 219 int error; 220 221 if (ireq->i_len < off) 222 return EINVAL; 223 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 224 if (error != 0) 225 return error; 226 ni = ieee80211_find_node(&ic->ic_sta, macaddr); 227 if (ni == NULL) 228 return EINVAL; 229 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 230 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 231 /* NB: copy out only the statistics */ 232 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off, 233 ireq->i_len - off); 234 ieee80211_free_node(ni); 235 return error; 236 } 237 238 static __inline uint8_t * 239 copyie(uint8_t *cp, const uint8_t *ie) 240 { 241 if (ie != NULL) { 242 memcpy(cp, ie, 2+ie[1]); 243 cp += 2+ie[1]; 244 } 245 return cp; 246 } 247 248 #ifdef COMPAT_FREEBSD6 249 #define IEEE80211_IOC_SCAN_RESULTS_OLD 24 250 251 struct scan_result_old { 252 uint16_t isr_len; /* length (mult of 4) */ 253 uint16_t isr_freq; /* MHz */ 254 uint16_t isr_flags; /* channel flags */ 255 uint8_t isr_noise; 256 uint8_t isr_rssi; 257 uint8_t isr_intval; /* beacon interval */ 258 uint8_t isr_capinfo; /* capabilities */ 259 uint8_t isr_erp; /* ERP element */ 260 uint8_t isr_bssid[IEEE80211_ADDR_LEN]; 261 uint8_t isr_nrates; 262 uint8_t isr_rates[IEEE80211_RATE_MAXSIZE]; 263 uint8_t isr_ssid_len; /* SSID length */ 264 uint8_t isr_ie_len; /* IE length */ 265 uint8_t isr_pad[5]; 266 /* variable length SSID followed by IE data */ 267 }; 268 269 struct oscanreq { 270 struct scan_result_old *sr; 271 size_t space; 272 }; 273 274 static size_t 275 old_scan_space(const struct ieee80211_scan_entry *se, int *ielen) 276 { 277 size_t len; 278 279 *ielen = 0; 280 if (se->se_wpa_ie != NULL) 281 *ielen += 2+se->se_wpa_ie[1]; 282 if (se->se_wme_ie != NULL) 283 *ielen += 2+se->se_wme_ie[1]; 284 /* 285 * NB: ie's can be no more than 255 bytes and the max 802.11 286 * packet is <3Kbytes so we are sure this doesn't overflow 287 * 16-bits; if this is a concern we can drop the ie's. 288 */ 289 len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen; 290 return roundup(len, sizeof(uint32_t)); 291 } 292 293 static void 294 old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se) 295 { 296 struct oscanreq *req = arg; 297 int ielen; 298 299 req->space += old_scan_space(se, &ielen); 300 } 301 302 static void 303 old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se) 304 { 305 struct oscanreq *req = arg; 306 struct scan_result_old *sr; 307 int ielen, len, nr, nxr; 308 uint8_t *cp; 309 310 len = old_scan_space(se, &ielen); 311 if (len > req->space) 312 return; 313 314 sr = req->sr; 315 memset(sr, 0, sizeof(*sr)); 316 sr->isr_ssid_len = se->se_ssid[1]; 317 /* NB: beware of overflow, isr_ie_len is 8 bits */ 318 sr->isr_ie_len = (ielen > 255 ? 0 : ielen); 319 sr->isr_len = len; 320 sr->isr_freq = se->se_chan->ic_freq; 321 sr->isr_flags = se->se_chan->ic_flags; 322 sr->isr_rssi = se->se_rssi; 323 sr->isr_noise = se->se_noise; 324 sr->isr_intval = se->se_intval; 325 sr->isr_capinfo = se->se_capinfo; 326 sr->isr_erp = se->se_erp; 327 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 328 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 329 memcpy(sr->isr_rates, se->se_rates+2, nr); 330 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 331 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 332 sr->isr_nrates = nr + nxr; 333 334 cp = (uint8_t *)(sr+1); 335 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 336 cp += sr->isr_ssid_len; 337 if (sr->isr_ie_len) { 338 cp = copyie(cp, se->se_wpa_ie); 339 cp = copyie(cp, se->se_wme_ie); 340 } 341 342 req->space -= len; 343 req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len); 344 } 345 346 static int 347 old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 348 { 349 struct oscanreq req; 350 int error; 351 352 if (ireq->i_len < sizeof(struct scan_result_old)) 353 return EFAULT; 354 355 error = 0; 356 req.space = 0; 357 ieee80211_scan_iterate(ic, old_get_scan_space, &req); 358 if (req.space > ireq->i_len) 359 req.space = ireq->i_len; 360 if (req.space > 0) { 361 size_t space; 362 void *p; 363 364 space = req.space; 365 /* XXX M_WAITOK after driver lock released */ 366 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO); 367 if (p == NULL) 368 return ENOMEM; 369 req.sr = p; 370 ieee80211_scan_iterate(ic, old_get_scan_result, &req); 371 ireq->i_len = space - req.space; 372 error = copyout(p, ireq->i_data, ireq->i_len); 373 FREE(p, M_TEMP); 374 } else 375 ireq->i_len = 0; 376 377 return error; 378 } 379 #endif /* COMPAT_FREEBSD6 */ 380 381 struct scanreq { 382 struct ieee80211req_scan_result *sr; 383 size_t space; 384 }; 385 386 static size_t 387 scan_space(const struct ieee80211_scan_entry *se, int *ielen) 388 { 389 size_t len; 390 391 *ielen = 0; 392 if (se->se_wpa_ie != NULL) 393 *ielen += 2+se->se_wpa_ie[1]; 394 if (se->se_rsn_ie != NULL) 395 *ielen += 2+se->se_rsn_ie[1]; 396 if (se->se_wme_ie != NULL) 397 *ielen += 2+se->se_wme_ie[1]; 398 if (se->se_ath_ie != NULL) 399 *ielen += 2+se->se_ath_ie[1]; 400 /* 401 * NB: ie's can be no more than 255 bytes and the max 802.11 402 * packet is <3Kbytes so we are sure this doesn't overflow 403 * 16-bits; if this is a concern we can drop the ie's. 404 */ 405 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen; 406 return roundup(len, sizeof(uint32_t)); 407 } 408 409 static void 410 get_scan_space(void *arg, const struct ieee80211_scan_entry *se) 411 { 412 struct scanreq *req = arg; 413 int ielen; 414 415 req->space += scan_space(se, &ielen); 416 } 417 418 static void 419 get_scan_result(void *arg, const struct ieee80211_scan_entry *se) 420 { 421 struct scanreq *req = arg; 422 struct ieee80211req_scan_result *sr; 423 int ielen, len, nr, nxr; 424 uint8_t *cp; 425 426 len = scan_space(se, &ielen); 427 if (len > req->space) 428 return; 429 430 sr = req->sr; 431 KASSERT(len <= 65535 && ielen <= 65535, 432 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen)); 433 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result); 434 sr->isr_ie_len = ielen; 435 sr->isr_len = len; 436 sr->isr_freq = se->se_chan->ic_freq; 437 sr->isr_flags = se->se_chan->ic_flags; 438 sr->isr_rssi = se->se_rssi; 439 sr->isr_noise = se->se_noise; 440 sr->isr_intval = se->se_intval; 441 sr->isr_capinfo = se->se_capinfo; 442 sr->isr_erp = se->se_erp; 443 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 444 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 445 memcpy(sr->isr_rates, se->se_rates+2, nr); 446 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 447 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 448 sr->isr_nrates = nr + nxr; 449 450 sr->isr_ssid_len = se->se_ssid[1]; 451 cp = ((uint8_t *)sr) + sr->isr_ie_off; 452 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 453 454 if (ielen) { 455 cp += sr->isr_ssid_len; 456 cp = copyie(cp, se->se_wpa_ie); 457 cp = copyie(cp, se->se_rsn_ie); 458 cp = copyie(cp, se->se_wme_ie); 459 cp = copyie(cp, se->se_ath_ie); 460 cp = copyie(cp, se->se_htcap_ie); 461 } 462 463 req->space -= len; 464 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len); 465 } 466 467 static int 468 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 469 { 470 struct scanreq req; 471 int error; 472 473 if (ireq->i_len < sizeof(struct ieee80211req_scan_result)) 474 return EFAULT; 475 476 error = 0; 477 req.space = 0; 478 ieee80211_scan_iterate(ic, get_scan_space, &req); 479 if (req.space > ireq->i_len) 480 req.space = ireq->i_len; 481 if (req.space > 0) { 482 size_t space; 483 void *p; 484 485 space = req.space; 486 /* XXX M_WAITOK after driver lock released */ 487 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO); 488 if (p == NULL) 489 return ENOMEM; 490 req.sr = p; 491 ieee80211_scan_iterate(ic, get_scan_result, &req); 492 ireq->i_len = space - req.space; 493 error = copyout(p, ireq->i_data, ireq->i_len); 494 FREE(p, M_TEMP); 495 } else 496 ireq->i_len = 0; 497 498 return error; 499 } 500 501 struct stainforeq { 502 struct ieee80211com *ic; 503 struct ieee80211req_sta_info *si; 504 size_t space; 505 }; 506 507 static size_t 508 sta_space(const struct ieee80211_node *ni, size_t *ielen) 509 { 510 *ielen = 0; 511 if (ni->ni_wpa_ie != NULL) 512 *ielen += 2+ni->ni_wpa_ie[1]; 513 if (ni->ni_rsn_ie != NULL) 514 *ielen += 2+ni->ni_rsn_ie[1]; 515 if (ni->ni_wme_ie != NULL) 516 *ielen += 2+ni->ni_wme_ie[1]; 517 if (ni->ni_ath_ie != NULL) 518 *ielen += 2+ni->ni_ath_ie[1]; 519 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, 520 sizeof(uint32_t)); 521 } 522 523 static void 524 get_sta_space(void *arg, struct ieee80211_node *ni) 525 { 526 struct stainforeq *req = arg; 527 struct ieee80211com *ic = ni->ni_ic; 528 size_t ielen; 529 530 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 531 ni->ni_associd == 0) /* only associated stations */ 532 return; 533 req->space += sta_space(ni, &ielen); 534 } 535 536 static void 537 get_sta_info(void *arg, struct ieee80211_node *ni) 538 { 539 struct stainforeq *req = arg; 540 struct ieee80211com *ic = ni->ni_ic; 541 struct ieee80211req_sta_info *si; 542 size_t ielen, len; 543 uint8_t *cp; 544 545 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 546 ni->ni_associd == 0) /* only associated stations */ 547 return; 548 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 549 return; 550 len = sta_space(ni, &ielen); 551 if (len > req->space) 552 return; 553 si = req->si; 554 si->isi_len = len; 555 si->isi_ie_off = sizeof(struct ieee80211req_sta_info); 556 si->isi_ie_len = ielen; 557 si->isi_freq = ni->ni_chan->ic_freq; 558 si->isi_flags = ni->ni_chan->ic_flags; 559 si->isi_state = ni->ni_flags; 560 si->isi_authmode = ni->ni_authmode; 561 ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise); 562 si->isi_noise = 0; /* XXX */ 563 si->isi_capinfo = ni->ni_capinfo; 564 si->isi_erp = ni->ni_erp; 565 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 566 si->isi_nrates = ni->ni_rates.rs_nrates; 567 if (si->isi_nrates > 15) 568 si->isi_nrates = 15; 569 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 570 si->isi_txrate = ni->ni_txrate; 571 si->isi_ie_len = ielen; 572 si->isi_associd = ni->ni_associd; 573 si->isi_txpower = ni->ni_txpower; 574 si->isi_vlan = ni->ni_vlan; 575 if (ni->ni_flags & IEEE80211_NODE_QOS) { 576 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 577 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 578 } else { 579 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID]; 580 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID]; 581 } 582 /* NB: leave all cases in case we relax ni_associd == 0 check */ 583 if (ieee80211_node_is_authorized(ni)) 584 si->isi_inact = ic->ic_inact_run; 585 else if (ni->ni_associd != 0) 586 si->isi_inact = ic->ic_inact_auth; 587 else 588 si->isi_inact = ic->ic_inact_init; 589 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 590 591 if (ielen) { 592 cp = ((uint8_t *)si) + si->isi_ie_off; 593 cp = copyie(cp, ni->ni_wpa_ie); 594 cp = copyie(cp, ni->ni_rsn_ie); 595 cp = copyie(cp, ni->ni_wme_ie); 596 cp = copyie(cp, ni->ni_ath_ie); 597 } 598 599 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len); 600 req->space -= len; 601 } 602 603 static int 604 getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq, 605 struct ieee80211_node *ni, int off) 606 { 607 struct stainforeq req; 608 size_t space; 609 void *p; 610 int error; 611 612 error = 0; 613 req.space = 0; 614 if (ni == NULL) 615 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); 616 else 617 get_sta_space(&req, ni); 618 if (req.space > ireq->i_len) 619 req.space = ireq->i_len; 620 if (req.space > 0) { 621 space = req.space; 622 /* XXX M_WAITOK after driver lock released */ 623 MALLOC(p, void *, space, M_TEMP, M_NOWAIT); 624 if (p == NULL) { 625 error = ENOMEM; 626 goto bad; 627 } 628 req.si = p; 629 if (ni == NULL) 630 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 631 else 632 get_sta_info(&req, ni); 633 ireq->i_len = space - req.space; 634 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len); 635 FREE(p, M_TEMP); 636 } else 637 ireq->i_len = 0; 638 bad: 639 if (ni != NULL) 640 ieee80211_free_node(ni); 641 return error; 642 } 643 644 static int 645 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 646 { 647 uint8_t macaddr[IEEE80211_ADDR_LEN]; 648 const int off = __offsetof(struct ieee80211req_sta_req, info); 649 struct ieee80211_node *ni; 650 int error; 651 652 if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) 653 return EFAULT; 654 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 655 if (error != 0) 656 return error; 657 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) { 658 ni = NULL; 659 } else { 660 ni = ieee80211_find_node(&ic->ic_sta, macaddr); 661 if (ni == NULL) 662 return EINVAL; 663 } 664 return getstainfo_common(ic, ireq, ni, off); 665 } 666 667 #ifdef COMPAT_FREEBSD6 668 #define IEEE80211_IOC_STA_INFO_OLD 45 669 670 static int 671 old_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 672 { 673 if (ireq->i_len < sizeof(struct ieee80211req_sta_info)) 674 return EFAULT; 675 return getstainfo_common(ic, ireq, NULL, 0); 676 } 677 #endif /* COMPAT_FREEBSD6 */ 678 679 static int 680 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 681 { 682 struct ieee80211_node *ni; 683 struct ieee80211req_sta_txpow txpow; 684 int error; 685 686 if (ireq->i_len != sizeof(txpow)) 687 return EINVAL; 688 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 689 if (error != 0) 690 return error; 691 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 692 if (ni == NULL) 693 return EINVAL; /* XXX */ 694 txpow.it_txpow = ni->ni_txpower; 695 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 696 ieee80211_free_node(ni); 697 return error; 698 } 699 700 static int 701 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 702 { 703 struct ieee80211_wme_state *wme = &ic->ic_wme; 704 struct wmeParams *wmep; 705 int ac; 706 707 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 708 return EINVAL; 709 710 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 711 if (ac >= WME_NUM_AC) 712 ac = WME_AC_BE; 713 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 714 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 715 else 716 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 717 switch (ireq->i_type) { 718 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 719 ireq->i_val = wmep->wmep_logcwmin; 720 break; 721 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 722 ireq->i_val = wmep->wmep_logcwmax; 723 break; 724 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 725 ireq->i_val = wmep->wmep_aifsn; 726 break; 727 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 728 ireq->i_val = wmep->wmep_txopLimit; 729 break; 730 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 731 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 732 ireq->i_val = wmep->wmep_acm; 733 break; 734 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 735 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 736 ireq->i_val = !wmep->wmep_noackPolicy; 737 break; 738 } 739 return 0; 740 } 741 742 static int 743 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 744 { 745 const struct ieee80211_aclator *acl = ic->ic_acl; 746 747 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); 748 } 749 750 /* 751 * Return the current ``state'' of an Atheros capbility. 752 * If associated in station mode report the negotiated 753 * setting. Otherwise report the current setting. 754 */ 755 static int 756 getathcap(struct ieee80211com *ic, int cap) 757 { 758 if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN) 759 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0; 760 else 761 return (ic->ic_flags & cap) != 0; 762 } 763 764 static int 765 ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq) 766 { 767 if (ireq->i_len != sizeof(struct ieee80211_channel)) 768 return EINVAL; 769 return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan)); 770 } 771 772 /* 773 * When building the kernel with -O2 on the i386 architecture, gcc 774 * seems to want to inline this function into ieee80211_ioctl() 775 * (which is the only routine that calls it). When this happens, 776 * ieee80211_ioctl() ends up consuming an additional 2K of stack 777 * space. (Exactly why it needs so much is unclear.) The problem 778 * is that it's possible for ieee80211_ioctl() to invoke other 779 * routines (including driver init functions) which could then find 780 * themselves perilously close to exhausting the stack. 781 * 782 * To avoid this, we deliberately prevent gcc from inlining this 783 * routine. Another way to avoid this is to use less agressive 784 * optimization when compiling this file (i.e. -O instead of -O2) 785 * but special-casing the compilation of this one module in the 786 * build system would be awkward. 787 */ 788 #ifdef __GNUC__ 789 __attribute__ ((noinline)) 790 #endif 791 static int 792 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 793 { 794 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 795 int error = 0; 796 u_int kid, len, m; 797 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 798 char tmpssid[IEEE80211_NWID_LEN]; 799 800 switch (ireq->i_type) { 801 case IEEE80211_IOC_SSID: 802 switch (ic->ic_state) { 803 case IEEE80211_S_INIT: 804 case IEEE80211_S_SCAN: 805 ireq->i_len = ic->ic_des_ssid[0].len; 806 memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len); 807 break; 808 default: 809 ireq->i_len = ic->ic_bss->ni_esslen; 810 memcpy(tmpssid, ic->ic_bss->ni_essid, 811 ireq->i_len); 812 break; 813 } 814 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 815 break; 816 case IEEE80211_IOC_NUMSSIDS: 817 ireq->i_val = 1; 818 break; 819 case IEEE80211_IOC_WEP: 820 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 821 ireq->i_val = IEEE80211_WEP_OFF; 822 else if (ic->ic_flags & IEEE80211_F_DROPUNENC) 823 ireq->i_val = IEEE80211_WEP_ON; 824 else 825 ireq->i_val = IEEE80211_WEP_MIXED; 826 break; 827 case IEEE80211_IOC_WEPKEY: 828 kid = (u_int) ireq->i_val; 829 if (kid >= IEEE80211_WEP_NKID) 830 return EINVAL; 831 len = (u_int) ic->ic_nw_keys[kid].wk_keylen; 832 /* NB: only root can read WEP keys */ 833 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { 834 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); 835 } else { 836 bzero(tmpkey, len); 837 } 838 ireq->i_len = len; 839 error = copyout(tmpkey, ireq->i_data, len); 840 break; 841 case IEEE80211_IOC_NUMWEPKEYS: 842 ireq->i_val = IEEE80211_WEP_NKID; 843 break; 844 case IEEE80211_IOC_WEPTXKEY: 845 ireq->i_val = ic->ic_def_txkey; 846 break; 847 case IEEE80211_IOC_AUTHMODE: 848 if (ic->ic_flags & IEEE80211_F_WPA) 849 ireq->i_val = IEEE80211_AUTH_WPA; 850 else 851 ireq->i_val = ic->ic_bss->ni_authmode; 852 break; 853 case IEEE80211_IOC_CHANNEL: 854 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan); 855 break; 856 case IEEE80211_IOC_POWERSAVE: 857 if (ic->ic_flags & IEEE80211_F_PMGTON) 858 ireq->i_val = IEEE80211_POWERSAVE_ON; 859 else 860 ireq->i_val = IEEE80211_POWERSAVE_OFF; 861 break; 862 case IEEE80211_IOC_POWERSAVESLEEP: 863 ireq->i_val = ic->ic_lintval; 864 break; 865 case IEEE80211_IOC_RTSTHRESHOLD: 866 ireq->i_val = ic->ic_rtsthreshold; 867 break; 868 case IEEE80211_IOC_PROTMODE: 869 ireq->i_val = ic->ic_protmode; 870 break; 871 case IEEE80211_IOC_TXPOWER: 872 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 873 return EINVAL; 874 ireq->i_val = ic->ic_txpowlimit; 875 break; 876 case IEEE80211_IOC_MCASTCIPHER: 877 ireq->i_val = rsn->rsn_mcastcipher; 878 break; 879 case IEEE80211_IOC_MCASTKEYLEN: 880 ireq->i_val = rsn->rsn_mcastkeylen; 881 break; 882 case IEEE80211_IOC_UCASTCIPHERS: 883 ireq->i_val = 0; 884 for (m = 0x1; m != 0; m <<= 1) 885 if (rsn->rsn_ucastcipherset & m) 886 ireq->i_val |= 1<<cap2cipher(m); 887 break; 888 case IEEE80211_IOC_UCASTCIPHER: 889 ireq->i_val = rsn->rsn_ucastcipher; 890 break; 891 case IEEE80211_IOC_UCASTKEYLEN: 892 ireq->i_val = rsn->rsn_ucastkeylen; 893 break; 894 case IEEE80211_IOC_KEYMGTALGS: 895 ireq->i_val = rsn->rsn_keymgmtset; 896 break; 897 case IEEE80211_IOC_RSNCAPS: 898 ireq->i_val = rsn->rsn_caps; 899 break; 900 case IEEE80211_IOC_WPA: 901 switch (ic->ic_flags & IEEE80211_F_WPA) { 902 case IEEE80211_F_WPA1: 903 ireq->i_val = 1; 904 break; 905 case IEEE80211_F_WPA2: 906 ireq->i_val = 2; 907 break; 908 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2: 909 ireq->i_val = 3; 910 break; 911 default: 912 ireq->i_val = 0; 913 break; 914 } 915 break; 916 case IEEE80211_IOC_CHANLIST: 917 error = ieee80211_ioctl_getchanlist(ic, ireq); 918 break; 919 case IEEE80211_IOC_ROAMING: 920 ireq->i_val = ic->ic_roaming; 921 break; 922 case IEEE80211_IOC_PRIVACY: 923 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0; 924 break; 925 case IEEE80211_IOC_DROPUNENCRYPTED: 926 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0; 927 break; 928 case IEEE80211_IOC_COUNTERMEASURES: 929 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0; 930 break; 931 case IEEE80211_IOC_DRIVER_CAPS: 932 ireq->i_val = ic->ic_caps>>16; 933 ireq->i_len = ic->ic_caps&0xffff; 934 break; 935 case IEEE80211_IOC_WME: 936 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0; 937 break; 938 case IEEE80211_IOC_HIDESSID: 939 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0; 940 break; 941 case IEEE80211_IOC_APBRIDGE: 942 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0; 943 break; 944 case IEEE80211_IOC_OPTIE: 945 if (ic->ic_opt_ie == NULL) 946 return EINVAL; 947 /* NB: truncate, caller can check length */ 948 if (ireq->i_len > ic->ic_opt_ie_len) 949 ireq->i_len = ic->ic_opt_ie_len; 950 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len); 951 break; 952 case IEEE80211_IOC_WPAKEY: 953 error = ieee80211_ioctl_getkey(ic, ireq); 954 break; 955 case IEEE80211_IOC_CHANINFO: 956 error = ieee80211_ioctl_getchaninfo(ic, ireq); 957 break; 958 case IEEE80211_IOC_BSSID: 959 if (ireq->i_len != IEEE80211_ADDR_LEN) 960 return EINVAL; 961 error = copyout(ic->ic_state == IEEE80211_S_RUN ? 962 ic->ic_bss->ni_bssid : 963 ic->ic_des_bssid, 964 ireq->i_data, ireq->i_len); 965 break; 966 case IEEE80211_IOC_WPAIE: 967 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type); 968 break; 969 case IEEE80211_IOC_WPAIE2: 970 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type); 971 break; 972 #ifdef COMPAT_FREEBSD6 973 case IEEE80211_IOC_SCAN_RESULTS_OLD: 974 error = old_getscanresults(ic, ireq); 975 break; 976 #endif 977 case IEEE80211_IOC_SCAN_RESULTS: 978 error = ieee80211_ioctl_getscanresults(ic, ireq); 979 break; 980 case IEEE80211_IOC_STA_STATS: 981 error = ieee80211_ioctl_getstastats(ic, ireq); 982 break; 983 case IEEE80211_IOC_TXPOWMAX: 984 ireq->i_val = ic->ic_bss->ni_txpower; 985 break; 986 case IEEE80211_IOC_STA_TXPOW: 987 error = ieee80211_ioctl_getstatxpow(ic, ireq); 988 break; 989 #ifdef COMPAT_FREEBSD6 990 case IEEE80211_IOC_STA_INFO_OLD: 991 error = old_getstainfo(ic, ireq); 992 break; 993 #endif 994 case IEEE80211_IOC_STA_INFO: 995 error = ieee80211_ioctl_getstainfo(ic, ireq); 996 break; 997 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 998 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 999 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1000 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1001 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1002 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 1003 error = ieee80211_ioctl_getwmeparam(ic, ireq); 1004 break; 1005 case IEEE80211_IOC_DTIM_PERIOD: 1006 ireq->i_val = ic->ic_dtim_period; 1007 break; 1008 case IEEE80211_IOC_BEACON_INTERVAL: 1009 /* NB: get from ic_bss for station mode */ 1010 ireq->i_val = ic->ic_bss->ni_intval; 1011 break; 1012 case IEEE80211_IOC_PUREG: 1013 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0; 1014 break; 1015 case IEEE80211_IOC_FF: 1016 ireq->i_val = getathcap(ic, IEEE80211_F_FF); 1017 break; 1018 case IEEE80211_IOC_TURBOP: 1019 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP); 1020 break; 1021 case IEEE80211_IOC_BGSCAN: 1022 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0; 1023 break; 1024 case IEEE80211_IOC_BGSCAN_IDLE: 1025 ireq->i_val = ic->ic_bgscanidle*hz/1000; /* ms */ 1026 break; 1027 case IEEE80211_IOC_BGSCAN_INTERVAL: 1028 ireq->i_val = ic->ic_bgscanintvl/hz; /* seconds */ 1029 break; 1030 case IEEE80211_IOC_SCANVALID: 1031 ireq->i_val = ic->ic_scanvalid/hz; /* seconds */ 1032 break; 1033 case IEEE80211_IOC_ROAM_RSSI_11A: 1034 ireq->i_val = ic->ic_roam.rssi11a; 1035 break; 1036 case IEEE80211_IOC_ROAM_RSSI_11B: 1037 ireq->i_val = ic->ic_roam.rssi11bOnly; 1038 break; 1039 case IEEE80211_IOC_ROAM_RSSI_11G: 1040 ireq->i_val = ic->ic_roam.rssi11b; 1041 break; 1042 case IEEE80211_IOC_ROAM_RATE_11A: 1043 ireq->i_val = ic->ic_roam.rate11a; 1044 break; 1045 case IEEE80211_IOC_ROAM_RATE_11B: 1046 ireq->i_val = ic->ic_roam.rate11bOnly; 1047 break; 1048 case IEEE80211_IOC_ROAM_RATE_11G: 1049 ireq->i_val = ic->ic_roam.rate11b; 1050 break; 1051 case IEEE80211_IOC_MCAST_RATE: 1052 ireq->i_val = ic->ic_mcast_rate; 1053 break; 1054 case IEEE80211_IOC_FRAGTHRESHOLD: 1055 ireq->i_val = ic->ic_fragthreshold; 1056 break; 1057 case IEEE80211_IOC_MACCMD: 1058 error = ieee80211_ioctl_getmaccmd(ic, ireq); 1059 break; 1060 case IEEE80211_IOC_BURST: 1061 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0; 1062 break; 1063 case IEEE80211_IOC_BMISSTHRESHOLD: 1064 ireq->i_val = ic->ic_bmissthreshold; 1065 break; 1066 case IEEE80211_IOC_CURCHAN: 1067 error = ieee80211_ioctl_getcurchan(ic, ireq); 1068 break; 1069 case IEEE80211_IOC_SHORTGI: 1070 ireq->i_val = 0; 1071 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20) 1072 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20; 1073 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40) 1074 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40; 1075 break; 1076 case IEEE80211_IOC_AMPDU: 1077 ireq->i_val = 0; 1078 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX) 1079 ireq->i_val |= 1; 1080 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX) 1081 ireq->i_val |= 2; 1082 break; 1083 case IEEE80211_IOC_AMPDU_LIMIT: 1084 ireq->i_val = ic->ic_ampdu_limit; /* XXX truncation? */ 1085 break; 1086 case IEEE80211_IOC_AMPDU_DENSITY: 1087 ireq->i_val = ic->ic_ampdu_density; 1088 break; 1089 case IEEE80211_IOC_AMSDU: 1090 ireq->i_val = 0; 1091 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX) 1092 ireq->i_val |= 1; 1093 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX) 1094 ireq->i_val |= 2; 1095 break; 1096 case IEEE80211_IOC_AMSDU_LIMIT: 1097 ireq->i_val = ic->ic_amsdu_limit; /* XXX truncation? */ 1098 break; 1099 case IEEE80211_IOC_PUREN: 1100 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0; 1101 break; 1102 case IEEE80211_IOC_DOTH: 1103 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0; 1104 break; 1105 case IEEE80211_IOC_HTCOMPAT: 1106 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0; 1107 break; 1108 case IEEE80211_IOC_INACTIVITY: 1109 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_INACT) != 0; 1110 break; 1111 case IEEE80211_IOC_HTPROTMODE: 1112 ireq->i_val = ic->ic_htprotmode; 1113 break; 1114 case IEEE80211_IOC_HTCONF: 1115 if (ic->ic_flags_ext & IEEE80211_FEXT_HT) { 1116 ireq->i_val = 1; 1117 if (ic->ic_flags_ext & IEEE80211_FEXT_USEHT40) 1118 ireq->i_val |= 2; 1119 } else 1120 ireq->i_val = 0; 1121 break; 1122 default: 1123 error = EINVAL; 1124 break; 1125 } 1126 return error; 1127 } 1128 1129 static int 1130 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq) 1131 { 1132 int error; 1133 void *ie, *oie; 1134 1135 /* 1136 * NB: Doing this for ap operation could be useful (e.g. for 1137 * WPA and/or WME) except that it typically is worthless 1138 * without being able to intervene when processing 1139 * association response frames--so disallow it for now. 1140 */ 1141 if (ic->ic_opmode != IEEE80211_M_STA) 1142 return EINVAL; 1143 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1144 return EINVAL; 1145 /* NB: data.length is validated by the wireless extensions code */ 1146 /* XXX M_WAITOK after driver lock released */ 1147 if (ireq->i_len > 0) { 1148 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT); 1149 if (ie == NULL) 1150 return ENOMEM; 1151 error = copyin(ireq->i_data, ie, ireq->i_len); 1152 if (error) { 1153 FREE(ie, M_DEVBUF); 1154 return error; 1155 } 1156 } else { 1157 ie = NULL; 1158 ireq->i_len = 0; 1159 } 1160 /* XXX sanity check data? */ 1161 oie = ic->ic_opt_ie; 1162 ic->ic_opt_ie = ie; 1163 ic->ic_opt_ie_len = ireq->i_len; 1164 if (oie != NULL) 1165 FREE(oie, M_DEVBUF); 1166 return 0; 1167 } 1168 1169 static int 1170 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1171 { 1172 struct ieee80211req_key ik; 1173 struct ieee80211_node *ni; 1174 struct ieee80211_key *wk; 1175 uint16_t kid; 1176 int error; 1177 1178 if (ireq->i_len != sizeof(ik)) 1179 return EINVAL; 1180 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1181 if (error) 1182 return error; 1183 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1184 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1185 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1186 return E2BIG; 1187 kid = ik.ik_keyix; 1188 if (kid == IEEE80211_KEYIX_NONE) { 1189 /* XXX unicast keys currently must be tx/rx */ 1190 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1191 return EINVAL; 1192 if (ic->ic_opmode == IEEE80211_M_STA) { 1193 ni = ieee80211_ref_node(ic->ic_bss); 1194 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) { 1195 ieee80211_free_node(ni); 1196 return EADDRNOTAVAIL; 1197 } 1198 } else { 1199 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr); 1200 if (ni == NULL) 1201 return ENOENT; 1202 } 1203 wk = &ni->ni_ucastkey; 1204 } else { 1205 if (kid >= IEEE80211_WEP_NKID) 1206 return EINVAL; 1207 wk = &ic->ic_nw_keys[kid]; 1208 /* 1209 * Global slots start off w/o any assigned key index. 1210 * Force one here for consistency with IEEE80211_IOC_WEPKEY. 1211 */ 1212 if (wk->wk_keyix == IEEE80211_KEYIX_NONE) 1213 wk->wk_keyix = kid; 1214 ni = NULL; 1215 } 1216 error = 0; 1217 ieee80211_key_update_begin(ic); 1218 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) { 1219 wk->wk_keylen = ik.ik_keylen; 1220 /* NB: MIC presence is implied by cipher type */ 1221 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1222 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1223 wk->wk_keyrsc = ik.ik_keyrsc; 1224 wk->wk_keytsc = 0; /* new key, reset */ 1225 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1226 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1227 if (!ieee80211_crypto_setkey(ic, wk, 1228 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr)) 1229 error = EIO; 1230 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1231 ic->ic_def_txkey = kid; 1232 } else 1233 error = ENXIO; 1234 ieee80211_key_update_end(ic); 1235 if (ni != NULL) 1236 ieee80211_free_node(ni); 1237 return error; 1238 } 1239 1240 static int 1241 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1242 { 1243 struct ieee80211req_del_key dk; 1244 int kid, error; 1245 1246 if (ireq->i_len != sizeof(dk)) 1247 return EINVAL; 1248 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1249 if (error) 1250 return error; 1251 kid = dk.idk_keyix; 1252 /* XXX uint8_t -> uint16_t */ 1253 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) { 1254 struct ieee80211_node *ni; 1255 1256 if (ic->ic_opmode == IEEE80211_M_STA) { 1257 ni = ieee80211_ref_node(ic->ic_bss); 1258 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1259 ieee80211_free_node(ni); 1260 return EADDRNOTAVAIL; 1261 } 1262 } else { 1263 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr); 1264 if (ni == NULL) 1265 return ENOENT; 1266 } 1267 /* XXX error return */ 1268 ieee80211_node_delucastkey(ni); 1269 ieee80211_free_node(ni); 1270 } else { 1271 if (kid >= IEEE80211_WEP_NKID) 1272 return EINVAL; 1273 /* XXX error return */ 1274 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]); 1275 } 1276 return 0; 1277 } 1278 1279 static void 1280 domlme(void *arg, struct ieee80211_node *ni) 1281 { 1282 struct ieee80211com *ic = ni->ni_ic; 1283 struct ieee80211req_mlme *mlme = arg; 1284 1285 if (ni->ni_associd != 0) { 1286 IEEE80211_SEND_MGMT(ic, ni, 1287 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1288 IEEE80211_FC0_SUBTYPE_DEAUTH : 1289 IEEE80211_FC0_SUBTYPE_DISASSOC, 1290 mlme->im_reason); 1291 } 1292 ieee80211_node_leave(ic, ni); 1293 } 1294 1295 struct scanlookup { 1296 const uint8_t *mac; 1297 int esslen; 1298 const uint8_t *essid; 1299 const struct ieee80211_scan_entry *se; 1300 }; 1301 1302 /* 1303 * Match mac address and any ssid. 1304 */ 1305 static void 1306 mlmelookup(void *arg, const struct ieee80211_scan_entry *se) 1307 { 1308 struct scanlookup *look = arg; 1309 1310 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) 1311 return; 1312 if (look->esslen != 0) { 1313 if (se->se_ssid[1] != look->esslen) 1314 return; 1315 if (memcmp(look->essid, se->se_ssid+2, look->esslen)) 1316 return; 1317 } 1318 look->se = se; 1319 } 1320 1321 static int 1322 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1323 { 1324 struct ieee80211req_mlme mlme; 1325 struct ieee80211_node *ni; 1326 int error; 1327 1328 if (ireq->i_len != sizeof(mlme)) 1329 return EINVAL; 1330 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1331 if (error) 1332 return error; 1333 switch (mlme.im_op) { 1334 case IEEE80211_MLME_ASSOC: 1335 /* XXX ibss/ahdemo */ 1336 if (ic->ic_opmode == IEEE80211_M_STA) { 1337 struct scanlookup lookup; 1338 1339 lookup.se = NULL; 1340 lookup.mac = mlme.im_macaddr; 1341 /* XXX use revised api w/ explicit ssid */ 1342 lookup.esslen = ic->ic_des_ssid[0].len; 1343 lookup.essid = ic->ic_des_ssid[0].ssid; 1344 ieee80211_scan_iterate(ic, mlmelookup, &lookup); 1345 if (lookup.se != NULL && 1346 ieee80211_sta_join(ic, lookup.se)) 1347 return 0; 1348 } 1349 return EINVAL; 1350 case IEEE80211_MLME_DISASSOC: 1351 case IEEE80211_MLME_DEAUTH: 1352 switch (ic->ic_opmode) { 1353 case IEEE80211_M_STA: 1354 /* XXX not quite right */ 1355 ieee80211_new_state(ic, IEEE80211_S_INIT, 1356 mlme.im_reason); 1357 break; 1358 case IEEE80211_M_HOSTAP: 1359 /* NB: the broadcast address means do 'em all */ 1360 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) { 1361 if ((ni = ieee80211_find_node(&ic->ic_sta, 1362 mlme.im_macaddr)) == NULL) 1363 return EINVAL; 1364 domlme(&mlme, ni); 1365 ieee80211_free_node(ni); 1366 } else { 1367 ieee80211_iterate_nodes(&ic->ic_sta, 1368 domlme, &mlme); 1369 } 1370 break; 1371 default: 1372 return EINVAL; 1373 } 1374 break; 1375 case IEEE80211_MLME_AUTHORIZE: 1376 case IEEE80211_MLME_UNAUTHORIZE: 1377 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1378 return EINVAL; 1379 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr); 1380 if (ni == NULL) 1381 return EINVAL; 1382 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE) 1383 ieee80211_node_authorize(ni); 1384 else 1385 ieee80211_node_unauthorize(ni); 1386 ieee80211_free_node(ni); 1387 break; 1388 default: 1389 return EINVAL; 1390 } 1391 return 0; 1392 } 1393 1394 static int 1395 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1396 { 1397 uint8_t mac[IEEE80211_ADDR_LEN]; 1398 const struct ieee80211_aclator *acl = ic->ic_acl; 1399 int error; 1400 1401 if (ireq->i_len != sizeof(mac)) 1402 return EINVAL; 1403 error = copyin(ireq->i_data, mac, ireq->i_len); 1404 if (error) 1405 return error; 1406 if (acl == NULL) { 1407 acl = ieee80211_aclator_get("mac"); 1408 if (acl == NULL || !acl->iac_attach(ic)) 1409 return EINVAL; 1410 ic->ic_acl = acl; 1411 } 1412 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1413 acl->iac_add(ic, mac); 1414 else 1415 acl->iac_remove(ic, mac); 1416 return 0; 1417 } 1418 1419 static int 1420 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1421 { 1422 const struct ieee80211_aclator *acl = ic->ic_acl; 1423 1424 switch (ireq->i_val) { 1425 case IEEE80211_MACCMD_POLICY_OPEN: 1426 case IEEE80211_MACCMD_POLICY_ALLOW: 1427 case IEEE80211_MACCMD_POLICY_DENY: 1428 if (acl == NULL) { 1429 acl = ieee80211_aclator_get("mac"); 1430 if (acl == NULL || !acl->iac_attach(ic)) 1431 return EINVAL; 1432 ic->ic_acl = acl; 1433 } 1434 acl->iac_setpolicy(ic, ireq->i_val); 1435 break; 1436 case IEEE80211_MACCMD_FLUSH: 1437 if (acl != NULL) 1438 acl->iac_flush(ic); 1439 /* NB: silently ignore when not in use */ 1440 break; 1441 case IEEE80211_MACCMD_DETACH: 1442 if (acl != NULL) { 1443 ic->ic_acl = NULL; 1444 acl->iac_detach(ic); 1445 } 1446 break; 1447 default: 1448 if (acl == NULL) 1449 return EINVAL; 1450 else 1451 return acl->iac_setioctl(ic, ireq); 1452 } 1453 return 0; 1454 } 1455 1456 static int 1457 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 1458 { 1459 struct ieee80211req_chanlist list; 1460 u_char chanlist[IEEE80211_CHAN_BYTES]; 1461 int i, j, nchan, error; 1462 1463 if (ireq->i_len != sizeof(list)) 1464 return EINVAL; 1465 error = copyin(ireq->i_data, &list, sizeof(list)); 1466 if (error) 1467 return error; 1468 memset(chanlist, 0, sizeof(chanlist)); 1469 /* 1470 * Since channel 0 is not available for DS, channel 1 1471 * is assigned to LSB on WaveLAN. 1472 */ 1473 if (ic->ic_phytype == IEEE80211_T_DS) 1474 i = 1; 1475 else 1476 i = 0; 1477 nchan = 0; 1478 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 1479 /* 1480 * NB: silently discard unavailable channels so users 1481 * can specify 1-255 to get all available channels. 1482 */ 1483 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) { 1484 setbit(chanlist, i); 1485 nchan++; 1486 } 1487 } 1488 if (nchan == 0) 1489 return EINVAL; 1490 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ 1491 isclr(chanlist, ic->ic_bsschan->ic_ieee)) 1492 ic->ic_bsschan = IEEE80211_CHAN_ANYC; 1493 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 1494 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0; 1495 } 1496 1497 static int 1498 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 1499 { 1500 struct ieee80211_node *ni; 1501 uint8_t macaddr[IEEE80211_ADDR_LEN]; 1502 int error; 1503 1504 /* 1505 * NB: we could copyin ieee80211req_sta_stats so apps 1506 * could make selective changes but that's overkill; 1507 * just clear all stats for now. 1508 */ 1509 if (ireq->i_len < IEEE80211_ADDR_LEN) 1510 return EINVAL; 1511 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1512 if (error != 0) 1513 return error; 1514 ni = ieee80211_find_node(&ic->ic_sta, macaddr); 1515 if (ni == NULL) 1516 return EINVAL; /* XXX */ 1517 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats)); 1518 ieee80211_free_node(ni); 1519 return 0; 1520 } 1521 1522 static int 1523 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1524 { 1525 struct ieee80211_node *ni; 1526 struct ieee80211req_sta_txpow txpow; 1527 int error; 1528 1529 if (ireq->i_len != sizeof(txpow)) 1530 return EINVAL; 1531 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1532 if (error != 0) 1533 return error; 1534 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 1535 if (ni == NULL) 1536 return EINVAL; /* XXX */ 1537 ni->ni_txpower = txpow.it_txpow; 1538 ieee80211_free_node(ni); 1539 return error; 1540 } 1541 1542 static int 1543 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1544 { 1545 struct ieee80211_wme_state *wme = &ic->ic_wme; 1546 struct wmeParams *wmep, *chanp; 1547 int isbss, ac; 1548 1549 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1550 return EINVAL; 1551 1552 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1553 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1554 if (ac >= WME_NUM_AC) 1555 ac = WME_AC_BE; 1556 if (isbss) { 1557 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1558 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1559 } else { 1560 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1561 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1562 } 1563 switch (ireq->i_type) { 1564 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1565 if (isbss) { 1566 wmep->wmep_logcwmin = ireq->i_val; 1567 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1568 chanp->wmep_logcwmin = ireq->i_val; 1569 } else { 1570 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1571 ireq->i_val; 1572 } 1573 break; 1574 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1575 if (isbss) { 1576 wmep->wmep_logcwmax = ireq->i_val; 1577 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1578 chanp->wmep_logcwmax = ireq->i_val; 1579 } else { 1580 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1581 ireq->i_val; 1582 } 1583 break; 1584 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1585 if (isbss) { 1586 wmep->wmep_aifsn = ireq->i_val; 1587 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1588 chanp->wmep_aifsn = ireq->i_val; 1589 } else { 1590 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1591 } 1592 break; 1593 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1594 if (isbss) { 1595 wmep->wmep_txopLimit = ireq->i_val; 1596 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1597 chanp->wmep_txopLimit = ireq->i_val; 1598 } else { 1599 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1600 ireq->i_val; 1601 } 1602 break; 1603 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1604 wmep->wmep_acm = ireq->i_val; 1605 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1606 chanp->wmep_acm = ireq->i_val; 1607 break; 1608 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1609 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1610 (ireq->i_val) == 0; 1611 break; 1612 } 1613 ieee80211_wme_updateparams(ic); 1614 return 0; 1615 } 1616 1617 static int 1618 cipher2cap(int cipher) 1619 { 1620 switch (cipher) { 1621 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP; 1622 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES; 1623 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 1624 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 1625 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 1626 } 1627 return 0; 1628 } 1629 1630 static int 1631 find11gchannel(struct ieee80211com *ic, int start, int freq) 1632 { 1633 const struct ieee80211_channel *c; 1634 int i; 1635 1636 for (i = start+1; i < ic->ic_nchans; i++) { 1637 c = &ic->ic_channels[i]; 1638 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1639 return 1; 1640 } 1641 /* NB: should not be needed but in case things are mis-sorted */ 1642 for (i = 0; i < start; i++) { 1643 c = &ic->ic_channels[i]; 1644 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1645 return 1; 1646 } 1647 return 0; 1648 } 1649 1650 static struct ieee80211_channel * 1651 findchannel(struct ieee80211com *ic, int ieee, int mode) 1652 { 1653 static const u_int chanflags[IEEE80211_MODE_MAX] = { 1654 0, /* IEEE80211_MODE_AUTO */ 1655 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 1656 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 1657 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */ 1658 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 1659 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ 1660 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 1661 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */ 1662 /* NB: handled specially below */ 1663 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */ 1664 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */ 1665 }; 1666 u_int modeflags; 1667 int i; 1668 1669 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode)); 1670 modeflags = chanflags[mode]; 1671 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO, 1672 ("no chanflags for mode %u", mode)); 1673 for (i = 0; i < ic->ic_nchans; i++) { 1674 struct ieee80211_channel *c = &ic->ic_channels[i]; 1675 1676 if (c->ic_ieee != ieee) 1677 continue; 1678 if (mode == IEEE80211_MODE_AUTO) { 1679 /* ignore turbo channels for autoselect */ 1680 if (IEEE80211_IS_CHAN_TURBO(c)) 1681 continue; 1682 /* 1683 * XXX special-case 11b/g channels so we 1684 * always select the g channel if both 1685 * are present. 1686 * XXX prefer HT to non-HT? 1687 */ 1688 if (!IEEE80211_IS_CHAN_B(c) || 1689 !find11gchannel(ic, i, c->ic_freq)) 1690 return c; 1691 } else { 1692 /* must check HT specially */ 1693 if ((mode == IEEE80211_MODE_11NA || 1694 mode == IEEE80211_MODE_11NG) && 1695 !IEEE80211_IS_CHAN_HT(c)) 1696 continue; 1697 if ((c->ic_flags & modeflags) == modeflags) 1698 return c; 1699 } 1700 } 1701 return NULL; 1702 } 1703 1704 /* 1705 * Check the specified against any desired mode (aka netband). 1706 * This is only used (presently) when operating in hostap mode 1707 * to enforce consistency. 1708 */ 1709 static int 1710 check_mode_consistency(const struct ieee80211_channel *c, int mode) 1711 { 1712 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel")); 1713 1714 switch (mode) { 1715 case IEEE80211_MODE_11B: 1716 return (IEEE80211_IS_CHAN_B(c)); 1717 case IEEE80211_MODE_11G: 1718 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c)); 1719 case IEEE80211_MODE_11A: 1720 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c)); 1721 case IEEE80211_MODE_STURBO_A: 1722 return (IEEE80211_IS_CHAN_STURBO(c)); 1723 case IEEE80211_MODE_11NA: 1724 return (IEEE80211_IS_CHAN_HTA(c)); 1725 case IEEE80211_MODE_11NG: 1726 return (IEEE80211_IS_CHAN_HTG(c)); 1727 } 1728 return 1; 1729 1730 } 1731 1732 /* 1733 * Common code to set the current channel. If the device 1734 * is up and running this may result in an immediate channel 1735 * change or a kick of the state machine. 1736 */ 1737 static int 1738 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) 1739 { 1740 int error; 1741 1742 if (c != IEEE80211_CHAN_ANYC) { 1743 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1744 !check_mode_consistency(c, ic->ic_des_mode)) 1745 return EINVAL; 1746 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan) 1747 return 0; /* NB: nothing to do */ 1748 } 1749 ic->ic_des_chan = c; 1750 1751 error = 0; 1752 if ((ic->ic_opmode == IEEE80211_M_MONITOR || 1753 ic->ic_opmode == IEEE80211_M_WDS) && 1754 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1755 /* 1756 * Monitor and wds modes can switch directly. 1757 */ 1758 ic->ic_curchan = ic->ic_des_chan; 1759 if (ic->ic_state == IEEE80211_S_RUN) 1760 ic->ic_set_channel(ic); 1761 } else { 1762 /* 1763 * Need to go through the state machine in case we 1764 * need to reassociate or the like. The state machine 1765 * will pickup the desired channel and avoid scanning. 1766 */ 1767 if (IS_UP_AUTO(ic)) 1768 error = ieee80211_init(ic, RESCAN); 1769 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1770 /* 1771 * When not up+running and a real channel has 1772 * been specified fix the current channel so 1773 * there is immediate feedback; e.g. via ifconfig. 1774 */ 1775 ic->ic_curchan = ic->ic_des_chan; 1776 } 1777 } 1778 return error; 1779 } 1780 1781 /* 1782 * Old api for setting the current channel; this is 1783 * deprecated because channel numbers are ambiguous. 1784 */ 1785 static int 1786 ieee80211_ioctl_setchannel(struct ieee80211com *ic, 1787 const struct ieee80211req *ireq) 1788 { 1789 struct ieee80211_channel *c; 1790 1791 /* XXX 0xffff overflows 16-bit signed */ 1792 if (ireq->i_val == 0 || 1793 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) { 1794 c = IEEE80211_CHAN_ANYC; 1795 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) { 1796 return EINVAL; 1797 } else { 1798 struct ieee80211_channel *c2; 1799 1800 c = findchannel(ic, ireq->i_val, ic->ic_des_mode); 1801 if (c == NULL) { 1802 c = findchannel(ic, ireq->i_val, 1803 IEEE80211_MODE_AUTO); 1804 if (c == NULL) 1805 return EINVAL; 1806 } 1807 /* 1808 * Fine tune channel selection based on desired mode: 1809 * if 11b is requested, find the 11b version of any 1810 * 11g channel returned, 1811 * if static turbo, find the turbo version of any 1812 * 11a channel return, 1813 * if 11na is requested, find the ht version of any 1814 * 11a channel returned, 1815 * if 11ng is requested, find the ht version of any 1816 * 11g channel returned, 1817 * otherwise we should be ok with what we've got. 1818 */ 1819 switch (ic->ic_des_mode) { 1820 case IEEE80211_MODE_11B: 1821 if (IEEE80211_IS_CHAN_ANYG(c)) { 1822 c2 = findchannel(ic, ireq->i_val, 1823 IEEE80211_MODE_11B); 1824 /* NB: should not happen, =>'s 11g w/o 11b */ 1825 if (c2 != NULL) 1826 c = c2; 1827 } 1828 break; 1829 case IEEE80211_MODE_TURBO_A: 1830 if (IEEE80211_IS_CHAN_A(c)) { 1831 c2 = findchannel(ic, ireq->i_val, 1832 IEEE80211_MODE_TURBO_A); 1833 if (c2 != NULL) 1834 c = c2; 1835 } 1836 break; 1837 case IEEE80211_MODE_11NA: 1838 if (IEEE80211_IS_CHAN_A(c)) { 1839 c2 = findchannel(ic, ireq->i_val, 1840 IEEE80211_MODE_11NA); 1841 if (c2 != NULL) 1842 c = c2; 1843 } 1844 break; 1845 case IEEE80211_MODE_11NG: 1846 if (IEEE80211_IS_CHAN_ANYG(c)) { 1847 c2 = findchannel(ic, ireq->i_val, 1848 IEEE80211_MODE_11NG); 1849 if (c2 != NULL) 1850 c = c2; 1851 } 1852 break; 1853 default: /* NB: no static turboG */ 1854 break; 1855 } 1856 } 1857 return setcurchan(ic, c); 1858 } 1859 1860 /* 1861 * New/current api for setting the current channel; a complete 1862 * channel description is provide so there is no ambiguity in 1863 * identifying the channel. 1864 */ 1865 static int 1866 ieee80211_ioctl_setcurchan(struct ieee80211com *ic, 1867 const struct ieee80211req *ireq) 1868 { 1869 struct ieee80211_channel chan, *c; 1870 int error; 1871 1872 if (ireq->i_len != sizeof(chan)) 1873 return EINVAL; 1874 error = copyin(ireq->i_data, &chan, sizeof(chan)); 1875 if (error != 0) 1876 return error; 1877 /* XXX 0xffff overflows 16-bit signed */ 1878 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { 1879 c = IEEE80211_CHAN_ANYC; 1880 } else { 1881 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); 1882 if (c == NULL) 1883 return EINVAL; 1884 } 1885 return setcurchan(ic, c); 1886 } 1887 1888 static int 1889 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1890 { 1891 static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 1892 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1893 int error; 1894 const struct ieee80211_authenticator *auth; 1895 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 1896 char tmpssid[IEEE80211_NWID_LEN]; 1897 uint8_t tmpbssid[IEEE80211_ADDR_LEN]; 1898 struct ieee80211_key *k; 1899 int j, caps; 1900 u_int kid; 1901 1902 error = 0; 1903 switch (ireq->i_type) { 1904 case IEEE80211_IOC_SSID: 1905 if (ireq->i_val != 0 || 1906 ireq->i_len > IEEE80211_NWID_LEN) 1907 return EINVAL; 1908 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 1909 if (error) 1910 break; 1911 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); 1912 ic->ic_des_ssid[0].len = ireq->i_len; 1913 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len); 1914 ic->ic_des_nssid = (ireq->i_len > 0); 1915 if (IS_UP_AUTO(ic)) 1916 error = ieee80211_init(ic, RESCAN); 1917 break; 1918 case IEEE80211_IOC_WEP: 1919 switch (ireq->i_val) { 1920 case IEEE80211_WEP_OFF: 1921 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1922 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1923 break; 1924 case IEEE80211_WEP_ON: 1925 ic->ic_flags |= IEEE80211_F_PRIVACY; 1926 ic->ic_flags |= IEEE80211_F_DROPUNENC; 1927 break; 1928 case IEEE80211_WEP_MIXED: 1929 ic->ic_flags |= IEEE80211_F_PRIVACY; 1930 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1931 break; 1932 } 1933 if (IS_UP_AUTO(ic)) 1934 error = ieee80211_init(ic, RESCAN); 1935 break; 1936 case IEEE80211_IOC_WEPKEY: 1937 kid = (u_int) ireq->i_val; 1938 if (kid >= IEEE80211_WEP_NKID) 1939 return EINVAL; 1940 k = &ic->ic_nw_keys[kid]; 1941 if (ireq->i_len == 0) { 1942 /* zero-len =>'s delete any existing key */ 1943 (void) ieee80211_crypto_delkey(ic, k); 1944 break; 1945 } 1946 if (ireq->i_len > sizeof(tmpkey)) 1947 return EINVAL; 1948 memset(tmpkey, 0, sizeof(tmpkey)); 1949 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 1950 if (error) 1951 break; 1952 ieee80211_key_update_begin(ic); 1953 k->wk_keyix = kid; /* NB: force fixed key id */ 1954 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 1955 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 1956 k->wk_keylen = ireq->i_len; 1957 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 1958 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 1959 error = EINVAL; 1960 } else 1961 error = EINVAL; 1962 ieee80211_key_update_end(ic); 1963 break; 1964 case IEEE80211_IOC_WEPTXKEY: 1965 kid = (u_int) ireq->i_val; 1966 if (kid >= IEEE80211_WEP_NKID && 1967 (uint16_t) kid != IEEE80211_KEYIX_NONE) 1968 return EINVAL; 1969 ic->ic_def_txkey = kid; 1970 break; 1971 case IEEE80211_IOC_AUTHMODE: 1972 switch (ireq->i_val) { 1973 case IEEE80211_AUTH_WPA: 1974 case IEEE80211_AUTH_8021X: /* 802.1x */ 1975 case IEEE80211_AUTH_OPEN: /* open */ 1976 case IEEE80211_AUTH_SHARED: /* shared-key */ 1977 case IEEE80211_AUTH_AUTO: /* auto */ 1978 auth = ieee80211_authenticator_get(ireq->i_val); 1979 if (auth == NULL) 1980 return EINVAL; 1981 break; 1982 default: 1983 return EINVAL; 1984 } 1985 switch (ireq->i_val) { 1986 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 1987 ic->ic_flags |= IEEE80211_F_PRIVACY; 1988 ireq->i_val = IEEE80211_AUTH_8021X; 1989 break; 1990 case IEEE80211_AUTH_OPEN: /* open */ 1991 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 1992 break; 1993 case IEEE80211_AUTH_SHARED: /* shared-key */ 1994 case IEEE80211_AUTH_8021X: /* 802.1x */ 1995 ic->ic_flags &= ~IEEE80211_F_WPA; 1996 /* both require a key so mark the PRIVACY capability */ 1997 ic->ic_flags |= IEEE80211_F_PRIVACY; 1998 break; 1999 case IEEE80211_AUTH_AUTO: /* auto */ 2000 ic->ic_flags &= ~IEEE80211_F_WPA; 2001 /* XXX PRIVACY handling? */ 2002 /* XXX what's the right way to do this? */ 2003 break; 2004 } 2005 /* NB: authenticator attach/detach happens on state change */ 2006 ic->ic_bss->ni_authmode = ireq->i_val; 2007 /* XXX mixed/mode/usage? */ 2008 ic->ic_auth = auth; 2009 if (IS_UP_AUTO(ic)) 2010 error = ieee80211_init(ic, RESCAN); 2011 break; 2012 case IEEE80211_IOC_CHANNEL: 2013 error = ieee80211_ioctl_setchannel(ic, ireq); 2014 break; 2015 case IEEE80211_IOC_POWERSAVE: 2016 switch (ireq->i_val) { 2017 case IEEE80211_POWERSAVE_OFF: 2018 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2019 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2020 error = ENETRESET; 2021 } 2022 break; 2023 case IEEE80211_POWERSAVE_ON: 2024 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 2025 error = EINVAL; 2026 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2027 ic->ic_flags |= IEEE80211_F_PMGTON; 2028 error = ENETRESET; 2029 } 2030 break; 2031 default: 2032 error = EINVAL; 2033 break; 2034 } 2035 if (error == ENETRESET) { 2036 /* 2037 * Switching in+out of power save mode 2038 * should not require a state change. 2039 */ 2040 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2041 } 2042 break; 2043 case IEEE80211_IOC_POWERSAVESLEEP: 2044 if (ireq->i_val < 0) 2045 return EINVAL; 2046 ic->ic_lintval = ireq->i_val; 2047 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2048 break; 2049 case IEEE80211_IOC_RTSTHRESHOLD: 2050 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2051 ireq->i_val <= IEEE80211_RTS_MAX)) 2052 return EINVAL; 2053 ic->ic_rtsthreshold = ireq->i_val; 2054 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2055 break; 2056 case IEEE80211_IOC_PROTMODE: 2057 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2058 return EINVAL; 2059 ic->ic_protmode = ireq->i_val; 2060 /* NB: if not operating in 11g this can wait */ 2061 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2062 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2063 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2064 break; 2065 case IEEE80211_IOC_TXPOWER: 2066 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2067 return EINVAL; 2068 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val && 2069 ireq->i_val <= IEEE80211_TXPOWER_MAX)) 2070 return EINVAL; 2071 ic->ic_txpowlimit = ireq->i_val; 2072 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2073 break; 2074 case IEEE80211_IOC_ROAMING: 2075 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2076 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2077 return EINVAL; 2078 ic->ic_roaming = ireq->i_val; 2079 /* XXXX reset? */ 2080 break; 2081 case IEEE80211_IOC_PRIVACY: 2082 if (ireq->i_val) { 2083 /* XXX check for key state? */ 2084 ic->ic_flags |= IEEE80211_F_PRIVACY; 2085 } else 2086 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2087 break; 2088 case IEEE80211_IOC_DROPUNENCRYPTED: 2089 if (ireq->i_val) 2090 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2091 else 2092 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2093 break; 2094 case IEEE80211_IOC_WPAKEY: 2095 error = ieee80211_ioctl_setkey(ic, ireq); 2096 break; 2097 case IEEE80211_IOC_DELKEY: 2098 error = ieee80211_ioctl_delkey(ic, ireq); 2099 break; 2100 case IEEE80211_IOC_MLME: 2101 error = ieee80211_ioctl_setmlme(ic, ireq); 2102 break; 2103 case IEEE80211_IOC_OPTIE: 2104 error = ieee80211_ioctl_setoptie(ic, ireq); 2105 break; 2106 case IEEE80211_IOC_COUNTERMEASURES: 2107 if (ireq->i_val) { 2108 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 2109 return EINVAL; 2110 ic->ic_flags |= IEEE80211_F_COUNTERM; 2111 } else 2112 ic->ic_flags &= ~IEEE80211_F_COUNTERM; 2113 break; 2114 case IEEE80211_IOC_WPA: 2115 if (ireq->i_val > 3) 2116 return EINVAL; 2117 /* XXX verify ciphers available */ 2118 ic->ic_flags &= ~IEEE80211_F_WPA; 2119 switch (ireq->i_val) { 2120 case 1: 2121 ic->ic_flags |= IEEE80211_F_WPA1; 2122 break; 2123 case 2: 2124 ic->ic_flags |= IEEE80211_F_WPA2; 2125 break; 2126 case 3: 2127 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2128 break; 2129 } 2130 error = ENETRESET; 2131 break; 2132 case IEEE80211_IOC_WME: 2133 if (ireq->i_val) { 2134 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2135 return EINVAL; 2136 ic->ic_flags |= IEEE80211_F_WME; 2137 } else 2138 ic->ic_flags &= ~IEEE80211_F_WME; 2139 if (IS_UP_AUTO(ic)) 2140 error = ieee80211_init(ic, 0); 2141 break; 2142 case IEEE80211_IOC_HIDESSID: 2143 if (ireq->i_val) 2144 ic->ic_flags |= IEEE80211_F_HIDESSID; 2145 else 2146 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2147 error = ENETRESET; 2148 break; 2149 case IEEE80211_IOC_APBRIDGE: 2150 if (ireq->i_val == 0) 2151 ic->ic_flags |= IEEE80211_F_NOBRIDGE; 2152 else 2153 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE; 2154 break; 2155 case IEEE80211_IOC_MCASTCIPHER: 2156 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 && 2157 !ieee80211_crypto_available(ireq->i_val)) 2158 return EINVAL; 2159 rsn->rsn_mcastcipher = ireq->i_val; 2160 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2161 break; 2162 case IEEE80211_IOC_MCASTKEYLEN: 2163 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2164 return EINVAL; 2165 /* XXX no way to verify driver capability */ 2166 rsn->rsn_mcastkeylen = ireq->i_val; 2167 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2168 break; 2169 case IEEE80211_IOC_UCASTCIPHERS: 2170 /* 2171 * Convert user-specified cipher set to the set 2172 * we can support (via hardware or software). 2173 * NB: this logic intentionally ignores unknown and 2174 * unsupported ciphers so folks can specify 0xff or 2175 * similar and get all available ciphers. 2176 */ 2177 caps = 0; 2178 for (j = 1; j < 32; j++) /* NB: skip WEP */ 2179 if ((ireq->i_val & (1<<j)) && 2180 ((ic->ic_caps & cipher2cap(j)) || 2181 ieee80211_crypto_available(j))) 2182 caps |= 1<<j; 2183 if (caps == 0) /* nothing available */ 2184 return EINVAL; 2185 /* XXX verify ciphers ok for unicast use? */ 2186 /* XXX disallow if running as it'll have no effect */ 2187 rsn->rsn_ucastcipherset = caps; 2188 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2189 break; 2190 case IEEE80211_IOC_UCASTCIPHER: 2191 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0) 2192 return EINVAL; 2193 rsn->rsn_ucastcipher = ireq->i_val; 2194 break; 2195 case IEEE80211_IOC_UCASTKEYLEN: 2196 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2197 return EINVAL; 2198 /* XXX no way to verify driver capability */ 2199 rsn->rsn_ucastkeylen = ireq->i_val; 2200 break; 2201 case IEEE80211_IOC_DRIVER_CAPS: 2202 /* NB: for testing */ 2203 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) | 2204 ((uint16_t) ireq->i_len); 2205 break; 2206 case IEEE80211_IOC_KEYMGTALGS: 2207 /* XXX check */ 2208 rsn->rsn_keymgmtset = ireq->i_val; 2209 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2210 break; 2211 case IEEE80211_IOC_RSNCAPS: 2212 /* XXX check */ 2213 rsn->rsn_caps = ireq->i_val; 2214 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2215 break; 2216 case IEEE80211_IOC_BSSID: 2217 if (ireq->i_len != sizeof(tmpbssid)) 2218 return EINVAL; 2219 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2220 if (error) 2221 break; 2222 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2223 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2224 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2225 else 2226 ic->ic_flags |= IEEE80211_F_DESBSSID; 2227 if (IS_UP_AUTO(ic)) 2228 error = ieee80211_init(ic, RESCAN); 2229 break; 2230 case IEEE80211_IOC_CHANLIST: 2231 error = ieee80211_ioctl_setchanlist(ic, ireq); 2232 break; 2233 case IEEE80211_IOC_SCAN_REQ: 2234 if (!IS_UP(ic)) 2235 return EINVAL; 2236 (void) ieee80211_start_scan(ic, 2237 IEEE80211_SCAN_ACTIVE | 2238 IEEE80211_SCAN_NOPICK | 2239 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER, 2240 /* XXX use ioctl params */ 2241 ic->ic_des_nssid, ic->ic_des_ssid); 2242 break; 2243 case IEEE80211_IOC_ADDMAC: 2244 case IEEE80211_IOC_DELMAC: 2245 error = ieee80211_ioctl_macmac(ic, ireq); 2246 break; 2247 case IEEE80211_IOC_MACCMD: 2248 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2249 break; 2250 case IEEE80211_IOC_STA_STATS: 2251 error = ieee80211_ioctl_setstastats(ic, ireq); 2252 break; 2253 case IEEE80211_IOC_STA_TXPOW: 2254 error = ieee80211_ioctl_setstatxpow(ic, ireq); 2255 break; 2256 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2257 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2258 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2259 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2260 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2261 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2262 error = ieee80211_ioctl_setwmeparam(ic, ireq); 2263 break; 2264 case IEEE80211_IOC_DTIM_PERIOD: 2265 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2266 ic->ic_opmode != IEEE80211_M_IBSS) 2267 return EINVAL; 2268 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2269 ireq->i_val <= IEEE80211_DTIM_MAX) { 2270 ic->ic_dtim_period = ireq->i_val; 2271 error = ENETRESET; /* requires restart */ 2272 } else 2273 error = EINVAL; 2274 break; 2275 case IEEE80211_IOC_BEACON_INTERVAL: 2276 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2277 ic->ic_opmode != IEEE80211_M_IBSS) 2278 return EINVAL; 2279 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2280 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2281 ic->ic_bintval = ireq->i_val; 2282 error = ENETRESET; /* requires restart */ 2283 } else 2284 error = EINVAL; 2285 break; 2286 case IEEE80211_IOC_PUREG: 2287 if (ireq->i_val) 2288 ic->ic_flags |= IEEE80211_F_PUREG; 2289 else 2290 ic->ic_flags &= ~IEEE80211_F_PUREG; 2291 /* NB: reset only if we're operating on an 11g channel */ 2292 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2293 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2294 error = ENETRESET; 2295 break; 2296 case IEEE80211_IOC_FF: 2297 if (ireq->i_val) { 2298 if ((ic->ic_caps & IEEE80211_C_FF) == 0) 2299 return EINVAL; 2300 ic->ic_flags |= IEEE80211_F_FF; 2301 } else 2302 ic->ic_flags &= ~IEEE80211_F_FF; 2303 error = ENETRESET; 2304 break; 2305 case IEEE80211_IOC_TURBOP: 2306 if (ireq->i_val) { 2307 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0) 2308 return EINVAL; 2309 ic->ic_flags |= IEEE80211_F_TURBOP; 2310 } else 2311 ic->ic_flags &= ~IEEE80211_F_TURBOP; 2312 error = ENETRESET; 2313 break; 2314 case IEEE80211_IOC_BGSCAN: 2315 if (ireq->i_val) { 2316 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0) 2317 return EINVAL; 2318 ic->ic_flags |= IEEE80211_F_BGSCAN; 2319 } else 2320 ic->ic_flags &= ~IEEE80211_F_BGSCAN; 2321 break; 2322 case IEEE80211_IOC_BGSCAN_IDLE: 2323 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN) 2324 ic->ic_bgscanidle = ireq->i_val*hz/1000; 2325 else 2326 error = EINVAL; 2327 break; 2328 case IEEE80211_IOC_BGSCAN_INTERVAL: 2329 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN) 2330 ic->ic_bgscanintvl = ireq->i_val*hz; 2331 else 2332 error = EINVAL; 2333 break; 2334 case IEEE80211_IOC_SCANVALID: 2335 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN) 2336 ic->ic_scanvalid = ireq->i_val*hz; 2337 else 2338 error = EINVAL; 2339 break; 2340 case IEEE80211_IOC_ROAM_RSSI_11A: 2341 ic->ic_roam.rssi11a = ireq->i_val; 2342 break; 2343 case IEEE80211_IOC_ROAM_RSSI_11B: 2344 ic->ic_roam.rssi11bOnly = ireq->i_val; 2345 break; 2346 case IEEE80211_IOC_ROAM_RSSI_11G: 2347 ic->ic_roam.rssi11b = ireq->i_val; 2348 break; 2349 case IEEE80211_IOC_ROAM_RATE_11A: 2350 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL; 2351 break; 2352 case IEEE80211_IOC_ROAM_RATE_11B: 2353 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL; 2354 break; 2355 case IEEE80211_IOC_ROAM_RATE_11G: 2356 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL; 2357 break; 2358 case IEEE80211_IOC_MCAST_RATE: 2359 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2360 break; 2361 case IEEE80211_IOC_FRAGTHRESHOLD: 2362 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2363 ireq->i_val != IEEE80211_FRAG_MAX) 2364 return EINVAL; 2365 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && 2366 ireq->i_val <= IEEE80211_FRAG_MAX)) 2367 return EINVAL; 2368 ic->ic_fragthreshold = ireq->i_val; 2369 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2370 break; 2371 case IEEE80211_IOC_BURST: 2372 if (ireq->i_val) { 2373 if ((ic->ic_caps & IEEE80211_C_BURST) == 0) 2374 return EINVAL; 2375 ic->ic_flags |= IEEE80211_F_BURST; 2376 } else 2377 ic->ic_flags &= ~IEEE80211_F_BURST; 2378 error = ENETRESET; /* XXX maybe not for station? */ 2379 break; 2380 case IEEE80211_IOC_BMISSTHRESHOLD: 2381 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val && 2382 ireq->i_val <= IEEE80211_HWBMISS_MAX)) 2383 return EINVAL; 2384 ic->ic_bmissthreshold = ireq->i_val; 2385 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2386 break; 2387 case IEEE80211_IOC_CURCHAN: 2388 error = ieee80211_ioctl_setcurchan(ic, ireq); 2389 break; 2390 case IEEE80211_IOC_SHORTGI: 2391 if (ireq->i_val) { 2392 #define IEEE80211_HTCAP_SHORTGI \ 2393 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) 2394 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0) 2395 return EINVAL; 2396 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20) 2397 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20; 2398 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40) 2399 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40; 2400 #undef IEEE80211_HTCAP_SHORTGI 2401 } else 2402 ic->ic_flags_ext &= 2403 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40); 2404 /* XXX kick state machine? */ 2405 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2406 break; 2407 case IEEE80211_IOC_AMPDU: 2408 if (ireq->i_val) { 2409 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0) 2410 return EINVAL; 2411 if (ireq->i_val & 1) 2412 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX; 2413 if (ireq->i_val & 2) 2414 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX; 2415 } else 2416 ic->ic_flags_ext &= 2417 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX); 2418 /* NB: reset only if we're operating on an 11n channel */ 2419 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2420 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2421 error = ENETRESET; 2422 break; 2423 case IEEE80211_IOC_AMPDU_LIMIT: 2424 /* XXX validate */ 2425 ic->ic_ampdu_limit = ireq->i_val; 2426 break; 2427 case IEEE80211_IOC_AMPDU_DENSITY: 2428 /* XXX validate */ 2429 ic->ic_ampdu_density = ireq->i_val; 2430 break; 2431 case IEEE80211_IOC_AMSDU: 2432 if (ireq->i_val) { 2433 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0) 2434 return EINVAL; 2435 if (ireq->i_val & 1) 2436 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX; 2437 if (ireq->i_val & 2) 2438 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX; 2439 } else 2440 ic->ic_flags_ext &= 2441 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX); 2442 /* NB: reset only if we're operating on an 11n channel */ 2443 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2444 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2445 error = ENETRESET; 2446 break; 2447 case IEEE80211_IOC_AMSDU_LIMIT: 2448 /* XXX validate */ 2449 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */ 2450 break; 2451 case IEEE80211_IOC_PUREN: 2452 if (ireq->i_val) { 2453 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2454 return EINVAL; 2455 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN; 2456 } else 2457 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN; 2458 /* NB: reset only if we're operating on an 11n channel */ 2459 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2460 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2461 error = ENETRESET; 2462 break; 2463 case IEEE80211_IOC_DOTH: 2464 if (ireq->i_val) { 2465 #if 0 2466 /* XXX no capability */ 2467 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0) 2468 return EINVAL; 2469 #endif 2470 ic->ic_flags |= IEEE80211_F_DOTH; 2471 } else 2472 ic->ic_flags &= ~IEEE80211_F_DOTH; 2473 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2474 break; 2475 case IEEE80211_IOC_HTCOMPAT: 2476 if (ireq->i_val) { 2477 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2478 return EINVAL; 2479 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT; 2480 } else 2481 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT; 2482 /* NB: reset only if we're operating on an 11n channel */ 2483 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2484 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2485 error = ENETRESET; 2486 break; 2487 case IEEE80211_IOC_INACTIVITY: 2488 if (ireq->i_val) 2489 ic->ic_flags_ext |= IEEE80211_FEXT_INACT; 2490 else 2491 ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT; 2492 break; 2493 case IEEE80211_IOC_HTPROTMODE: 2494 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2495 return EINVAL; 2496 ic->ic_htprotmode = ireq->i_val ? 2497 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE; 2498 /* NB: if not operating in 11n this can wait */ 2499 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2500 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2501 error = ERESTART; 2502 break; 2503 case IEEE80211_IOC_HTCONF: 2504 if (ireq->i_val & 1) 2505 ic->ic_flags_ext |= IEEE80211_FEXT_HT; 2506 else 2507 ic->ic_flags_ext &= ~IEEE80211_FEXT_HT; 2508 if (ireq->i_val & 2) 2509 ic->ic_flags_ext |= IEEE80211_FEXT_USEHT40; 2510 else 2511 ic->ic_flags_ext &= ~IEEE80211_FEXT_USEHT40; 2512 error = ENETRESET; 2513 break; 2514 default: 2515 error = EINVAL; 2516 break; 2517 } 2518 if (error == ENETRESET) 2519 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0; 2520 return error; 2521 } 2522 2523 int 2524 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2525 { 2526 struct ifnet *ifp = ic->ic_ifp; 2527 int error = 0; 2528 struct ifreq *ifr; 2529 struct ifaddr *ifa; /* XXX */ 2530 2531 switch (cmd) { 2532 case SIOCSIFMEDIA: 2533 case SIOCGIFMEDIA: 2534 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 2535 &ic->ic_media, cmd); 2536 break; 2537 case SIOCG80211: 2538 error = ieee80211_ioctl_get80211(ic, cmd, 2539 (struct ieee80211req *) data); 2540 break; 2541 case SIOCS80211: 2542 error = priv_check(curthread, PRIV_NET80211_MANAGE); 2543 if (error == 0) 2544 error = ieee80211_ioctl_set80211(ic, cmd, 2545 (struct ieee80211req *) data); 2546 break; 2547 case SIOCG80211STATS: 2548 ifr = (struct ifreq *)data; 2549 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2550 break; 2551 case SIOCSIFMTU: 2552 ifr = (struct ifreq *)data; 2553 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2554 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2555 error = EINVAL; 2556 else 2557 ifp->if_mtu = ifr->ifr_mtu; 2558 break; 2559 case SIOCSIFADDR: 2560 /* 2561 * XXX Handle this directly so we can supress if_init calls. 2562 * XXX This should be done in ether_ioctl but for the moment 2563 * XXX there are too many other parts of the system that 2564 * XXX set IFF_UP and so supress if_init being called when 2565 * XXX it should be. 2566 */ 2567 ifa = (struct ifaddr *) data; 2568 switch (ifa->ifa_addr->sa_family) { 2569 #ifdef INET 2570 case AF_INET: 2571 if ((ifp->if_flags & IFF_UP) == 0) { 2572 ifp->if_flags |= IFF_UP; 2573 ifp->if_init(ifp->if_softc); 2574 } 2575 arp_ifinit(ifp, ifa); 2576 break; 2577 #endif 2578 #ifdef IPX 2579 /* 2580 * XXX - This code is probably wrong, 2581 * but has been copied many times. 2582 */ 2583 case AF_IPX: { 2584 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 2585 2586 if (ipx_nullhost(*ina)) 2587 ina->x_host = *(union ipx_host *) 2588 IF_LLADDR(ifp); 2589 else 2590 bcopy((caddr_t) ina->x_host.c_host, 2591 (caddr_t) IF_LLADDR(ifp), 2592 ETHER_ADDR_LEN); 2593 /* fall thru... */ 2594 } 2595 #endif 2596 default: 2597 if ((ifp->if_flags & IFF_UP) == 0) { 2598 ifp->if_flags |= IFF_UP; 2599 ifp->if_init(ifp->if_softc); 2600 } 2601 break; 2602 } 2603 break; 2604 default: 2605 error = ether_ioctl(ifp, cmd, data); 2606 break; 2607 } 2608 return error; 2609 } 2610