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