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