1 /* $NetBSD: ieee80211_ioctl.c,v 1.30 2006/03/02 03:38:48 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.35 2005/08/30 14:27:47 avatar Exp $"); 37 #endif 38 #ifdef __NetBSD__ 39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.30 2006/03/02 03:38:48 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 #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 u_int ielen = 0; 1004 1005 memset(sr, 0, sizeof(*sr)); 1006 sr->isr_ssid_len = ni->ni_esslen; 1007 if (ni->ni_wpa_ie != NULL) 1008 ielen += 2+ni->ni_wpa_ie[1]; 1009 if (ni->ni_wme_ie != NULL) 1010 ielen += 2+ni->ni_wme_ie[1]; 1011 1012 /* 1013 * The value sr->isr_ie_len is defined as a uint8_t, so we 1014 * need to be careful to avoid an integer overflow. If the 1015 * value would overflow, we will set isr_ie_len to zero, and 1016 * ieee80211_ioctl_getscanresults (below) will avoid copying 1017 * the (overflowing) data. 1018 */ 1019 if (ielen > 255) 1020 ielen = 0; 1021 sr->isr_ie_len = ielen; 1022 sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len; 1023 sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t)); 1024 if (ni->ni_chan != IEEE80211_CHAN_ANYC) { 1025 sr->isr_freq = ni->ni_chan->ic_freq; 1026 sr->isr_flags = ni->ni_chan->ic_flags; 1027 } 1028 sr->isr_rssi = ic->ic_node_getrssi(ni); 1029 sr->isr_intval = ni->ni_intval; 1030 sr->isr_capinfo = ni->ni_capinfo; 1031 sr->isr_erp = ni->ni_erp; 1032 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid); 1033 sr->isr_nrates = ni->ni_rates.rs_nrates; 1034 if (sr->isr_nrates > 15) 1035 sr->isr_nrates = 15; 1036 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates); 1037 } 1038 1039 static int 1040 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 1041 { 1042 union { 1043 struct ieee80211req_scan_result res; 1044 char data[sizeof(struct ieee80211req_scan_result) + IEEE80211_NWID_LEN + 256 * 2]; 1045 } u; 1046 struct ieee80211req_scan_result *sr = &u.res; 1047 struct ieee80211_node_table *nt; 1048 struct ieee80211_node *ni; 1049 int error, space; 1050 u_int8_t *p, *cp; 1051 1052 p = ireq->i_data; 1053 space = ireq->i_len; 1054 error = 0; 1055 /* XXX locking */ 1056 nt = &ic->ic_scan; 1057 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 1058 /* NB: skip pre-scan node state */ 1059 if (ni->ni_chan == IEEE80211_CHAN_ANYC) 1060 continue; 1061 get_scan_result(sr, ni); 1062 if (sr->isr_len > sizeof(u)) 1063 continue; /* XXX */ 1064 if (space < sr->isr_len) 1065 break; 1066 cp = (u_int8_t *)(sr+1); 1067 memcpy(cp, ni->ni_essid, ni->ni_esslen); 1068 cp += ni->ni_esslen; 1069 if (sr->isr_ie_len > 0 && ni->ni_wpa_ie != NULL) { 1070 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1071 cp += 2+ni->ni_wpa_ie[1]; 1072 } 1073 if (sr->isr_ie_len > 0 && ni->ni_wme_ie != NULL) { 1074 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1075 cp += 2+ni->ni_wme_ie[1]; 1076 } 1077 error = copyout(sr, p, sr->isr_len); 1078 if (error) 1079 break; 1080 p += sr->isr_len; 1081 space -= sr->isr_len; 1082 } 1083 ireq->i_len -= space; 1084 return error; 1085 } 1086 1087 struct stainforeq { 1088 struct ieee80211com *ic; 1089 struct ieee80211req_sta_info *si; 1090 size_t space; 1091 }; 1092 1093 static size_t 1094 sta_space(const struct ieee80211_node *ni, size_t *ielen) 1095 { 1096 *ielen = 0; 1097 if (ni->ni_wpa_ie != NULL) 1098 *ielen += 2+ni->ni_wpa_ie[1]; 1099 if (ni->ni_wme_ie != NULL) 1100 *ielen += 2+ni->ni_wme_ie[1]; 1101 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, 1102 sizeof(u_int32_t)); 1103 } 1104 1105 static void 1106 get_sta_space(void *arg, struct ieee80211_node *ni) 1107 { 1108 struct stainforeq *req = arg; 1109 struct ieee80211com *ic = ni->ni_ic; 1110 size_t ielen; 1111 1112 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1113 ni->ni_associd == 0) /* only associated stations */ 1114 return; 1115 req->space += sta_space(ni, &ielen); 1116 } 1117 1118 static void 1119 get_sta_info(void *arg, struct ieee80211_node *ni) 1120 { 1121 struct stainforeq *req = arg; 1122 struct ieee80211com *ic = ni->ni_ic; 1123 struct ieee80211req_sta_info *si; 1124 size_t ielen, len; 1125 u_int8_t *cp; 1126 1127 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1128 ni->ni_associd == 0) /* only associated stations */ 1129 return; 1130 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 1131 return; 1132 len = sta_space(ni, &ielen); 1133 if (len > req->space) 1134 return; 1135 si = req->si; 1136 si->isi_len = len; 1137 si->isi_ie_len = ielen; 1138 si->isi_freq = ni->ni_chan->ic_freq; 1139 si->isi_flags = ni->ni_chan->ic_flags; 1140 si->isi_state = ni->ni_flags; 1141 si->isi_authmode = ni->ni_authmode; 1142 si->isi_rssi = ic->ic_node_getrssi(ni); 1143 si->isi_capinfo = ni->ni_capinfo; 1144 si->isi_erp = ni->ni_erp; 1145 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 1146 si->isi_nrates = ni->ni_rates.rs_nrates; 1147 if (si->isi_nrates > 15) 1148 si->isi_nrates = 15; 1149 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 1150 si->isi_txrate = ni->ni_txrate; 1151 si->isi_associd = ni->ni_associd; 1152 si->isi_txpower = ni->ni_txpower; 1153 si->isi_vlan = ni->ni_vlan; 1154 if (ni->ni_flags & IEEE80211_NODE_QOS) { 1155 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 1156 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 1157 } else { 1158 si->isi_txseqs[0] = ni->ni_txseqs[0]; 1159 si->isi_rxseqs[0] = ni->ni_rxseqs[0]; 1160 } 1161 /* NB: leave all cases in case we relax ni_associd == 0 check */ 1162 if (ieee80211_node_is_authorized(ni)) 1163 si->isi_inact = ic->ic_inact_run; 1164 else if (ni->ni_associd != 0) 1165 si->isi_inact = ic->ic_inact_auth; 1166 else 1167 si->isi_inact = ic->ic_inact_init; 1168 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 1169 1170 cp = (u_int8_t *)(si+1); 1171 if (ni->ni_wpa_ie != NULL) { 1172 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1173 cp += 2+ni->ni_wpa_ie[1]; 1174 } 1175 if (ni->ni_wme_ie != NULL) { 1176 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1177 cp += 2+ni->ni_wme_ie[1]; 1178 } 1179 1180 req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len); 1181 req->space -= len; 1182 } 1183 1184 static int 1185 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 1186 { 1187 struct stainforeq req; 1188 int error; 1189 1190 if (ireq->i_len < sizeof(struct stainforeq)) 1191 return EFAULT; 1192 1193 error = 0; 1194 req.space = 0; 1195 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); 1196 if (req.space > ireq->i_len) 1197 req.space = ireq->i_len; 1198 if (req.space > 0) { 1199 size_t space; 1200 void *p; 1201 1202 space = req.space; 1203 /* XXX M_WAITOK after driver lock released */ 1204 MALLOC(p, void *, space, M_TEMP, M_NOWAIT); 1205 if (p == NULL) 1206 return ENOMEM; 1207 req.si = p; 1208 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 1209 ireq->i_len = space - req.space; 1210 error = copyout(p, ireq->i_data, ireq->i_len); 1211 FREE(p, M_TEMP); 1212 } else 1213 ireq->i_len = 0; 1214 1215 return error; 1216 } 1217 1218 static int 1219 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1220 { 1221 struct ieee80211_node *ni; 1222 struct ieee80211req_sta_txpow txpow; 1223 int error; 1224 1225 if (ireq->i_len != sizeof(txpow)) 1226 return EINVAL; 1227 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1228 if (error != 0) 1229 return error; 1230 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 1231 if (ni == NULL) 1232 return EINVAL; /* XXX */ 1233 txpow.it_txpow = ni->ni_txpower; 1234 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 1235 ieee80211_free_node(ni); 1236 return error; 1237 } 1238 1239 static int 1240 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1241 { 1242 struct ieee80211_wme_state *wme = &ic->ic_wme; 1243 struct wmeParams *wmep; 1244 int ac; 1245 1246 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1247 return EINVAL; 1248 1249 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1250 if (ac >= WME_NUM_AC) 1251 ac = WME_AC_BE; 1252 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 1253 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1254 else 1255 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1256 switch (ireq->i_type) { 1257 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1258 ireq->i_val = wmep->wmep_logcwmin; 1259 break; 1260 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1261 ireq->i_val = wmep->wmep_logcwmax; 1262 break; 1263 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1264 ireq->i_val = wmep->wmep_aifsn; 1265 break; 1266 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1267 ireq->i_val = wmep->wmep_txopLimit; 1268 break; 1269 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1270 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1271 ireq->i_val = wmep->wmep_acm; 1272 break; 1273 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1274 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1275 ireq->i_val = !wmep->wmep_noackPolicy; 1276 break; 1277 } 1278 return 0; 1279 } 1280 1281 static int 1282 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1283 { 1284 const struct ieee80211_aclator *acl = ic->ic_acl; 1285 1286 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); 1287 } 1288 1289 /* 1290 * When building the kernel with -O2 on the i386 architecture, gcc 1291 * seems to want to inline this function into ieee80211_ioctl() 1292 * (which is the only routine that calls it). When this happens, 1293 * ieee80211_ioctl() ends up consuming an additional 2K of stack 1294 * space. (Exactly why it needs so much is unclear.) The problem 1295 * is that it's possible for ieee80211_ioctl() to invoke other 1296 * routines (including driver init functions) which could then find 1297 * themselves perilously close to exhausting the stack. 1298 * 1299 * To avoid this, we deliberately prevent gcc from inlining this 1300 * routine. Another way to avoid this is to use less agressive 1301 * optimization when compiling this file (i.e. -O instead of -O2) 1302 * but special-casing the compilation of this one module in the 1303 * build system would be awkward. 1304 */ 1305 #ifdef __GNUC__ 1306 __attribute__ ((noinline)) 1307 #endif 1308 static int 1309 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1310 { 1311 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1312 int error = 0; 1313 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 1314 u_int kid, len; 1315 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 1316 char tmpssid[IEEE80211_NWID_LEN]; 1317 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 1318 u_int m; 1319 1320 switch (ireq->i_type) { 1321 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 1322 case IEEE80211_IOC_SSID: 1323 switch (ic->ic_state) { 1324 case IEEE80211_S_INIT: 1325 case IEEE80211_S_SCAN: 1326 ireq->i_len = ic->ic_des_esslen; 1327 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len); 1328 break; 1329 default: 1330 ireq->i_len = ic->ic_bss->ni_esslen; 1331 memcpy(tmpssid, ic->ic_bss->ni_essid, 1332 ireq->i_len); 1333 break; 1334 } 1335 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 1336 break; 1337 case IEEE80211_IOC_NUMSSIDS: 1338 ireq->i_val = 1; 1339 break; 1340 case IEEE80211_IOC_WEP: 1341 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 1342 ireq->i_val = IEEE80211_WEP_OFF; 1343 else if (ic->ic_flags & IEEE80211_F_DROPUNENC) 1344 ireq->i_val = IEEE80211_WEP_ON; 1345 else 1346 ireq->i_val = IEEE80211_WEP_MIXED; 1347 break; 1348 case IEEE80211_IOC_WEPKEY: 1349 kid = (u_int) ireq->i_val; 1350 if (kid >= IEEE80211_WEP_NKID) 1351 return EINVAL; 1352 len = (u_int) ic->ic_nw_keys[kid].wk_keylen; 1353 /* NB: only root can read WEP keys */ 1354 if (suser(curproc->p_ucred, &curproc->p_acflag) == 0) { 1355 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); 1356 } else { 1357 bzero(tmpkey, len); 1358 } 1359 ireq->i_len = len; 1360 error = copyout(tmpkey, ireq->i_data, len); 1361 break; 1362 case IEEE80211_IOC_NUMWEPKEYS: 1363 ireq->i_val = IEEE80211_WEP_NKID; 1364 break; 1365 case IEEE80211_IOC_WEPTXKEY: 1366 ireq->i_val = ic->ic_def_txkey; 1367 break; 1368 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 1369 case IEEE80211_IOC_AUTHMODE: 1370 if (ic->ic_flags & IEEE80211_F_WPA) 1371 ireq->i_val = IEEE80211_AUTH_WPA; 1372 else 1373 ireq->i_val = ic->ic_bss->ni_authmode; 1374 break; 1375 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 1376 case IEEE80211_IOC_CHANNEL: 1377 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan); 1378 break; 1379 case IEEE80211_IOC_POWERSAVE: 1380 if (ic->ic_flags & IEEE80211_F_PMGTON) 1381 ireq->i_val = IEEE80211_POWERSAVE_ON; 1382 else 1383 ireq->i_val = IEEE80211_POWERSAVE_OFF; 1384 break; 1385 case IEEE80211_IOC_POWERSAVESLEEP: 1386 ireq->i_val = ic->ic_lintval; 1387 break; 1388 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 1389 case IEEE80211_IOC_RTSTHRESHOLD: 1390 ireq->i_val = ic->ic_rtsthreshold; 1391 break; 1392 case IEEE80211_IOC_PROTMODE: 1393 ireq->i_val = ic->ic_protmode; 1394 break; 1395 case IEEE80211_IOC_TXPOWER: 1396 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 1397 return EINVAL; 1398 ireq->i_val = ic->ic_txpowlimit; 1399 break; 1400 case IEEE80211_IOC_MCASTCIPHER: 1401 ireq->i_val = rsn->rsn_mcastcipher; 1402 break; 1403 case IEEE80211_IOC_MCASTKEYLEN: 1404 ireq->i_val = rsn->rsn_mcastkeylen; 1405 break; 1406 case IEEE80211_IOC_UCASTCIPHERS: 1407 ireq->i_val = 0; 1408 for (m = 0x1; m != 0; m <<= 1) 1409 if (rsn->rsn_ucastcipherset & m) 1410 ireq->i_val |= 1<<cap2cipher(m); 1411 break; 1412 case IEEE80211_IOC_UCASTCIPHER: 1413 ireq->i_val = rsn->rsn_ucastcipher; 1414 break; 1415 case IEEE80211_IOC_UCASTKEYLEN: 1416 ireq->i_val = rsn->rsn_ucastkeylen; 1417 break; 1418 case IEEE80211_IOC_KEYMGTALGS: 1419 ireq->i_val = rsn->rsn_keymgmtset; 1420 break; 1421 case IEEE80211_IOC_RSNCAPS: 1422 ireq->i_val = rsn->rsn_caps; 1423 break; 1424 case IEEE80211_IOC_WPA: 1425 switch (ic->ic_flags & IEEE80211_F_WPA) { 1426 case IEEE80211_F_WPA1: 1427 ireq->i_val = 1; 1428 break; 1429 case IEEE80211_F_WPA2: 1430 ireq->i_val = 2; 1431 break; 1432 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2: 1433 ireq->i_val = 3; 1434 break; 1435 default: 1436 ireq->i_val = 0; 1437 break; 1438 } 1439 break; 1440 case IEEE80211_IOC_CHANLIST: 1441 error = ieee80211_ioctl_getchanlist(ic, ireq); 1442 break; 1443 case IEEE80211_IOC_ROAMING: 1444 ireq->i_val = ic->ic_roaming; 1445 break; 1446 case IEEE80211_IOC_PRIVACY: 1447 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0; 1448 break; 1449 case IEEE80211_IOC_DROPUNENCRYPTED: 1450 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0; 1451 break; 1452 case IEEE80211_IOC_COUNTERMEASURES: 1453 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0; 1454 break; 1455 case IEEE80211_IOC_DRIVER_CAPS: 1456 ireq->i_val = ic->ic_caps>>16; 1457 ireq->i_len = ic->ic_caps&0xffff; 1458 break; 1459 case IEEE80211_IOC_WME: 1460 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0; 1461 break; 1462 case IEEE80211_IOC_HIDESSID: 1463 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0; 1464 break; 1465 case IEEE80211_IOC_APBRIDGE: 1466 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0; 1467 break; 1468 case IEEE80211_IOC_OPTIE: 1469 if (ic->ic_opt_ie == NULL) 1470 return EINVAL; 1471 /* NB: truncate, caller can check length */ 1472 if (ireq->i_len > ic->ic_opt_ie_len) 1473 ireq->i_len = ic->ic_opt_ie_len; 1474 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len); 1475 break; 1476 case IEEE80211_IOC_WPAKEY: 1477 error = ieee80211_ioctl_getkey(ic, ireq); 1478 break; 1479 case IEEE80211_IOC_CHANINFO: 1480 error = ieee80211_ioctl_getchaninfo(ic, ireq); 1481 break; 1482 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 1483 case IEEE80211_IOC_BSSID: 1484 if (ireq->i_len != IEEE80211_ADDR_LEN) 1485 return EINVAL; 1486 error = copyout(ic->ic_state == IEEE80211_S_RUN ? 1487 ic->ic_bss->ni_bssid : 1488 ic->ic_des_bssid, 1489 ireq->i_data, ireq->i_len); 1490 break; 1491 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 1492 case IEEE80211_IOC_WPAIE: 1493 error = ieee80211_ioctl_getwpaie(ic, ireq); 1494 break; 1495 case IEEE80211_IOC_SCAN_RESULTS: 1496 error = ieee80211_ioctl_getscanresults(ic, ireq); 1497 break; 1498 case IEEE80211_IOC_STA_STATS: 1499 error = ieee80211_ioctl_getstastats(ic, ireq); 1500 break; 1501 case IEEE80211_IOC_TXPOWMAX: 1502 ireq->i_val = ic->ic_bss->ni_txpower; 1503 break; 1504 case IEEE80211_IOC_STA_TXPOW: 1505 error = ieee80211_ioctl_getstatxpow(ic, ireq); 1506 break; 1507 case IEEE80211_IOC_STA_INFO: 1508 error = ieee80211_ioctl_getstainfo(ic, ireq); 1509 break; 1510 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1511 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1512 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1513 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1514 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1515 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 1516 error = ieee80211_ioctl_getwmeparam(ic, ireq); 1517 break; 1518 case IEEE80211_IOC_DTIM_PERIOD: 1519 ireq->i_val = ic->ic_dtim_period; 1520 break; 1521 case IEEE80211_IOC_BEACON_INTERVAL: 1522 /* NB: get from ic_bss for station mode */ 1523 ireq->i_val = ic->ic_bss->ni_intval; 1524 break; 1525 case IEEE80211_IOC_PUREG: 1526 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0; 1527 break; 1528 case IEEE80211_IOC_MCAST_RATE: 1529 ireq->i_val = ic->ic_mcast_rate; 1530 break; 1531 case IEEE80211_IOC_FRAGTHRESHOLD: 1532 ireq->i_val = ic->ic_fragthreshold; 1533 break; 1534 case IEEE80211_IOC_MACCMD: 1535 error = ieee80211_ioctl_getmaccmd(ic, ireq); 1536 break; 1537 default: 1538 error = EINVAL; 1539 break; 1540 } 1541 return error; 1542 } 1543 1544 static int 1545 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq) 1546 { 1547 int error; 1548 void *ie; 1549 1550 /* 1551 * NB: Doing this for ap operation could be useful (e.g. for 1552 * WPA and/or WME) except that it typically is worthless 1553 * without being able to intervene when processing 1554 * association response frames--so disallow it for now. 1555 */ 1556 if (ic->ic_opmode != IEEE80211_M_STA) 1557 return EINVAL; 1558 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1559 return EINVAL; 1560 /* NB: data.length is validated by the wireless extensions code */ 1561 MALLOC(ie, void *, (u_long)ireq->i_len, M_DEVBUF, M_WAITOK); 1562 if (ie == NULL) 1563 return ENOMEM; 1564 error = copyin(ireq->i_data, ie, ireq->i_len); 1565 /* XXX sanity check data? */ 1566 if (ic->ic_opt_ie != NULL) 1567 FREE(ic->ic_opt_ie, M_DEVBUF); 1568 ic->ic_opt_ie = ie; 1569 ic->ic_opt_ie_len = ireq->i_len; 1570 return 0; 1571 } 1572 1573 static int 1574 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1575 { 1576 struct ieee80211req_key ik; 1577 struct ieee80211_node *ni; 1578 struct ieee80211_key *wk; 1579 u_int16_t kid; 1580 int error; 1581 1582 if (ireq->i_len != sizeof(ik)) 1583 return EINVAL; 1584 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1585 if (error) 1586 return error; 1587 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1588 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1589 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1590 return E2BIG; 1591 kid = ik.ik_keyix; 1592 if (kid == IEEE80211_KEYIX_NONE) { 1593 /* XXX unicast keys currently must be tx/rx */ 1594 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1595 return EINVAL; 1596 if (ic->ic_opmode == IEEE80211_M_STA) { 1597 ni = ieee80211_ref_node(ic->ic_bss); 1598 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) { 1599 ieee80211_free_node(ni); 1600 return EADDRNOTAVAIL; 1601 } 1602 } else { 1603 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr); 1604 if (ni == NULL) 1605 return ENOENT; 1606 } 1607 wk = &ni->ni_ucastkey; 1608 } else { 1609 if (kid >= IEEE80211_WEP_NKID) 1610 return EINVAL; 1611 wk = &ic->ic_nw_keys[kid]; 1612 ni = NULL; 1613 } 1614 error = 0; 1615 ieee80211_key_update_begin(ic); 1616 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) { 1617 wk->wk_keylen = ik.ik_keylen; 1618 /* NB: MIC presence is implied by cipher type */ 1619 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1620 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1621 wk->wk_keyrsc = ik.ik_keyrsc; 1622 wk->wk_keytsc = 0; /* new key, reset */ 1623 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1624 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1625 if (!ieee80211_crypto_setkey(ic, wk, 1626 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr)) 1627 error = EIO; 1628 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1629 ic->ic_def_txkey = kid; 1630 } else 1631 error = ENXIO; 1632 ieee80211_key_update_end(ic); 1633 if (ni != NULL) 1634 ieee80211_free_node(ni); 1635 return error; 1636 } 1637 1638 static int 1639 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1640 { 1641 struct ieee80211req_del_key dk; 1642 int kid, error; 1643 1644 if (ireq->i_len != sizeof(dk)) 1645 return EINVAL; 1646 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1647 if (error) 1648 return error; 1649 kid = dk.idk_keyix; 1650 /* XXX u_int8_t -> u_int16_t */ 1651 if (dk.idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) { 1652 struct ieee80211_node *ni; 1653 1654 if (ic->ic_opmode == IEEE80211_M_STA) { 1655 ni = ieee80211_ref_node(ic->ic_bss); 1656 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1657 ieee80211_free_node(ni); 1658 return EADDRNOTAVAIL; 1659 } 1660 } else { 1661 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr); 1662 if (ni == NULL) 1663 return ENOENT; 1664 } 1665 /* XXX error return */ 1666 ieee80211_node_delucastkey(ni); 1667 ieee80211_free_node(ni); 1668 } else { 1669 if (kid >= IEEE80211_WEP_NKID) 1670 return EINVAL; 1671 /* XXX error return */ 1672 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]); 1673 } 1674 return 0; 1675 } 1676 1677 #ifndef IEEE80211_NO_HOSTAP 1678 static void 1679 domlme(void *arg, struct ieee80211_node *ni) 1680 { 1681 struct ieee80211com *ic = ni->ni_ic; 1682 struct ieee80211req_mlme *mlme = arg; 1683 1684 if (ni->ni_associd != 0) { 1685 IEEE80211_SEND_MGMT(ic, ni, 1686 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1687 IEEE80211_FC0_SUBTYPE_DEAUTH : 1688 IEEE80211_FC0_SUBTYPE_DISASSOC, 1689 mlme->im_reason); 1690 } 1691 ieee80211_node_leave(ic, ni); 1692 } 1693 #endif /* !IEEE80211_NO_HOSTAP */ 1694 1695 static int 1696 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1697 { 1698 struct ieee80211req_mlme mlme; 1699 struct ieee80211_node *ni; 1700 int error; 1701 1702 if (ireq->i_len != sizeof(mlme)) 1703 return EINVAL; 1704 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1705 if (error) 1706 return error; 1707 switch (mlme.im_op) { 1708 case IEEE80211_MLME_ASSOC: 1709 if (ic->ic_opmode != IEEE80211_M_STA) 1710 return EINVAL; 1711 /* XXX must be in S_SCAN state? */ 1712 1713 if (mlme.im_ssid_len != 0) { 1714 /* 1715 * Desired ssid specified; must match both bssid and 1716 * ssid to distinguish ap advertising multiple ssid's. 1717 */ 1718 ni = ieee80211_find_node_with_ssid(&ic->ic_scan, 1719 mlme.im_macaddr, 1720 mlme.im_ssid_len, mlme.im_ssid); 1721 } else { 1722 /* 1723 * Normal case; just match bssid. 1724 */ 1725 ni = ieee80211_find_node(&ic->ic_scan, mlme.im_macaddr); 1726 } 1727 if (ni == NULL) 1728 return EINVAL; 1729 if (!ieee80211_sta_join(ic, ni)) { 1730 ieee80211_free_node(ni); 1731 return EINVAL; 1732 } 1733 break; 1734 case IEEE80211_MLME_DISASSOC: 1735 case IEEE80211_MLME_DEAUTH: 1736 switch (ic->ic_opmode) { 1737 case IEEE80211_M_STA: 1738 /* XXX not quite right */ 1739 ieee80211_new_state(ic, IEEE80211_S_INIT, 1740 mlme.im_reason); 1741 break; 1742 case IEEE80211_M_HOSTAP: 1743 #ifndef IEEE80211_NO_HOSTAP 1744 /* NB: the broadcast address means do 'em all */ 1745 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) { 1746 if ((ni = ieee80211_find_node(&ic->ic_sta, 1747 mlme.im_macaddr)) == NULL) 1748 return EINVAL; 1749 domlme(&mlme, ni); 1750 ieee80211_free_node(ni); 1751 } else { 1752 ieee80211_iterate_nodes(&ic->ic_sta, 1753 domlme, &mlme); 1754 } 1755 #endif /* !IEEE80211_NO_HOSTAP */ 1756 break; 1757 default: 1758 return EINVAL; 1759 } 1760 break; 1761 case IEEE80211_MLME_AUTHORIZE: 1762 case IEEE80211_MLME_UNAUTHORIZE: 1763 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1764 return EINVAL; 1765 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr); 1766 if (ni == NULL) 1767 return EINVAL; 1768 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE) 1769 ieee80211_node_authorize(ni); 1770 else 1771 ieee80211_node_unauthorize(ni); 1772 ieee80211_free_node(ni); 1773 break; 1774 default: 1775 return EINVAL; 1776 } 1777 return 0; 1778 } 1779 1780 static int 1781 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1782 { 1783 u_int8_t mac[IEEE80211_ADDR_LEN]; 1784 const struct ieee80211_aclator *acl = ic->ic_acl; 1785 int error; 1786 1787 if (ireq->i_len != sizeof(mac)) 1788 return EINVAL; 1789 error = copyin(ireq->i_data, mac, ireq->i_len); 1790 if (error) 1791 return error; 1792 if (acl == NULL) { 1793 acl = ieee80211_aclator_get("mac"); 1794 if (acl == NULL || !acl->iac_attach(ic)) 1795 return EINVAL; 1796 ic->ic_acl = acl; 1797 } 1798 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1799 acl->iac_add(ic, mac); 1800 else 1801 acl->iac_remove(ic, mac); 1802 return 0; 1803 } 1804 1805 static int 1806 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1807 { 1808 const struct ieee80211_aclator *acl = ic->ic_acl; 1809 1810 switch (ireq->i_val) { 1811 case IEEE80211_MACCMD_POLICY_OPEN: 1812 case IEEE80211_MACCMD_POLICY_ALLOW: 1813 case IEEE80211_MACCMD_POLICY_DENY: 1814 if (acl == NULL) { 1815 acl = ieee80211_aclator_get("mac"); 1816 if (acl == NULL || !acl->iac_attach(ic)) 1817 return EINVAL; 1818 ic->ic_acl = acl; 1819 } 1820 acl->iac_setpolicy(ic, ireq->i_val); 1821 break; 1822 case IEEE80211_MACCMD_FLUSH: 1823 if (acl != NULL) 1824 acl->iac_flush(ic); 1825 /* NB: silently ignore when not in use */ 1826 break; 1827 case IEEE80211_MACCMD_DETACH: 1828 if (acl != NULL) { 1829 ic->ic_acl = NULL; 1830 acl->iac_detach(ic); 1831 } 1832 break; 1833 default: 1834 if (acl == NULL) 1835 return EINVAL; 1836 else 1837 return acl->iac_setioctl(ic, ireq); 1838 } 1839 return 0; 1840 } 1841 1842 static int 1843 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 1844 { 1845 struct ieee80211req_chanlist list; 1846 u_char chanlist[IEEE80211_CHAN_BYTES]; 1847 int i, j, error; 1848 1849 if (ireq->i_len != sizeof(list)) 1850 return EINVAL; 1851 error = copyin(ireq->i_data, &list, sizeof(list)); 1852 if (error) 1853 return error; 1854 memset(chanlist, 0, sizeof(chanlist)); 1855 /* 1856 * Since channel 0 is not available for DS, channel 1 1857 * is assigned to LSB on WaveLAN. 1858 */ 1859 if (ic->ic_phytype == IEEE80211_T_DS) 1860 i = 1; 1861 else 1862 i = 0; 1863 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 1864 /* 1865 * NB: silently discard unavailable channels so users 1866 * can specify 1-255 to get all available channels. 1867 */ 1868 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) 1869 setbit(chanlist, i); 1870 } 1871 if (ic->ic_ibss_chan == NULL || 1872 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 1873 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 1874 if (isset(chanlist, i)) { 1875 ic->ic_ibss_chan = &ic->ic_channels[i]; 1876 goto found; 1877 } 1878 return EINVAL; /* no active channels */ 1879 found: 1880 ; 1881 } 1882 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 1883 return IS_UP_AUTO(ic) ? ENETRESET : 0; 1884 } 1885 1886 static int 1887 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1888 { 1889 struct ieee80211_node *ni; 1890 struct ieee80211req_sta_txpow txpow; 1891 int error; 1892 1893 if (ireq->i_len != sizeof(txpow)) 1894 return EINVAL; 1895 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1896 if (error != 0) 1897 return error; 1898 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 1899 if (ni == NULL) 1900 return EINVAL; /* XXX */ 1901 ni->ni_txpower = txpow.it_txpow; 1902 ieee80211_free_node(ni); 1903 return error; 1904 } 1905 1906 static int 1907 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1908 { 1909 struct ieee80211_wme_state *wme = &ic->ic_wme; 1910 struct wmeParams *wmep, *chanp; 1911 int isbss, ac; 1912 1913 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1914 return EINVAL; 1915 1916 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1917 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1918 if (ac >= WME_NUM_AC) 1919 ac = WME_AC_BE; 1920 if (isbss) { 1921 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1922 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1923 } else { 1924 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1925 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1926 } 1927 switch (ireq->i_type) { 1928 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1929 if (isbss) { 1930 wmep->wmep_logcwmin = ireq->i_val; 1931 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1932 chanp->wmep_logcwmin = ireq->i_val; 1933 } else { 1934 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1935 ireq->i_val; 1936 } 1937 break; 1938 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1939 if (isbss) { 1940 wmep->wmep_logcwmax = ireq->i_val; 1941 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1942 chanp->wmep_logcwmax = ireq->i_val; 1943 } else { 1944 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1945 ireq->i_val; 1946 } 1947 break; 1948 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1949 if (isbss) { 1950 wmep->wmep_aifsn = ireq->i_val; 1951 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1952 chanp->wmep_aifsn = ireq->i_val; 1953 } else { 1954 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1955 } 1956 break; 1957 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1958 if (isbss) { 1959 wmep->wmep_txopLimit = ireq->i_val; 1960 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1961 chanp->wmep_txopLimit = ireq->i_val; 1962 } else { 1963 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1964 ireq->i_val; 1965 } 1966 break; 1967 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1968 wmep->wmep_acm = ireq->i_val; 1969 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1970 chanp->wmep_acm = ireq->i_val; 1971 break; 1972 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1973 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1974 (ireq->i_val) == 0; 1975 break; 1976 } 1977 ieee80211_wme_updateparams(ic); 1978 return 0; 1979 } 1980 1981 static int 1982 cipher2cap(int cipher) 1983 { 1984 switch (cipher) { 1985 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP; 1986 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES; 1987 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 1988 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 1989 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 1990 } 1991 return 0; 1992 } 1993 1994 static int 1995 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1996 { 1997 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 1998 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; 1999 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 2000 char tmpssid[IEEE80211_NWID_LEN]; 2001 u_int8_t tmpbssid[IEEE80211_ADDR_LEN]; 2002 struct ieee80211_key *k; 2003 u_int kid; 2004 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2005 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 2006 int error; 2007 const struct ieee80211_authenticator *auth; 2008 int j, caps; 2009 2010 error = 0; 2011 switch (ireq->i_type) { 2012 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2013 case IEEE80211_IOC_SSID: 2014 if (ireq->i_val != 0 || 2015 ireq->i_len > IEEE80211_NWID_LEN) 2016 return EINVAL; 2017 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 2018 if (error) 2019 break; 2020 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 2021 ic->ic_des_esslen = ireq->i_len; 2022 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); 2023 error = ENETRESET; 2024 break; 2025 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2026 case IEEE80211_IOC_WEP: 2027 switch (ireq->i_val) { 2028 case IEEE80211_WEP_OFF: 2029 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2030 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2031 break; 2032 case IEEE80211_WEP_ON: 2033 ic->ic_flags |= IEEE80211_F_PRIVACY; 2034 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2035 break; 2036 case IEEE80211_WEP_MIXED: 2037 ic->ic_flags |= IEEE80211_F_PRIVACY; 2038 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2039 break; 2040 } 2041 error = ENETRESET; 2042 break; 2043 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2044 case IEEE80211_IOC_WEPKEY: 2045 kid = (u_int) ireq->i_val; 2046 if (kid >= IEEE80211_WEP_NKID) 2047 return EINVAL; 2048 k = &ic->ic_nw_keys[kid]; 2049 if (ireq->i_len == 0) { 2050 /* zero-len =>'s delete any existing key */ 2051 (void) ieee80211_crypto_delkey(ic, k); 2052 break; 2053 } 2054 if (ireq->i_len > sizeof(tmpkey)) 2055 return EINVAL; 2056 memset(tmpkey, 0, sizeof(tmpkey)); 2057 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 2058 if (error) 2059 break; 2060 ieee80211_key_update_begin(ic); 2061 k->wk_keyix = kid; /* NB: force fixed key id */ 2062 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 2063 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2064 k->wk_keylen = ireq->i_len; 2065 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 2066 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 2067 error = EINVAL; 2068 } else 2069 error = EINVAL; 2070 ieee80211_key_update_end(ic); 2071 if (!error) /* NB: for compatibility */ 2072 error = ENETRESET; 2073 break; 2074 case IEEE80211_IOC_WEPTXKEY: 2075 kid = (u_int) ireq->i_val; 2076 if (kid >= IEEE80211_WEP_NKID && 2077 (u_int16_t) kid != IEEE80211_KEYIX_NONE) 2078 return EINVAL; 2079 ic->ic_def_txkey = kid; 2080 error = ENETRESET; /* push to hardware */ 2081 break; 2082 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2083 case IEEE80211_IOC_AUTHMODE: 2084 switch (ireq->i_val) { 2085 case IEEE80211_AUTH_WPA: 2086 case IEEE80211_AUTH_8021X: /* 802.1x */ 2087 case IEEE80211_AUTH_OPEN: /* open */ 2088 case IEEE80211_AUTH_SHARED: /* shared-key */ 2089 case IEEE80211_AUTH_AUTO: /* auto */ 2090 auth = ieee80211_authenticator_get(ireq->i_val); 2091 if (auth == NULL) 2092 return EINVAL; 2093 break; 2094 default: 2095 return EINVAL; 2096 } 2097 switch (ireq->i_val) { 2098 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 2099 ic->ic_flags |= IEEE80211_F_PRIVACY; 2100 ireq->i_val = IEEE80211_AUTH_8021X; 2101 break; 2102 case IEEE80211_AUTH_OPEN: /* open */ 2103 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 2104 break; 2105 case IEEE80211_AUTH_SHARED: /* shared-key */ 2106 case IEEE80211_AUTH_8021X: /* 802.1x */ 2107 ic->ic_flags &= ~IEEE80211_F_WPA; 2108 /* both require a key so mark the PRIVACY capability */ 2109 ic->ic_flags |= IEEE80211_F_PRIVACY; 2110 break; 2111 case IEEE80211_AUTH_AUTO: /* auto */ 2112 ic->ic_flags &= ~IEEE80211_F_WPA; 2113 /* XXX PRIVACY handling? */ 2114 /* XXX what's the right way to do this? */ 2115 break; 2116 } 2117 /* NB: authenticator attach/detach happens on state change */ 2118 ic->ic_bss->ni_authmode = ireq->i_val; 2119 /* XXX mixed/mode/usage? */ 2120 ic->ic_auth = auth; 2121 error = ENETRESET; 2122 break; 2123 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2124 case IEEE80211_IOC_CHANNEL: 2125 /* XXX 0xffff overflows 16-bit signed */ 2126 if (ireq->i_val == 0 || 2127 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 2128 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 2129 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 2130 isclr(ic->ic_chan_active, ireq->i_val)) { 2131 return EINVAL; 2132 } else 2133 ic->ic_ibss_chan = ic->ic_des_chan = 2134 &ic->ic_channels[ireq->i_val]; 2135 switch (ic->ic_state) { 2136 case IEEE80211_S_INIT: 2137 case IEEE80211_S_SCAN: 2138 error = ENETRESET; 2139 break; 2140 default: 2141 /* 2142 * If the desired channel has changed (to something 2143 * other than any) and we're not already scanning, 2144 * then kick the state machine. 2145 */ 2146 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 2147 ic->ic_bss->ni_chan != ic->ic_des_chan && 2148 (ic->ic_flags & IEEE80211_F_SCAN) == 0) 2149 error = ENETRESET; 2150 break; 2151 } 2152 if (error == ENETRESET && 2153 ic->ic_opmode == IEEE80211_M_MONITOR) { 2154 if (IS_UP(ic)) { 2155 /* 2156 * Monitor mode can switch directly. 2157 */ 2158 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) 2159 ic->ic_curchan = ic->ic_des_chan; 2160 error = ic->ic_reset(ic->ic_ifp); 2161 } else 2162 error = 0; 2163 } 2164 break; 2165 case IEEE80211_IOC_POWERSAVE: 2166 switch (ireq->i_val) { 2167 case IEEE80211_POWERSAVE_OFF: 2168 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2169 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2170 error = ENETRESET; 2171 } 2172 break; 2173 case IEEE80211_POWERSAVE_ON: 2174 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 2175 error = EINVAL; 2176 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2177 ic->ic_flags |= IEEE80211_F_PMGTON; 2178 error = ENETRESET; 2179 } 2180 break; 2181 default: 2182 error = EINVAL; 2183 break; 2184 } 2185 break; 2186 case IEEE80211_IOC_POWERSAVESLEEP: 2187 if (ireq->i_val < 0) 2188 return EINVAL; 2189 ic->ic_lintval = ireq->i_val; 2190 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2191 break; 2192 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2193 case IEEE80211_IOC_RTSTHRESHOLD: 2194 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2195 ireq->i_val <= IEEE80211_RTS_MAX)) 2196 return EINVAL; 2197 ic->ic_rtsthreshold = ireq->i_val; 2198 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2199 break; 2200 case IEEE80211_IOC_PROTMODE: 2201 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2202 return EINVAL; 2203 ic->ic_protmode = ireq->i_val; 2204 /* NB: if not operating in 11g this can wait */ 2205 if (ic->ic_curmode == IEEE80211_MODE_11G) 2206 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2207 break; 2208 case IEEE80211_IOC_TXPOWER: 2209 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2210 return EINVAL; 2211 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 2212 ireq->i_val < IEEE80211_TXPOWER_MAX)) 2213 return EINVAL; 2214 ic->ic_txpowlimit = ireq->i_val; 2215 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2216 break; 2217 case IEEE80211_IOC_ROAMING: 2218 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2219 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2220 return EINVAL; 2221 ic->ic_roaming = ireq->i_val; 2222 /* XXXX reset? */ 2223 break; 2224 case IEEE80211_IOC_PRIVACY: 2225 if (ireq->i_val) { 2226 /* XXX check for key state? */ 2227 ic->ic_flags |= IEEE80211_F_PRIVACY; 2228 } else 2229 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2230 break; 2231 case IEEE80211_IOC_DROPUNENCRYPTED: 2232 if (ireq->i_val) 2233 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2234 else 2235 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2236 break; 2237 case IEEE80211_IOC_WPAKEY: 2238 error = ieee80211_ioctl_setkey(ic, ireq); 2239 break; 2240 case IEEE80211_IOC_DELKEY: 2241 error = ieee80211_ioctl_delkey(ic, ireq); 2242 break; 2243 case IEEE80211_IOC_MLME: 2244 error = ieee80211_ioctl_setmlme(ic, ireq); 2245 break; 2246 case IEEE80211_IOC_OPTIE: 2247 error = ieee80211_ioctl_setoptie(ic, ireq); 2248 break; 2249 case IEEE80211_IOC_COUNTERMEASURES: 2250 if (ireq->i_val) { 2251 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 2252 return EINVAL; 2253 ic->ic_flags |= IEEE80211_F_COUNTERM; 2254 } else 2255 ic->ic_flags &= ~IEEE80211_F_COUNTERM; 2256 break; 2257 case IEEE80211_IOC_WPA: 2258 if (ireq->i_val > 3) 2259 return EINVAL; 2260 /* XXX verify ciphers available */ 2261 ic->ic_flags &= ~IEEE80211_F_WPA; 2262 switch (ireq->i_val) { 2263 case 1: 2264 ic->ic_flags |= IEEE80211_F_WPA1; 2265 break; 2266 case 2: 2267 ic->ic_flags |= IEEE80211_F_WPA2; 2268 break; 2269 case 3: 2270 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2271 break; 2272 } 2273 error = ENETRESET; /* XXX? */ 2274 break; 2275 case IEEE80211_IOC_WME: 2276 if (ireq->i_val) { 2277 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2278 return EINVAL; 2279 ic->ic_flags |= IEEE80211_F_WME; 2280 } else 2281 ic->ic_flags &= ~IEEE80211_F_WME; 2282 error = ENETRESET; /* XXX maybe not for station? */ 2283 break; 2284 case IEEE80211_IOC_HIDESSID: 2285 if (ireq->i_val) 2286 ic->ic_flags |= IEEE80211_F_HIDESSID; 2287 else 2288 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2289 error = ENETRESET; 2290 break; 2291 case IEEE80211_IOC_APBRIDGE: 2292 if (ireq->i_val == 0) 2293 ic->ic_flags |= IEEE80211_F_NOBRIDGE; 2294 else 2295 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE; 2296 break; 2297 case IEEE80211_IOC_MCASTCIPHER: 2298 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 && 2299 !ieee80211_crypto_available(ireq->i_val)) 2300 return EINVAL; 2301 rsn->rsn_mcastcipher = ireq->i_val; 2302 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2303 break; 2304 case IEEE80211_IOC_MCASTKEYLEN: 2305 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2306 return EINVAL; 2307 /* XXX no way to verify driver capability */ 2308 rsn->rsn_mcastkeylen = ireq->i_val; 2309 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2310 break; 2311 case IEEE80211_IOC_UCASTCIPHERS: 2312 /* 2313 * Convert user-specified cipher set to the set 2314 * we can support (via hardware or software). 2315 * NB: this logic intentionally ignores unknown and 2316 * unsupported ciphers so folks can specify 0xff or 2317 * similar and get all available ciphers. 2318 */ 2319 caps = 0; 2320 for (j = 1; j < 32; j++) /* NB: skip WEP */ 2321 if ((ireq->i_val & (1<<j)) && 2322 ((ic->ic_caps & cipher2cap(j)) || 2323 ieee80211_crypto_available(j))) 2324 caps |= 1<<j; 2325 if (caps == 0) /* nothing available */ 2326 return EINVAL; 2327 /* XXX verify ciphers ok for unicast use? */ 2328 /* XXX disallow if running as it'll have no effect */ 2329 rsn->rsn_ucastcipherset = caps; 2330 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2331 break; 2332 case IEEE80211_IOC_UCASTCIPHER: 2333 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0) 2334 return EINVAL; 2335 rsn->rsn_ucastcipher = ireq->i_val; 2336 break; 2337 case IEEE80211_IOC_UCASTKEYLEN: 2338 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2339 return EINVAL; 2340 /* XXX no way to verify driver capability */ 2341 rsn->rsn_ucastkeylen = ireq->i_val; 2342 break; 2343 case IEEE80211_IOC_DRIVER_CAPS: 2344 /* NB: for testing */ 2345 ic->ic_caps = (((u_int16_t) ireq->i_val) << 16) | 2346 ((u_int16_t) ireq->i_len); 2347 break; 2348 case IEEE80211_IOC_KEYMGTALGS: 2349 /* XXX check */ 2350 rsn->rsn_keymgmtset = ireq->i_val; 2351 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2352 break; 2353 case IEEE80211_IOC_RSNCAPS: 2354 /* XXX check */ 2355 rsn->rsn_caps = ireq->i_val; 2356 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2357 break; 2358 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2359 case IEEE80211_IOC_BSSID: 2360 /* NB: should only be set when in STA mode */ 2361 if (ic->ic_opmode != IEEE80211_M_STA) 2362 return EINVAL; 2363 if (ireq->i_len != sizeof(tmpbssid)) 2364 return EINVAL; 2365 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2366 if (error) 2367 break; 2368 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2369 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2370 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2371 else 2372 ic->ic_flags |= IEEE80211_F_DESBSSID; 2373 error = ENETRESET; 2374 break; 2375 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2376 case IEEE80211_IOC_CHANLIST: 2377 error = ieee80211_ioctl_setchanlist(ic, ireq); 2378 break; 2379 case IEEE80211_IOC_SCAN_REQ: 2380 if (ic->ic_opmode == IEEE80211_M_HOSTAP) /* XXX ignore */ 2381 break; 2382 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 2383 if (error == 0) /* XXX background scan */ 2384 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2385 break; 2386 case IEEE80211_IOC_ADDMAC: 2387 case IEEE80211_IOC_DELMAC: 2388 error = ieee80211_ioctl_macmac(ic, ireq); 2389 break; 2390 case IEEE80211_IOC_MACCMD: 2391 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2392 break; 2393 case IEEE80211_IOC_STA_TXPOW: 2394 error = ieee80211_ioctl_setstatxpow(ic, ireq); 2395 break; 2396 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2397 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2398 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2399 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2400 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2401 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2402 error = ieee80211_ioctl_setwmeparam(ic, ireq); 2403 break; 2404 case IEEE80211_IOC_DTIM_PERIOD: 2405 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2406 ic->ic_opmode != IEEE80211_M_IBSS) 2407 return EINVAL; 2408 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2409 ireq->i_val <= IEEE80211_DTIM_MAX) { 2410 ic->ic_dtim_period = ireq->i_val; 2411 error = ENETRESET; /* requires restart */ 2412 } else 2413 error = EINVAL; 2414 break; 2415 case IEEE80211_IOC_BEACON_INTERVAL: 2416 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2417 ic->ic_opmode != IEEE80211_M_IBSS) 2418 return EINVAL; 2419 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2420 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2421 ic->ic_bintval = ireq->i_val; 2422 error = ENETRESET; /* requires restart */ 2423 } else 2424 error = EINVAL; 2425 break; 2426 case IEEE80211_IOC_PUREG: 2427 if (ireq->i_val) 2428 ic->ic_flags |= IEEE80211_F_PUREG; 2429 else 2430 ic->ic_flags &= ~IEEE80211_F_PUREG; 2431 /* NB: reset only if we're operating on an 11g channel */ 2432 if (ic->ic_curmode == IEEE80211_MODE_11G) 2433 error = ENETRESET; 2434 break; 2435 case IEEE80211_IOC_MCAST_RATE: 2436 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2437 break; 2438 case IEEE80211_IOC_FRAGTHRESHOLD: 2439 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2440 ireq->i_val != IEEE80211_FRAG_MAX) 2441 return EINVAL; 2442 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && 2443 ireq->i_val <= IEEE80211_FRAG_MAX)) 2444 return EINVAL; 2445 ic->ic_fragthreshold = ireq->i_val; 2446 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2447 break; 2448 default: 2449 error = EINVAL; 2450 break; 2451 } 2452 if (error == ENETRESET && !IS_UP_AUTO(ic)) 2453 error = 0; 2454 return error; 2455 } 2456 2457 #ifdef __FreeBSD__ 2458 int 2459 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2460 { 2461 struct ifnet *ifp = ic->ic_ifp; 2462 int error = 0; 2463 struct ifreq *ifr; 2464 struct ifaddr *ifa; /* XXX */ 2465 2466 switch (cmd) { 2467 case SIOCSIFMEDIA: 2468 case SIOCGIFMEDIA: 2469 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 2470 &ic->ic_media, cmd); 2471 break; 2472 case SIOCG80211: 2473 error = ieee80211_ioctl_get80211(ic, cmd, 2474 (struct ieee80211req *) data); 2475 break; 2476 case SIOCS80211: 2477 error = suser(curthread); 2478 if (error == 0) 2479 error = ieee80211_ioctl_set80211(ic, cmd, 2480 (struct ieee80211req *) data); 2481 break; 2482 case SIOCGIFGENERIC: 2483 error = ieee80211_cfgget(ic, cmd, data); 2484 break; 2485 case SIOCSIFGENERIC: 2486 error = suser(curthread); 2487 if (error) 2488 break; 2489 error = ieee80211_cfgset(ic, cmd, data); 2490 break; 2491 case SIOCG80211STATS: 2492 ifr = (struct ifreq *)data; 2493 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2494 break; 2495 case SIOCSIFMTU: 2496 ifr = (struct ifreq *)data; 2497 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2498 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2499 error = EINVAL; 2500 else 2501 ifp->if_mtu = ifr->ifr_mtu; 2502 break; 2503 case SIOCSIFADDR: 2504 /* 2505 * XXX Handle this directly so we can supress if_init calls. 2506 * XXX This should be done in ether_ioctl but for the moment 2507 * XXX there are too many other parts of the system that 2508 * XXX set IFF_UP and so supress if_init being called when 2509 * XXX it should be. 2510 */ 2511 ifa = (struct ifaddr *) data; 2512 switch (ifa->ifa_addr->sa_family) { 2513 #ifdef INET 2514 case AF_INET: 2515 if ((ifp->if_flags & IFF_UP) == 0) { 2516 ifp->if_flags |= IFF_UP; 2517 ifp->if_init(ifp->if_softc); 2518 } 2519 arp_ifinit(ifp, ifa); 2520 break; 2521 #endif 2522 #ifdef IPX 2523 /* 2524 * XXX - This code is probably wrong, 2525 * but has been copied many times. 2526 */ 2527 case AF_IPX: { 2528 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 2529 2530 if (ipx_nullhost(*ina)) 2531 ina->x_host = *(union ipx_host *) 2532 IFP2ENADDR(ifp); 2533 else 2534 bcopy((caddr_t) ina->x_host.c_host, 2535 (caddr_t) IFP2ENADDR(ifp), 2536 ETHER_ADDR_LEN); 2537 /* fall thru... */ 2538 } 2539 #endif 2540 default: 2541 if ((ifp->if_flags & IFF_UP) == 0) { 2542 ifp->if_flags |= IFF_UP; 2543 ifp->if_init(ifp->if_softc); 2544 } 2545 break; 2546 } 2547 break; 2548 default: 2549 error = ether_ioctl(ifp, cmd, data); 2550 break; 2551 } 2552 return error; 2553 } 2554 #endif /* __FreeBSD__ */ 2555 2556 #ifdef COMPAT_20 2557 static void 2558 ieee80211_get_ostats(struct ieee80211_ostats *ostats, 2559 struct ieee80211_stats *stats) 2560 { 2561 #define COPYSTATS1(__ostats, __nstats, __dstmemb, __srcmemb, __lastmemb)\ 2562 (void)memcpy(&(__ostats)->__dstmemb, &(__nstats)->__srcmemb, \ 2563 offsetof(struct ieee80211_stats, __lastmemb) - \ 2564 offsetof(struct ieee80211_stats, __srcmemb)) 2565 #define COPYSTATS(__ostats, __nstats, __dstmemb, __lastmemb) \ 2566 COPYSTATS1(__ostats, __nstats, __dstmemb, __dstmemb, __lastmemb) 2567 2568 COPYSTATS(ostats, stats, is_rx_badversion, is_rx_unencrypted); 2569 COPYSTATS(ostats, stats, is_rx_wepfail, is_rx_beacon); 2570 COPYSTATS(ostats, stats, is_rx_rstoobig, is_rx_auth_countermeasures); 2571 COPYSTATS(ostats, stats, is_rx_assoc_bss, is_rx_assoc_badwpaie); 2572 COPYSTATS(ostats, stats, is_rx_deauth, is_rx_unauth); 2573 COPYSTATS1(ostats, stats, is_tx_nombuf, is_tx_nobuf, is_tx_badcipher); 2574 COPYSTATS(ostats, stats, is_scan_active, is_crypto_tkip); 2575 } 2576 #endif /* COMPAT_20 */ 2577 2578 #ifdef __NetBSD__ 2579 int 2580 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2581 { 2582 struct ifnet *ifp = ic->ic_ifp; 2583 struct ifreq *ifr = (struct ifreq *)data; 2584 int i, error = 0, kid, klen, s; 2585 struct ieee80211_key *k; 2586 struct ieee80211_nwid nwid; 2587 struct ieee80211_nwkey *nwkey; 2588 struct ieee80211_power *power; 2589 struct ieee80211_bssid *bssid; 2590 struct ieee80211chanreq *chanreq; 2591 struct ieee80211_channel *chan; 2592 uint32_t oflags; 2593 #ifdef COMPAT_20 2594 struct ieee80211_ostats ostats; 2595 #endif /* COMPAT_20 */ 2596 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; 2597 u_int8_t tmpkey[IEEE80211_WEP_NKID][IEEE80211_KEYBUF_SIZE]; 2598 2599 switch (cmd) { 2600 case SIOCSIFMEDIA: 2601 case SIOCGIFMEDIA: 2602 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 2603 break; 2604 case SIOCG80211: 2605 error = ieee80211_ioctl_get80211(ic, cmd, 2606 (struct ieee80211req *) data); 2607 break; 2608 case SIOCS80211: 2609 if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0) 2610 break; 2611 error = ieee80211_ioctl_set80211(ic, cmd, 2612 (struct ieee80211req *) data); 2613 break; 2614 case SIOCS80211NWID: 2615 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 2616 break; 2617 if (nwid.i_len > IEEE80211_NWID_LEN) { 2618 error = EINVAL; 2619 break; 2620 } 2621 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 2622 ic->ic_des_esslen = nwid.i_len; 2623 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 2624 error = ENETRESET; 2625 break; 2626 case SIOCG80211NWID: 2627 memset(&nwid, 0, sizeof(nwid)); 2628 switch (ic->ic_state) { 2629 case IEEE80211_S_INIT: 2630 case IEEE80211_S_SCAN: 2631 nwid.i_len = ic->ic_des_esslen; 2632 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 2633 break; 2634 default: 2635 nwid.i_len = ic->ic_bss->ni_esslen; 2636 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 2637 break; 2638 } 2639 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 2640 break; 2641 case SIOCS80211NWKEY: 2642 nwkey = (struct ieee80211_nwkey *)data; 2643 /* transmit key index out of range? */ 2644 kid = nwkey->i_defkid - 1; 2645 if (kid < 0 || kid >= IEEE80211_WEP_NKID) { 2646 error = EINVAL; 2647 break; 2648 } 2649 /* no such transmit key is set? */ 2650 if (nwkey->i_key[kid].i_keylen == 0 || 2651 (nwkey->i_key[kid].i_keylen == -1 && 2652 ic->ic_nw_keys[kid].wk_keylen == 0)) { 2653 if (nwkey->i_wepon != IEEE80211_NWKEY_OPEN) { 2654 error = EINVAL; 2655 break; 2656 } 2657 } 2658 /* check key lengths */ 2659 for (kid = 0; kid < IEEE80211_WEP_NKID; kid++) { 2660 klen = nwkey->i_key[kid].i_keylen; 2661 if ((klen > 0 && 2662 klen < IEEE80211_WEP_KEYLEN) || 2663 klen > sizeof(ic->ic_nw_keys[kid].wk_key)) { 2664 error = EINVAL; 2665 break; 2666 } 2667 } 2668 2669 if (error) 2670 break; 2671 2672 /* copy in keys */ 2673 (void)memset(tmpkey, 0, sizeof(tmpkey)); 2674 for (kid = 0; kid < IEEE80211_WEP_NKID; kid++) { 2675 klen = nwkey->i_key[kid].i_keylen; 2676 if (klen <= 0) 2677 continue; 2678 if ((error = copyin(nwkey->i_key[kid].i_keydat, 2679 tmpkey[kid], klen)) != 0) 2680 break; 2681 } 2682 2683 if (error) 2684 break; 2685 2686 /* set keys */ 2687 ieee80211_key_update_begin(ic); 2688 for (kid = 0; kid < IEEE80211_WEP_NKID; kid++) { 2689 klen = nwkey->i_key[kid].i_keylen; 2690 if (klen <= 0) 2691 continue; 2692 k = &ic->ic_nw_keys[kid]; 2693 k->wk_keyix = kid; 2694 if (!ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 2695 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2696 error = EINVAL; 2697 continue; 2698 } 2699 k->wk_keylen = nwkey->i_key[kid].i_keylen; 2700 (void)memcpy(k->wk_key, tmpkey[kid], 2701 sizeof(tmpkey[kid])); 2702 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 2703 error = EINVAL; 2704 } 2705 ieee80211_key_update_end(ic); 2706 2707 if (error) 2708 break; 2709 2710 /* delete keys */ 2711 for (kid = 0; kid < IEEE80211_WEP_NKID; kid++) { 2712 klen = nwkey->i_key[kid].i_keylen; 2713 k = &ic->ic_nw_keys[kid]; 2714 if (klen <= 0) 2715 (void)ieee80211_crypto_delkey(ic, k); 2716 } 2717 2718 /* set transmit key */ 2719 kid = nwkey->i_defkid - 1; 2720 if (ic->ic_def_txkey != kid) { 2721 ic->ic_def_txkey = kid; 2722 error = ENETRESET; 2723 } 2724 oflags = ic->ic_flags; 2725 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) { 2726 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2727 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2728 } else { 2729 ic->ic_flags |= IEEE80211_F_PRIVACY; 2730 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2731 } 2732 if (oflags != ic->ic_flags) 2733 error = ENETRESET; 2734 break; 2735 case SIOCG80211NWKEY: 2736 nwkey = (struct ieee80211_nwkey *)data; 2737 if (ic->ic_flags & IEEE80211_F_PRIVACY) 2738 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 2739 else 2740 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 2741 nwkey->i_defkid = ic->ic_def_txkey + 1; 2742 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2743 if (nwkey->i_key[i].i_keydat == NULL) 2744 continue; 2745 /* do not show any keys to non-root user */ 2746 if ((error = suser(curproc->p_ucred, 2747 &curproc->p_acflag)) != 0) 2748 break; 2749 nwkey->i_key[i].i_keylen = ic->ic_nw_keys[i].wk_keylen; 2750 if ((error = copyout(ic->ic_nw_keys[i].wk_key, 2751 nwkey->i_key[i].i_keydat, 2752 ic->ic_nw_keys[i].wk_keylen)) != 0) 2753 break; 2754 } 2755 break; 2756 case SIOCS80211POWER: 2757 power = (struct ieee80211_power *)data; 2758 ic->ic_lintval = power->i_maxsleep; 2759 if (power->i_enabled != 0) { 2760 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 2761 error = EINVAL; 2762 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2763 ic->ic_flags |= IEEE80211_F_PMGTON; 2764 error = ENETRESET; 2765 } 2766 } else { 2767 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2768 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2769 error = ENETRESET; 2770 } 2771 } 2772 break; 2773 case SIOCG80211POWER: 2774 power = (struct ieee80211_power *)data; 2775 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 2776 power->i_maxsleep = ic->ic_lintval; 2777 break; 2778 case SIOCS80211BSSID: 2779 bssid = (struct ieee80211_bssid *)data; 2780 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 2781 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2782 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2783 else 2784 ic->ic_flags |= IEEE80211_F_DESBSSID; 2785 error = ENETRESET; 2786 break; 2787 case SIOCG80211BSSID: 2788 bssid = (struct ieee80211_bssid *)data; 2789 switch (ic->ic_state) { 2790 case IEEE80211_S_INIT: 2791 case IEEE80211_S_SCAN: 2792 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 2793 IEEE80211_ADDR_COPY(bssid->i_bssid, 2794 ic->ic_myaddr); 2795 else if (ic->ic_flags & IEEE80211_F_DESBSSID) 2796 IEEE80211_ADDR_COPY(bssid->i_bssid, 2797 ic->ic_des_bssid); 2798 else 2799 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 2800 break; 2801 default: 2802 IEEE80211_ADDR_COPY(bssid->i_bssid, 2803 ic->ic_bss->ni_bssid); 2804 break; 2805 } 2806 break; 2807 case SIOCS80211CHANNEL: 2808 chanreq = (struct ieee80211chanreq *)data; 2809 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 2810 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 2811 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 2812 isclr(ic->ic_chan_active, chanreq->i_channel)) { 2813 error = EINVAL; 2814 break; 2815 } else 2816 ic->ic_ibss_chan = ic->ic_des_chan = 2817 &ic->ic_channels[chanreq->i_channel]; 2818 switch (ic->ic_state) { 2819 case IEEE80211_S_INIT: 2820 case IEEE80211_S_SCAN: 2821 error = ENETRESET; 2822 break; 2823 default: 2824 if (ic->ic_opmode == IEEE80211_M_STA) { 2825 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 2826 ic->ic_bss->ni_chan != ic->ic_des_chan) 2827 error = ENETRESET; 2828 } else { 2829 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 2830 error = ENETRESET; 2831 } 2832 break; 2833 } 2834 break; 2835 case SIOCG80211CHANNEL: 2836 chanreq = (struct ieee80211chanreq *)data; 2837 switch (ic->ic_state) { 2838 case IEEE80211_S_INIT: 2839 case IEEE80211_S_SCAN: 2840 if (ic->ic_opmode == IEEE80211_M_STA) 2841 chan = ic->ic_des_chan; 2842 else 2843 chan = ic->ic_ibss_chan; 2844 break; 2845 default: 2846 chan = ic->ic_bss->ni_chan; 2847 break; 2848 } 2849 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 2850 break; 2851 case SIOCGIFGENERIC: 2852 error = ieee80211_cfgget(ic, cmd, data); 2853 break; 2854 case SIOCSIFGENERIC: 2855 error = suser(curproc->p_ucred, &curproc->p_acflag); 2856 if (error) 2857 break; 2858 error = ieee80211_cfgset(ic, cmd, data); 2859 break; 2860 #ifdef COMPAT_20 2861 case OSIOCG80211STATS: 2862 case OSIOCG80211ZSTATS: 2863 ifr = (struct ifreq *)data; 2864 s = splnet(); 2865 ieee80211_get_ostats(&ostats, &ic->ic_stats); 2866 error = copyout(&ostats, ifr->ifr_data, sizeof(ostats)); 2867 if (error == 0 && cmd == OSIOCG80211ZSTATS) 2868 (void)memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 2869 splx(s); 2870 break; 2871 #endif /* COMPAT_20 */ 2872 case SIOCG80211ZSTATS: 2873 case SIOCG80211STATS: 2874 ifr = (struct ifreq *)data; 2875 s = splnet(); 2876 error = copyout(&ic->ic_stats, ifr->ifr_buf, 2877 MIN(sizeof(ic->ic_stats), ifr->ifr_buflen)); 2878 if (error == 0 && cmd == SIOCG80211ZSTATS) 2879 (void)memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 2880 splx(s); 2881 break; 2882 case SIOCSIFMTU: 2883 ifr = (struct ifreq *)data; 2884 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2885 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2886 error = EINVAL; 2887 else 2888 ifp->if_mtu = ifr->ifr_mtu; 2889 break; 2890 default: 2891 error = ether_ioctl(ifp, cmd, data); 2892 break; 2893 } 2894 return error; 2895 } 2896 #endif /* __NetBSD__ */ 2897