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