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