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