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