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