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