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