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