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