1 /* $NetBSD: ieee80211_ioctl.c,v 1.40 2006/10/12 01:32:30 christos Exp $ */ 2 /*- 3 * Copyright (c) 2001 Atsushi Onoe 4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 #ifdef __FreeBSD__ 36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.35 2005/08/30 14:27:47 avatar Exp $"); 37 #endif 38 #ifdef __NetBSD__ 39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.40 2006/10/12 01:32:30 christos Exp $"); 40 #endif 41 42 /* 43 * IEEE 802.11 ioctl support (FreeBSD-specific) 44 */ 45 46 #include "opt_inet.h" 47 48 #include <sys/endian.h> 49 #include <sys/param.h> 50 #include <sys/kernel.h> 51 #include <sys/socket.h> 52 #include <sys/sockio.h> 53 #include <sys/systm.h> 54 #include <sys/proc.h> 55 #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 __unused, 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(curlwp->l_cred, 364 KAUTH_GENERIC_ISSUSER, &curlwp->l_acflag); 365 if (error) { 366 memset(keys, 0, sizeof(*keys)); 367 error = 0; 368 break; 369 } 370 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 371 keys->wi_keys[i].wi_keylen = 372 htole16(ic->ic_nw_keys[i].wk_keylen); 373 memcpy(keys->wi_keys[i].wi_keydat, 374 ic->ic_nw_keys[i].wk_key, 375 ic->ic_nw_keys[i].wk_keylen); 376 } 377 wreq->wi_len = sizeof(*keys) / 2; 378 break; 379 case WI_RID_MAX_DATALEN: 380 wreq->wi_val[0] = htole16(ic->ic_fragthreshold); 381 wreq->wi_len = 1; 382 break; 383 case WI_RID_DBM_ADJUST: 384 /* not supported, we just pass rssi value from driver. */ 385 break; 386 case WI_RID_IFACE_STATS: 387 /* XXX: should be implemented in lower drivers */ 388 break; 389 case WI_RID_READ_APS: 390 /* 391 * Don't return results until active scan completes. 392 */ 393 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 394 struct wi_read_ap_args args; 395 396 args.i = 0; 397 args.ap = (void *)((char *)wreq->wi_val + sizeof(i)); 398 args.max = (void *)(wreq + 1); 399 ieee80211_iterate_nodes(&ic->ic_scan, 400 wi_read_ap_result, &args); 401 memcpy(wreq->wi_val, &args.i, sizeof(args.i)); 402 wreq->wi_len = (sizeof(int) + 403 sizeof(struct wi_apinfo) * args.i) / 2; 404 } else 405 error = EINPROGRESS; 406 break; 407 #if 0 408 case WI_RID_SCAN_RES: /* compatibility interface */ 409 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 410 struct wi_read_prism2_args args; 411 struct wi_scan_p2_hdr *p2; 412 413 /* NB: use Prism2 format so we can include rate info */ 414 p2 = (struct wi_scan_p2_hdr *)wreq->wi_val; 415 args.i = 0; 416 args.res = (void *)&p2[1]; 417 args.max = (void *)(wreq + 1); 418 ieee80211_iterate_nodes(&ic->ic_scan, 419 wi_read_prism2_result, &args); 420 p2->wi_rsvd = 0; 421 p2->wi_reason = args.i; 422 wreq->wi_len = (sizeof(*p2) + 423 sizeof(struct wi_scan_res) * args.i) / 2; 424 } else 425 error = EINPROGRESS; 426 break; 427 case WI_RID_READ_CACHE: { 428 struct wi_read_sigcache_args args; 429 args.i = 0; 430 args.wsc = (struct wi_sigcache *) wreq->wi_val; 431 args.max = (void *)(wreq + 1); 432 ieee80211_iterate_nodes(&ic->ic_scan, wi_read_sigcache, &args); 433 wreq->wi_len = sizeof(struct wi_sigcache) * args.i / 2; 434 break; 435 } 436 #endif 437 default: 438 error = EINVAL; 439 break; 440 } 441 if (error == 0) { 442 wreq->wi_len++; 443 error = copyout(wreq, ifr->ifr_data, sizeof(*wreq)); 444 } 445 out: 446 free(wreq, M_TEMP); 447 return error; 448 } 449 450 static int 451 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) 452 { 453 #define IEEERATE(_ic,_m,_i) \ 454 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) 455 int i, nrates = ic->ic_sup_rates[mode].rs_nrates; 456 for (i = 0; i < nrates; i++) 457 if (IEEERATE(ic, mode, i) == rate) 458 return i; 459 return -1; 460 #undef IEEERATE 461 } 462 463 /* 464 * Prepare to do a user-initiated scan for AP's. If no 465 * current/default channel is setup or the current channel 466 * is invalid then pick the first available channel from 467 * the active list as the place to start the scan. 468 */ 469 static int 470 ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[]) 471 { 472 473 /* 474 * XXX don't permit a scan to be started unless we 475 * know the device is ready. For the moment this means 476 * the device is marked up as this is the required to 477 * initialize the hardware. It would be better to permit 478 * scanning prior to being up but that'll require some 479 * changes to the infrastructure. 480 */ 481 if (!IS_UP(ic)) 482 return EINVAL; 483 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 484 /* 485 * We force the state to INIT before calling ieee80211_new_state 486 * to get ieee80211_begin_scan called. We really want to scan w/o 487 * altering the current state but that's not possible right now. 488 */ 489 /* XXX handle proberequest case */ 490 ic->ic_state = IEEE80211_S_INIT; /* XXX bypass state machine */ 491 return 0; 492 } 493 494 int 495 ieee80211_cfgset(struct ieee80211com *ic, u_long cmd __unused, caddr_t data) 496 { 497 struct ifnet *ifp = ic->ic_ifp; 498 int i, j, len, error, rate; 499 struct ifreq *ifr = (struct ifreq *)data; 500 struct wi_ltv_keys *keys; 501 struct wi_req *wreq; 502 u_int8_t chanlist[IEEE80211_CHAN_BYTES]; 503 504 wreq = malloc(sizeof(*wreq), M_TEMP, M_WAITOK); 505 error = copyin(ifr->ifr_data, wreq, sizeof(*wreq)); 506 if (error) 507 goto out; 508 len = wreq->wi_len ? (wreq->wi_len - 1) * 2 : 0; 509 switch (wreq->wi_type) { 510 case WI_RID_SERIALNO: 511 case WI_RID_NODENAME: 512 case WI_RID_CURRENT_SSID: 513 error = EPERM; 514 goto out; 515 case WI_RID_OWN_SSID: 516 case WI_RID_DESIRED_SSID: 517 if (le16toh(wreq->wi_val[0]) * 2 > len || 518 le16toh(wreq->wi_val[0]) > IEEE80211_NWID_LEN) { 519 error = ENOSPC; 520 break; 521 } 522 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); 523 ic->ic_des_esslen = le16toh(wreq->wi_val[0]) * 2; 524 memcpy(ic->ic_des_essid, &wreq->wi_val[1], ic->ic_des_esslen); 525 error = ENETRESET; 526 break; 527 case WI_RID_CURRENT_BSSID: 528 error = EPERM; 529 goto out; 530 case WI_RID_OWN_CHNL: 531 if (len != 2) 532 goto invalid; 533 i = le16toh(wreq->wi_val[0]); 534 if (i < 0 || 535 i > IEEE80211_CHAN_MAX || 536 isclr(ic->ic_chan_active, i)) 537 goto invalid; 538 ic->ic_ibss_chan = &ic->ic_channels[i]; 539 if (ic->ic_opmode == IEEE80211_M_MONITOR) 540 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 541 else 542 error = ENETRESET; 543 break; 544 case WI_RID_CURRENT_CHAN: 545 case WI_RID_COMMS_QUALITY: 546 error = EPERM; 547 goto out; 548 case WI_RID_PROMISC: 549 if (len != 2) 550 goto invalid; 551 if (ifp->if_flags & IFF_PROMISC) { 552 if (wreq->wi_val[0] == 0) { 553 ifp->if_flags &= ~IFF_PROMISC; 554 error = ENETRESET; 555 } 556 } else { 557 if (wreq->wi_val[0] != 0) { 558 ifp->if_flags |= IFF_PROMISC; 559 error = ENETRESET; 560 } 561 } 562 break; 563 case WI_RID_PORTTYPE: 564 if (len != 2) 565 goto invalid; 566 switch (le16toh(wreq->wi_val[0])) { 567 case IEEE80211_M_STA: 568 break; 569 case IEEE80211_M_IBSS: 570 if (!(ic->ic_caps & IEEE80211_C_IBSS)) 571 goto invalid; 572 break; 573 case IEEE80211_M_AHDEMO: 574 if (ic->ic_phytype != IEEE80211_T_DS || 575 !(ic->ic_caps & IEEE80211_C_AHDEMO)) 576 goto invalid; 577 break; 578 case IEEE80211_M_HOSTAP: 579 if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) 580 goto invalid; 581 break; 582 default: 583 goto invalid; 584 } 585 if (le16toh(wreq->wi_val[0]) != ic->ic_opmode) { 586 ic->ic_opmode = le16toh(wreq->wi_val[0]); 587 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 588 } 589 break; 590 #if 0 591 case WI_RID_MAC_NODE: 592 if (len != IEEE80211_ADDR_LEN) 593 goto invalid; 594 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq->wi_val); 595 /* if_init will copy lladdr into ic_myaddr */ 596 error = ENETRESET; 597 break; 598 #endif 599 case WI_RID_TX_RATE: 600 if (len != 2) 601 goto invalid; 602 if (wreq->wi_val[0] == 0) { 603 /* auto */ 604 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 605 break; 606 } 607 rate = 2 * le16toh(wreq->wi_val[0]); 608 if (ic->ic_curmode == IEEE80211_MODE_AUTO) { 609 /* 610 * In autoselect mode search for the rate. We take 611 * the first instance which may not be right, but we 612 * are limited by the interface. Note that we also 613 * lock the mode to insure the rate is meaningful 614 * when it is used. 615 */ 616 for (j = IEEE80211_MODE_11A; 617 j < IEEE80211_MODE_MAX; j++) { 618 if ((ic->ic_modecaps & (1<<j)) == 0) 619 continue; 620 i = findrate(ic, j, rate); 621 if (i != -1) { 622 /* lock mode too */ 623 ic->ic_curmode = j; 624 goto setrate; 625 } 626 } 627 } else { 628 i = findrate(ic, ic->ic_curmode, rate); 629 if (i != -1) 630 goto setrate; 631 } 632 goto invalid; 633 setrate: 634 ic->ic_fixed_rate = i; 635 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 636 break; 637 case WI_RID_CUR_TX_RATE: 638 error = EPERM; 639 goto out; 640 case WI_RID_FRAG_THRESH: 641 if (len != 2) 642 goto invalid; 643 ic->ic_fragthreshold = le16toh(wreq->wi_val[0]); 644 error = ENETRESET; 645 break; 646 case WI_RID_RTS_THRESH: 647 if (len != 2) 648 goto invalid; 649 ic->ic_rtsthreshold = le16toh(wreq->wi_val[0]); 650 error = ENETRESET; 651 break; 652 case WI_RID_CREATE_IBSS: 653 if (len != 2) 654 goto invalid; 655 if (wreq->wi_val[0] != 0) { 656 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) 657 goto invalid; 658 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 659 ic->ic_flags |= IEEE80211_F_IBSSON; 660 if (ic->ic_opmode == IEEE80211_M_IBSS && 661 ic->ic_state == IEEE80211_S_SCAN) 662 error = IS_UP_AUTO(ic) ? ENETRESET : 0; 663 } 664 } else { 665 if (ic->ic_flags & IEEE80211_F_IBSSON) { 666 ic->ic_flags &= ~IEEE80211_F_IBSSON; 667 if (ic->ic_flags & IEEE80211_F_SIBSS) { 668 ic->ic_flags &= ~IEEE80211_F_SIBSS; 669 error = IS_UP_AUTO(ic) ? ENETRESET : 0; 670 } 671 } 672 } 673 break; 674 case WI_RID_MICROWAVE_OVEN: 675 if (len != 2) 676 goto invalid; 677 if (wreq->wi_val[0] != 0) 678 goto invalid; /* not supported */ 679 break; 680 case WI_RID_ROAMING_MODE: 681 if (len != 2) 682 goto invalid; 683 i = le16toh(wreq->wi_val[0]); 684 if (i > IEEE80211_ROAMING_MANUAL) 685 goto invalid; /* not supported */ 686 ic->ic_roaming = i; 687 break; 688 case WI_RID_SYSTEM_SCALE: 689 if (len != 2) 690 goto invalid; 691 if (le16toh(wreq->wi_val[0]) != 1) 692 goto invalid; /* not supported */ 693 break; 694 case WI_RID_PM_ENABLED: 695 if (len != 2) 696 goto invalid; 697 if (wreq->wi_val[0] != 0) { 698 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 699 goto invalid; 700 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 701 ic->ic_flags |= IEEE80211_F_PMGTON; 702 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 703 } 704 } else { 705 if (ic->ic_flags & IEEE80211_F_PMGTON) { 706 ic->ic_flags &= ~IEEE80211_F_PMGTON; 707 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 708 } 709 } 710 break; 711 case WI_RID_MAX_SLEEP: 712 if (len != 2) 713 goto invalid; 714 ic->ic_lintval = le16toh(wreq->wi_val[0]); 715 if (ic->ic_flags & IEEE80211_F_PMGTON) 716 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 717 break; 718 case WI_RID_CUR_BEACON_INT: 719 case WI_RID_WEP_AVAIL: 720 error = EPERM; 721 goto out; 722 case WI_RID_CNFAUTHMODE: 723 if (len != 2) 724 goto invalid; 725 i = le16toh(wreq->wi_val[0]); 726 if (i > IEEE80211_AUTH_WPA) 727 goto invalid; 728 ic->ic_bss->ni_authmode = i; /* XXX ENETRESET? */ 729 error = ENETRESET; 730 break; 731 case WI_RID_ENCRYPTION: 732 if (len != 2) 733 goto invalid; 734 if (wreq->wi_val[0] != 0) { 735 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 736 goto invalid; 737 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) { 738 ic->ic_flags |= IEEE80211_F_PRIVACY; 739 error = ENETRESET; 740 } 741 } else { 742 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 743 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 744 error = ENETRESET; 745 } 746 } 747 break; 748 case WI_RID_TX_CRYPT_KEY: 749 if (len != 2) 750 goto invalid; 751 i = le16toh(wreq->wi_val[0]); 752 if (i >= IEEE80211_WEP_NKID) 753 goto invalid; 754 ic->ic_def_txkey = i; 755 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 756 break; 757 case WI_RID_DEFLT_CRYPT_KEYS: 758 if (len != sizeof(struct wi_ltv_keys)) 759 goto invalid; 760 keys = (struct wi_ltv_keys *)wreq; 761 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 762 len = le16toh(keys->wi_keys[i].wi_keylen); 763 if (len != 0 && len < IEEE80211_WEP_KEYLEN) 764 goto invalid; 765 if (len > IEEE80211_KEYBUF_SIZE) 766 goto invalid; 767 } 768 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 769 struct ieee80211_key *k = &ic->ic_nw_keys[i]; 770 771 len = le16toh(keys->wi_keys[i].wi_keylen); 772 k->wk_keylen = len; 773 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 774 memset(k->wk_key, 0, sizeof(k->wk_key)); 775 memcpy(k->wk_key, keys->wi_keys[i].wi_keydat, len); 776 #if 0 777 k->wk_type = IEEE80211_CIPHER_WEP; 778 #endif 779 } 780 error = ENETRESET; 781 break; 782 case WI_RID_MAX_DATALEN: 783 if (len != 2) 784 goto invalid; 785 len = le16toh(wreq->wi_val[0]); 786 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) 787 goto invalid; 788 ic->ic_fragthreshold = len; 789 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 790 break; 791 case WI_RID_IFACE_STATS: 792 error = EPERM; 793 break; 794 case WI_RID_SCAN_REQ: /* XXX wicontrol */ 795 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 796 break; 797 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 798 if (error == 0) 799 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 800 break; 801 case WI_RID_SCAN_APS: 802 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 803 break; 804 len--; /* XXX: tx rate? */ 805 /* FALLTHRU */ 806 case WI_RID_CHANNEL_LIST: 807 memset(chanlist, 0, sizeof(chanlist)); 808 /* 809 * Since channel 0 is not available for DS, channel 1 810 * is assigned to LSB on WaveLAN. 811 */ 812 if (ic->ic_phytype == IEEE80211_T_DS) 813 i = 1; 814 else 815 i = 0; 816 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 817 if ((j / 8) >= len) 818 break; 819 if (isclr((u_int8_t *)wreq->wi_val, j)) 820 continue; 821 if (isclr(ic->ic_chan_active, i)) { 822 if (wreq->wi_type != WI_RID_CHANNEL_LIST) 823 continue; 824 if (isclr(ic->ic_chan_avail, i)) { 825 error = EPERM; 826 goto out; 827 } 828 } 829 setbit(chanlist, i); 830 } 831 error = ieee80211_setupscan(ic, chanlist); 832 if (wreq->wi_type == WI_RID_CHANNEL_LIST) { 833 /* NB: ignore error from ieee80211_setupscan */ 834 error = ENETRESET; 835 } else if (error == 0) 836 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 837 break; 838 default: 839 goto invalid; 840 } 841 if (error == ENETRESET && !IS_UP_AUTO(ic)) 842 error = 0; 843 out: 844 free(wreq, M_TEMP); 845 return error; 846 invalid: 847 free(wreq, M_TEMP); 848 return EINVAL; 849 } 850 851 static int 852 cap2cipher(int flag) 853 { 854 switch (flag) { 855 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP; 856 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB; 857 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM; 858 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP; 859 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP; 860 } 861 return -1; 862 } 863 864 static int 865 ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq) 866 { 867 struct ieee80211_node *ni; 868 struct ieee80211req_key ik; 869 struct ieee80211_key *wk; 870 const struct ieee80211_cipher *cip; 871 u_int kid; 872 int error; 873 874 if (ireq->i_len != sizeof(ik)) 875 return EINVAL; 876 error = copyin(ireq->i_data, &ik, sizeof(ik)); 877 if (error) 878 return error; 879 kid = ik.ik_keyix; 880 if (kid == IEEE80211_KEYIX_NONE) { 881 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr); 882 if (ni == NULL) 883 return EINVAL; /* XXX */ 884 wk = &ni->ni_ucastkey; 885 } else { 886 if (kid >= IEEE80211_WEP_NKID) 887 return EINVAL; 888 wk = &ic->ic_nw_keys[kid]; 889 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr); 890 ni = NULL; 891 } 892 cip = wk->wk_cipher; 893 ik.ik_type = cip->ic_cipher; 894 ik.ik_keylen = wk->wk_keylen; 895 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 896 if (wk->wk_keyix == ic->ic_def_txkey) 897 ik.ik_flags |= IEEE80211_KEY_DEFAULT; 898 if (kauth_authorize_generic(curlwp->l_cred, KAUTH_GENERIC_ISSUSER, 899 &curlwp->l_acflag) == 0) { 900 /* NB: only root can read key data */ 901 ik.ik_keyrsc = wk->wk_keyrsc; 902 ik.ik_keytsc = wk->wk_keytsc; 903 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen); 904 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) { 905 memcpy(ik.ik_keydata+wk->wk_keylen, 906 wk->wk_key + IEEE80211_KEYBUF_SIZE, 907 IEEE80211_MICBUF_SIZE); 908 ik.ik_keylen += IEEE80211_MICBUF_SIZE; 909 } 910 } else { 911 ik.ik_keyrsc = 0; 912 ik.ik_keytsc = 0; 913 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); 914 } 915 if (ni != NULL) 916 ieee80211_free_node(ni); 917 return copyout(&ik, ireq->i_data, sizeof(ik)); 918 } 919 920 static int 921 ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 922 { 923 size_t len = ireq->i_len; 924 925 if (sizeof(ic->ic_chan_active) < len) { 926 len = sizeof(ic->ic_chan_active); 927 } 928 return copyout(&ic->ic_chan_active, ireq->i_data, len); 929 } 930 931 static int 932 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) 933 { 934 struct ieee80211req_chaninfo *chans; 935 int i, space, error; 936 937 /* 938 * Since channel 0 is not available for DS, channel 1 939 * is assigned to LSB on WaveLAN. 940 */ 941 if (ic->ic_phytype == IEEE80211_T_DS) 942 i = 1; 943 else 944 i = 0; 945 946 chans = malloc(sizeof(*chans), M_TEMP, M_WAITOK|M_ZERO); 947 948 for (; i <= IEEE80211_CHAN_MAX; i++) 949 if (isset(ic->ic_chan_avail, i)) { 950 struct ieee80211_channel *c = &ic->ic_channels[i]; 951 chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq; 952 chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags; 953 chans->ic_nchans++; 954 } 955 space = __offsetof(struct ieee80211req_chaninfo, 956 ic_chans[chans->ic_nchans]); 957 if (space > ireq->i_len) 958 space = ireq->i_len; 959 error = copyout(chans, ireq->i_data, space); 960 free(chans, M_TEMP); 961 return error; 962 } 963 964 static int 965 ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq) 966 { 967 struct ieee80211_node *ni; 968 struct ieee80211req_wpaie wpaie; 969 int error; 970 971 if (ireq->i_len < IEEE80211_ADDR_LEN) 972 return EINVAL; 973 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 974 if (error != 0) 975 return error; 976 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr); 977 if (ni == NULL) 978 return EINVAL; /* XXX */ 979 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 980 if (ni->ni_wpa_ie != NULL) { 981 int ielen = ni->ni_wpa_ie[1] + 2; 982 if (ielen > sizeof(wpaie.wpa_ie)) 983 ielen = sizeof(wpaie.wpa_ie); 984 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); 985 } 986 ieee80211_free_node(ni); 987 if (ireq->i_len > sizeof(wpaie)) 988 ireq->i_len = sizeof(wpaie); 989 return copyout(&wpaie, ireq->i_data, ireq->i_len); 990 } 991 992 static int 993 ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 994 { 995 struct ieee80211_node *ni; 996 u_int8_t macaddr[IEEE80211_ADDR_LEN]; 997 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 998 int error; 999 1000 if (ireq->i_len < off) 1001 return EINVAL; 1002 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1003 if (error != 0) 1004 return error; 1005 ni = ieee80211_find_node(&ic->ic_sta, macaddr); 1006 if (ni == NULL) 1007 return EINVAL; /* XXX */ 1008 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 1009 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 1010 /* NB: copy out only the statistics */ 1011 error = copyout(&ni->ni_stats, (u_int8_t *) ireq->i_data + off, 1012 ireq->i_len - off); 1013 ieee80211_free_node(ni); 1014 return error; 1015 } 1016 1017 static void 1018 get_scan_result(struct ieee80211req_scan_result *sr, 1019 const struct ieee80211_node *ni) 1020 { 1021 struct ieee80211com *ic = ni->ni_ic; 1022 u_int ielen = 0; 1023 1024 memset(sr, 0, sizeof(*sr)); 1025 sr->isr_ssid_len = ni->ni_esslen; 1026 if (ni->ni_wpa_ie != NULL) 1027 ielen += 2+ni->ni_wpa_ie[1]; 1028 if (ni->ni_wme_ie != NULL) 1029 ielen += 2+ni->ni_wme_ie[1]; 1030 1031 /* 1032 * The value sr->isr_ie_len is defined as a uint8_t, so we 1033 * need to be careful to avoid an integer overflow. If the 1034 * value would overflow, we will set isr_ie_len to zero, and 1035 * ieee80211_ioctl_getscanresults (below) will avoid copying 1036 * the (overflowing) data. 1037 */ 1038 if (ielen > 255) 1039 ielen = 0; 1040 sr->isr_ie_len = ielen; 1041 sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len; 1042 sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t)); 1043 if (ni->ni_chan != IEEE80211_CHAN_ANYC) { 1044 sr->isr_freq = ni->ni_chan->ic_freq; 1045 sr->isr_flags = ni->ni_chan->ic_flags; 1046 } 1047 sr->isr_rssi = ic->ic_node_getrssi(ni); 1048 sr->isr_intval = ni->ni_intval; 1049 sr->isr_capinfo = ni->ni_capinfo; 1050 sr->isr_erp = ni->ni_erp; 1051 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid); 1052 sr->isr_nrates = ni->ni_rates.rs_nrates; 1053 if (sr->isr_nrates > 15) 1054 sr->isr_nrates = 15; 1055 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates); 1056 } 1057 1058 static int 1059 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 1060 { 1061 union { 1062 struct ieee80211req_scan_result res; 1063 char data[sizeof(struct ieee80211req_scan_result) + IEEE80211_NWID_LEN + 256 * 2]; 1064 } u; 1065 struct ieee80211req_scan_result *sr = &u.res; 1066 struct ieee80211_node_table *nt; 1067 struct ieee80211_node *ni; 1068 int error, space; 1069 u_int8_t *p, *cp; 1070 1071 p = ireq->i_data; 1072 space = ireq->i_len; 1073 error = 0; 1074 /* XXX locking */ 1075 nt = &ic->ic_scan; 1076 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 1077 /* NB: skip pre-scan node state */ 1078 if (ni->ni_chan == IEEE80211_CHAN_ANYC) 1079 continue; 1080 get_scan_result(sr, ni); 1081 if (sr->isr_len > sizeof(u)) 1082 continue; /* XXX */ 1083 if (space < sr->isr_len) 1084 break; 1085 cp = (u_int8_t *)(sr+1); 1086 memcpy(cp, ni->ni_essid, ni->ni_esslen); 1087 cp += ni->ni_esslen; 1088 if (sr->isr_ie_len > 0 && ni->ni_wpa_ie != NULL) { 1089 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1090 cp += 2+ni->ni_wpa_ie[1]; 1091 } 1092 if (sr->isr_ie_len > 0 && ni->ni_wme_ie != NULL) { 1093 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1094 cp += 2+ni->ni_wme_ie[1]; 1095 } 1096 error = copyout(sr, p, sr->isr_len); 1097 if (error) 1098 break; 1099 p += sr->isr_len; 1100 space -= sr->isr_len; 1101 } 1102 ireq->i_len -= space; 1103 return error; 1104 } 1105 1106 struct stainforeq { 1107 struct ieee80211com *ic; 1108 struct ieee80211req_sta_info *si; 1109 size_t space; 1110 }; 1111 1112 static size_t 1113 sta_space(const struct ieee80211_node *ni, size_t *ielen) 1114 { 1115 *ielen = 0; 1116 if (ni->ni_wpa_ie != NULL) 1117 *ielen += 2+ni->ni_wpa_ie[1]; 1118 if (ni->ni_wme_ie != NULL) 1119 *ielen += 2+ni->ni_wme_ie[1]; 1120 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, 1121 sizeof(u_int32_t)); 1122 } 1123 1124 static void 1125 get_sta_space(void *arg, struct ieee80211_node *ni) 1126 { 1127 struct stainforeq *req = arg; 1128 struct ieee80211com *ic = ni->ni_ic; 1129 size_t ielen; 1130 1131 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1132 ni->ni_associd == 0) /* only associated stations */ 1133 return; 1134 req->space += sta_space(ni, &ielen); 1135 } 1136 1137 static void 1138 get_sta_info(void *arg, struct ieee80211_node *ni) 1139 { 1140 struct stainforeq *req = arg; 1141 struct ieee80211com *ic = ni->ni_ic; 1142 struct ieee80211req_sta_info *si; 1143 size_t ielen, len; 1144 u_int8_t *cp; 1145 1146 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1147 ni->ni_associd == 0) /* only associated stations */ 1148 return; 1149 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 1150 return; 1151 len = sta_space(ni, &ielen); 1152 if (len > req->space) 1153 return; 1154 si = req->si; 1155 si->isi_len = len; 1156 si->isi_ie_len = ielen; 1157 si->isi_freq = ni->ni_chan->ic_freq; 1158 si->isi_flags = ni->ni_chan->ic_flags; 1159 si->isi_state = ni->ni_flags; 1160 si->isi_authmode = ni->ni_authmode; 1161 si->isi_rssi = ic->ic_node_getrssi(ni); 1162 si->isi_capinfo = ni->ni_capinfo; 1163 si->isi_erp = ni->ni_erp; 1164 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 1165 si->isi_nrates = ni->ni_rates.rs_nrates; 1166 if (si->isi_nrates > 15) 1167 si->isi_nrates = 15; 1168 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 1169 si->isi_txrate = ni->ni_txrate; 1170 si->isi_associd = ni->ni_associd; 1171 si->isi_txpower = ni->ni_txpower; 1172 si->isi_vlan = ni->ni_vlan; 1173 if (ni->ni_flags & IEEE80211_NODE_QOS) { 1174 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 1175 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 1176 } else { 1177 si->isi_txseqs[0] = ni->ni_txseqs[0]; 1178 si->isi_rxseqs[0] = ni->ni_rxseqs[0]; 1179 } 1180 /* NB: leave all cases in case we relax ni_associd == 0 check */ 1181 if (ieee80211_node_is_authorized(ni)) 1182 si->isi_inact = ic->ic_inact_run; 1183 else if (ni->ni_associd != 0) 1184 si->isi_inact = ic->ic_inact_auth; 1185 else 1186 si->isi_inact = ic->ic_inact_init; 1187 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 1188 1189 cp = (u_int8_t *)(si+1); 1190 if (ni->ni_wpa_ie != NULL) { 1191 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1192 cp += 2+ni->ni_wpa_ie[1]; 1193 } 1194 if (ni->ni_wme_ie != NULL) { 1195 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1196 cp += 2+ni->ni_wme_ie[1]; 1197 } 1198 1199 req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len); 1200 req->space -= len; 1201 } 1202 1203 static int 1204 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 1205 { 1206 struct stainforeq req; 1207 int error; 1208 1209 if (ireq->i_len < sizeof(struct stainforeq)) 1210 return EFAULT; 1211 1212 error = 0; 1213 req.space = 0; 1214 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); 1215 if (req.space > ireq->i_len) 1216 req.space = ireq->i_len; 1217 if (req.space > 0) { 1218 size_t space; 1219 void *p; 1220 1221 space = req.space; 1222 /* XXX M_WAITOK after driver lock released */ 1223 p = malloc(space, M_TEMP, M_NOWAIT); 1224 if (p == NULL) 1225 return ENOMEM; 1226 req.si = p; 1227 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 1228 ireq->i_len = space - req.space; 1229 error = copyout(p, ireq->i_data, ireq->i_len); 1230 FREE(p, M_TEMP); 1231 } else 1232 ireq->i_len = 0; 1233 1234 return error; 1235 } 1236 1237 static int 1238 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1239 { 1240 struct ieee80211_node *ni; 1241 struct ieee80211req_sta_txpow txpow; 1242 int error; 1243 1244 if (ireq->i_len != sizeof(txpow)) 1245 return EINVAL; 1246 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1247 if (error != 0) 1248 return error; 1249 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr); 1250 if (ni == NULL) 1251 return EINVAL; /* XXX */ 1252 txpow.it_txpow = ni->ni_txpower; 1253 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 1254 ieee80211_free_node(ni); 1255 return error; 1256 } 1257 1258 static int 1259 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1260 { 1261 struct ieee80211_wme_state *wme = &ic->ic_wme; 1262 struct wmeParams *wmep; 1263 int ac; 1264 1265 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1266 return EINVAL; 1267 1268 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1269 if (ac >= WME_NUM_AC) 1270 ac = WME_AC_BE; 1271 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 1272 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1273 else 1274 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1275 switch (ireq->i_type) { 1276 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1277 ireq->i_val = wmep->wmep_logcwmin; 1278 break; 1279 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1280 ireq->i_val = wmep->wmep_logcwmax; 1281 break; 1282 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1283 ireq->i_val = wmep->wmep_aifsn; 1284 break; 1285 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1286 ireq->i_val = wmep->wmep_txopLimit; 1287 break; 1288 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1289 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1290 ireq->i_val = wmep->wmep_acm; 1291 break; 1292 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1293 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1294 ireq->i_val = !wmep->wmep_noackPolicy; 1295 break; 1296 } 1297 return 0; 1298 } 1299 1300 static int 1301 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1302 { 1303 const struct ieee80211_aclator *acl = ic->ic_acl; 1304 1305 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); 1306 } 1307 1308 /* 1309 * When building the kernel with -O2 on the i386 architecture, gcc 1310 * seems to want to inline this function into ieee80211_ioctl() 1311 * (which is the only routine that calls it). When this happens, 1312 * ieee80211_ioctl() ends up consuming an additional 2K of stack 1313 * space. (Exactly why it needs so much is unclear.) The problem 1314 * is that it's possible for ieee80211_ioctl() to invoke other 1315 * routines (including driver init functions) which could then find 1316 * themselves perilously close to exhausting the stack. 1317 * 1318 * To avoid this, we deliberately prevent gcc from inlining this 1319 * routine. Another way to avoid this is to use less agressive 1320 * optimization when compiling this file (i.e. -O instead of -O2) 1321 * but special-casing the compilation of this one module in the 1322 * build system would be awkward. 1323 */ 1324 #ifdef __GNUC__ 1325 __attribute__ ((__noinline__)) 1326 #endif 1327 static int 1328 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd __unused, 1329 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(curlwp->l_cred, KAUTH_GENERIC_ISSUSER, 1375 &curlwp->l_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 __unused, 2017 struct ieee80211req *ireq) 2018 { 2019 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2020 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; 2021 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 2022 char tmpssid[IEEE80211_NWID_LEN]; 2023 u_int8_t tmpbssid[IEEE80211_ADDR_LEN]; 2024 struct ieee80211_key *k; 2025 u_int kid; 2026 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2027 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 2028 int error; 2029 const struct ieee80211_authenticator *auth; 2030 int j, caps; 2031 2032 error = 0; 2033 switch (ireq->i_type) { 2034 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2035 case IEEE80211_IOC_SSID: 2036 if (ireq->i_val != 0 || 2037 ireq->i_len > IEEE80211_NWID_LEN) 2038 return EINVAL; 2039 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 2040 if (error) 2041 break; 2042 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 2043 ic->ic_des_esslen = ireq->i_len; 2044 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); 2045 error = ENETRESET; 2046 break; 2047 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2048 case IEEE80211_IOC_WEP: 2049 switch (ireq->i_val) { 2050 case IEEE80211_WEP_OFF: 2051 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2052 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2053 break; 2054 case IEEE80211_WEP_ON: 2055 ic->ic_flags |= IEEE80211_F_PRIVACY; 2056 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2057 break; 2058 case IEEE80211_WEP_MIXED: 2059 ic->ic_flags |= IEEE80211_F_PRIVACY; 2060 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2061 break; 2062 } 2063 error = ENETRESET; 2064 break; 2065 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2066 case IEEE80211_IOC_WEPKEY: 2067 kid = (u_int) ireq->i_val; 2068 if (kid >= IEEE80211_WEP_NKID) 2069 return EINVAL; 2070 k = &ic->ic_nw_keys[kid]; 2071 if (ireq->i_len == 0) { 2072 /* zero-len =>'s delete any existing key */ 2073 (void) ieee80211_crypto_delkey(ic, k); 2074 break; 2075 } 2076 if (ireq->i_len > sizeof(tmpkey)) 2077 return EINVAL; 2078 memset(tmpkey, 0, sizeof(tmpkey)); 2079 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 2080 if (error) 2081 break; 2082 ieee80211_key_update_begin(ic); 2083 k->wk_keyix = kid; /* NB: force fixed key id */ 2084 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 2085 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2086 k->wk_keylen = ireq->i_len; 2087 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 2088 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 2089 error = EINVAL; 2090 } else 2091 error = EINVAL; 2092 ieee80211_key_update_end(ic); 2093 if (!error) /* NB: for compatibility */ 2094 error = ENETRESET; 2095 break; 2096 case IEEE80211_IOC_WEPTXKEY: 2097 kid = (u_int) ireq->i_val; 2098 if (kid >= IEEE80211_WEP_NKID && 2099 (u_int16_t) kid != IEEE80211_KEYIX_NONE) 2100 return EINVAL; 2101 ic->ic_def_txkey = kid; 2102 error = ENETRESET; /* push to hardware */ 2103 break; 2104 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2105 case IEEE80211_IOC_AUTHMODE: 2106 switch (ireq->i_val) { 2107 case IEEE80211_AUTH_WPA: 2108 case IEEE80211_AUTH_8021X: /* 802.1x */ 2109 case IEEE80211_AUTH_OPEN: /* open */ 2110 case IEEE80211_AUTH_SHARED: /* shared-key */ 2111 case IEEE80211_AUTH_AUTO: /* auto */ 2112 auth = ieee80211_authenticator_get(ireq->i_val); 2113 if (auth == NULL) 2114 return EINVAL; 2115 break; 2116 default: 2117 return EINVAL; 2118 } 2119 switch (ireq->i_val) { 2120 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 2121 ic->ic_flags |= IEEE80211_F_PRIVACY; 2122 ireq->i_val = IEEE80211_AUTH_8021X; 2123 break; 2124 case IEEE80211_AUTH_OPEN: /* open */ 2125 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 2126 break; 2127 case IEEE80211_AUTH_SHARED: /* shared-key */ 2128 case IEEE80211_AUTH_8021X: /* 802.1x */ 2129 ic->ic_flags &= ~IEEE80211_F_WPA; 2130 /* both require a key so mark the PRIVACY capability */ 2131 ic->ic_flags |= IEEE80211_F_PRIVACY; 2132 break; 2133 case IEEE80211_AUTH_AUTO: /* auto */ 2134 ic->ic_flags &= ~IEEE80211_F_WPA; 2135 /* XXX PRIVACY handling? */ 2136 /* XXX what's the right way to do this? */ 2137 break; 2138 } 2139 /* NB: authenticator attach/detach happens on state change */ 2140 ic->ic_bss->ni_authmode = ireq->i_val; 2141 /* XXX mixed/mode/usage? */ 2142 ic->ic_auth = auth; 2143 error = ENETRESET; 2144 break; 2145 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2146 case IEEE80211_IOC_CHANNEL: 2147 /* XXX 0xffff overflows 16-bit signed */ 2148 if (ireq->i_val == 0 || 2149 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 2150 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 2151 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 2152 isclr(ic->ic_chan_active, ireq->i_val)) { 2153 return EINVAL; 2154 } else 2155 ic->ic_ibss_chan = ic->ic_des_chan = 2156 &ic->ic_channels[ireq->i_val]; 2157 switch (ic->ic_state) { 2158 case IEEE80211_S_INIT: 2159 case IEEE80211_S_SCAN: 2160 error = ENETRESET; 2161 break; 2162 default: 2163 /* 2164 * If the desired channel has changed (to something 2165 * other than any) and we're not already scanning, 2166 * then kick the state machine. 2167 */ 2168 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 2169 ic->ic_bss->ni_chan != ic->ic_des_chan && 2170 (ic->ic_flags & IEEE80211_F_SCAN) == 0) 2171 error = ENETRESET; 2172 break; 2173 } 2174 if (error == ENETRESET && 2175 ic->ic_opmode == IEEE80211_M_MONITOR) { 2176 if (IS_UP(ic)) { 2177 /* 2178 * Monitor mode can switch directly. 2179 */ 2180 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) 2181 ic->ic_curchan = ic->ic_des_chan; 2182 error = ic->ic_reset(ic->ic_ifp); 2183 } else 2184 error = 0; 2185 } 2186 break; 2187 case IEEE80211_IOC_POWERSAVE: 2188 switch (ireq->i_val) { 2189 case IEEE80211_POWERSAVE_OFF: 2190 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2191 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2192 error = ENETRESET; 2193 } 2194 break; 2195 case IEEE80211_POWERSAVE_ON: 2196 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 2197 error = EINVAL; 2198 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2199 ic->ic_flags |= IEEE80211_F_PMGTON; 2200 error = ENETRESET; 2201 } 2202 break; 2203 default: 2204 error = EINVAL; 2205 break; 2206 } 2207 break; 2208 case IEEE80211_IOC_POWERSAVESLEEP: 2209 if (ireq->i_val < 0) 2210 return EINVAL; 2211 ic->ic_lintval = ireq->i_val; 2212 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2213 break; 2214 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2215 case IEEE80211_IOC_RTSTHRESHOLD: 2216 if (!(IEEE80211_RTS_MIN <= ireq->i_val && 2217 ireq->i_val <= IEEE80211_RTS_MAX)) 2218 return EINVAL; 2219 ic->ic_rtsthreshold = ireq->i_val; 2220 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2221 break; 2222 case IEEE80211_IOC_PROTMODE: 2223 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2224 return EINVAL; 2225 ic->ic_protmode = ireq->i_val; 2226 /* NB: if not operating in 11g this can wait */ 2227 if (ic->ic_curmode == IEEE80211_MODE_11G) 2228 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2229 break; 2230 case IEEE80211_IOC_TXPOWER: 2231 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2232 return EINVAL; 2233 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 2234 ireq->i_val < IEEE80211_TXPOWER_MAX)) 2235 return EINVAL; 2236 ic->ic_txpowlimit = ireq->i_val; 2237 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2238 break; 2239 case IEEE80211_IOC_ROAMING: 2240 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2241 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2242 return EINVAL; 2243 ic->ic_roaming = ireq->i_val; 2244 /* XXXX reset? */ 2245 break; 2246 case IEEE80211_IOC_PRIVACY: 2247 if (ireq->i_val) { 2248 /* XXX check for key state? */ 2249 ic->ic_flags |= IEEE80211_F_PRIVACY; 2250 } else 2251 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2252 break; 2253 case IEEE80211_IOC_DROPUNENCRYPTED: 2254 if (ireq->i_val) 2255 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2256 else 2257 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2258 break; 2259 case IEEE80211_IOC_WPAKEY: 2260 error = ieee80211_ioctl_setkey(ic, ireq); 2261 break; 2262 case IEEE80211_IOC_DELKEY: 2263 error = ieee80211_ioctl_delkey(ic, ireq); 2264 break; 2265 case IEEE80211_IOC_MLME: 2266 error = ieee80211_ioctl_setmlme(ic, ireq); 2267 break; 2268 case IEEE80211_IOC_OPTIE: 2269 error = ieee80211_ioctl_setoptie(ic, ireq); 2270 break; 2271 case IEEE80211_IOC_COUNTERMEASURES: 2272 if (ireq->i_val) { 2273 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 2274 return EINVAL; 2275 ic->ic_flags |= IEEE80211_F_COUNTERM; 2276 } else 2277 ic->ic_flags &= ~IEEE80211_F_COUNTERM; 2278 break; 2279 case IEEE80211_IOC_WPA: 2280 if (ireq->i_val > 3) 2281 return EINVAL; 2282 /* XXX verify ciphers available */ 2283 ic->ic_flags &= ~IEEE80211_F_WPA; 2284 switch (ireq->i_val) { 2285 case 1: 2286 ic->ic_flags |= IEEE80211_F_WPA1; 2287 break; 2288 case 2: 2289 ic->ic_flags |= IEEE80211_F_WPA2; 2290 break; 2291 case 3: 2292 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2293 break; 2294 } 2295 error = ENETRESET; /* XXX? */ 2296 break; 2297 case IEEE80211_IOC_WME: 2298 if (ireq->i_val) { 2299 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2300 return EINVAL; 2301 ic->ic_flags |= IEEE80211_F_WME; 2302 } else 2303 ic->ic_flags &= ~IEEE80211_F_WME; 2304 error = ENETRESET; /* XXX maybe not for station? */ 2305 break; 2306 case IEEE80211_IOC_HIDESSID: 2307 if (ireq->i_val) 2308 ic->ic_flags |= IEEE80211_F_HIDESSID; 2309 else 2310 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2311 error = ENETRESET; 2312 break; 2313 case IEEE80211_IOC_APBRIDGE: 2314 if (ireq->i_val == 0) 2315 ic->ic_flags |= IEEE80211_F_NOBRIDGE; 2316 else 2317 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE; 2318 break; 2319 case IEEE80211_IOC_MCASTCIPHER: 2320 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 && 2321 !ieee80211_crypto_available(ireq->i_val)) 2322 return EINVAL; 2323 rsn->rsn_mcastcipher = ireq->i_val; 2324 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2325 break; 2326 case IEEE80211_IOC_MCASTKEYLEN: 2327 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2328 return EINVAL; 2329 /* XXX no way to verify driver capability */ 2330 rsn->rsn_mcastkeylen = ireq->i_val; 2331 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2332 break; 2333 case IEEE80211_IOC_UCASTCIPHERS: 2334 /* 2335 * Convert user-specified cipher set to the set 2336 * we can support (via hardware or software). 2337 * NB: this logic intentionally ignores unknown and 2338 * unsupported ciphers so folks can specify 0xff or 2339 * similar and get all available ciphers. 2340 */ 2341 caps = 0; 2342 for (j = 1; j < 32; j++) /* NB: skip WEP */ 2343 if ((ireq->i_val & (1<<j)) && 2344 ((ic->ic_caps & cipher2cap(j)) || 2345 ieee80211_crypto_available(j))) 2346 caps |= 1<<j; 2347 if (caps == 0) /* nothing available */ 2348 return EINVAL; 2349 /* XXX verify ciphers ok for unicast use? */ 2350 /* XXX disallow if running as it'll have no effect */ 2351 rsn->rsn_ucastcipherset = caps; 2352 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2353 break; 2354 case IEEE80211_IOC_UCASTCIPHER: 2355 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0) 2356 return EINVAL; 2357 rsn->rsn_ucastcipher = ireq->i_val; 2358 break; 2359 case IEEE80211_IOC_UCASTKEYLEN: 2360 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2361 return EINVAL; 2362 /* XXX no way to verify driver capability */ 2363 rsn->rsn_ucastkeylen = ireq->i_val; 2364 break; 2365 case IEEE80211_IOC_DRIVER_CAPS: 2366 /* NB: for testing */ 2367 ic->ic_caps = (((u_int16_t) ireq->i_val) << 16) | 2368 ((u_int16_t) ireq->i_len); 2369 break; 2370 case IEEE80211_IOC_KEYMGTALGS: 2371 /* XXX check */ 2372 rsn->rsn_keymgmtset = ireq->i_val; 2373 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2374 break; 2375 case IEEE80211_IOC_RSNCAPS: 2376 /* XXX check */ 2377 rsn->rsn_caps = ireq->i_val; 2378 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2379 break; 2380 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211) 2381 case IEEE80211_IOC_BSSID: 2382 /* NB: should only be set when in STA mode */ 2383 if (ic->ic_opmode != IEEE80211_M_STA) 2384 return EINVAL; 2385 if (ireq->i_len != sizeof(tmpbssid)) 2386 return EINVAL; 2387 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2388 if (error) 2389 break; 2390 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2391 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2392 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2393 else 2394 ic->ic_flags |= IEEE80211_F_DESBSSID; 2395 error = ENETRESET; 2396 break; 2397 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */ 2398 case IEEE80211_IOC_CHANLIST: 2399 error = ieee80211_ioctl_setchanlist(ic, ireq); 2400 break; 2401 case IEEE80211_IOC_SCAN_REQ: 2402 if (ic->ic_opmode == IEEE80211_M_HOSTAP) /* XXX ignore */ 2403 break; 2404 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 2405 if (error == 0) /* XXX background scan */ 2406 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2407 break; 2408 case IEEE80211_IOC_ADDMAC: 2409 case IEEE80211_IOC_DELMAC: 2410 error = ieee80211_ioctl_macmac(ic, ireq); 2411 break; 2412 case IEEE80211_IOC_MACCMD: 2413 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2414 break; 2415 case IEEE80211_IOC_STA_TXPOW: 2416 error = ieee80211_ioctl_setstatxpow(ic, ireq); 2417 break; 2418 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2419 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2420 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2421 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2422 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2423 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2424 error = ieee80211_ioctl_setwmeparam(ic, ireq); 2425 break; 2426 case IEEE80211_IOC_DTIM_PERIOD: 2427 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2428 ic->ic_opmode != IEEE80211_M_IBSS) 2429 return EINVAL; 2430 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2431 ireq->i_val <= IEEE80211_DTIM_MAX) { 2432 ic->ic_dtim_period = ireq->i_val; 2433 error = ENETRESET; /* requires restart */ 2434 } else 2435 error = EINVAL; 2436 break; 2437 case IEEE80211_IOC_BEACON_INTERVAL: 2438 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2439 ic->ic_opmode != IEEE80211_M_IBSS) 2440 return EINVAL; 2441 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2442 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2443 ic->ic_bintval = ireq->i_val; 2444 error = ENETRESET; /* requires restart */ 2445 } else 2446 error = EINVAL; 2447 break; 2448 case IEEE80211_IOC_PUREG: 2449 if (ireq->i_val) 2450 ic->ic_flags |= IEEE80211_F_PUREG; 2451 else 2452 ic->ic_flags &= ~IEEE80211_F_PUREG; 2453 /* NB: reset only if we're operating on an 11g channel */ 2454 if (ic->ic_curmode == IEEE80211_MODE_11G) 2455 error = ENETRESET; 2456 break; 2457 case IEEE80211_IOC_MCAST_RATE: 2458 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2459 break; 2460 case IEEE80211_IOC_FRAGTHRESHOLD: 2461 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2462 ireq->i_val != IEEE80211_FRAG_MAX) 2463 return EINVAL; 2464 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && 2465 ireq->i_val <= IEEE80211_FRAG_MAX)) 2466 return EINVAL; 2467 ic->ic_fragthreshold = ireq->i_val; 2468 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2469 break; 2470 default: 2471 error = EINVAL; 2472 break; 2473 } 2474 if (error == ENETRESET && !IS_UP_AUTO(ic)) 2475 error = 0; 2476 return error; 2477 } 2478 2479 #ifdef __FreeBSD__ 2480 int 2481 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2482 { 2483 struct ifnet *ifp = ic->ic_ifp; 2484 int error = 0; 2485 struct ifreq *ifr; 2486 struct ifaddr *ifa; /* XXX */ 2487 2488 switch (cmd) { 2489 case SIOCSIFMEDIA: 2490 case SIOCGIFMEDIA: 2491 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 2492 &ic->ic_media, cmd); 2493 break; 2494 case SIOCG80211: 2495 error = ieee80211_ioctl_get80211(ic, cmd, 2496 (struct ieee80211req *) data); 2497 break; 2498 case SIOCS80211: 2499 error = suser(curthread); 2500 if (error == 0) 2501 error = ieee80211_ioctl_set80211(ic, cmd, 2502 (struct ieee80211req *) data); 2503 break; 2504 case SIOCGIFGENERIC: 2505 error = ieee80211_cfgget(ic, cmd, data); 2506 break; 2507 case SIOCSIFGENERIC: 2508 error = suser(curthread); 2509 if (error) 2510 break; 2511 error = ieee80211_cfgset(ic, cmd, data); 2512 break; 2513 case SIOCG80211STATS: 2514 ifr = (struct ifreq *)data; 2515 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2516 break; 2517 case SIOCSIFMTU: 2518 ifr = (struct ifreq *)data; 2519 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2520 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2521 error = EINVAL; 2522 else 2523 ifp->if_mtu = ifr->ifr_mtu; 2524 break; 2525 case SIOCSIFADDR: 2526 /* 2527 * XXX Handle this directly so we can supress if_init calls. 2528 * XXX This should be done in ether_ioctl but for the moment 2529 * XXX there are too many other parts of the system that 2530 * XXX set IFF_UP and so supress if_init being called when 2531 * XXX it should be. 2532 */ 2533 ifa = (struct ifaddr *) data; 2534 switch (ifa->ifa_addr->sa_family) { 2535 #ifdef INET 2536 case AF_INET: 2537 if ((ifp->if_flags & IFF_UP) == 0) { 2538 ifp->if_flags |= IFF_UP; 2539 ifp->if_init(ifp->if_softc); 2540 } 2541 arp_ifinit(ifp, ifa); 2542 break; 2543 #endif 2544 #ifdef IPX 2545 /* 2546 * XXX - This code is probably wrong, 2547 * but has been copied many times. 2548 */ 2549 case AF_IPX: { 2550 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 2551 2552 if (ipx_nullhost(*ina)) 2553 ina->x_host = *(union ipx_host *) 2554 IFP2ENADDR(ifp); 2555 else 2556 bcopy((caddr_t) ina->x_host.c_host, 2557 (caddr_t) IFP2ENADDR(ifp), 2558 ETHER_ADDR_LEN); 2559 /* fall thru... */ 2560 } 2561 #endif 2562 default: 2563 if ((ifp->if_flags & IFF_UP) == 0) { 2564 ifp->if_flags |= IFF_UP; 2565 ifp->if_init(ifp->if_softc); 2566 } 2567 break; 2568 } 2569 break; 2570 default: 2571 error = ether_ioctl(ifp, cmd, data); 2572 break; 2573 } 2574 return error; 2575 } 2576 #endif /* __FreeBSD__ */ 2577 2578 #ifdef COMPAT_20 2579 static void 2580 ieee80211_get_ostats(struct ieee80211_ostats *ostats, 2581 struct ieee80211_stats *stats) 2582 { 2583 #define COPYSTATS1(__ostats, __nstats, __dstmemb, __srcmemb, __lastmemb)\ 2584 (void)memcpy(&(__ostats)->__dstmemb, &(__nstats)->__srcmemb, \ 2585 offsetof(struct ieee80211_stats, __lastmemb) - \ 2586 offsetof(struct ieee80211_stats, __srcmemb)) 2587 #define COPYSTATS(__ostats, __nstats, __dstmemb, __lastmemb) \ 2588 COPYSTATS1(__ostats, __nstats, __dstmemb, __dstmemb, __lastmemb) 2589 2590 COPYSTATS(ostats, stats, is_rx_badversion, is_rx_unencrypted); 2591 COPYSTATS(ostats, stats, is_rx_wepfail, is_rx_beacon); 2592 COPYSTATS(ostats, stats, is_rx_rstoobig, is_rx_auth_countermeasures); 2593 COPYSTATS(ostats, stats, is_rx_assoc_bss, is_rx_assoc_badwpaie); 2594 COPYSTATS(ostats, stats, is_rx_deauth, is_rx_unauth); 2595 COPYSTATS1(ostats, stats, is_tx_nombuf, is_tx_nobuf, is_tx_badcipher); 2596 COPYSTATS(ostats, stats, is_scan_active, is_crypto_tkip); 2597 } 2598 #endif /* COMPAT_20 */ 2599 2600 #ifdef __NetBSD__ 2601 int 2602 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2603 { 2604 struct ifnet *ifp = ic->ic_ifp; 2605 struct ifreq *ifr = (struct ifreq *)data; 2606 int i, error = 0, kid, klen, s; 2607 struct ieee80211_key *k; 2608 struct ieee80211_nwid nwid; 2609 struct ieee80211_nwkey *nwkey; 2610 struct ieee80211_power *power; 2611 struct ieee80211_bssid *bssid; 2612 struct ieee80211chanreq *chanreq; 2613 struct ieee80211_channel *chan; 2614 uint32_t oflags; 2615 #ifdef COMPAT_20 2616 struct ieee80211_ostats ostats; 2617 #endif /* COMPAT_20 */ 2618 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; 2619 u_int8_t tmpkey[IEEE80211_WEP_NKID][IEEE80211_KEYBUF_SIZE]; 2620 2621 switch (cmd) { 2622 case SIOCSIFMEDIA: 2623 case SIOCGIFMEDIA: 2624 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 2625 break; 2626 case SIOCG80211: 2627 error = ieee80211_ioctl_get80211(ic, cmd, 2628 (struct ieee80211req *) data); 2629 break; 2630 case SIOCS80211: 2631 if ((error = kauth_authorize_generic(curlwp->l_cred, 2632 KAUTH_GENERIC_ISSUSER, &curlwp->l_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(curlwp->l_cred, 2770 KAUTH_GENERIC_ISSUSER, &curlwp->l_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_curchan; 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(curlwp->l_cred, 2879 KAUTH_GENERIC_ISSUSER, &curlwp->l_acflag); 2880 if (error) 2881 break; 2882 error = ieee80211_cfgset(ic, cmd, data); 2883 break; 2884 #ifdef COMPAT_20 2885 case OSIOCG80211STATS: 2886 case OSIOCG80211ZSTATS: 2887 ifr = (struct ifreq *)data; 2888 s = splnet(); 2889 ieee80211_get_ostats(&ostats, &ic->ic_stats); 2890 error = copyout(&ostats, ifr->ifr_data, sizeof(ostats)); 2891 if (error == 0 && cmd == OSIOCG80211ZSTATS) 2892 (void)memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 2893 splx(s); 2894 break; 2895 #endif /* COMPAT_20 */ 2896 case SIOCG80211ZSTATS: 2897 case SIOCG80211STATS: 2898 ifr = (struct ifreq *)data; 2899 s = splnet(); 2900 error = copyout(&ic->ic_stats, ifr->ifr_buf, 2901 MIN(sizeof(ic->ic_stats), ifr->ifr_buflen)); 2902 if (error == 0 && cmd == SIOCG80211ZSTATS) 2903 (void)memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 2904 splx(s); 2905 break; 2906 case SIOCSIFMTU: 2907 ifr = (struct ifreq *)data; 2908 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2909 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2910 error = EINVAL; 2911 else 2912 ifp->if_mtu = ifr->ifr_mtu; 2913 break; 2914 default: 2915 error = ether_ioctl(ifp, cmd, data); 2916 break; 2917 } 2918 return error; 2919 } 2920 #endif /* __NetBSD__ */ 2921