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 default: 1112 error = EINVAL; 1113 break; 1114 } 1115 return error; 1116 } 1117 1118 static int 1119 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq) 1120 { 1121 int error; 1122 void *ie, *oie; 1123 1124 /* 1125 * NB: Doing this for ap operation could be useful (e.g. for 1126 * WPA and/or WME) except that it typically is worthless 1127 * without being able to intervene when processing 1128 * association response frames--so disallow it for now. 1129 */ 1130 if (ic->ic_opmode != IEEE80211_M_STA) 1131 return EINVAL; 1132 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1133 return EINVAL; 1134 /* NB: data.length is validated by the wireless extensions code */ 1135 /* XXX M_WAITOK after driver lock released */ 1136 if (ireq->i_len > 0) { 1137 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT); 1138 if (ie == NULL) 1139 return ENOMEM; 1140 error = copyin(ireq->i_data, ie, ireq->i_len); 1141 if (error) { 1142 FREE(ie, M_DEVBUF); 1143 return error; 1144 } 1145 } else { 1146 ie = NULL; 1147 ireq->i_len = 0; 1148 } 1149 /* XXX sanity check data? */ 1150 oie = ic->ic_opt_ie; 1151 ic->ic_opt_ie = ie; 1152 ic->ic_opt_ie_len = ireq->i_len; 1153 if (oie != NULL) 1154 FREE(oie, M_DEVBUF); 1155 return 0; 1156 } 1157 1158 static int 1159 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1160 { 1161 struct ieee80211req_key ik; 1162 struct ieee80211_node *ni; 1163 struct ieee80211_key *wk; 1164 uint16_t kid; 1165 int error; 1166 1167 if (ireq->i_len != sizeof(ik)) 1168 return EINVAL; 1169 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1170 if (error) 1171 return error; 1172 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1173 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1174 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1175 return E2BIG; 1176 kid = ik.ik_keyix; 1177 if (kid == IEEE80211_KEYIX_NONE) { 1178 /* XXX unicast keys currently must be tx/rx */ 1179 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1180 return EINVAL; 1181 if (ic->ic_opmode == IEEE80211_M_STA) { 1182 ni = ieee80211_ref_node(ic->ic_bss); 1183 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) { 1184 ieee80211_free_node(ni); 1185 return EADDRNOTAVAIL; 1186 } 1187 } else { 1188 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr); 1189 if (ni == NULL) 1190 return ENOENT; 1191 } 1192 wk = &ni->ni_ucastkey; 1193 } else { 1194 if (kid >= IEEE80211_WEP_NKID) 1195 return EINVAL; 1196 wk = &ic->ic_nw_keys[kid]; 1197 /* 1198 * Global slots start off w/o any assigned key index. 1199 * Force one here for consistency with IEEE80211_IOC_WEPKEY. 1200 */ 1201 if (wk->wk_keyix == IEEE80211_KEYIX_NONE) 1202 wk->wk_keyix = kid; 1203 ni = NULL; 1204 } 1205 error = 0; 1206 ieee80211_key_update_begin(ic); 1207 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) { 1208 wk->wk_keylen = ik.ik_keylen; 1209 /* NB: MIC presence is implied by cipher type */ 1210 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1211 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1212 wk->wk_keyrsc = ik.ik_keyrsc; 1213 wk->wk_keytsc = 0; /* new key, reset */ 1214 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1215 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1216 if (!ieee80211_crypto_setkey(ic, wk, 1217 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr)) 1218 error = EIO; 1219 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1220 ic->ic_def_txkey = kid; 1221 } else 1222 error = ENXIO; 1223 ieee80211_key_update_end(ic); 1224 if (ni != NULL) 1225 ieee80211_free_node(ni); 1226 return error; 1227 } 1228 1229 static int 1230 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1231 { 1232 struct ieee80211req_del_key dk; 1233 int kid, error; 1234 1235 if (ireq->i_len != sizeof(dk)) 1236 return EINVAL; 1237 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1238 if (error) 1239 return error; 1240 kid = dk.idk_keyix; 1241 /* XXX uint8_t -> uint16_t */ 1242 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) { 1243 struct ieee80211_node *ni; 1244 1245 if (ic->ic_opmode == IEEE80211_M_STA) { 1246 ni = ieee80211_ref_node(ic->ic_bss); 1247 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1248 ieee80211_free_node(ni); 1249 return EADDRNOTAVAIL; 1250 } 1251 } else { 1252 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr); 1253 if (ni == NULL) 1254 return ENOENT; 1255 } 1256 /* XXX error return */ 1257 ieee80211_node_delucastkey(ni); 1258 ieee80211_free_node(ni); 1259 } else { 1260 if (kid >= IEEE80211_WEP_NKID) 1261 return EINVAL; 1262 /* XXX error return */ 1263 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]); 1264 } 1265 return 0; 1266 } 1267 1268 static void 1269 domlme(void *arg, struct ieee80211_node *ni) 1270 { 1271 struct ieee80211com *ic = ni->ni_ic; 1272 struct ieee80211req_mlme *mlme = arg; 1273 1274 if (ni->ni_associd != 0) { 1275 IEEE80211_SEND_MGMT(ic, ni, 1276 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1277 IEEE80211_FC0_SUBTYPE_DEAUTH : 1278 IEEE80211_FC0_SUBTYPE_DISASSOC, 1279 mlme->im_reason); 1280 } 1281 ieee80211_node_leave(ic, ni); 1282 } 1283 1284 struct scanlookup { 1285 const uint8_t *mac; 1286 int esslen; 1287 const uint8_t *essid; 1288 const struct ieee80211_scan_entry *se; 1289 }; 1290 1291 /* 1292 * Match mac address and any ssid. 1293 */ 1294 static void 1295 mlmelookup(void *arg, const struct ieee80211_scan_entry *se) 1296 { 1297 struct scanlookup *look = arg; 1298 1299 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) 1300 return; 1301 if (look->esslen != 0) { 1302 if (se->se_ssid[1] != look->esslen) 1303 return; 1304 if (memcmp(look->essid, se->se_ssid+2, look->esslen)) 1305 return; 1306 } 1307 look->se = se; 1308 } 1309 1310 static int 1311 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1312 { 1313 struct ieee80211req_mlme mlme; 1314 struct ieee80211_node *ni; 1315 int error; 1316 1317 if (ireq->i_len != sizeof(mlme)) 1318 return EINVAL; 1319 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1320 if (error) 1321 return error; 1322 switch (mlme.im_op) { 1323 case IEEE80211_MLME_ASSOC: 1324 /* XXX ibss/ahdemo */ 1325 if (ic->ic_opmode == IEEE80211_M_STA) { 1326 struct scanlookup lookup; 1327 1328 lookup.se = NULL; 1329 lookup.mac = mlme.im_macaddr; 1330 /* XXX use revised api w/ explicit ssid */ 1331 lookup.esslen = ic->ic_des_ssid[0].len; 1332 lookup.essid = ic->ic_des_ssid[0].ssid; 1333 ieee80211_scan_iterate(ic, mlmelookup, &lookup); 1334 if (lookup.se != NULL && 1335 ieee80211_sta_join(ic, lookup.se)) 1336 return 0; 1337 } 1338 return EINVAL; 1339 case IEEE80211_MLME_DISASSOC: 1340 case IEEE80211_MLME_DEAUTH: 1341 switch (ic->ic_opmode) { 1342 case IEEE80211_M_STA: 1343 /* XXX not quite right */ 1344 ieee80211_new_state(ic, IEEE80211_S_INIT, 1345 mlme.im_reason); 1346 break; 1347 case IEEE80211_M_HOSTAP: 1348 /* NB: the broadcast address means do 'em all */ 1349 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) { 1350 if ((ni = ieee80211_find_node(&ic->ic_sta, 1351 mlme.im_macaddr)) == NULL) 1352 return EINVAL; 1353 domlme(&mlme, ni); 1354 ieee80211_free_node(ni); 1355 } else { 1356 ieee80211_iterate_nodes(&ic->ic_sta, 1357 domlme, &mlme); 1358 } 1359 break; 1360 default: 1361 return EINVAL; 1362 } 1363 break; 1364 case IEEE80211_MLME_AUTHORIZE: 1365 case IEEE80211_MLME_UNAUTHORIZE: 1366 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1367 return EINVAL; 1368 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr); 1369 if (ni == NULL) 1370 return EINVAL; 1371 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE) 1372 ieee80211_node_authorize(ni); 1373 else 1374 ieee80211_node_unauthorize(ni); 1375 ieee80211_free_node(ni); 1376 break; 1377 default: 1378 return EINVAL; 1379 } 1380 return 0; 1381 } 1382 1383 static int 1384 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1385 { 1386 uint8_t mac[IEEE80211_ADDR_LEN]; 1387 const struct ieee80211_aclator *acl = ic->ic_acl; 1388 int error; 1389 1390 if (ireq->i_len != sizeof(mac)) 1391 return EINVAL; 1392 error = copyin(ireq->i_data, mac, ireq->i_len); 1393 if (error) 1394 return error; 1395 if (acl == NULL) { 1396 acl = ieee80211_aclator_get("mac"); 1397 if (acl == NULL || !acl->iac_attach(ic)) 1398 return EINVAL; 1399 ic->ic_acl = acl; 1400 } 1401 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1402 acl->iac_add(ic, mac); 1403 else 1404 acl->iac_remove(ic, mac); 1405 return 0; 1406 } 1407 1408 static int 1409 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1410 { 1411 const struct ieee80211_aclator *acl = ic->ic_acl; 1412 1413 switch (ireq->i_val) { 1414 case IEEE80211_MACCMD_POLICY_OPEN: 1415 case IEEE80211_MACCMD_POLICY_ALLOW: 1416 case IEEE80211_MACCMD_POLICY_DENY: 1417 if (acl == NULL) { 1418 acl = ieee80211_aclator_get("mac"); 1419 if (acl == NULL || !acl->iac_attach(ic)) 1420 return EINVAL; 1421 ic->ic_acl = acl; 1422 } 1423 acl->iac_setpolicy(ic, ireq->i_val); 1424 break; 1425 case IEEE80211_MACCMD_FLUSH: 1426 if (acl != NULL) 1427 acl->iac_flush(ic); 1428 /* NB: silently ignore when not in use */ 1429 break; 1430 case IEEE80211_MACCMD_DETACH: 1431 if (acl != NULL) { 1432 ic->ic_acl = NULL; 1433 acl->iac_detach(ic); 1434 } 1435 break; 1436 default: 1437 if (acl == NULL) 1438 return EINVAL; 1439 else 1440 return acl->iac_setioctl(ic, ireq); 1441 } 1442 return 0; 1443 } 1444 1445 static int 1446 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 1447 { 1448 struct ieee80211req_chanlist list; 1449 u_char chanlist[IEEE80211_CHAN_BYTES]; 1450 int i, j, nchan, error; 1451 1452 if (ireq->i_len != sizeof(list)) 1453 return EINVAL; 1454 error = copyin(ireq->i_data, &list, sizeof(list)); 1455 if (error) 1456 return error; 1457 memset(chanlist, 0, sizeof(chanlist)); 1458 /* 1459 * Since channel 0 is not available for DS, channel 1 1460 * is assigned to LSB on WaveLAN. 1461 */ 1462 if (ic->ic_phytype == IEEE80211_T_DS) 1463 i = 1; 1464 else 1465 i = 0; 1466 nchan = 0; 1467 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 1468 /* 1469 * NB: silently discard unavailable channels so users 1470 * can specify 1-255 to get all available channels. 1471 */ 1472 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) { 1473 setbit(chanlist, i); 1474 nchan++; 1475 } 1476 } 1477 if (nchan == 0) 1478 return EINVAL; 1479 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ 1480 isclr(chanlist, ic->ic_bsschan->ic_ieee)) 1481 ic->ic_bsschan = IEEE80211_CHAN_ANYC; 1482 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 1483 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0; 1484 } 1485 1486 static int 1487 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 1488 { 1489 struct ieee80211_node *ni; 1490 uint8_t macaddr[IEEE80211_ADDR_LEN]; 1491 int error; 1492 1493 /* 1494 * NB: we could copyin ieee80211req_sta_stats so apps 1495 * could make selective changes but that's overkill; 1496 * just clear all stats for now. 1497 */ 1498 if (ireq->i_len < IEEE80211_ADDR_LEN) 1499 return EINVAL; 1500 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1501 if (error != 0) 1502 return error; 1503 ni = ieee80211_find_node(&ic->ic_sta, macaddr); 1504 if (ni == NULL) 1505 return EINVAL; /* XXX */ 1506 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats)); 1507 ieee80211_free_node(ni); 1508 return 0; 1509 } 1510 1511 static int 1512 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1513 { 1514 struct ieee80211_node *ni; 1515 struct ieee80211req_sta_txpow txpow; 1516 int error; 1517 1518 if (ireq->i_len != sizeof(txpow)) 1519 return EINVAL; 1520 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1521 if (error != 0) 1522 return error; 1523 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 1524 if (ni == NULL) 1525 return EINVAL; /* XXX */ 1526 ni->ni_txpower = txpow.it_txpow; 1527 ieee80211_free_node(ni); 1528 return error; 1529 } 1530 1531 static int 1532 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1533 { 1534 struct ieee80211_wme_state *wme = &ic->ic_wme; 1535 struct wmeParams *wmep, *chanp; 1536 int isbss, ac; 1537 1538 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1539 return EINVAL; 1540 1541 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1542 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1543 if (ac >= WME_NUM_AC) 1544 ac = WME_AC_BE; 1545 if (isbss) { 1546 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1547 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1548 } else { 1549 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1550 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1551 } 1552 switch (ireq->i_type) { 1553 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1554 if (isbss) { 1555 wmep->wmep_logcwmin = ireq->i_val; 1556 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1557 chanp->wmep_logcwmin = ireq->i_val; 1558 } else { 1559 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1560 ireq->i_val; 1561 } 1562 break; 1563 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1564 if (isbss) { 1565 wmep->wmep_logcwmax = ireq->i_val; 1566 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1567 chanp->wmep_logcwmax = ireq->i_val; 1568 } else { 1569 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1570 ireq->i_val; 1571 } 1572 break; 1573 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1574 if (isbss) { 1575 wmep->wmep_aifsn = ireq->i_val; 1576 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1577 chanp->wmep_aifsn = ireq->i_val; 1578 } else { 1579 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1580 } 1581 break; 1582 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1583 if (isbss) { 1584 wmep->wmep_txopLimit = ireq->i_val; 1585 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1586 chanp->wmep_txopLimit = ireq->i_val; 1587 } else { 1588 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1589 ireq->i_val; 1590 } 1591 break; 1592 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1593 wmep->wmep_acm = ireq->i_val; 1594 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1595 chanp->wmep_acm = ireq->i_val; 1596 break; 1597 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1598 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1599 (ireq->i_val) == 0; 1600 break; 1601 } 1602 ieee80211_wme_updateparams(ic); 1603 return 0; 1604 } 1605 1606 static int 1607 cipher2cap(int cipher) 1608 { 1609 switch (cipher) { 1610 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP; 1611 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES; 1612 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 1613 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 1614 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 1615 } 1616 return 0; 1617 } 1618 1619 static int 1620 find11gchannel(struct ieee80211com *ic, int start, int freq) 1621 { 1622 const struct ieee80211_channel *c; 1623 int i; 1624 1625 for (i = start+1; i < ic->ic_nchans; i++) { 1626 c = &ic->ic_channels[i]; 1627 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1628 return 1; 1629 } 1630 /* NB: should not be needed but in case things are mis-sorted */ 1631 for (i = 0; i < start; i++) { 1632 c = &ic->ic_channels[i]; 1633 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1634 return 1; 1635 } 1636 return 0; 1637 } 1638 1639 static struct ieee80211_channel * 1640 findchannel(struct ieee80211com *ic, int ieee, int mode) 1641 { 1642 static const u_int chanflags[IEEE80211_MODE_MAX] = { 1643 0, /* IEEE80211_MODE_AUTO */ 1644 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 1645 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 1646 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */ 1647 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 1648 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ 1649 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 1650 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */ 1651 /* NB: handled specially below */ 1652 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */ 1653 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */ 1654 }; 1655 u_int modeflags; 1656 int i; 1657 1658 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode)); 1659 modeflags = chanflags[mode]; 1660 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO, 1661 ("no chanflags for mode %u", mode)); 1662 for (i = 0; i < ic->ic_nchans; i++) { 1663 struct ieee80211_channel *c = &ic->ic_channels[i]; 1664 1665 if (c->ic_ieee != ieee) 1666 continue; 1667 if (mode == IEEE80211_MODE_AUTO) { 1668 /* ignore turbo channels for autoselect */ 1669 if (IEEE80211_IS_CHAN_TURBO(c)) 1670 continue; 1671 /* 1672 * XXX special-case 11b/g channels so we 1673 * always select the g channel if both 1674 * are present. 1675 * XXX prefer HT to non-HT? 1676 */ 1677 if (!IEEE80211_IS_CHAN_B(c) || 1678 !find11gchannel(ic, i, c->ic_freq)) 1679 return c; 1680 } else { 1681 /* must check HT specially */ 1682 if ((mode == IEEE80211_MODE_11NA || 1683 mode == IEEE80211_MODE_11NG) && 1684 !IEEE80211_IS_CHAN_HT(c)) 1685 continue; 1686 if ((c->ic_flags & modeflags) == modeflags) 1687 return c; 1688 } 1689 } 1690 return NULL; 1691 } 1692 1693 /* 1694 * Check the specified against any desired mode (aka netband). 1695 * This is only used (presently) when operating in hostap mode 1696 * to enforce consistency. 1697 */ 1698 static int 1699 check_mode_consistency(const struct ieee80211_channel *c, int mode) 1700 { 1701 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel")); 1702 1703 switch (mode) { 1704 case IEEE80211_MODE_11B: 1705 return (IEEE80211_IS_CHAN_B(c)); 1706 case IEEE80211_MODE_11G: 1707 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c)); 1708 case IEEE80211_MODE_11A: 1709 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c)); 1710 case IEEE80211_MODE_STURBO_A: 1711 return (IEEE80211_IS_CHAN_STURBO(c)); 1712 case IEEE80211_MODE_11NA: 1713 return (IEEE80211_IS_CHAN_HTA(c)); 1714 case IEEE80211_MODE_11NG: 1715 return (IEEE80211_IS_CHAN_HTG(c)); 1716 } 1717 return 1; 1718 1719 } 1720 1721 /* 1722 * Common code to set the current channel. If the device 1723 * is up and running this may result in an immediate channel 1724 * change or a kick of the state machine. 1725 */ 1726 static int 1727 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) 1728 { 1729 int error; 1730 1731 if (c != IEEE80211_CHAN_ANYC) { 1732 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1733 !check_mode_consistency(c, ic->ic_des_mode)) 1734 return EINVAL; 1735 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan) 1736 return 0; /* NB: nothing to do */ 1737 } 1738 ic->ic_des_chan = c; 1739 1740 error = 0; 1741 if ((ic->ic_opmode == IEEE80211_M_MONITOR || 1742 ic->ic_opmode == IEEE80211_M_WDS) && 1743 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1744 /* 1745 * Monitor and wds modes can switch directly. 1746 */ 1747 ic->ic_curchan = ic->ic_des_chan; 1748 if (ic->ic_state == IEEE80211_S_RUN) 1749 ic->ic_set_channel(ic); 1750 } else { 1751 /* 1752 * Need to go through the state machine in case we 1753 * need to reassociate or the like. The state machine 1754 * will pickup the desired channel and avoid scanning. 1755 */ 1756 if (IS_UP_AUTO(ic)) 1757 error = ieee80211_init(ic, RESCAN); 1758 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1759 /* 1760 * When not up+running and a real channel has 1761 * been specified fix the current channel so 1762 * there is immediate feedback; e.g. via ifconfig. 1763 */ 1764 ic->ic_curchan = ic->ic_des_chan; 1765 } 1766 } 1767 return error; 1768 } 1769 1770 /* 1771 * Old api for setting the current channel; this is 1772 * deprecated because channel numbers are ambiguous. 1773 */ 1774 static int 1775 ieee80211_ioctl_setchannel(struct ieee80211com *ic, 1776 const struct ieee80211req *ireq) 1777 { 1778 struct ieee80211_channel *c; 1779 1780 /* XXX 0xffff overflows 16-bit signed */ 1781 if (ireq->i_val == 0 || 1782 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) { 1783 c = IEEE80211_CHAN_ANYC; 1784 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) { 1785 return EINVAL; 1786 } else { 1787 struct ieee80211_channel *c2; 1788 1789 c = findchannel(ic, ireq->i_val, ic->ic_des_mode); 1790 if (c == NULL) { 1791 c = findchannel(ic, ireq->i_val, 1792 IEEE80211_MODE_AUTO); 1793 if (c == NULL) 1794 return EINVAL; 1795 } 1796 /* 1797 * Fine tune channel selection based on desired mode: 1798 * if 11b is requested, find the 11b version of any 1799 * 11g channel returned, 1800 * if static turbo, find the turbo version of any 1801 * 11a channel return, 1802 * if 11na is requested, find the ht version of any 1803 * 11a channel returned, 1804 * if 11ng is requested, find the ht version of any 1805 * 11g channel returned, 1806 * otherwise we should be ok with what we've got. 1807 */ 1808 switch (ic->ic_des_mode) { 1809 case IEEE80211_MODE_11B: 1810 if (IEEE80211_IS_CHAN_ANYG(c)) { 1811 c2 = findchannel(ic, ireq->i_val, 1812 IEEE80211_MODE_11B); 1813 /* NB: should not happen, =>'s 11g w/o 11b */ 1814 if (c2 != NULL) 1815 c = c2; 1816 } 1817 break; 1818 case IEEE80211_MODE_TURBO_A: 1819 if (IEEE80211_IS_CHAN_A(c)) { 1820 c2 = findchannel(ic, ireq->i_val, 1821 IEEE80211_MODE_TURBO_A); 1822 if (c2 != NULL) 1823 c = c2; 1824 } 1825 break; 1826 case IEEE80211_MODE_11NA: 1827 if (IEEE80211_IS_CHAN_A(c)) { 1828 c2 = findchannel(ic, ireq->i_val, 1829 IEEE80211_MODE_11NA); 1830 if (c2 != NULL) 1831 c = c2; 1832 } 1833 break; 1834 case IEEE80211_MODE_11NG: 1835 if (IEEE80211_IS_CHAN_ANYG(c)) { 1836 c2 = findchannel(ic, ireq->i_val, 1837 IEEE80211_MODE_11NG); 1838 if (c2 != NULL) 1839 c = c2; 1840 } 1841 break; 1842 default: /* NB: no static turboG */ 1843 break; 1844 } 1845 } 1846 return setcurchan(ic, c); 1847 } 1848 1849 /* 1850 * New/current api for setting the current channel; a complete 1851 * channel description is provide so there is no ambiguity in 1852 * identifying the channel. 1853 */ 1854 static int 1855 ieee80211_ioctl_setcurchan(struct ieee80211com *ic, 1856 const struct ieee80211req *ireq) 1857 { 1858 struct ieee80211_channel chan, *c; 1859 int error; 1860 1861 if (ireq->i_len != sizeof(chan)) 1862 return EINVAL; 1863 error = copyin(ireq->i_data, &chan, sizeof(chan)); 1864 if (error != 0) 1865 return error; 1866 /* XXX 0xffff overflows 16-bit signed */ 1867 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { 1868 c = IEEE80211_CHAN_ANYC; 1869 } else { 1870 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); 1871 if (c == NULL) 1872 return EINVAL; 1873 } 1874 return setcurchan(ic, c); 1875 } 1876 1877 static int 1878 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1879 { 1880 static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 1881 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1882 int error; 1883 const struct ieee80211_authenticator *auth; 1884 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 1885 char tmpssid[IEEE80211_NWID_LEN]; 1886 uint8_t tmpbssid[IEEE80211_ADDR_LEN]; 1887 struct ieee80211_key *k; 1888 int j, caps; 1889 u_int kid; 1890 1891 error = 0; 1892 switch (ireq->i_type) { 1893 case IEEE80211_IOC_SSID: 1894 if (ireq->i_val != 0 || 1895 ireq->i_len > IEEE80211_NWID_LEN) 1896 return EINVAL; 1897 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 1898 if (error) 1899 break; 1900 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); 1901 ic->ic_des_ssid[0].len = ireq->i_len; 1902 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len); 1903 ic->ic_des_nssid = (ireq->i_len > 0); 1904 if (IS_UP_AUTO(ic)) 1905 error = ieee80211_init(ic, RESCAN); 1906 break; 1907 case IEEE80211_IOC_WEP: 1908 switch (ireq->i_val) { 1909 case IEEE80211_WEP_OFF: 1910 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1911 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1912 break; 1913 case IEEE80211_WEP_ON: 1914 ic->ic_flags |= IEEE80211_F_PRIVACY; 1915 ic->ic_flags |= IEEE80211_F_DROPUNENC; 1916 break; 1917 case IEEE80211_WEP_MIXED: 1918 ic->ic_flags |= IEEE80211_F_PRIVACY; 1919 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1920 break; 1921 } 1922 if (IS_UP_AUTO(ic)) 1923 error = ieee80211_init(ic, RESCAN); 1924 break; 1925 case IEEE80211_IOC_WEPKEY: 1926 kid = (u_int) ireq->i_val; 1927 if (kid >= IEEE80211_WEP_NKID) 1928 return EINVAL; 1929 k = &ic->ic_nw_keys[kid]; 1930 if (ireq->i_len == 0) { 1931 /* zero-len =>'s delete any existing key */ 1932 (void) ieee80211_crypto_delkey(ic, k); 1933 break; 1934 } 1935 if (ireq->i_len > sizeof(tmpkey)) 1936 return EINVAL; 1937 memset(tmpkey, 0, sizeof(tmpkey)); 1938 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 1939 if (error) 1940 break; 1941 ieee80211_key_update_begin(ic); 1942 k->wk_keyix = kid; /* NB: force fixed key id */ 1943 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 1944 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 1945 k->wk_keylen = ireq->i_len; 1946 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 1947 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 1948 error = EINVAL; 1949 } else 1950 error = EINVAL; 1951 ieee80211_key_update_end(ic); 1952 break; 1953 case IEEE80211_IOC_WEPTXKEY: 1954 kid = (u_int) ireq->i_val; 1955 if (kid >= IEEE80211_WEP_NKID && 1956 (uint16_t) kid != IEEE80211_KEYIX_NONE) 1957 return EINVAL; 1958 ic->ic_def_txkey = kid; 1959 break; 1960 case IEEE80211_IOC_AUTHMODE: 1961 switch (ireq->i_val) { 1962 case IEEE80211_AUTH_WPA: 1963 case IEEE80211_AUTH_8021X: /* 802.1x */ 1964 case IEEE80211_AUTH_OPEN: /* open */ 1965 case IEEE80211_AUTH_SHARED: /* shared-key */ 1966 case IEEE80211_AUTH_AUTO: /* auto */ 1967 auth = ieee80211_authenticator_get(ireq->i_val); 1968 if (auth == NULL) 1969 return EINVAL; 1970 break; 1971 default: 1972 return EINVAL; 1973 } 1974 switch (ireq->i_val) { 1975 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 1976 ic->ic_flags |= IEEE80211_F_PRIVACY; 1977 ireq->i_val = IEEE80211_AUTH_8021X; 1978 break; 1979 case IEEE80211_AUTH_OPEN: /* open */ 1980 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 1981 break; 1982 case IEEE80211_AUTH_SHARED: /* shared-key */ 1983 case IEEE80211_AUTH_8021X: /* 802.1x */ 1984 ic->ic_flags &= ~IEEE80211_F_WPA; 1985 /* both require a key so mark the PRIVACY capability */ 1986 ic->ic_flags |= IEEE80211_F_PRIVACY; 1987 break; 1988 case IEEE80211_AUTH_AUTO: /* auto */ 1989 ic->ic_flags &= ~IEEE80211_F_WPA; 1990 /* XXX PRIVACY handling? */ 1991 /* XXX what's the right way to do this? */ 1992 break; 1993 } 1994 /* NB: authenticator attach/detach happens on state change */ 1995 ic->ic_bss->ni_authmode = ireq->i_val; 1996 /* XXX mixed/mode/usage? */ 1997 ic->ic_auth = auth; 1998 if (IS_UP_AUTO(ic)) 1999 error = ieee80211_init(ic, RESCAN); 2000 break; 2001 case IEEE80211_IOC_CHANNEL: 2002 error = ieee80211_ioctl_setchannel(ic, ireq); 2003 break; 2004 case IEEE80211_IOC_POWERSAVE: 2005 switch (ireq->i_val) { 2006 case IEEE80211_POWERSAVE_OFF: 2007 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2008 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2009 error = ENETRESET; 2010 } 2011 break; 2012 case IEEE80211_POWERSAVE_ON: 2013 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 2014 error = EINVAL; 2015 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2016 ic->ic_flags |= IEEE80211_F_PMGTON; 2017 error = ENETRESET; 2018 } 2019 break; 2020 default: 2021 error = EINVAL; 2022 break; 2023 } 2024 if (error == ENETRESET) { 2025 /* 2026 * Switching in+out of power save mode 2027 * should not require a state change. 2028 */ 2029 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2030 } 2031 break; 2032 case IEEE80211_IOC_POWERSAVESLEEP: 2033 if (ireq->i_val < 0) 2034 return EINVAL; 2035 ic->ic_lintval = ireq->i_val; 2036 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2037 break; 2038 case IEEE80211_IOC_RTSTHRESHOLD: 2039 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2040 ireq->i_val <= IEEE80211_RTS_MAX)) 2041 return EINVAL; 2042 ic->ic_rtsthreshold = ireq->i_val; 2043 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2044 break; 2045 case IEEE80211_IOC_PROTMODE: 2046 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2047 return EINVAL; 2048 ic->ic_protmode = ireq->i_val; 2049 /* NB: if not operating in 11g this can wait */ 2050 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2051 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2052 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2053 break; 2054 case IEEE80211_IOC_TXPOWER: 2055 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2056 return EINVAL; 2057 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val && 2058 ireq->i_val <= IEEE80211_TXPOWER_MAX)) 2059 return EINVAL; 2060 ic->ic_txpowlimit = ireq->i_val; 2061 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2062 break; 2063 case IEEE80211_IOC_ROAMING: 2064 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2065 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2066 return EINVAL; 2067 ic->ic_roaming = ireq->i_val; 2068 /* XXXX reset? */ 2069 break; 2070 case IEEE80211_IOC_PRIVACY: 2071 if (ireq->i_val) { 2072 /* XXX check for key state? */ 2073 ic->ic_flags |= IEEE80211_F_PRIVACY; 2074 } else 2075 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2076 break; 2077 case IEEE80211_IOC_DROPUNENCRYPTED: 2078 if (ireq->i_val) 2079 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2080 else 2081 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2082 break; 2083 case IEEE80211_IOC_WPAKEY: 2084 error = ieee80211_ioctl_setkey(ic, ireq); 2085 break; 2086 case IEEE80211_IOC_DELKEY: 2087 error = ieee80211_ioctl_delkey(ic, ireq); 2088 break; 2089 case IEEE80211_IOC_MLME: 2090 error = ieee80211_ioctl_setmlme(ic, ireq); 2091 break; 2092 case IEEE80211_IOC_OPTIE: 2093 error = ieee80211_ioctl_setoptie(ic, ireq); 2094 break; 2095 case IEEE80211_IOC_COUNTERMEASURES: 2096 if (ireq->i_val) { 2097 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 2098 return EINVAL; 2099 ic->ic_flags |= IEEE80211_F_COUNTERM; 2100 } else 2101 ic->ic_flags &= ~IEEE80211_F_COUNTERM; 2102 break; 2103 case IEEE80211_IOC_WPA: 2104 if (ireq->i_val > 3) 2105 return EINVAL; 2106 /* XXX verify ciphers available */ 2107 ic->ic_flags &= ~IEEE80211_F_WPA; 2108 switch (ireq->i_val) { 2109 case 1: 2110 ic->ic_flags |= IEEE80211_F_WPA1; 2111 break; 2112 case 2: 2113 ic->ic_flags |= IEEE80211_F_WPA2; 2114 break; 2115 case 3: 2116 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2117 break; 2118 } 2119 error = ENETRESET; 2120 break; 2121 case IEEE80211_IOC_WME: 2122 if (ireq->i_val) { 2123 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2124 return EINVAL; 2125 ic->ic_flags |= IEEE80211_F_WME; 2126 } else 2127 ic->ic_flags &= ~IEEE80211_F_WME; 2128 if (IS_UP_AUTO(ic)) 2129 error = ieee80211_init(ic, 0); 2130 break; 2131 case IEEE80211_IOC_HIDESSID: 2132 if (ireq->i_val) 2133 ic->ic_flags |= IEEE80211_F_HIDESSID; 2134 else 2135 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2136 error = ENETRESET; 2137 break; 2138 case IEEE80211_IOC_APBRIDGE: 2139 if (ireq->i_val == 0) 2140 ic->ic_flags |= IEEE80211_F_NOBRIDGE; 2141 else 2142 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE; 2143 break; 2144 case IEEE80211_IOC_MCASTCIPHER: 2145 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 && 2146 !ieee80211_crypto_available(ireq->i_val)) 2147 return EINVAL; 2148 rsn->rsn_mcastcipher = ireq->i_val; 2149 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2150 break; 2151 case IEEE80211_IOC_MCASTKEYLEN: 2152 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2153 return EINVAL; 2154 /* XXX no way to verify driver capability */ 2155 rsn->rsn_mcastkeylen = ireq->i_val; 2156 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2157 break; 2158 case IEEE80211_IOC_UCASTCIPHERS: 2159 /* 2160 * Convert user-specified cipher set to the set 2161 * we can support (via hardware or software). 2162 * NB: this logic intentionally ignores unknown and 2163 * unsupported ciphers so folks can specify 0xff or 2164 * similar and get all available ciphers. 2165 */ 2166 caps = 0; 2167 for (j = 1; j < 32; j++) /* NB: skip WEP */ 2168 if ((ireq->i_val & (1<<j)) && 2169 ((ic->ic_caps & cipher2cap(j)) || 2170 ieee80211_crypto_available(j))) 2171 caps |= 1<<j; 2172 if (caps == 0) /* nothing available */ 2173 return EINVAL; 2174 /* XXX verify ciphers ok for unicast use? */ 2175 /* XXX disallow if running as it'll have no effect */ 2176 rsn->rsn_ucastcipherset = caps; 2177 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2178 break; 2179 case IEEE80211_IOC_UCASTCIPHER: 2180 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0) 2181 return EINVAL; 2182 rsn->rsn_ucastcipher = ireq->i_val; 2183 break; 2184 case IEEE80211_IOC_UCASTKEYLEN: 2185 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2186 return EINVAL; 2187 /* XXX no way to verify driver capability */ 2188 rsn->rsn_ucastkeylen = ireq->i_val; 2189 break; 2190 case IEEE80211_IOC_DRIVER_CAPS: 2191 /* NB: for testing */ 2192 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) | 2193 ((uint16_t) ireq->i_len); 2194 break; 2195 case IEEE80211_IOC_KEYMGTALGS: 2196 /* XXX check */ 2197 rsn->rsn_keymgmtset = ireq->i_val; 2198 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2199 break; 2200 case IEEE80211_IOC_RSNCAPS: 2201 /* XXX check */ 2202 rsn->rsn_caps = ireq->i_val; 2203 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2204 break; 2205 case IEEE80211_IOC_BSSID: 2206 if (ireq->i_len != sizeof(tmpbssid)) 2207 return EINVAL; 2208 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2209 if (error) 2210 break; 2211 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2212 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2213 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2214 else 2215 ic->ic_flags |= IEEE80211_F_DESBSSID; 2216 if (IS_UP_AUTO(ic)) 2217 error = ieee80211_init(ic, RESCAN); 2218 break; 2219 case IEEE80211_IOC_CHANLIST: 2220 error = ieee80211_ioctl_setchanlist(ic, ireq); 2221 break; 2222 case IEEE80211_IOC_SCAN_REQ: 2223 if (!IS_UP(ic)) 2224 return EINVAL; 2225 (void) ieee80211_start_scan(ic, 2226 IEEE80211_SCAN_ACTIVE | 2227 IEEE80211_SCAN_NOPICK | 2228 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER, 2229 /* XXX use ioctl params */ 2230 ic->ic_des_nssid, ic->ic_des_ssid); 2231 break; 2232 case IEEE80211_IOC_ADDMAC: 2233 case IEEE80211_IOC_DELMAC: 2234 error = ieee80211_ioctl_macmac(ic, ireq); 2235 break; 2236 case IEEE80211_IOC_MACCMD: 2237 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2238 break; 2239 case IEEE80211_IOC_STA_STATS: 2240 error = ieee80211_ioctl_setstastats(ic, ireq); 2241 break; 2242 case IEEE80211_IOC_STA_TXPOW: 2243 error = ieee80211_ioctl_setstatxpow(ic, ireq); 2244 break; 2245 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2246 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2247 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2248 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2249 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2250 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2251 error = ieee80211_ioctl_setwmeparam(ic, ireq); 2252 break; 2253 case IEEE80211_IOC_DTIM_PERIOD: 2254 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2255 ic->ic_opmode != IEEE80211_M_IBSS) 2256 return EINVAL; 2257 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2258 ireq->i_val <= IEEE80211_DTIM_MAX) { 2259 ic->ic_dtim_period = ireq->i_val; 2260 error = ENETRESET; /* requires restart */ 2261 } else 2262 error = EINVAL; 2263 break; 2264 case IEEE80211_IOC_BEACON_INTERVAL: 2265 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2266 ic->ic_opmode != IEEE80211_M_IBSS) 2267 return EINVAL; 2268 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2269 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2270 ic->ic_bintval = ireq->i_val; 2271 error = ENETRESET; /* requires restart */ 2272 } else 2273 error = EINVAL; 2274 break; 2275 case IEEE80211_IOC_PUREG: 2276 if (ireq->i_val) 2277 ic->ic_flags |= IEEE80211_F_PUREG; 2278 else 2279 ic->ic_flags &= ~IEEE80211_F_PUREG; 2280 /* NB: reset only if we're operating on an 11g channel */ 2281 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2282 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) 2283 error = ENETRESET; 2284 break; 2285 case IEEE80211_IOC_FF: 2286 if (ireq->i_val) { 2287 if ((ic->ic_caps & IEEE80211_C_FF) == 0) 2288 return EINVAL; 2289 ic->ic_flags |= IEEE80211_F_FF; 2290 } else 2291 ic->ic_flags &= ~IEEE80211_F_FF; 2292 error = ENETRESET; 2293 break; 2294 case IEEE80211_IOC_TURBOP: 2295 if (ireq->i_val) { 2296 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0) 2297 return EINVAL; 2298 ic->ic_flags |= IEEE80211_F_TURBOP; 2299 } else 2300 ic->ic_flags &= ~IEEE80211_F_TURBOP; 2301 error = ENETRESET; 2302 break; 2303 case IEEE80211_IOC_BGSCAN: 2304 if (ireq->i_val) { 2305 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0) 2306 return EINVAL; 2307 ic->ic_flags |= IEEE80211_F_BGSCAN; 2308 } else 2309 ic->ic_flags &= ~IEEE80211_F_BGSCAN; 2310 break; 2311 case IEEE80211_IOC_BGSCAN_IDLE: 2312 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN) 2313 ic->ic_bgscanidle = ireq->i_val*hz/1000; 2314 else 2315 error = EINVAL; 2316 break; 2317 case IEEE80211_IOC_BGSCAN_INTERVAL: 2318 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN) 2319 ic->ic_bgscanintvl = ireq->i_val*hz; 2320 else 2321 error = EINVAL; 2322 break; 2323 case IEEE80211_IOC_SCANVALID: 2324 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN) 2325 ic->ic_scanvalid = ireq->i_val*hz; 2326 else 2327 error = EINVAL; 2328 break; 2329 case IEEE80211_IOC_ROAM_RSSI_11A: 2330 ic->ic_roam.rssi11a = ireq->i_val; 2331 break; 2332 case IEEE80211_IOC_ROAM_RSSI_11B: 2333 ic->ic_roam.rssi11bOnly = ireq->i_val; 2334 break; 2335 case IEEE80211_IOC_ROAM_RSSI_11G: 2336 ic->ic_roam.rssi11b = ireq->i_val; 2337 break; 2338 case IEEE80211_IOC_ROAM_RATE_11A: 2339 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL; 2340 break; 2341 case IEEE80211_IOC_ROAM_RATE_11B: 2342 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL; 2343 break; 2344 case IEEE80211_IOC_ROAM_RATE_11G: 2345 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL; 2346 break; 2347 case IEEE80211_IOC_MCAST_RATE: 2348 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2349 break; 2350 case IEEE80211_IOC_FRAGTHRESHOLD: 2351 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2352 ireq->i_val != IEEE80211_FRAG_MAX) 2353 return EINVAL; 2354 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && 2355 ireq->i_val <= IEEE80211_FRAG_MAX)) 2356 return EINVAL; 2357 ic->ic_fragthreshold = ireq->i_val; 2358 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2359 break; 2360 case IEEE80211_IOC_BURST: 2361 if (ireq->i_val) { 2362 if ((ic->ic_caps & IEEE80211_C_BURST) == 0) 2363 return EINVAL; 2364 ic->ic_flags |= IEEE80211_F_BURST; 2365 } else 2366 ic->ic_flags &= ~IEEE80211_F_BURST; 2367 error = ENETRESET; /* XXX maybe not for station? */ 2368 break; 2369 case IEEE80211_IOC_BMISSTHRESHOLD: 2370 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val && 2371 ireq->i_val <= IEEE80211_HWBMISS_MAX)) 2372 return EINVAL; 2373 ic->ic_bmissthreshold = ireq->i_val; 2374 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2375 break; 2376 case IEEE80211_IOC_CURCHAN: 2377 error = ieee80211_ioctl_setcurchan(ic, ireq); 2378 break; 2379 case IEEE80211_IOC_SHORTGI: 2380 if (ireq->i_val) { 2381 #define IEEE80211_HTCAP_SHORTGI \ 2382 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) 2383 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0) 2384 return EINVAL; 2385 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20) 2386 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20; 2387 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40) 2388 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40; 2389 #undef IEEE80211_HTCAP_SHORTGI 2390 } else 2391 ic->ic_flags_ext &= 2392 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40); 2393 /* XXX kick state machine? */ 2394 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2395 break; 2396 case IEEE80211_IOC_AMPDU: 2397 if (ireq->i_val) { 2398 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0) 2399 return EINVAL; 2400 if (ireq->i_val & 1) 2401 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX; 2402 if (ireq->i_val & 2) 2403 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX; 2404 } else 2405 ic->ic_flags_ext &= 2406 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX); 2407 /* NB: reset only if we're operating on an 11n channel */ 2408 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2409 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2410 error = ENETRESET; 2411 break; 2412 case IEEE80211_IOC_AMPDU_LIMIT: 2413 /* XXX validate */ 2414 ic->ic_ampdu_limit = ireq->i_val; 2415 break; 2416 case IEEE80211_IOC_AMPDU_DENSITY: 2417 /* XXX validate */ 2418 ic->ic_ampdu_density = ireq->i_val; 2419 break; 2420 case IEEE80211_IOC_AMSDU: 2421 if (ireq->i_val) { 2422 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0) 2423 return EINVAL; 2424 if (ireq->i_val & 1) 2425 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX; 2426 if (ireq->i_val & 2) 2427 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX; 2428 } else 2429 ic->ic_flags_ext &= 2430 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX); 2431 /* NB: reset only if we're operating on an 11n channel */ 2432 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2433 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2434 error = ENETRESET; 2435 break; 2436 case IEEE80211_IOC_AMSDU_LIMIT: 2437 /* XXX validate */ 2438 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */ 2439 break; 2440 case IEEE80211_IOC_PUREN: 2441 if (ireq->i_val) { 2442 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2443 return EINVAL; 2444 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN; 2445 } else 2446 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN; 2447 /* NB: reset only if we're operating on an 11n channel */ 2448 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2449 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2450 error = ENETRESET; 2451 break; 2452 case IEEE80211_IOC_DOTH: 2453 if (ireq->i_val) { 2454 #if 0 2455 /* XXX no capability */ 2456 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0) 2457 return EINVAL; 2458 #endif 2459 ic->ic_flags |= IEEE80211_F_DOTH; 2460 } else 2461 ic->ic_flags &= ~IEEE80211_F_DOTH; 2462 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2463 break; 2464 case IEEE80211_IOC_HTCOMPAT: 2465 if (ireq->i_val) { 2466 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2467 return EINVAL; 2468 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT; 2469 } else 2470 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT; 2471 /* NB: reset only if we're operating on an 11n channel */ 2472 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2473 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2474 error = ENETRESET; 2475 break; 2476 case IEEE80211_IOC_INACTIVITY: 2477 if (ireq->i_val) 2478 ic->ic_flags_ext |= IEEE80211_FEXT_INACT; 2479 else 2480 ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT; 2481 break; 2482 default: 2483 error = EINVAL; 2484 break; 2485 } 2486 if (error == ENETRESET) 2487 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0; 2488 return error; 2489 } 2490 2491 int 2492 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2493 { 2494 struct ifnet *ifp = ic->ic_ifp; 2495 int error = 0; 2496 struct ifreq *ifr; 2497 struct ifaddr *ifa; /* XXX */ 2498 2499 switch (cmd) { 2500 case SIOCSIFMEDIA: 2501 case SIOCGIFMEDIA: 2502 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 2503 &ic->ic_media, cmd); 2504 break; 2505 case SIOCG80211: 2506 error = ieee80211_ioctl_get80211(ic, cmd, 2507 (struct ieee80211req *) data); 2508 break; 2509 case SIOCS80211: 2510 error = priv_check(curthread, PRIV_NET80211_MANAGE); 2511 if (error == 0) 2512 error = ieee80211_ioctl_set80211(ic, cmd, 2513 (struct ieee80211req *) data); 2514 break; 2515 case SIOCG80211STATS: 2516 ifr = (struct ifreq *)data; 2517 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2518 break; 2519 case SIOCSIFMTU: 2520 ifr = (struct ifreq *)data; 2521 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2522 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2523 error = EINVAL; 2524 else 2525 ifp->if_mtu = ifr->ifr_mtu; 2526 break; 2527 case SIOCSIFADDR: 2528 /* 2529 * XXX Handle this directly so we can supress if_init calls. 2530 * XXX This should be done in ether_ioctl but for the moment 2531 * XXX there are too many other parts of the system that 2532 * XXX set IFF_UP and so supress if_init being called when 2533 * XXX it should be. 2534 */ 2535 ifa = (struct ifaddr *) data; 2536 switch (ifa->ifa_addr->sa_family) { 2537 #ifdef INET 2538 case AF_INET: 2539 if ((ifp->if_flags & IFF_UP) == 0) { 2540 ifp->if_flags |= IFF_UP; 2541 ifp->if_init(ifp->if_softc); 2542 } 2543 arp_ifinit(ifp, ifa); 2544 break; 2545 #endif 2546 #ifdef IPX 2547 /* 2548 * XXX - This code is probably wrong, 2549 * but has been copied many times. 2550 */ 2551 case AF_IPX: { 2552 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 2553 2554 if (ipx_nullhost(*ina)) 2555 ina->x_host = *(union ipx_host *) 2556 IF_LLADDR(ifp); 2557 else 2558 bcopy((caddr_t) ina->x_host.c_host, 2559 (caddr_t) IF_LLADDR(ifp), 2560 ETHER_ADDR_LEN); 2561 /* fall thru... */ 2562 } 2563 #endif 2564 default: 2565 if ((ifp->if_flags & IFF_UP) == 0) { 2566 ifp->if_flags |= IFF_UP; 2567 ifp->if_init(ifp->if_softc); 2568 } 2569 break; 2570 } 2571 break; 2572 default: 2573 error = ether_ioctl(ifp, cmd, data); 2574 break; 2575 } 2576 return error; 2577 } 2578