ieee80211_ioctl.c (170360) | ieee80211_ioctl.c (170530) |
---|---|
1/*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002-2007 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: --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002-2007 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: --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 170360 2007-06-06 04:56:04Z sam $"); | 28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 170530 2007-06-11 03:36:55Z sam $"); |
29 30#include "opt_compat.h" 31 32/* 33 * IEEE 802.11 ioctl support (FreeBSD-specific) 34 */ 35 36#include "opt_inet.h" --- 20 unchanged lines hidden (view full) --- 57#ifdef IPX 58#include <netipx/ipx.h> 59#include <netipx/ipx_if.h> 60#endif 61 62#include <net80211/ieee80211_var.h> 63#include <net80211/ieee80211_ioctl.h> 64 | 29 30#include "opt_compat.h" 31 32/* 33 * IEEE 802.11 ioctl support (FreeBSD-specific) 34 */ 35 36#include "opt_inet.h" --- 20 unchanged lines hidden (view full) --- 57#ifdef IPX 58#include <netipx/ipx.h> 59#include <netipx/ipx_if.h> 60#endif 61 62#include <net80211/ieee80211_var.h> 63#include <net80211/ieee80211_ioctl.h> 64 |
65#include <dev/wi/if_wavelan_ieee.h> 66 | |
67#define IS_UP(_ic) \ 68 (((_ic)->ic_ifp->if_flags & IFF_UP) && \ 69 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING)) 70#define IS_UP_AUTO(_ic) \ 71 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO) | 65#define IS_UP(_ic) \ 66 (((_ic)->ic_ifp->if_flags & IFF_UP) && \ 67 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING)) 68#define IS_UP_AUTO(_ic) \ 69 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO) |
70#define RESCAN 1 |
|
72 | 71 |
73/* 74 * XXX 75 * Wireless LAN specific configuration interface, which is compatible 76 * with wicontrol(8). 77 */ | 72static struct ieee80211_channel *findchannel(struct ieee80211com *, 73 int ieee, int mode); |
78 | 74 |
79struct wi_read_ap_args { 80 int i; /* result count */ 81 struct wi_apinfo *ap; /* current entry in result buffer */ 82 caddr_t max; /* result buffer bound */ 83}; 84 85static void 86wi_read_ap_result(void *arg, struct ieee80211_node *ni) 87{ 88 struct ieee80211com *ic = ni->ni_ic; 89 struct wi_read_ap_args *sa = arg; 90 struct wi_apinfo *ap = sa->ap; 91 struct ieee80211_rateset *rs; 92 int j; 93 94 if ((caddr_t)(ap + 1) > sa->max) 95 return; 96 memset(ap, 0, sizeof(struct wi_apinfo)); 97 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 98 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); 99 ap->namelen = ic->ic_des_esslen; 100 if (ic->ic_des_esslen) 101 memcpy(ap->name, ic->ic_des_essid, 102 ic->ic_des_esslen); 103 } else { 104 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); 105 ap->namelen = ni->ni_esslen; 106 if (ni->ni_esslen) 107 memcpy(ap->name, ni->ni_essid, 108 ni->ni_esslen); 109 } 110 ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); 111 ap->signal = ic->ic_node_getrssi(ni); 112 ap->capinfo = ni->ni_capinfo; 113 ap->interval = ni->ni_intval; 114 rs = &ni->ni_rates; 115 for (j = 0; j < rs->rs_nrates; j++) { 116 if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) { 117 ap->rate = (rs->rs_rates[j] & 118 IEEE80211_RATE_VAL) * 5; /* XXX */ 119 } 120 } 121 sa->i++; 122 sa->ap++; 123} 124 125struct wi_read_prism2_args { 126 int i; /* result count */ 127 struct wi_scan_res *res;/* current entry in result buffer */ 128 caddr_t max; /* result buffer bound */ 129}; 130 131static void 132wi_read_prism2_result(void *arg, struct ieee80211_node *ni) 133{ 134 struct ieee80211com *ic = ni->ni_ic; 135 struct wi_read_prism2_args *sa = arg; 136 struct wi_scan_res *res = sa->res; 137 138 if ((caddr_t)(res + 1) > sa->max) 139 return; 140 res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); 141 res->wi_noise = 0; 142 res->wi_signal = ic->ic_node_getrssi(ni); 143 IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); 144 res->wi_interval = ni->ni_intval; 145 res->wi_capinfo = ni->ni_capinfo; 146 res->wi_ssid_len = ni->ni_esslen; 147 memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN); 148 /* NB: assumes wi_srates holds <= ni->ni_rates */ 149 memcpy(res->wi_srates, ni->ni_rates.rs_rates, 150 sizeof(res->wi_srates)); 151 if (ni->ni_rates.rs_nrates < 10) 152 res->wi_srates[ni->ni_rates.rs_nrates] = 0; 153 res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate]; 154 res->wi_rsvd = 0; 155 156 sa->i++; 157 sa->res++; 158} 159 160struct wi_read_sigcache_args { 161 int i; /* result count */ 162 struct wi_sigcache *wsc;/* current entry in result buffer */ 163 caddr_t max; /* result buffer bound */ 164}; 165 166static void 167wi_read_sigcache(void *arg, struct ieee80211_node *ni) 168{ 169 struct ieee80211com *ic = ni->ni_ic; 170 struct wi_read_sigcache_args *sa = arg; 171 struct wi_sigcache *wsc = sa->wsc; 172 173 if ((caddr_t)(wsc + 1) > sa->max) 174 return; 175 memset(wsc, 0, sizeof(struct wi_sigcache)); 176 IEEE80211_ADDR_COPY(wsc->macsrc, ni->ni_macaddr); 177 wsc->signal = ic->ic_node_getrssi(ni); 178 179 sa->wsc++; 180 sa->i++; 181} 182 183int 184ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data) 185{ 186 struct ifnet *ifp = ic->ic_ifp; 187 int i, j, error; 188 struct ifreq *ifr = (struct ifreq *)data; 189 struct wi_req wreq; 190 struct wi_ltv_keys *keys; 191 192 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 193 if (error) 194 return error; 195 wreq.wi_len = 0; 196 switch (wreq.wi_type) { 197 case WI_RID_SERIALNO: 198 /* nothing appropriate */ 199 break; 200 case WI_RID_NODENAME: 201 strcpy((char *)&wreq.wi_val[1], hostname); 202 wreq.wi_val[0] = htole16(strlen(hostname)); 203 wreq.wi_len = (1 + strlen(hostname) + 1) / 2; 204 break; 205 case WI_RID_CURRENT_SSID: 206 if (ic->ic_state != IEEE80211_S_RUN) { 207 wreq.wi_val[0] = 0; 208 wreq.wi_len = 1; 209 break; 210 } 211 wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen); 212 memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid, 213 ic->ic_bss->ni_esslen); 214 wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2; 215 break; 216 case WI_RID_OWN_SSID: 217 case WI_RID_DESIRED_SSID: 218 wreq.wi_val[0] = htole16(ic->ic_des_esslen); 219 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen); 220 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2; 221 break; 222 case WI_RID_CURRENT_BSSID: 223 if (ic->ic_state == IEEE80211_S_RUN) 224 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid); 225 else 226 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); 227 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 228 break; 229 case WI_RID_CHANNEL_LIST: 230 memset(wreq.wi_val, 0, sizeof(wreq.wi_val)); 231 /* 232 * Since channel 0 is not available for DS, channel 1 233 * is assigned to LSB on WaveLAN. 234 */ 235 if (ic->ic_phytype == IEEE80211_T_DS) 236 i = 1; 237 else 238 i = 0; 239 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) 240 if (isset(ic->ic_chan_active, i)) { 241 setbit((u_int8_t *)wreq.wi_val, j); 242 wreq.wi_len = j / 16 + 1; 243 } 244 break; 245 case WI_RID_OWN_CHNL: 246 wreq.wi_val[0] = htole16( 247 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 248 wreq.wi_len = 1; 249 break; 250 case WI_RID_CURRENT_CHAN: 251 wreq.wi_val[0] = htole16( 252 ieee80211_chan2ieee(ic, ic->ic_curchan)); 253 wreq.wi_len = 1; 254 break; 255 case WI_RID_COMMS_QUALITY: 256 wreq.wi_val[0] = 0; /* quality */ 257 wreq.wi_val[1] = htole16(ic->ic_node_getrssi(ic->ic_bss)); 258 wreq.wi_val[2] = 0; /* noise */ 259 wreq.wi_len = 3; 260 break; 261 case WI_RID_PROMISC: 262 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0); 263 wreq.wi_len = 1; 264 break; 265 case WI_RID_PORTTYPE: 266 wreq.wi_val[0] = htole16(ic->ic_opmode); 267 wreq.wi_len = 1; 268 break; 269 case WI_RID_MAC_NODE: 270 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); 271 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 272 break; 273 case WI_RID_TX_RATE: 274 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) 275 wreq.wi_val[0] = 0; /* auto */ 276 else 277 wreq.wi_val[0] = htole16( 278 (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] & 279 IEEE80211_RATE_VAL) / 2); 280 wreq.wi_len = 1; 281 break; 282 case WI_RID_CUR_TX_RATE: 283 wreq.wi_val[0] = htole16( 284 (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] & 285 IEEE80211_RATE_VAL) / 2); 286 wreq.wi_len = 1; 287 break; 288 case WI_RID_RTS_THRESH: 289 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); 290 wreq.wi_len = 1; 291 break; 292 case WI_RID_CREATE_IBSS: 293 wreq.wi_val[0] = 294 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0); 295 wreq.wi_len = 1; 296 break; 297 case WI_RID_MICROWAVE_OVEN: 298 wreq.wi_val[0] = 0; /* no ... not supported */ 299 wreq.wi_len = 1; 300 break; 301 case WI_RID_ROAMING_MODE: 302 wreq.wi_val[0] = htole16(ic->ic_roaming); /* XXX map */ 303 wreq.wi_len = 1; 304 break; 305 case WI_RID_SYSTEM_SCALE: 306 wreq.wi_val[0] = htole16(1); /* low density ... not supp */ 307 wreq.wi_len = 1; 308 break; 309 case WI_RID_PM_ENABLED: 310 wreq.wi_val[0] = 311 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); 312 wreq.wi_len = 1; 313 break; 314 case WI_RID_MAX_SLEEP: 315 wreq.wi_val[0] = htole16(ic->ic_lintval); 316 wreq.wi_len = 1; 317 break; 318 case WI_RID_CUR_BEACON_INT: 319 wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval); 320 wreq.wi_len = 1; 321 break; 322 case WI_RID_WEP_AVAIL: 323 wreq.wi_val[0] = htole16(1); /* always available */ 324 wreq.wi_len = 1; 325 break; 326 case WI_RID_CNFAUTHMODE: 327 wreq.wi_val[0] = htole16(1); /* TODO: open system only */ 328 wreq.wi_len = 1; 329 break; 330 case WI_RID_ENCRYPTION: 331 wreq.wi_val[0] = 332 htole16((ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0); 333 wreq.wi_len = 1; 334 break; 335 case WI_RID_TX_CRYPT_KEY: 336 wreq.wi_val[0] = htole16(ic->ic_def_txkey); 337 wreq.wi_len = 1; 338 break; 339 case WI_RID_DEFLT_CRYPT_KEYS: 340 keys = (struct wi_ltv_keys *)&wreq; 341 /* do not show keys to non-root user */ 342 error = priv_check(curthread, PRIV_NET80211_GETKEY); 343 if (error) { 344 memset(keys, 0, sizeof(*keys)); 345 error = 0; 346 break; 347 } 348 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 349 keys->wi_keys[i].wi_keylen = 350 htole16(ic->ic_nw_keys[i].wk_keylen); 351 memcpy(keys->wi_keys[i].wi_keydat, 352 ic->ic_nw_keys[i].wk_key, 353 ic->ic_nw_keys[i].wk_keylen); 354 } 355 wreq.wi_len = sizeof(*keys) / 2; 356 break; 357 case WI_RID_MAX_DATALEN: 358 wreq.wi_val[0] = htole16(ic->ic_fragthreshold); 359 wreq.wi_len = 1; 360 break; 361 case WI_RID_IFACE_STATS: 362 /* XXX: should be implemented in lower drivers */ 363 break; 364 case WI_RID_READ_APS: 365 /* 366 * Don't return results until active scan completes. 367 */ 368 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 369 struct wi_read_ap_args args; 370 371 args.i = 0; 372 args.ap = (void *)((char *)wreq.wi_val + sizeof(i)); 373 args.max = (void *)(&wreq + 1); 374 ieee80211_iterate_nodes(&ic->ic_scan, 375 wi_read_ap_result, &args); 376 memcpy(wreq.wi_val, &args.i, sizeof(args.i)); 377 wreq.wi_len = (sizeof(int) + 378 sizeof(struct wi_apinfo) * args.i) / 2; 379 } else 380 error = EINPROGRESS; 381 break; 382 case WI_RID_PRISM2: 383 /* NB: we lie so WI_RID_SCAN_RES can include rates */ 384 wreq.wi_val[0] = 1; 385 wreq.wi_len = sizeof(u_int16_t) / 2; 386 break; 387 case WI_RID_SCAN_RES: /* compatibility interface */ 388 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 389 struct wi_read_prism2_args args; 390 struct wi_scan_p2_hdr *p2; 391 392 /* NB: use Prism2 format so we can include rate info */ 393 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; 394 args.i = 0; 395 args.res = (void *)&p2[1]; 396 args.max = (void *)(&wreq + 1); 397 ieee80211_iterate_nodes(&ic->ic_scan, 398 wi_read_prism2_result, &args); 399 p2->wi_rsvd = 0; 400 p2->wi_reason = args.i; 401 wreq.wi_len = (sizeof(*p2) + 402 sizeof(struct wi_scan_res) * args.i) / 2; 403 } else 404 error = EINPROGRESS; 405 break; 406 case WI_RID_READ_CACHE: { 407 struct wi_read_sigcache_args args; 408 args.i = 0; 409 args.wsc = (struct wi_sigcache *) wreq.wi_val; 410 args.max = (void *)(&wreq + 1); 411 ieee80211_iterate_nodes(&ic->ic_scan, wi_read_sigcache, &args); 412 wreq.wi_len = sizeof(struct wi_sigcache) * args.i / 2; 413 break; 414 } 415 default: 416 error = EINVAL; 417 break; 418 } 419 if (error == 0) { 420 wreq.wi_len++; 421 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 422 } 423 return error; 424} 425 | |
426static int | 75static int |
427findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) 428{ 429#define IEEERATE(_ic,_m,_i) \ 430 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) 431 int i, nrates = ic->ic_sup_rates[mode].rs_nrates; 432 for (i = 0; i < nrates; i++) 433 if (IEEERATE(ic, mode, i) == rate) 434 return i; 435 return -1; 436#undef IEEERATE 437} 438 439/* 440 * Prepare to do a user-initiated scan for AP's. If no 441 * current/default channel is setup or the current channel 442 * is invalid then pick the first available channel from 443 * the active list as the place to start the scan. 444 */ 445static int 446ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[]) 447{ 448 449 /* 450 * XXX don't permit a scan to be started unless we 451 * know the device is ready. For the moment this means 452 * the device is marked up as this is the required to 453 * initialize the hardware. It would be better to permit 454 * scanning prior to being up but that'll require some 455 * changes to the infrastructure. 456 */ 457 if (!IS_UP(ic)) 458 return EINVAL; 459 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 460 /* 461 * We force the state to INIT before calling ieee80211_new_state 462 * to get ieee80211_begin_scan called. We really want to scan w/o 463 * altering the current state but that's not possible right now. 464 */ 465 /* XXX handle proberequest case */ 466 ic->ic_state = IEEE80211_S_INIT; /* XXX bypass state machine */ 467 return 0; 468} 469 470int 471ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data) 472{ 473 struct ifnet *ifp = ic->ic_ifp; 474 int i, j, len, error, rate; 475 struct ifreq *ifr = (struct ifreq *)data; 476 struct wi_ltv_keys *keys; 477 struct wi_req wreq; 478 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)]; 479 480 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 481 if (error) 482 return error; 483 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0; 484 switch (wreq.wi_type) { 485 case WI_RID_SERIALNO: 486 case WI_RID_NODENAME: 487 return EPERM; 488 case WI_RID_CURRENT_SSID: 489 return EPERM; 490 case WI_RID_OWN_SSID: 491 case WI_RID_DESIRED_SSID: 492 if (le16toh(wreq.wi_val[0]) * 2 > len || 493 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) { 494 error = ENOSPC; 495 break; 496 } 497 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); 498 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2; 499 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen); 500 error = ENETRESET; 501 break; 502 case WI_RID_CURRENT_BSSID: 503 return EPERM; 504 case WI_RID_OWN_CHNL: 505 if (len != 2) 506 return EINVAL; 507 i = le16toh(wreq.wi_val[0]); 508 if (i < 0 || 509 i > IEEE80211_CHAN_MAX || 510 isclr(ic->ic_chan_active, i)) 511 return EINVAL; 512 ic->ic_ibss_chan = &ic->ic_channels[i]; 513 if (ic->ic_opmode == IEEE80211_M_MONITOR) 514 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 515 else 516 error = ENETRESET; 517 break; 518 case WI_RID_CURRENT_CHAN: 519 return EPERM; 520 case WI_RID_COMMS_QUALITY: 521 return EPERM; 522 case WI_RID_PROMISC: 523 if (len != 2) 524 return EINVAL; 525 if (ifp->if_flags & IFF_PROMISC) { 526 if (wreq.wi_val[0] == 0) { 527 ifp->if_flags &= ~IFF_PROMISC; 528 error = ENETRESET; 529 } 530 } else { 531 if (wreq.wi_val[0] != 0) { 532 ifp->if_flags |= IFF_PROMISC; 533 error = ENETRESET; 534 } 535 } 536 break; 537 case WI_RID_PORTTYPE: 538 if (len != 2) 539 return EINVAL; 540 switch (le16toh(wreq.wi_val[0])) { 541 case IEEE80211_M_STA: 542 break; 543 case IEEE80211_M_IBSS: 544 if (!(ic->ic_caps & IEEE80211_C_IBSS)) 545 return EINVAL; 546 break; 547 case IEEE80211_M_AHDEMO: 548 if (ic->ic_phytype != IEEE80211_T_DS || 549 !(ic->ic_caps & IEEE80211_C_AHDEMO)) 550 return EINVAL; 551 break; 552 case IEEE80211_M_HOSTAP: 553 if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) 554 return EINVAL; 555 break; 556 default: 557 return EINVAL; 558 } 559 if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { 560 ic->ic_opmode = le16toh(wreq.wi_val[0]); 561 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 562 } 563 break; 564#if 0 565 case WI_RID_MAC_NODE: 566 if (len != IEEE80211_ADDR_LEN) 567 return EINVAL; 568 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val); 569 /* if_init will copy lladdr into ic_myaddr */ 570 error = ENETRESET; 571 break; 572#endif 573 case WI_RID_TX_RATE: 574 if (len != 2) 575 return EINVAL; 576 if (wreq.wi_val[0] == 0) { 577 /* auto */ 578 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 579 break; 580 } 581 rate = 2 * le16toh(wreq.wi_val[0]); 582 if (ic->ic_curmode == IEEE80211_MODE_AUTO) { 583 /* 584 * In autoselect mode search for the rate. We take 585 * the first instance which may not be right, but we 586 * are limited by the interface. Note that we also 587 * lock the mode to insure the rate is meaningful 588 * when it is used. 589 */ 590 for (j = IEEE80211_MODE_11A; 591 j < IEEE80211_MODE_MAX; j++) { 592 if (isclr(ic->ic_modecaps, j)) 593 continue; 594 i = findrate(ic, j, rate); 595 if (i != -1) { 596 /* lock mode too */ 597 ic->ic_curmode = j; 598 goto setrate; 599 } 600 } 601 } else { 602 i = findrate(ic, ic->ic_curmode, rate); 603 if (i != -1) 604 goto setrate; 605 } 606 return EINVAL; 607 setrate: 608 ic->ic_fixed_rate = i; 609 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 610 break; 611 case WI_RID_CUR_TX_RATE: 612 return EPERM; 613 case WI_RID_RTS_THRESH: 614 if (len != 2) 615 return EINVAL; 616 if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN) 617 return EINVAL; /* TODO: RTS */ 618 break; 619 case WI_RID_CREATE_IBSS: 620 if (len != 2) 621 return EINVAL; 622 if (wreq.wi_val[0] != 0) { 623 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) 624 return EINVAL; 625 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 626 ic->ic_flags |= IEEE80211_F_IBSSON; 627 if (ic->ic_opmode == IEEE80211_M_IBSS && 628 ic->ic_state == IEEE80211_S_SCAN) 629 error = IS_UP_AUTO(ic) ? ENETRESET : 0; 630 } 631 } else { 632 if (ic->ic_flags & IEEE80211_F_IBSSON) { 633 ic->ic_flags &= ~IEEE80211_F_IBSSON; 634 if (ic->ic_flags & IEEE80211_F_SIBSS) { 635 ic->ic_flags &= ~IEEE80211_F_SIBSS; 636 error = IS_UP_AUTO(ic) ? ENETRESET : 0; 637 } 638 } 639 } 640 break; 641 case WI_RID_MICROWAVE_OVEN: 642 if (len != 2) 643 return EINVAL; 644 if (wreq.wi_val[0] != 0) 645 return EINVAL; /* not supported */ 646 break; 647 case WI_RID_ROAMING_MODE: 648 if (len != 2) 649 return EINVAL; 650 i = le16toh(wreq.wi_val[0]); 651 if (i > IEEE80211_ROAMING_MANUAL) 652 return EINVAL; /* not supported */ 653 ic->ic_roaming = i; 654 break; 655 case WI_RID_SYSTEM_SCALE: 656 if (len != 2) 657 return EINVAL; 658 if (le16toh(wreq.wi_val[0]) != 1) 659 return EINVAL; /* not supported */ 660 break; 661 case WI_RID_PM_ENABLED: 662 if (len != 2) 663 return EINVAL; 664 if (wreq.wi_val[0] != 0) { 665 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 666 return EINVAL; 667 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 668 ic->ic_flags |= IEEE80211_F_PMGTON; 669 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 670 } 671 } else { 672 if (ic->ic_flags & IEEE80211_F_PMGTON) { 673 ic->ic_flags &= ~IEEE80211_F_PMGTON; 674 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 675 } 676 } 677 break; 678 case WI_RID_MAX_SLEEP: 679 if (len != 2) 680 return EINVAL; 681 ic->ic_lintval = le16toh(wreq.wi_val[0]); 682 if (ic->ic_flags & IEEE80211_F_PMGTON) 683 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 684 break; 685 case WI_RID_CUR_BEACON_INT: 686 return EPERM; 687 case WI_RID_WEP_AVAIL: 688 return EPERM; 689 case WI_RID_CNFAUTHMODE: 690 if (len != 2) 691 return EINVAL; 692 i = le16toh(wreq.wi_val[0]); 693 if (i > IEEE80211_AUTH_WPA) 694 return EINVAL; 695 ic->ic_bss->ni_authmode = i; /* XXX ENETRESET? */ 696 error = ENETRESET; 697 break; 698 case WI_RID_ENCRYPTION: 699 if (len != 2) 700 return EINVAL; 701 if (wreq.wi_val[0] != 0) { 702 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 703 return EINVAL; 704 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) { 705 ic->ic_flags |= IEEE80211_F_PRIVACY; 706 error = ENETRESET; 707 } 708 } else { 709 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 710 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 711 error = ENETRESET; 712 } 713 } 714 break; 715 case WI_RID_TX_CRYPT_KEY: 716 if (len != 2) 717 return EINVAL; 718 i = le16toh(wreq.wi_val[0]); 719 if (i >= IEEE80211_WEP_NKID) 720 return EINVAL; 721 ic->ic_def_txkey = i; 722 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 723 break; 724 case WI_RID_DEFLT_CRYPT_KEYS: 725 if (len != sizeof(struct wi_ltv_keys)) 726 return EINVAL; 727 keys = (struct wi_ltv_keys *)&wreq; 728 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 729 len = le16toh(keys->wi_keys[i].wi_keylen); 730 if (len != 0 && len < IEEE80211_WEP_KEYLEN) 731 return EINVAL; 732 if (len > IEEE80211_KEYBUF_SIZE) 733 return EINVAL; 734 } 735 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 736 struct ieee80211_key *k = &ic->ic_nw_keys[i]; 737 738 len = le16toh(keys->wi_keys[i].wi_keylen); 739 k->wk_keylen = len; 740 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 741 memset(k->wk_key, 0, sizeof(k->wk_key)); 742 memcpy(k->wk_key, keys->wi_keys[i].wi_keydat, len); 743#if 0 744 k->wk_type = IEEE80211_CIPHER_WEP; 745#endif 746 } 747 error = ENETRESET; 748 break; 749 case WI_RID_MAX_DATALEN: 750 if (len != 2) 751 return EINVAL; 752 len = le16toh(wreq.wi_val[0]); 753 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) 754 return EINVAL; 755 ic->ic_fragthreshold = len; 756 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 757 break; 758 case WI_RID_IFACE_STATS: 759 error = EPERM; 760 break; 761 case WI_RID_SCAN_REQ: /* XXX wicontrol */ 762 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 763 break; 764 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 765 if (error == 0) 766 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 767 break; 768 case WI_RID_SCAN_APS: 769 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 770 break; 771 len--; /* XXX: tx rate? */ 772 /* FALLTHRU */ 773 case WI_RID_CHANNEL_LIST: 774 memset(chanlist, 0, sizeof(chanlist)); 775 /* 776 * Since channel 0 is not available for DS, channel 1 777 * is assigned to LSB on WaveLAN. 778 */ 779 if (ic->ic_phytype == IEEE80211_T_DS) 780 i = 1; 781 else 782 i = 0; 783 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 784 if ((j / 8) >= len) 785 break; 786 if (isclr((u_int8_t *)wreq.wi_val, j)) 787 continue; 788 if (isclr(ic->ic_chan_active, i)) { 789 if (wreq.wi_type != WI_RID_CHANNEL_LIST) 790 continue; 791 if (isclr(ic->ic_chan_avail, i)) 792 return EPERM; 793 } 794 setbit(chanlist, i); 795 } 796 error = ieee80211_setupscan(ic, chanlist); 797 if (wreq.wi_type == WI_RID_CHANNEL_LIST) { 798 /* NB: ignore error from ieee80211_setupscan */ 799 error = ENETRESET; 800 } else if (error == 0) 801 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 802 break; 803 default: 804 error = EINVAL; 805 break; 806 } 807 if (error == ENETRESET && !IS_UP_AUTO(ic)) 808 error = 0; 809 return error; 810} 811 812static int | |
813cap2cipher(int flag) 814{ 815 switch (flag) { 816 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP; 817 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB; 818 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM; 819 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP; 820 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP; --- 63 unchanged lines hidden (view full) --- 884 if (sizeof(ic->ic_chan_active) < ireq->i_len) 885 ireq->i_len = sizeof(ic->ic_chan_active); 886 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 887} 888 889static int 890ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) 891{ | 76cap2cipher(int flag) 77{ 78 switch (flag) { 79 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP; 80 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB; 81 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM; 82 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP; 83 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP; --- 63 unchanged lines hidden (view full) --- 147 if (sizeof(ic->ic_chan_active) < ireq->i_len) 148 ireq->i_len = sizeof(ic->ic_chan_active); 149 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 150} 151 152static int 153ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) 154{ |
892 struct ieee80211req_chaninfo chans; /* XXX off stack? */ 893 int i, space; | 155 int space; |
894 | 156 |
895 /* 896 * Since channel 0 is not available for DS, channel 1 897 * is assigned to LSB on WaveLAN. 898 */ 899 if (ic->ic_phytype == IEEE80211_T_DS) 900 i = 1; 901 else 902 i = 0; 903 memset(&chans, 0, sizeof(chans)); 904 for (; i <= IEEE80211_CHAN_MAX; i++) 905 if (isset(ic->ic_chan_avail, i)) { 906 struct ieee80211_channel *c = &ic->ic_channels[i]; 907 chans.ic_chans[chans.ic_nchans].ic_freq = c->ic_freq; 908 chans.ic_chans[chans.ic_nchans].ic_flags = c->ic_flags; 909 chans.ic_nchans++; 910 } | |
911 space = __offsetof(struct ieee80211req_chaninfo, | 157 space = __offsetof(struct ieee80211req_chaninfo, |
912 ic_chans[chans.ic_nchans]); | 158 ic_chans[ic->ic_nchans]); |
913 if (space > ireq->i_len) 914 space = ireq->i_len; | 159 if (space > ireq->i_len) 160 space = ireq->i_len; |
915 return copyout(&chans, ireq->i_data, space); | 161 /* XXX assumes compatible layout */ 162 return copyout(&ic->ic_nchans, ireq->i_data, space); |
916} 917 918static int | 163} 164 165static int |
919ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq) | 166ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req) |
920{ 921 struct ieee80211_node *ni; | 167{ 168 struct ieee80211_node *ni; |
922 struct ieee80211req_wpaie wpaie; | 169 struct ieee80211req_wpaie2 wpaie; |
923 int error; 924 925 if (ireq->i_len < IEEE80211_ADDR_LEN) 926 return EINVAL; 927 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 928 if (error != 0) 929 return error; 930 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr); 931 if (ni == NULL) | 170 int error; 171 172 if (ireq->i_len < IEEE80211_ADDR_LEN) 173 return EINVAL; 174 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 175 if (error != 0) 176 return error; 177 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr); 178 if (ni == NULL) |
932 return EINVAL; /* XXX */ | 179 return ENOENT; /* XXX */ |
933 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 934 if (ni->ni_wpa_ie != NULL) { 935 int ielen = ni->ni_wpa_ie[1] + 2; 936 if (ielen > sizeof(wpaie.wpa_ie)) 937 ielen = sizeof(wpaie.wpa_ie); 938 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); 939 } | 180 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 181 if (ni->ni_wpa_ie != NULL) { 182 int ielen = ni->ni_wpa_ie[1] + 2; 183 if (ielen > sizeof(wpaie.wpa_ie)) 184 ielen = sizeof(wpaie.wpa_ie); 185 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); 186 } |
187 if (req == IEEE80211_IOC_WPAIE2) { 188 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie)); 189 if (ni->ni_rsn_ie != NULL) { 190 int ielen = ni->ni_rsn_ie[1] + 2; 191 if (ielen > sizeof(wpaie.rsn_ie)) 192 ielen = sizeof(wpaie.rsn_ie); 193 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen); 194 } 195 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2)) 196 ireq->i_len = sizeof(struct ieee80211req_wpaie2); 197 } else { 198 /* compatibility op, may overwrite wpa ie */ 199 /* XXX check ic_flags? */ 200 if (ni->ni_rsn_ie != NULL) { 201 int ielen = ni->ni_rsn_ie[1] + 2; 202 if (ielen > sizeof(wpaie.wpa_ie)) 203 ielen = sizeof(wpaie.wpa_ie); 204 memcpy(wpaie.wpa_ie, ni->ni_rsn_ie, ielen); 205 } 206 if (ireq->i_len > sizeof(struct ieee80211req_wpaie)) 207 ireq->i_len = sizeof(struct ieee80211req_wpaie); 208 } |
|
940 ieee80211_free_node(ni); | 209 ieee80211_free_node(ni); |
941 if (ireq->i_len > sizeof(wpaie)) 942 ireq->i_len = sizeof(wpaie); | |
943 return copyout(&wpaie, ireq->i_data, ireq->i_len); 944} 945 946static int 947ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 948{ 949 struct ieee80211_node *ni; | 210 return copyout(&wpaie, ireq->i_data, ireq->i_len); 211} 212 213static int 214ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 215{ 216 struct ieee80211_node *ni; |
950 u_int8_t macaddr[IEEE80211_ADDR_LEN]; | 217 uint8_t macaddr[IEEE80211_ADDR_LEN]; |
951 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 952 int error; 953 954 if (ireq->i_len < off) 955 return EINVAL; 956 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 957 if (error != 0) 958 return error; 959 ni = ieee80211_find_node(&ic->ic_sta, macaddr); | 218 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 219 int error; 220 221 if (ireq->i_len < off) 222 return EINVAL; 223 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 224 if (error != 0) 225 return error; 226 ni = ieee80211_find_node(&ic->ic_sta, macaddr); |
960 if (ni == NULL) { 961 /* XXX special-case sta-mode until bss is node in ic_sta */ 962 if (ic->ic_opmode != IEEE80211_M_STA) 963 return ENOENT; 964 ni = ieee80211_ref_node(ic->ic_bss); 965 } | 227 if (ni == NULL) 228 return EINVAL; |
966 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 967 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 968 /* NB: copy out only the statistics */ | 229 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 230 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 231 /* NB: copy out only the statistics */ |
969 error = copyout(&ni->ni_stats, (u_int8_t *) ireq->i_data + off, | 232 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off, |
970 ireq->i_len - off); 971 ieee80211_free_node(ni); 972 return error; 973} 974 | 233 ireq->i_len - off); 234 ieee80211_free_node(ni); 235 return error; 236} 237 |
238static __inline uint8_t * 239copyie(uint8_t *cp, const uint8_t *ie) 240{ 241 if (ie != NULL) { 242 memcpy(cp, ie, 2+ie[1]); 243 cp += 2+ie[1]; 244 } 245 return cp; 246} 247 |
|
975#ifdef COMPAT_FREEBSD6 976#define IEEE80211_IOC_SCAN_RESULTS_OLD 24 977 978struct scan_result_old { | 248#ifdef COMPAT_FREEBSD6 249#define IEEE80211_IOC_SCAN_RESULTS_OLD 24 250 251struct scan_result_old { |
979 u_int16_t isr_len; /* length (mult of 4) */ 980 u_int16_t isr_freq; /* MHz */ 981 u_int16_t isr_flags; /* channel flags */ 982 u_int8_t isr_noise; 983 u_int8_t isr_rssi; 984 u_int8_t isr_intval; /* beacon interval */ 985 u_int8_t isr_capinfo; /* capabilities */ 986 u_int8_t isr_erp; /* ERP element */ 987 u_int8_t isr_bssid[IEEE80211_ADDR_LEN]; 988 u_int8_t isr_nrates; 989 u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE]; 990 u_int8_t isr_ssid_len; /* SSID length */ 991 u_int8_t isr_ie_len; /* IE length */ 992 u_int8_t isr_pad[5]; | 252 uint16_t isr_len; /* length (mult of 4) */ 253 uint16_t isr_freq; /* MHz */ 254 uint16_t isr_flags; /* channel flags */ 255 uint8_t isr_noise; 256 uint8_t isr_rssi; 257 uint8_t isr_intval; /* beacon interval */ 258 uint8_t isr_capinfo; /* capabilities */ 259 uint8_t isr_erp; /* ERP element */ 260 uint8_t isr_bssid[IEEE80211_ADDR_LEN]; 261 uint8_t isr_nrates; 262 uint8_t isr_rates[IEEE80211_RATE_MAXSIZE]; 263 uint8_t isr_ssid_len; /* SSID length */ 264 uint8_t isr_ie_len; /* IE length */ 265 uint8_t isr_pad[5]; |
993 /* variable length SSID followed by IE data */ 994}; 995 | 266 /* variable length SSID followed by IE data */ 267}; 268 |
269struct oscanreq { 270 struct scan_result_old *sr; 271 size_t space; 272}; 273 274static size_t 275old_scan_space(const struct ieee80211_scan_entry *se, int *ielen) 276{ 277 size_t len; 278 279 *ielen = 0; 280 if (se->se_wpa_ie != NULL) 281 *ielen += 2+se->se_wpa_ie[1]; 282 if (se->se_wme_ie != NULL) 283 *ielen += 2+se->se_wme_ie[1]; 284 /* 285 * NB: ie's can be no more than 255 bytes and the max 802.11 286 * packet is <3Kbytes so we are sure this doesn't overflow 287 * 16-bits; if this is a concern we can drop the ie's. 288 */ 289 len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen; 290 return roundup(len, sizeof(uint32_t)); 291} 292 |
|
996static void | 293static void |
997old_get_scan_result(struct scan_result_old *sr, 998 const struct ieee80211_node *ni) | 294old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se) |
999{ | 295{ |
1000 struct ieee80211com *ic = ni->ni_ic; 1001 u_int ielen; | 296 struct oscanreq *req = arg; 297 int ielen; |
1002 | 298 |
299 req->space += old_scan_space(se, &ielen); 300} 301 302static void 303old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se) 304{ 305 struct oscanreq *req = arg; 306 struct scan_result_old *sr; 307 int ielen, len, nr, nxr; 308 uint8_t *cp; 309 310 len = old_scan_space(se, &ielen); 311 if (len > req->space) 312 return; 313 314 sr = req->sr; |
|
1003 memset(sr, 0, sizeof(*sr)); | 315 memset(sr, 0, sizeof(*sr)); |
1004 sr->isr_ssid_len = ni->ni_esslen; 1005 ielen = 0; 1006 if (ni->ni_wpa_ie != NULL) 1007 ielen += 2+ni->ni_wpa_ie[1]; 1008 if (ni->ni_wme_ie != NULL) 1009 ielen += 2+ni->ni_wme_ie[1]; | 316 sr->isr_ssid_len = se->se_ssid[1]; |
1010 /* NB: beware of overflow, isr_ie_len is 8 bits */ 1011 sr->isr_ie_len = (ielen > 255 ? 0 : ielen); | 317 /* NB: beware of overflow, isr_ie_len is 8 bits */ 318 sr->isr_ie_len = (ielen > 255 ? 0 : ielen); |
1012 sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len; 1013 sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t)); 1014 if (ni->ni_chan != IEEE80211_CHAN_ANYC) { 1015 sr->isr_freq = ni->ni_chan->ic_freq; 1016 sr->isr_flags = ni->ni_chan->ic_flags; | 319 sr->isr_len = len; 320 sr->isr_freq = se->se_chan->ic_freq; 321 sr->isr_flags = se->se_chan->ic_flags; 322 sr->isr_rssi = se->se_rssi; 323 sr->isr_noise = se->se_noise; 324 sr->isr_intval = se->se_intval; 325 sr->isr_capinfo = se->se_capinfo; 326 sr->isr_erp = se->se_erp; 327 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 328 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 329 memcpy(sr->isr_rates, se->se_rates+2, nr); 330 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 331 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 332 sr->isr_nrates = nr + nxr; 333 334 cp = (uint8_t *)(sr+1); 335 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 336 cp += sr->isr_ssid_len; 337 if (sr->isr_ie_len) { 338 cp = copyie(cp, se->se_wpa_ie); 339 cp = copyie(cp, se->se_wme_ie); |
1017 } | 340 } |
1018 sr->isr_rssi = ic->ic_node_getrssi(ni); 1019 sr->isr_intval = ni->ni_intval; 1020 sr->isr_capinfo = ni->ni_capinfo; 1021 sr->isr_erp = ni->ni_erp; 1022 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid); 1023 sr->isr_nrates = ni->ni_rates.rs_nrates; 1024 if (sr->isr_nrates > 15) 1025 sr->isr_nrates = 15; 1026 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates); | 341 342 req->space -= len; 343 req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len); |
1027} 1028 1029static int 1030old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 1031{ | 344} 345 346static int 347old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 348{ |
1032 union { 1033 struct scan_result_old res; 1034 char data[512]; /* XXX shrink? */ 1035 } u; 1036 struct scan_result_old *sr = &u.res; 1037 struct ieee80211_node_table *nt; 1038 struct ieee80211_node *ni; 1039 int error, space; 1040 u_int8_t *p, *cp; | 349 struct oscanreq req; 350 int error; |
1041 | 351 |
1042 p = ireq->i_data; 1043 space = ireq->i_len; | 352 if (ireq->i_len < sizeof(struct scan_result_old)) 353 return EFAULT; 354 |
1044 error = 0; | 355 error = 0; |
1045 /* XXX locking */ 1046 nt = &ic->ic_scan; 1047 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 1048 /* NB: skip pre-scan node state */ 1049 if (ni->ni_chan == IEEE80211_CHAN_ANYC) 1050 continue; 1051 old_get_scan_result(sr, ni); 1052 if (sr->isr_len > sizeof(u)) 1053 continue; /* XXX */ 1054 if (space < sr->isr_len) 1055 break; 1056 cp = (u_int8_t *)(sr+1); 1057 memcpy(cp, ni->ni_essid, ni->ni_esslen); 1058 cp += ni->ni_esslen; 1059 if (sr->isr_ie_len) { 1060 if (ni->ni_wpa_ie != NULL) { 1061 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1062 cp += 2+ni->ni_wpa_ie[1]; 1063 } 1064 if (ni->ni_wme_ie != NULL) { 1065 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1066 cp += 2+ni->ni_wme_ie[1]; 1067 } 1068 } 1069 error = copyout(sr, p, sr->isr_len); 1070 if (error) 1071 break; 1072 p += sr->isr_len; 1073 space -= sr->isr_len; 1074 } 1075 ireq->i_len -= space; | 356 req.space = 0; 357 ieee80211_scan_iterate(ic, old_get_scan_space, &req); 358 if (req.space > ireq->i_len) 359 req.space = ireq->i_len; 360 if (req.space > 0) { 361 size_t space; 362 void *p; 363 364 space = req.space; 365 /* XXX M_WAITOK after driver lock released */ 366 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO); 367 if (p == NULL) 368 return ENOMEM; 369 req.sr = p; 370 ieee80211_scan_iterate(ic, old_get_scan_result, &req); 371 ireq->i_len = space - req.space; 372 error = copyout(p, ireq->i_data, ireq->i_len); 373 FREE(p, M_TEMP); 374 } else 375 ireq->i_len = 0; 376 |
1076 return error; 1077} 1078#endif /* COMPAT_FREEBSD6 */ 1079 | 377 return error; 378} 379#endif /* COMPAT_FREEBSD6 */ 380 |
1080struct scanresultsreq { | 381struct scanreq { |
1081 struct ieee80211req_scan_result *sr; | 382 struct ieee80211req_scan_result *sr; |
1082 size_t space; | 383 size_t space; |
1083}; 1084 1085static size_t | 384}; 385 386static size_t |
1086scan_space(const struct ieee80211_node *ni, size_t *ielen) | 387scan_space(const struct ieee80211_scan_entry *se, int *ielen) |
1087{ 1088 size_t len; 1089 1090 *ielen = 0; | 388{ 389 size_t len; 390 391 *ielen = 0; |
1091 if (ni->ni_wpa_ie != NULL) 1092 *ielen += 2+ni->ni_wpa_ie[1]; 1093 if (ni->ni_wme_ie != NULL) 1094 *ielen += 2+ni->ni_wme_ie[1]; | 392 if (se->se_wpa_ie != NULL) 393 *ielen += 2+se->se_wpa_ie[1]; 394 if (se->se_rsn_ie != NULL) 395 *ielen += 2+se->se_rsn_ie[1]; 396 if (se->se_wme_ie != NULL) 397 *ielen += 2+se->se_wme_ie[1]; 398 if (se->se_ath_ie != NULL) 399 *ielen += 2+se->se_ath_ie[1]; |
1095 /* 1096 * NB: ie's can be no more than 255 bytes and the max 802.11 1097 * packet is <3Kbytes so we are sure this doesn't overflow 1098 * 16-bits; if this is a concern we can drop the ie's. 1099 */ | 400 /* 401 * NB: ie's can be no more than 255 bytes and the max 802.11 402 * packet is <3Kbytes so we are sure this doesn't overflow 403 * 16-bits; if this is a concern we can drop the ie's. 404 */ |
1100 len = sizeof(struct ieee80211req_scan_result) + ni->ni_esslen + *ielen; 1101 return roundup(len, sizeof(u_int32_t)); | 405 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen; 406 return roundup(len, sizeof(uint32_t)); |
1102} 1103 1104static void | 407} 408 409static void |
1105get_scan_space(void *arg, struct ieee80211_node *ni) | 410get_scan_space(void *arg, const struct ieee80211_scan_entry *se) |
1106{ | 411{ |
1107 struct scanresultsreq *req = arg; 1108 size_t ielen; | 412 struct scanreq *req = arg; 413 int ielen; |
1109 | 414 |
1110 req->space += scan_space(ni, &ielen); | 415 req->space += scan_space(se, &ielen); |
1111} 1112 1113static void | 416} 417 418static void |
1114get_scan_result(void *arg, struct ieee80211_node *ni) | 419get_scan_result(void *arg, const struct ieee80211_scan_entry *se) |
1115{ | 420{ |
1116 struct scanresultsreq *req = arg; 1117 struct ieee80211com *ic = ni->ni_ic; | 421 struct scanreq *req = arg; |
1118 struct ieee80211req_scan_result *sr; | 422 struct ieee80211req_scan_result *sr; |
1119 size_t ielen, len; 1120 u_int8_t *cp; | 423 int ielen, len, nr, nxr; 424 uint8_t *cp; |
1121 | 425 |
1122 len = scan_space(ni, &ielen); | 426 len = scan_space(se, &ielen); |
1123 if (len > req->space) 1124 return; | 427 if (len > req->space) 428 return; |
429 |
|
1125 sr = req->sr; 1126 KASSERT(len <= 65535 && ielen <= 65535, | 430 sr = req->sr; 431 KASSERT(len <= 65535 && ielen <= 65535, |
1127 ("len %zu ssid %u ie %zu", len, ni->ni_esslen, ielen)); 1128 sr->isr_len = len; 1129 sr->isr_ssid_len = ni->ni_esslen; | 432 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen)); 433 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result); |
1130 sr->isr_ie_len = ielen; | 434 sr->isr_ie_len = ielen; |
1131 if (ni->ni_chan != IEEE80211_CHAN_ANYC) { 1132 sr->isr_freq = ni->ni_chan->ic_freq; 1133 sr->isr_flags = ni->ni_chan->ic_flags; | 435 sr->isr_len = len; 436 sr->isr_freq = se->se_chan->ic_freq; 437 sr->isr_flags = se->se_chan->ic_flags; 438 sr->isr_rssi = se->se_rssi; 439 sr->isr_noise = se->se_noise; 440 sr->isr_intval = se->se_intval; 441 sr->isr_capinfo = se->se_capinfo; 442 sr->isr_erp = se->se_erp; 443 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid); 444 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE); 445 memcpy(sr->isr_rates, se->se_rates+2, nr); 446 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr); 447 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr); 448 sr->isr_nrates = nr + nxr; 449 450 sr->isr_ssid_len = se->se_ssid[1]; 451 cp = ((uint8_t *)sr) + sr->isr_ie_off; 452 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len); 453 454 if (ielen) { 455 cp += sr->isr_ssid_len; 456 cp = copyie(cp, se->se_wpa_ie); 457 cp = copyie(cp, se->se_rsn_ie); 458 cp = copyie(cp, se->se_wme_ie); 459 cp = copyie(cp, se->se_ath_ie); 460 cp = copyie(cp, se->se_htcap_ie); |
1134 } | 461 } |
1135 /* XXX need to rev driver apis for signal data */ 1136 sr->isr_rssi = (int8_t) ic->ic_node_getrssi(ni); 1137 sr->isr_intval = ni->ni_intval; 1138 sr->isr_capinfo = ni->ni_capinfo; 1139 sr->isr_erp = ni->ni_erp; 1140 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid); 1141 sr->isr_nrates = ni->ni_rates.rs_nrates; 1142 if (sr->isr_nrates > 15) 1143 sr->isr_nrates = 15; 1144 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates); 1145 cp = (u_int8_t *)(sr+1); 1146 memcpy(cp, ni->ni_essid, ni->ni_esslen); 1147 cp += ni->ni_esslen; 1148 if (sr->isr_ie_len) { 1149 if (ni->ni_wpa_ie != NULL) { 1150 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1151 cp += 2+ni->ni_wpa_ie[1]; 1152 } 1153 if (ni->ni_wme_ie != NULL) { 1154 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1155 cp += 2+ni->ni_wme_ie[1]; 1156 } 1157 } | |
1158 | 462 |
1159 req->sr = (struct ieee80211req_scan_result *)(((u_int8_t *)sr) + len); | |
1160 req->space -= len; | 463 req->space -= len; |
464 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len); |
|
1161} 1162 1163static int 1164ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 1165{ | 465} 466 467static int 468ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 469{ |
1166 struct scanresultsreq req; | 470 struct scanreq req; |
1167 int error; 1168 1169 if (ireq->i_len < sizeof(struct ieee80211req_scan_result)) 1170 return EFAULT; 1171 1172 error = 0; 1173 req.space = 0; | 471 int error; 472 473 if (ireq->i_len < sizeof(struct ieee80211req_scan_result)) 474 return EFAULT; 475 476 error = 0; 477 req.space = 0; |
1174 ieee80211_iterate_nodes(&ic->ic_scan, get_scan_space, &req); | 478 ieee80211_scan_iterate(ic, get_scan_space, &req); |
1175 if (req.space > ireq->i_len) 1176 req.space = ireq->i_len; 1177 if (req.space > 0) { 1178 size_t space; 1179 void *p; 1180 1181 space = req.space; 1182 /* XXX M_WAITOK after driver lock released */ 1183 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO); 1184 if (p == NULL) 1185 return ENOMEM; 1186 req.sr = p; | 479 if (req.space > ireq->i_len) 480 req.space = ireq->i_len; 481 if (req.space > 0) { 482 size_t space; 483 void *p; 484 485 space = req.space; 486 /* XXX M_WAITOK after driver lock released */ 487 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO); 488 if (p == NULL) 489 return ENOMEM; 490 req.sr = p; |
1187 ieee80211_iterate_nodes(&ic->ic_scan, get_scan_result, &req); | 491 ieee80211_scan_iterate(ic, get_scan_result, &req); |
1188 ireq->i_len = space - req.space; 1189 error = copyout(p, ireq->i_data, ireq->i_len); 1190 FREE(p, M_TEMP); 1191 } else 1192 ireq->i_len = 0; 1193 1194 return error; 1195} --- 5 unchanged lines hidden (view full) --- 1201}; 1202 1203static size_t 1204sta_space(const struct ieee80211_node *ni, size_t *ielen) 1205{ 1206 *ielen = 0; 1207 if (ni->ni_wpa_ie != NULL) 1208 *ielen += 2+ni->ni_wpa_ie[1]; | 492 ireq->i_len = space - req.space; 493 error = copyout(p, ireq->i_data, ireq->i_len); 494 FREE(p, M_TEMP); 495 } else 496 ireq->i_len = 0; 497 498 return error; 499} --- 5 unchanged lines hidden (view full) --- 505}; 506 507static size_t 508sta_space(const struct ieee80211_node *ni, size_t *ielen) 509{ 510 *ielen = 0; 511 if (ni->ni_wpa_ie != NULL) 512 *ielen += 2+ni->ni_wpa_ie[1]; |
513 if (ni->ni_rsn_ie != NULL) 514 *ielen += 2+ni->ni_rsn_ie[1]; |
|
1209 if (ni->ni_wme_ie != NULL) 1210 *ielen += 2+ni->ni_wme_ie[1]; | 515 if (ni->ni_wme_ie != NULL) 516 *ielen += 2+ni->ni_wme_ie[1]; |
517 if (ni->ni_ath_ie != NULL) 518 *ielen += 2+ni->ni_ath_ie[1]; |
|
1211 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, | 519 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen, |
1212 sizeof(u_int32_t)); | 520 sizeof(uint32_t)); |
1213} 1214 1215static void 1216get_sta_space(void *arg, struct ieee80211_node *ni) 1217{ 1218 struct stainforeq *req = arg; 1219 struct ieee80211com *ic = ni->ni_ic; 1220 size_t ielen; --- 6 unchanged lines hidden (view full) --- 1227 1228static void 1229get_sta_info(void *arg, struct ieee80211_node *ni) 1230{ 1231 struct stainforeq *req = arg; 1232 struct ieee80211com *ic = ni->ni_ic; 1233 struct ieee80211req_sta_info *si; 1234 size_t ielen, len; | 521} 522 523static void 524get_sta_space(void *arg, struct ieee80211_node *ni) 525{ 526 struct stainforeq *req = arg; 527 struct ieee80211com *ic = ni->ni_ic; 528 size_t ielen; --- 6 unchanged lines hidden (view full) --- 535 536static void 537get_sta_info(void *arg, struct ieee80211_node *ni) 538{ 539 struct stainforeq *req = arg; 540 struct ieee80211com *ic = ni->ni_ic; 541 struct ieee80211req_sta_info *si; 542 size_t ielen, len; |
1235 u_int8_t *cp; | 543 uint8_t *cp; |
1236 1237 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1238 ni->ni_associd == 0) /* only associated stations */ 1239 return; 1240 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 1241 return; 1242 len = sta_space(ni, &ielen); 1243 if (len > req->space) 1244 return; 1245 si = req->si; | 544 545 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 546 ni->ni_associd == 0) /* only associated stations */ 547 return; 548 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */ 549 return; 550 len = sta_space(ni, &ielen); 551 if (len > req->space) 552 return; 553 si = req->si; |
1246 KASSERT(len <= 65535 && ielen <= 65535, ("len %zu ie %zu", len, ielen)); | |
1247 si->isi_len = len; | 554 si->isi_len = len; |
555 si->isi_ie_off = sizeof(struct ieee80211req_sta_info); |
|
1248 si->isi_ie_len = ielen; 1249 si->isi_freq = ni->ni_chan->ic_freq; 1250 si->isi_flags = ni->ni_chan->ic_flags; 1251 si->isi_state = ni->ni_flags; 1252 si->isi_authmode = ni->ni_authmode; | 556 si->isi_ie_len = ielen; 557 si->isi_freq = ni->ni_chan->ic_freq; 558 si->isi_flags = ni->ni_chan->ic_flags; 559 si->isi_state = ni->ni_flags; 560 si->isi_authmode = ni->ni_authmode; |
1253 si->isi_rssi = ic->ic_node_getrssi(ni); | 561 ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise); |
1254 si->isi_noise = 0; /* XXX */ 1255 si->isi_capinfo = ni->ni_capinfo; 1256 si->isi_erp = ni->ni_erp; 1257 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 1258 si->isi_nrates = ni->ni_rates.rs_nrates; 1259 if (si->isi_nrates > 15) 1260 si->isi_nrates = 15; 1261 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 1262 si->isi_txrate = ni->ni_txrate; | 562 si->isi_noise = 0; /* XXX */ 563 si->isi_capinfo = ni->ni_capinfo; 564 si->isi_erp = ni->ni_erp; 565 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 566 si->isi_nrates = ni->ni_rates.rs_nrates; 567 if (si->isi_nrates > 15) 568 si->isi_nrates = 15; 569 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 570 si->isi_txrate = ni->ni_txrate; |
571 si->isi_ie_len = ielen; |
|
1263 si->isi_associd = ni->ni_associd; 1264 si->isi_txpower = ni->ni_txpower; 1265 si->isi_vlan = ni->ni_vlan; 1266 if (ni->ni_flags & IEEE80211_NODE_QOS) { 1267 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 1268 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 1269 } else { 1270 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID]; 1271 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID]; 1272 } 1273 /* NB: leave all cases in case we relax ni_associd == 0 check */ 1274 if (ieee80211_node_is_authorized(ni)) 1275 si->isi_inact = ic->ic_inact_run; 1276 else if (ni->ni_associd != 0) 1277 si->isi_inact = ic->ic_inact_auth; 1278 else 1279 si->isi_inact = ic->ic_inact_init; 1280 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 1281 | 572 si->isi_associd = ni->ni_associd; 573 si->isi_txpower = ni->ni_txpower; 574 si->isi_vlan = ni->ni_vlan; 575 if (ni->ni_flags & IEEE80211_NODE_QOS) { 576 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 577 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 578 } else { 579 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID]; 580 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID]; 581 } 582 /* NB: leave all cases in case we relax ni_associd == 0 check */ 583 if (ieee80211_node_is_authorized(ni)) 584 si->isi_inact = ic->ic_inact_run; 585 else if (ni->ni_associd != 0) 586 si->isi_inact = ic->ic_inact_auth; 587 else 588 si->isi_inact = ic->ic_inact_init; 589 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 590 |
1282 cp = (u_int8_t *)(si+1); 1283 if (ni->ni_wpa_ie != NULL) { 1284 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1285 cp += 2+ni->ni_wpa_ie[1]; | 591 if (ielen) { 592 cp = ((uint8_t *)si) + si->isi_ie_off; 593 cp = copyie(cp, ni->ni_wpa_ie); 594 cp = copyie(cp, ni->ni_rsn_ie); 595 cp = copyie(cp, ni->ni_wme_ie); 596 cp = copyie(cp, ni->ni_ath_ie); |
1286 } | 597 } |
1287 if (ni->ni_wme_ie != NULL) { 1288 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1289 cp += 2+ni->ni_wme_ie[1]; 1290 } | |
1291 | 598 |
1292 req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len); | 599 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len); |
1293 req->space -= len; 1294} 1295 1296static int 1297getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq, 1298 struct ieee80211_node *ni, int off) 1299{ 1300 struct stainforeq req; --- 18 unchanged lines hidden (view full) --- 1319 goto bad; 1320 } 1321 req.si = p; 1322 if (ni == NULL) 1323 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 1324 else 1325 get_sta_info(&req, ni); 1326 ireq->i_len = space - req.space; | 600 req->space -= len; 601} 602 603static int 604getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq, 605 struct ieee80211_node *ni, int off) 606{ 607 struct stainforeq req; --- 18 unchanged lines hidden (view full) --- 626 goto bad; 627 } 628 req.si = p; 629 if (ni == NULL) 630 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); 631 else 632 get_sta_info(&req, ni); 633 ireq->i_len = space - req.space; |
1327 error = copyout(p, (u_int8_t *) ireq->i_data+off, ireq->i_len); | 634 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len); |
1328 FREE(p, M_TEMP); 1329 } else 1330 ireq->i_len = 0; 1331bad: 1332 if (ni != NULL) 1333 ieee80211_free_node(ni); 1334 return error; 1335} 1336 1337static int 1338ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 1339{ | 635 FREE(p, M_TEMP); 636 } else 637 ireq->i_len = 0; 638bad: 639 if (ni != NULL) 640 ieee80211_free_node(ni); 641 return error; 642} 643 644static int 645ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 646{ |
1340 u_int8_t macaddr[IEEE80211_ADDR_LEN]; | 647 uint8_t macaddr[IEEE80211_ADDR_LEN]; |
1341 const int off = __offsetof(struct ieee80211req_sta_req, info); 1342 struct ieee80211_node *ni; 1343 int error; 1344 1345 if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) 1346 return EFAULT; 1347 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 1348 if (error != 0) 1349 return error; 1350 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) { 1351 ni = NULL; 1352 } else { 1353 ni = ieee80211_find_node(&ic->ic_sta, macaddr); | 648 const int off = __offsetof(struct ieee80211req_sta_req, info); 649 struct ieee80211_node *ni; 650 int error; 651 652 if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) 653 return EFAULT; 654 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 655 if (error != 0) 656 return error; 657 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) { 658 ni = NULL; 659 } else { 660 ni = ieee80211_find_node(&ic->ic_sta, macaddr); |
1354 if (ni == NULL) { 1355 /* XXX special-case sta-mode until bss is in ic_sta */ 1356 if (ic->ic_opmode != IEEE80211_M_STA) 1357 return EINVAL; /* XXX */ 1358 ni = ieee80211_ref_node(ic->ic_bss); 1359 } | 661 if (ni == NULL) 662 return EINVAL; |
1360 } 1361 return getstainfo_common(ic, ireq, ni, off); 1362} 1363 1364#ifdef COMPAT_FREEBSD6 1365#define IEEE80211_IOC_STA_INFO_OLD 45 1366 1367static int --- 72 unchanged lines hidden (view full) --- 1440ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1441{ 1442 const struct ieee80211_aclator *acl = ic->ic_acl; 1443 1444 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); 1445} 1446 1447/* | 663 } 664 return getstainfo_common(ic, ireq, ni, off); 665} 666 667#ifdef COMPAT_FREEBSD6 668#define IEEE80211_IOC_STA_INFO_OLD 45 669 670static int --- 72 unchanged lines hidden (view full) --- 743ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 744{ 745 const struct ieee80211_aclator *acl = ic->ic_acl; 746 747 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); 748} 749 750/* |
751 * Return the current ``state'' of an Atheros capbility. 752 * If associated in station mode report the negotiated 753 * setting. Otherwise report the current setting. 754 */ 755static int 756getathcap(struct ieee80211com *ic, int cap) 757{ 758 if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN) 759 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0; 760 else 761 return (ic->ic_flags & cap) != 0; 762} 763 764static int 765ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq) 766{ 767 if (ireq->i_len != sizeof(struct ieee80211_channel)) 768 return EINVAL; 769 return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan)); 770} 771 772/* |
|
1448 * When building the kernel with -O2 on the i386 architecture, gcc 1449 * seems to want to inline this function into ieee80211_ioctl() 1450 * (which is the only routine that calls it). When this happens, 1451 * ieee80211_ioctl() ends up consuming an additional 2K of stack 1452 * space. (Exactly why it needs so much is unclear.) The problem 1453 * is that it's possible for ieee80211_ioctl() to invoke other 1454 * routines (including driver init functions) which could then find 1455 * themselves perilously close to exhausting the stack. --- 8 unchanged lines hidden (view full) --- 1464__attribute__ ((noinline)) 1465#endif 1466static int 1467ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1468{ 1469 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1470 int error = 0; 1471 u_int kid, len, m; | 773 * When building the kernel with -O2 on the i386 architecture, gcc 774 * seems to want to inline this function into ieee80211_ioctl() 775 * (which is the only routine that calls it). When this happens, 776 * ieee80211_ioctl() ends up consuming an additional 2K of stack 777 * space. (Exactly why it needs so much is unclear.) The problem 778 * is that it's possible for ieee80211_ioctl() to invoke other 779 * routines (including driver init functions) which could then find 780 * themselves perilously close to exhausting the stack. --- 8 unchanged lines hidden (view full) --- 789__attribute__ ((noinline)) 790#endif 791static int 792ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 793{ 794 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 795 int error = 0; 796 u_int kid, len, m; |
1472 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; | 797 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; |
1473 char tmpssid[IEEE80211_NWID_LEN]; 1474 1475 switch (ireq->i_type) { 1476 case IEEE80211_IOC_SSID: 1477 switch (ic->ic_state) { 1478 case IEEE80211_S_INIT: 1479 case IEEE80211_S_SCAN: | 798 char tmpssid[IEEE80211_NWID_LEN]; 799 800 switch (ireq->i_type) { 801 case IEEE80211_IOC_SSID: 802 switch (ic->ic_state) { 803 case IEEE80211_S_INIT: 804 case IEEE80211_S_SCAN: |
1480 ireq->i_len = ic->ic_des_esslen; 1481 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len); | 805 ireq->i_len = ic->ic_des_ssid[0].len; 806 memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len); |
1482 break; 1483 default: 1484 ireq->i_len = ic->ic_bss->ni_esslen; 1485 memcpy(tmpssid, ic->ic_bss->ni_essid, 1486 ireq->i_len); 1487 break; 1488 } 1489 error = copyout(tmpssid, ireq->i_data, ireq->i_len); --- 144 unchanged lines hidden (view full) --- 1634 if (ireq->i_len != IEEE80211_ADDR_LEN) 1635 return EINVAL; 1636 error = copyout(ic->ic_state == IEEE80211_S_RUN ? 1637 ic->ic_bss->ni_bssid : 1638 ic->ic_des_bssid, 1639 ireq->i_data, ireq->i_len); 1640 break; 1641 case IEEE80211_IOC_WPAIE: | 807 break; 808 default: 809 ireq->i_len = ic->ic_bss->ni_esslen; 810 memcpy(tmpssid, ic->ic_bss->ni_essid, 811 ireq->i_len); 812 break; 813 } 814 error = copyout(tmpssid, ireq->i_data, ireq->i_len); --- 144 unchanged lines hidden (view full) --- 959 if (ireq->i_len != IEEE80211_ADDR_LEN) 960 return EINVAL; 961 error = copyout(ic->ic_state == IEEE80211_S_RUN ? 962 ic->ic_bss->ni_bssid : 963 ic->ic_des_bssid, 964 ireq->i_data, ireq->i_len); 965 break; 966 case IEEE80211_IOC_WPAIE: |
1642 error = ieee80211_ioctl_getwpaie(ic, ireq); | 967 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type); |
1643 break; | 968 break; |
969 case IEEE80211_IOC_WPAIE2: 970 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type); 971 break; |
|
1644#ifdef COMPAT_FREEBSD6 1645 case IEEE80211_IOC_SCAN_RESULTS_OLD: 1646 error = old_getscanresults(ic, ireq); 1647 break; 1648#endif 1649 case IEEE80211_IOC_SCAN_RESULTS: 1650 error = ieee80211_ioctl_getscanresults(ic, ireq); 1651 break; --- 27 unchanged lines hidden (view full) --- 1679 break; 1680 case IEEE80211_IOC_BEACON_INTERVAL: 1681 /* NB: get from ic_bss for station mode */ 1682 ireq->i_val = ic->ic_bss->ni_intval; 1683 break; 1684 case IEEE80211_IOC_PUREG: 1685 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0; 1686 break; | 972#ifdef COMPAT_FREEBSD6 973 case IEEE80211_IOC_SCAN_RESULTS_OLD: 974 error = old_getscanresults(ic, ireq); 975 break; 976#endif 977 case IEEE80211_IOC_SCAN_RESULTS: 978 error = ieee80211_ioctl_getscanresults(ic, ireq); 979 break; --- 27 unchanged lines hidden (view full) --- 1007 break; 1008 case IEEE80211_IOC_BEACON_INTERVAL: 1009 /* NB: get from ic_bss for station mode */ 1010 ireq->i_val = ic->ic_bss->ni_intval; 1011 break; 1012 case IEEE80211_IOC_PUREG: 1013 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0; 1014 break; |
1015 case IEEE80211_IOC_FF: 1016 ireq->i_val = getathcap(ic, IEEE80211_F_FF); 1017 break; 1018 case IEEE80211_IOC_TURBOP: 1019 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP); 1020 break; 1021 case IEEE80211_IOC_BGSCAN: 1022 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0; 1023 break; 1024 case IEEE80211_IOC_BGSCAN_IDLE: 1025 ireq->i_val = ic->ic_bgscanidle*hz/1000; /* ms */ 1026 break; 1027 case IEEE80211_IOC_BGSCAN_INTERVAL: 1028 ireq->i_val = ic->ic_bgscanintvl/hz; /* seconds */ 1029 break; 1030 case IEEE80211_IOC_SCANVALID: 1031 ireq->i_val = ic->ic_scanvalid/hz; /* seconds */ 1032 break; 1033 case IEEE80211_IOC_ROAM_RSSI_11A: 1034 ireq->i_val = ic->ic_roam.rssi11a; 1035 break; 1036 case IEEE80211_IOC_ROAM_RSSI_11B: 1037 ireq->i_val = ic->ic_roam.rssi11bOnly; 1038 break; 1039 case IEEE80211_IOC_ROAM_RSSI_11G: 1040 ireq->i_val = ic->ic_roam.rssi11b; 1041 break; 1042 case IEEE80211_IOC_ROAM_RATE_11A: 1043 ireq->i_val = ic->ic_roam.rate11a; 1044 break; 1045 case IEEE80211_IOC_ROAM_RATE_11B: 1046 ireq->i_val = ic->ic_roam.rate11bOnly; 1047 break; 1048 case IEEE80211_IOC_ROAM_RATE_11G: 1049 ireq->i_val = ic->ic_roam.rate11b; 1050 break; |
|
1687 case IEEE80211_IOC_MCAST_RATE: 1688 ireq->i_val = ic->ic_mcast_rate; 1689 break; 1690 case IEEE80211_IOC_FRAGTHRESHOLD: 1691 ireq->i_val = ic->ic_fragthreshold; 1692 break; 1693 case IEEE80211_IOC_MACCMD: 1694 error = ieee80211_ioctl_getmaccmd(ic, ireq); 1695 break; 1696 case IEEE80211_IOC_BURST: 1697 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0; 1698 break; 1699 case IEEE80211_IOC_BMISSTHRESHOLD: 1700 ireq->i_val = ic->ic_bmissthreshold; 1701 break; | 1051 case IEEE80211_IOC_MCAST_RATE: 1052 ireq->i_val = ic->ic_mcast_rate; 1053 break; 1054 case IEEE80211_IOC_FRAGTHRESHOLD: 1055 ireq->i_val = ic->ic_fragthreshold; 1056 break; 1057 case IEEE80211_IOC_MACCMD: 1058 error = ieee80211_ioctl_getmaccmd(ic, ireq); 1059 break; 1060 case IEEE80211_IOC_BURST: 1061 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0; 1062 break; 1063 case IEEE80211_IOC_BMISSTHRESHOLD: 1064 ireq->i_val = ic->ic_bmissthreshold; 1065 break; |
1066 case IEEE80211_IOC_CURCHAN: 1067 error = ieee80211_ioctl_getcurchan(ic, ireq); 1068 break; 1069 case IEEE80211_IOC_SHORTGI: 1070 ireq->i_val = 0; 1071 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20) 1072 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20; 1073 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40) 1074 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40; 1075 break; 1076 case IEEE80211_IOC_AMPDU: 1077 ireq->i_val = 0; 1078 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX) 1079 ireq->i_val |= 1; 1080 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX) 1081 ireq->i_val |= 2; 1082 break; 1083 case IEEE80211_IOC_AMPDU_LIMIT: 1084 ireq->i_val = ic->ic_ampdu_limit; /* XXX truncation? */ 1085 break; 1086 case IEEE80211_IOC_AMPDU_DENSITY: 1087 ireq->i_val = ic->ic_ampdu_density; 1088 break; 1089 case IEEE80211_IOC_AMSDU: 1090 ireq->i_val = 0; 1091 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX) 1092 ireq->i_val |= 1; 1093 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX) 1094 ireq->i_val |= 2; 1095 break; 1096 case IEEE80211_IOC_AMSDU_LIMIT: 1097 ireq->i_val = ic->ic_amsdu_limit; /* XXX truncation? */ 1098 break; 1099 case IEEE80211_IOC_PUREN: 1100 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0; 1101 break; 1102 case IEEE80211_IOC_DOTH: 1103 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0; 1104 break; 1105 case IEEE80211_IOC_HTCOMPAT: 1106 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0; 1107 break; |
|
1702 default: 1703 error = EINVAL; 1704 break; 1705 } 1706 return error; 1707} 1708 1709static int --- 7 unchanged lines hidden (view full) --- 1717 * WPA and/or WME) except that it typically is worthless 1718 * without being able to intervene when processing 1719 * association response frames--so disallow it for now. 1720 */ 1721 if (ic->ic_opmode != IEEE80211_M_STA) 1722 return EINVAL; 1723 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1724 return EINVAL; | 1108 default: 1109 error = EINVAL; 1110 break; 1111 } 1112 return error; 1113} 1114 1115static int --- 7 unchanged lines hidden (view full) --- 1123 * WPA and/or WME) except that it typically is worthless 1124 * without being able to intervene when processing 1125 * association response frames--so disallow it for now. 1126 */ 1127 if (ic->ic_opmode != IEEE80211_M_STA) 1128 return EINVAL; 1129 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1130 return EINVAL; |
1131 /* NB: data.length is validated by the wireless extensions code */ 1132 /* XXX M_WAITOK after driver lock released */ |
|
1725 if (ireq->i_len > 0) { 1726 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT); 1727 if (ie == NULL) 1728 return ENOMEM; 1729 error = copyin(ireq->i_data, ie, ireq->i_len); 1730 if (error) { 1731 FREE(ie, M_DEVBUF); 1732 return error; --- 12 unchanged lines hidden (view full) --- 1745} 1746 1747static int 1748ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1749{ 1750 struct ieee80211req_key ik; 1751 struct ieee80211_node *ni; 1752 struct ieee80211_key *wk; | 1133 if (ireq->i_len > 0) { 1134 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT); 1135 if (ie == NULL) 1136 return ENOMEM; 1137 error = copyin(ireq->i_data, ie, ireq->i_len); 1138 if (error) { 1139 FREE(ie, M_DEVBUF); 1140 return error; --- 12 unchanged lines hidden (view full) --- 1153} 1154 1155static int 1156ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1157{ 1158 struct ieee80211req_key ik; 1159 struct ieee80211_node *ni; 1160 struct ieee80211_key *wk; |
1753 u_int16_t kid; | 1161 uint16_t kid; |
1754 int error; 1755 1756 if (ireq->i_len != sizeof(ik)) 1757 return EINVAL; 1758 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1759 if (error) 1760 return error; 1761 /* NB: cipher support is verified by ieee80211_crypt_newkey */ --- 60 unchanged lines hidden (view full) --- 1822 int kid, error; 1823 1824 if (ireq->i_len != sizeof(dk)) 1825 return EINVAL; 1826 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1827 if (error) 1828 return error; 1829 kid = dk.idk_keyix; | 1162 int error; 1163 1164 if (ireq->i_len != sizeof(ik)) 1165 return EINVAL; 1166 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1167 if (error) 1168 return error; 1169 /* NB: cipher support is verified by ieee80211_crypt_newkey */ --- 60 unchanged lines hidden (view full) --- 1230 int kid, error; 1231 1232 if (ireq->i_len != sizeof(dk)) 1233 return EINVAL; 1234 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1235 if (error) 1236 return error; 1237 kid = dk.idk_keyix; |
1830 /* XXX u_int8_t -> u_int16_t */ 1831 if (dk.idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) { | 1238 /* XXX uint8_t -> uint16_t */ 1239 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) { |
1832 struct ieee80211_node *ni; 1833 1834 if (ic->ic_opmode == IEEE80211_M_STA) { 1835 ni = ieee80211_ref_node(ic->ic_bss); 1836 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1837 ieee80211_free_node(ni); 1838 return EADDRNOTAVAIL; 1839 } --- 25 unchanged lines hidden (view full) --- 1865 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1866 IEEE80211_FC0_SUBTYPE_DEAUTH : 1867 IEEE80211_FC0_SUBTYPE_DISASSOC, 1868 mlme->im_reason); 1869 } 1870 ieee80211_node_leave(ic, ni); 1871} 1872 | 1240 struct ieee80211_node *ni; 1241 1242 if (ic->ic_opmode == IEEE80211_M_STA) { 1243 ni = ieee80211_ref_node(ic->ic_bss); 1244 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) { 1245 ieee80211_free_node(ni); 1246 return EADDRNOTAVAIL; 1247 } --- 25 unchanged lines hidden (view full) --- 1273 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1274 IEEE80211_FC0_SUBTYPE_DEAUTH : 1275 IEEE80211_FC0_SUBTYPE_DISASSOC, 1276 mlme->im_reason); 1277 } 1278 ieee80211_node_leave(ic, ni); 1279} 1280 |
1281struct scanlookup { 1282 const uint8_t *mac; 1283 int esslen; 1284 const uint8_t *essid; 1285 const struct ieee80211_scan_entry *se; 1286}; 1287 1288/* 1289 * Match mac address and any ssid. 1290 */ 1291static void 1292mlmelookup(void *arg, const struct ieee80211_scan_entry *se) 1293{ 1294 struct scanlookup *look = arg; 1295 1296 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) 1297 return; 1298 if (look->esslen != 0) { 1299 if (se->se_ssid[1] != look->esslen) 1300 return; 1301 if (memcmp(look->essid, se->se_ssid+2, look->esslen)) 1302 return; 1303 } 1304 look->se = se; 1305} 1306 |
|
1873static int 1874ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1875{ 1876 struct ieee80211req_mlme mlme; 1877 struct ieee80211_node *ni; 1878 int error; 1879 1880 if (ireq->i_len != sizeof(mlme)) 1881 return EINVAL; 1882 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1883 if (error) 1884 return error; 1885 switch (mlme.im_op) { 1886 case IEEE80211_MLME_ASSOC: | 1307static int 1308ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1309{ 1310 struct ieee80211req_mlme mlme; 1311 struct ieee80211_node *ni; 1312 int error; 1313 1314 if (ireq->i_len != sizeof(mlme)) 1315 return EINVAL; 1316 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1317 if (error) 1318 return error; 1319 switch (mlme.im_op) { 1320 case IEEE80211_MLME_ASSOC: |
1887 if (ic->ic_opmode != IEEE80211_M_STA) 1888 return EINVAL; 1889 /* XXX must be in S_SCAN state? */ | 1321 /* XXX ibss/ahdemo */ 1322 if (ic->ic_opmode == IEEE80211_M_STA) { 1323 struct scanlookup lookup; |
1890 | 1324 |
1891 if (mlme.im_ssid_len != 0) { 1892 /* 1893 * Desired ssid specified; must match both bssid and 1894 * ssid to distinguish ap advertising multiple ssid's. 1895 */ 1896 ni = ieee80211_find_node_with_ssid(&ic->ic_scan, 1897 mlme.im_macaddr, 1898 mlme.im_ssid_len, mlme.im_ssid); 1899 } else { 1900 /* 1901 * Normal case; just match bssid. 1902 */ 1903 ni = ieee80211_find_node(&ic->ic_scan, mlme.im_macaddr); | 1325 lookup.se = NULL; 1326 lookup.mac = mlme.im_macaddr; 1327 /* XXX use revised api w/ explicit ssid */ 1328 lookup.esslen = ic->ic_des_ssid[0].len; 1329 lookup.essid = ic->ic_des_ssid[0].ssid; 1330 ieee80211_scan_iterate(ic, mlmelookup, &lookup); 1331 if (lookup.se != NULL && 1332 ieee80211_sta_join(ic, lookup.se)) 1333 return 0; |
1904 } | 1334 } |
1905 if (ni == NULL) 1906 return EINVAL; 1907 if (!ieee80211_sta_join(ic, ni)) { 1908 ieee80211_free_node(ni); 1909 return EINVAL; 1910 } 1911 break; | 1335 return EINVAL; |
1912 case IEEE80211_MLME_DISASSOC: 1913 case IEEE80211_MLME_DEAUTH: 1914 switch (ic->ic_opmode) { 1915 case IEEE80211_M_STA: 1916 /* XXX not quite right */ 1917 ieee80211_new_state(ic, IEEE80211_S_INIT, 1918 mlme.im_reason); 1919 break; --- 31 unchanged lines hidden (view full) --- 1951 return EINVAL; 1952 } 1953 return 0; 1954} 1955 1956static int 1957ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1958{ | 1336 case IEEE80211_MLME_DISASSOC: 1337 case IEEE80211_MLME_DEAUTH: 1338 switch (ic->ic_opmode) { 1339 case IEEE80211_M_STA: 1340 /* XXX not quite right */ 1341 ieee80211_new_state(ic, IEEE80211_S_INIT, 1342 mlme.im_reason); 1343 break; --- 31 unchanged lines hidden (view full) --- 1375 return EINVAL; 1376 } 1377 return 0; 1378} 1379 1380static int 1381ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1382{ |
1959 u_int8_t mac[IEEE80211_ADDR_LEN]; | 1383 uint8_t mac[IEEE80211_ADDR_LEN]; |
1960 const struct ieee80211_aclator *acl = ic->ic_acl; 1961 int error; 1962 1963 if (ireq->i_len != sizeof(mac)) 1964 return EINVAL; 1965 error = copyin(ireq->i_data, mac, ireq->i_len); 1966 if (error) 1967 return error; --- 47 unchanged lines hidden (view full) --- 2015 return 0; 2016} 2017 2018static int 2019ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 2020{ 2021 struct ieee80211req_chanlist list; 2022 u_char chanlist[IEEE80211_CHAN_BYTES]; | 1384 const struct ieee80211_aclator *acl = ic->ic_acl; 1385 int error; 1386 1387 if (ireq->i_len != sizeof(mac)) 1388 return EINVAL; 1389 error = copyin(ireq->i_data, mac, ireq->i_len); 1390 if (error) 1391 return error; --- 47 unchanged lines hidden (view full) --- 1439 return 0; 1440} 1441 1442static int 1443ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 1444{ 1445 struct ieee80211req_chanlist list; 1446 u_char chanlist[IEEE80211_CHAN_BYTES]; |
2023 int i, j, error; | 1447 int i, j, nchan, error; |
2024 2025 if (ireq->i_len != sizeof(list)) 2026 return EINVAL; 2027 error = copyin(ireq->i_data, &list, sizeof(list)); 2028 if (error) 2029 return error; 2030 memset(chanlist, 0, sizeof(chanlist)); 2031 /* 2032 * Since channel 0 is not available for DS, channel 1 2033 * is assigned to LSB on WaveLAN. 2034 */ 2035 if (ic->ic_phytype == IEEE80211_T_DS) 2036 i = 1; 2037 else 2038 i = 0; | 1448 1449 if (ireq->i_len != sizeof(list)) 1450 return EINVAL; 1451 error = copyin(ireq->i_data, &list, sizeof(list)); 1452 if (error) 1453 return error; 1454 memset(chanlist, 0, sizeof(chanlist)); 1455 /* 1456 * Since channel 0 is not available for DS, channel 1 1457 * is assigned to LSB on WaveLAN. 1458 */ 1459 if (ic->ic_phytype == IEEE80211_T_DS) 1460 i = 1; 1461 else 1462 i = 0; |
1463 nchan = 0; |
|
2039 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 2040 /* 2041 * NB: silently discard unavailable channels so users 2042 * can specify 1-255 to get all available channels. 2043 */ | 1464 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 1465 /* 1466 * NB: silently discard unavailable channels so users 1467 * can specify 1-255 to get all available channels. 1468 */ |
2044 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) | 1469 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) { |
2045 setbit(chanlist, i); | 1470 setbit(chanlist, i); |
1471 nchan++; 1472 } |
|
2046 } | 1473 } |
2047 if (ic->ic_ibss_chan == NULL || 2048 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 2049 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 2050 if (isset(chanlist, i)) { 2051 ic->ic_ibss_chan = &ic->ic_channels[i]; 2052 goto found; 2053 } 2054 return EINVAL; /* no active channels */ 2055found: 2056 ; 2057 } | 1474 if (nchan == 0) 1475 return EINVAL; 1476 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ 1477 isclr(chanlist, ic->ic_bsschan->ic_ieee)) 1478 ic->ic_bsschan = IEEE80211_CHAN_ANYC; |
2058 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); | 1479 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); |
2059 return IS_UP_AUTO(ic) ? ENETRESET : 0; | 1480 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0; |
2060} 2061 2062static int 2063ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 2064{ 2065 struct ieee80211_node *ni; | 1481} 1482 1483static int 1484ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 1485{ 1486 struct ieee80211_node *ni; |
2066 u_int8_t macaddr[IEEE80211_ADDR_LEN]; | 1487 uint8_t macaddr[IEEE80211_ADDR_LEN]; |
2067 int error; 2068 2069 /* 2070 * NB: we could copyin ieee80211req_sta_stats so apps 2071 * could make selective changes but that's overkill; 2072 * just clear all stats for now. 2073 */ 2074 if (ireq->i_len < IEEE80211_ADDR_LEN) --- 113 unchanged lines hidden (view full) --- 2188 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 2189 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 2190 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 2191 } 2192 return 0; 2193} 2194 2195static int | 1488 int error; 1489 1490 /* 1491 * NB: we could copyin ieee80211req_sta_stats so apps 1492 * could make selective changes but that's overkill; 1493 * just clear all stats for now. 1494 */ 1495 if (ireq->i_len < IEEE80211_ADDR_LEN) --- 113 unchanged lines hidden (view full) --- 1609 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 1610 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 1611 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 1612 } 1613 return 0; 1614} 1615 1616static int |
1617find11gchannel(struct ieee80211com *ic, int start, int freq) 1618{ 1619 const struct ieee80211_channel *c; 1620 int i; 1621 1622 for (i = start+1; i < ic->ic_nchans; i++) { 1623 c = &ic->ic_channels[i]; 1624 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1625 return 1; 1626 } 1627 /* NB: should not be needed but in case things are mis-sorted */ 1628 for (i = 0; i < start; i++) { 1629 c = &ic->ic_channels[i]; 1630 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 1631 return 1; 1632 } 1633 return 0; 1634} 1635 1636static struct ieee80211_channel * 1637findchannel(struct ieee80211com *ic, int ieee, int mode) 1638{ 1639 static const u_int chanflags[IEEE80211_MODE_MAX] = { 1640 0, /* IEEE80211_MODE_AUTO */ 1641 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 1642 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 1643 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */ 1644 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 1645 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ 1646 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 1647 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */ 1648 /* NB: handled specially below */ 1649 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */ 1650 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */ 1651 }; 1652 u_int modeflags; 1653 int i; 1654 1655 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode)); 1656 modeflags = chanflags[mode]; 1657 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO, 1658 ("no chanflags for mode %u", mode)); 1659 for (i = 0; i < ic->ic_nchans; i++) { 1660 struct ieee80211_channel *c = &ic->ic_channels[i]; 1661 1662 if (c->ic_ieee != ieee) 1663 continue; 1664 if (mode == IEEE80211_MODE_AUTO) { 1665 /* ignore turbo channels for autoselect */ 1666 if (IEEE80211_IS_CHAN_TURBO(c)) 1667 continue; 1668 /* 1669 * XXX special-case 11b/g channels so we 1670 * always select the g channel if both 1671 * are present. 1672 * XXX prefer HT to non-HT? 1673 */ 1674 if (!IEEE80211_IS_CHAN_B(c) || 1675 !find11gchannel(ic, i, c->ic_freq)) 1676 return c; 1677 } else { 1678 /* must check HT specially */ 1679 if ((mode == IEEE80211_MODE_11NA || 1680 mode == IEEE80211_MODE_11NG) && 1681 !IEEE80211_IS_CHAN_HT(c)) 1682 continue; 1683 if ((c->ic_flags & modeflags) == modeflags) 1684 return c; 1685 } 1686 } 1687 return NULL; 1688} 1689 1690/* 1691 * Check the specified against any desired mode (aka netband). 1692 * This is only used (presently) when operating in hostap mode 1693 * to enforce consistency. 1694 */ 1695static int 1696check_mode_consistency(const struct ieee80211_channel *c, int mode) 1697{ 1698 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel")); 1699 1700 switch (mode) { 1701 case IEEE80211_MODE_11B: 1702 return (IEEE80211_IS_CHAN_B(c)); 1703 case IEEE80211_MODE_11G: 1704 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c)); 1705 case IEEE80211_MODE_11A: 1706 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c)); 1707 case IEEE80211_MODE_STURBO_A: 1708 return (IEEE80211_IS_CHAN_STURBO(c)); 1709 case IEEE80211_MODE_11NA: 1710 return (IEEE80211_IS_CHAN_HTA(c)); 1711 case IEEE80211_MODE_11NG: 1712 return (IEEE80211_IS_CHAN_HTG(c)); 1713 } 1714 return 1; 1715 1716} 1717 1718/* 1719 * Common code to set the current channel. If the device 1720 * is up and running this may result in an immediate channel 1721 * change or a kick of the state machine. 1722 */ 1723static int 1724setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) 1725{ 1726 int error; 1727 1728 if (c != IEEE80211_CHAN_ANYC) { 1729 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1730 !check_mode_consistency(c, ic->ic_des_mode)) 1731 return EINVAL; 1732 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan) 1733 return 0; /* NB: nothing to do */ 1734 } 1735 ic->ic_des_chan = c; 1736 1737 error = 0; 1738 if ((ic->ic_opmode == IEEE80211_M_MONITOR || 1739 ic->ic_opmode == IEEE80211_M_WDS) && 1740 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1741 /* 1742 * Monitor and wds modes can switch directly. 1743 */ 1744 ic->ic_curchan = ic->ic_des_chan; 1745 if (ic->ic_state == IEEE80211_S_RUN) 1746 ic->ic_set_channel(ic); 1747 } else { 1748 /* 1749 * Need to go through the state machine in case we 1750 * need to reassociate or the like. The state machine 1751 * will pickup the desired channel and avoid scanning. 1752 */ 1753 if (IS_UP_AUTO(ic)) 1754 error = ieee80211_init(ic, RESCAN); 1755 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1756 /* 1757 * When not up+running and a real channel has 1758 * been specified fix the current channel so 1759 * there is immediate feedback; e.g. via ifconfig. 1760 */ 1761 ic->ic_curchan = ic->ic_des_chan; 1762 } 1763 } 1764 return error; 1765} 1766 1767/* 1768 * Old api for setting the current channel; this is 1769 * deprecated because channel numbers are ambiguous. 1770 */ 1771static int 1772ieee80211_ioctl_setchannel(struct ieee80211com *ic, 1773 const struct ieee80211req *ireq) 1774{ 1775 struct ieee80211_channel *c; 1776 1777 /* XXX 0xffff overflows 16-bit signed */ 1778 if (ireq->i_val == 0 || 1779 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) { 1780 c = IEEE80211_CHAN_ANYC; 1781 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) { 1782 return EINVAL; 1783 } else { 1784 struct ieee80211_channel *c2; 1785 1786 c = findchannel(ic, ireq->i_val, ic->ic_des_mode); 1787 if (c == NULL) { 1788 c = findchannel(ic, ireq->i_val, 1789 IEEE80211_MODE_AUTO); 1790 if (c == NULL) 1791 return EINVAL; 1792 } 1793 /* 1794 * Fine tune channel selection based on desired mode: 1795 * if 11b is requested, find the 11b version of any 1796 * 11g channel returned, 1797 * if static turbo, find the turbo version of any 1798 * 11a channel return, 1799 * if 11na is requested, find the ht version of any 1800 * 11a channel returned, 1801 * if 11ng is requested, find the ht version of any 1802 * 11g channel returned, 1803 * otherwise we should be ok with what we've got. 1804 */ 1805 switch (ic->ic_des_mode) { 1806 case IEEE80211_MODE_11B: 1807 if (IEEE80211_IS_CHAN_ANYG(c)) { 1808 c2 = findchannel(ic, ireq->i_val, 1809 IEEE80211_MODE_11B); 1810 /* NB: should not happen, =>'s 11g w/o 11b */ 1811 if (c2 != NULL) 1812 c = c2; 1813 } 1814 break; 1815 case IEEE80211_MODE_TURBO_A: 1816 if (IEEE80211_IS_CHAN_A(c)) { 1817 c2 = findchannel(ic, ireq->i_val, 1818 IEEE80211_MODE_TURBO_A); 1819 if (c2 != NULL) 1820 c = c2; 1821 } 1822 break; 1823 case IEEE80211_MODE_11NA: 1824 if (IEEE80211_IS_CHAN_A(c)) { 1825 c2 = findchannel(ic, ireq->i_val, 1826 IEEE80211_MODE_11NA); 1827 if (c2 != NULL) 1828 c = c2; 1829 } 1830 break; 1831 case IEEE80211_MODE_11NG: 1832 if (IEEE80211_IS_CHAN_ANYG(c)) { 1833 c2 = findchannel(ic, ireq->i_val, 1834 IEEE80211_MODE_11NG); 1835 if (c2 != NULL) 1836 c = c2; 1837 } 1838 break; 1839 default: /* NB: no static turboG */ 1840 break; 1841 } 1842 } 1843 return setcurchan(ic, c); 1844} 1845 1846/* 1847 * New/current api for setting the current channel; a complete 1848 * channel description is provide so there is no ambiguity in 1849 * identifying the channel. 1850 */ 1851static int 1852ieee80211_ioctl_setcurchan(struct ieee80211com *ic, 1853 const struct ieee80211req *ireq) 1854{ 1855 struct ieee80211_channel chan, *c; 1856 int error; 1857 1858 if (ireq->i_len != sizeof(chan)) 1859 return EINVAL; 1860 error = copyin(ireq->i_data, &chan, sizeof(chan)); 1861 if (error != 0) 1862 return error; 1863 /* XXX 0xffff overflows 16-bit signed */ 1864 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { 1865 c = IEEE80211_CHAN_ANYC; 1866 } else { 1867 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); 1868 if (c == NULL) 1869 return EINVAL; 1870 } 1871 return setcurchan(ic, c); 1872} 1873 1874static int |
|
2196ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 2197{ | 1875ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1876{ |
2198 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; | 1877 static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; |
2199 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 2200 int error; 2201 const struct ieee80211_authenticator *auth; | 1878 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1879 int error; 1880 const struct ieee80211_authenticator *auth; |
2202 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; | 1881 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; |
2203 char tmpssid[IEEE80211_NWID_LEN]; | 1882 char tmpssid[IEEE80211_NWID_LEN]; |
2204 u_int8_t tmpbssid[IEEE80211_ADDR_LEN]; | 1883 uint8_t tmpbssid[IEEE80211_ADDR_LEN]; |
2205 struct ieee80211_key *k; 2206 int j, caps; 2207 u_int kid; 2208 2209 error = 0; 2210 switch (ireq->i_type) { 2211 case IEEE80211_IOC_SSID: 2212 if (ireq->i_val != 0 || 2213 ireq->i_len > IEEE80211_NWID_LEN) 2214 return EINVAL; 2215 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 2216 if (error) 2217 break; | 1884 struct ieee80211_key *k; 1885 int j, caps; 1886 u_int kid; 1887 1888 error = 0; 1889 switch (ireq->i_type) { 1890 case IEEE80211_IOC_SSID: 1891 if (ireq->i_val != 0 || 1892 ireq->i_len > IEEE80211_NWID_LEN) 1893 return EINVAL; 1894 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 1895 if (error) 1896 break; |
2218 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 2219 ic->ic_des_esslen = ireq->i_len; 2220 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); 2221 error = ENETRESET; | 1897 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); 1898 ic->ic_des_ssid[0].len = ireq->i_len; 1899 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len); 1900 ic->ic_des_nssid = (ireq->i_len > 0); 1901 if (IS_UP_AUTO(ic)) 1902 error = ieee80211_init(ic, RESCAN); |
2222 break; 2223 case IEEE80211_IOC_WEP: 2224 switch (ireq->i_val) { 2225 case IEEE80211_WEP_OFF: 2226 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2227 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2228 break; 2229 case IEEE80211_WEP_ON: 2230 ic->ic_flags |= IEEE80211_F_PRIVACY; 2231 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2232 break; 2233 case IEEE80211_WEP_MIXED: 2234 ic->ic_flags |= IEEE80211_F_PRIVACY; 2235 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2236 break; 2237 } | 1903 break; 1904 case IEEE80211_IOC_WEP: 1905 switch (ireq->i_val) { 1906 case IEEE80211_WEP_OFF: 1907 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1908 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1909 break; 1910 case IEEE80211_WEP_ON: 1911 ic->ic_flags |= IEEE80211_F_PRIVACY; 1912 ic->ic_flags |= IEEE80211_F_DROPUNENC; 1913 break; 1914 case IEEE80211_WEP_MIXED: 1915 ic->ic_flags |= IEEE80211_F_PRIVACY; 1916 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 1917 break; 1918 } |
2238 error = ENETRESET; | 1919 if (IS_UP_AUTO(ic)) 1920 error = ieee80211_init(ic, RESCAN); |
2239 break; 2240 case IEEE80211_IOC_WEPKEY: 2241 kid = (u_int) ireq->i_val; 2242 if (kid >= IEEE80211_WEP_NKID) 2243 return EINVAL; 2244 k = &ic->ic_nw_keys[kid]; 2245 if (ireq->i_len == 0) { 2246 /* zero-len =>'s delete any existing key */ --- 12 unchanged lines hidden (view full) --- 2259 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 2260 k->wk_keylen = ireq->i_len; 2261 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 2262 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 2263 error = EINVAL; 2264 } else 2265 error = EINVAL; 2266 ieee80211_key_update_end(ic); | 1921 break; 1922 case IEEE80211_IOC_WEPKEY: 1923 kid = (u_int) ireq->i_val; 1924 if (kid >= IEEE80211_WEP_NKID) 1925 return EINVAL; 1926 k = &ic->ic_nw_keys[kid]; 1927 if (ireq->i_len == 0) { 1928 /* zero-len =>'s delete any existing key */ --- 12 unchanged lines hidden (view full) --- 1941 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) { 1942 k->wk_keylen = ireq->i_len; 1943 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 1944 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr)) 1945 error = EINVAL; 1946 } else 1947 error = EINVAL; 1948 ieee80211_key_update_end(ic); |
2267 if (!error) /* NB: for compatibility */ 2268 error = ENETRESET; | |
2269 break; 2270 case IEEE80211_IOC_WEPTXKEY: 2271 kid = (u_int) ireq->i_val; 2272 if (kid >= IEEE80211_WEP_NKID && | 1949 break; 1950 case IEEE80211_IOC_WEPTXKEY: 1951 kid = (u_int) ireq->i_val; 1952 if (kid >= IEEE80211_WEP_NKID && |
2273 (u_int16_t) kid != IEEE80211_KEYIX_NONE) | 1953 (uint16_t) kid != IEEE80211_KEYIX_NONE) |
2274 return EINVAL; 2275 ic->ic_def_txkey = kid; | 1954 return EINVAL; 1955 ic->ic_def_txkey = kid; |
2276 error = ENETRESET; /* push to hardware */ | |
2277 break; 2278 case IEEE80211_IOC_AUTHMODE: 2279 switch (ireq->i_val) { 2280 case IEEE80211_AUTH_WPA: 2281 case IEEE80211_AUTH_8021X: /* 802.1x */ 2282 case IEEE80211_AUTH_OPEN: /* open */ 2283 case IEEE80211_AUTH_SHARED: /* shared-key */ 2284 case IEEE80211_AUTH_AUTO: /* auto */ --- 23 unchanged lines hidden (view full) --- 2308 /* XXX PRIVACY handling? */ 2309 /* XXX what's the right way to do this? */ 2310 break; 2311 } 2312 /* NB: authenticator attach/detach happens on state change */ 2313 ic->ic_bss->ni_authmode = ireq->i_val; 2314 /* XXX mixed/mode/usage? */ 2315 ic->ic_auth = auth; | 1956 break; 1957 case IEEE80211_IOC_AUTHMODE: 1958 switch (ireq->i_val) { 1959 case IEEE80211_AUTH_WPA: 1960 case IEEE80211_AUTH_8021X: /* 802.1x */ 1961 case IEEE80211_AUTH_OPEN: /* open */ 1962 case IEEE80211_AUTH_SHARED: /* shared-key */ 1963 case IEEE80211_AUTH_AUTO: /* auto */ --- 23 unchanged lines hidden (view full) --- 1987 /* XXX PRIVACY handling? */ 1988 /* XXX what's the right way to do this? */ 1989 break; 1990 } 1991 /* NB: authenticator attach/detach happens on state change */ 1992 ic->ic_bss->ni_authmode = ireq->i_val; 1993 /* XXX mixed/mode/usage? */ 1994 ic->ic_auth = auth; |
2316 error = ENETRESET; | 1995 if (IS_UP_AUTO(ic)) 1996 error = ieee80211_init(ic, RESCAN); |
2317 break; 2318 case IEEE80211_IOC_CHANNEL: | 1997 break; 1998 case IEEE80211_IOC_CHANNEL: |
2319 /* XXX 0xffff overflows 16-bit signed */ 2320 if (ireq->i_val == 0 || 2321 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 2322 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 2323 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 2324 isclr(ic->ic_chan_active, ireq->i_val)) { 2325 return EINVAL; 2326 } else 2327 ic->ic_ibss_chan = ic->ic_des_chan = 2328 &ic->ic_channels[ireq->i_val]; 2329 switch (ic->ic_state) { 2330 case IEEE80211_S_INIT: 2331 case IEEE80211_S_SCAN: 2332 error = ENETRESET; 2333 break; 2334 default: 2335 /* 2336 * If the desired channel has changed (to something 2337 * other than any) and we're not already scanning, 2338 * then kick the state machine. 2339 */ 2340 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 2341 ic->ic_bss->ni_chan != ic->ic_des_chan && 2342 (ic->ic_flags & IEEE80211_F_SCAN) == 0) 2343 error = ENETRESET; 2344 break; 2345 } 2346 if (error == ENETRESET && 2347 ic->ic_opmode == IEEE80211_M_MONITOR) { 2348 if (IS_UP(ic)) { 2349 /* 2350 * Monitor mode can switch directly. 2351 */ 2352 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) 2353 ic->ic_curchan = ic->ic_des_chan; 2354 error = ic->ic_reset(ic->ic_ifp); 2355 } else 2356 error = 0; 2357 } | 1999 error = ieee80211_ioctl_setchannel(ic, ireq); |
2358 break; 2359 case IEEE80211_IOC_POWERSAVE: 2360 switch (ireq->i_val) { 2361 case IEEE80211_POWERSAVE_OFF: 2362 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2363 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2364 error = ENETRESET; 2365 } --- 31 unchanged lines hidden (view full) --- 2397 ic->ic_rtsthreshold = ireq->i_val; 2398 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2399 break; 2400 case IEEE80211_IOC_PROTMODE: 2401 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2402 return EINVAL; 2403 ic->ic_protmode = ireq->i_val; 2404 /* NB: if not operating in 11g this can wait */ | 2000 break; 2001 case IEEE80211_IOC_POWERSAVE: 2002 switch (ireq->i_val) { 2003 case IEEE80211_POWERSAVE_OFF: 2004 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2005 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2006 error = ENETRESET; 2007 } --- 31 unchanged lines hidden (view full) --- 2039 ic->ic_rtsthreshold = ireq->i_val; 2040 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2041 break; 2042 case IEEE80211_IOC_PROTMODE: 2043 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2044 return EINVAL; 2045 ic->ic_protmode = ireq->i_val; 2046 /* NB: if not operating in 11g this can wait */ |
2405 if (ic->ic_curmode == IEEE80211_MODE_11G) | 2047 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2048 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) |
2406 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2407 break; 2408 case IEEE80211_IOC_TXPOWER: 2409 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2410 return EINVAL; | 2049 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2050 break; 2051 case IEEE80211_IOC_TXPOWER: 2052 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2053 return EINVAL; |
2411 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 2412 ireq->i_val < IEEE80211_TXPOWER_MAX)) | 2054 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val && 2055 ireq->i_val <= IEEE80211_TXPOWER_MAX)) |
2413 return EINVAL; 2414 ic->ic_txpowlimit = ireq->i_val; 2415 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2416 break; 2417 case IEEE80211_IOC_ROAMING: 2418 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2419 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2420 return EINVAL; --- 44 unchanged lines hidden (view full) --- 2465 break; 2466 case 2: 2467 ic->ic_flags |= IEEE80211_F_WPA2; 2468 break; 2469 case 3: 2470 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2471 break; 2472 } | 2056 return EINVAL; 2057 ic->ic_txpowlimit = ireq->i_val; 2058 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2059 break; 2060 case IEEE80211_IOC_ROAMING: 2061 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2062 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2063 return EINVAL; --- 44 unchanged lines hidden (view full) --- 2108 break; 2109 case 2: 2110 ic->ic_flags |= IEEE80211_F_WPA2; 2111 break; 2112 case 3: 2113 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; 2114 break; 2115 } |
2473 error = ENETRESET; /* XXX? */ | 2116 error = ENETRESET; |
2474 break; 2475 case IEEE80211_IOC_WME: 2476 if (ireq->i_val) { 2477 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2478 return EINVAL; 2479 ic->ic_flags |= IEEE80211_F_WME; 2480 } else 2481 ic->ic_flags &= ~IEEE80211_F_WME; | 2117 break; 2118 case IEEE80211_IOC_WME: 2119 if (ireq->i_val) { 2120 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2121 return EINVAL; 2122 ic->ic_flags |= IEEE80211_F_WME; 2123 } else 2124 ic->ic_flags &= ~IEEE80211_F_WME; |
2482 error = ENETRESET; /* XXX maybe not for station? */ | 2125 if (IS_UP_AUTO(ic)) 2126 error = ieee80211_init(ic, 0); |
2483 break; 2484 case IEEE80211_IOC_HIDESSID: 2485 if (ireq->i_val) 2486 ic->ic_flags |= IEEE80211_F_HIDESSID; 2487 else 2488 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2489 error = ENETRESET; 2490 break; --- 46 unchanged lines hidden (view full) --- 2537 case IEEE80211_IOC_UCASTKEYLEN: 2538 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2539 return EINVAL; 2540 /* XXX no way to verify driver capability */ 2541 rsn->rsn_ucastkeylen = ireq->i_val; 2542 break; 2543 case IEEE80211_IOC_DRIVER_CAPS: 2544 /* NB: for testing */ | 2127 break; 2128 case IEEE80211_IOC_HIDESSID: 2129 if (ireq->i_val) 2130 ic->ic_flags |= IEEE80211_F_HIDESSID; 2131 else 2132 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2133 error = ENETRESET; 2134 break; --- 46 unchanged lines hidden (view full) --- 2181 case IEEE80211_IOC_UCASTKEYLEN: 2182 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2183 return EINVAL; 2184 /* XXX no way to verify driver capability */ 2185 rsn->rsn_ucastkeylen = ireq->i_val; 2186 break; 2187 case IEEE80211_IOC_DRIVER_CAPS: 2188 /* NB: for testing */ |
2545 ic->ic_caps = (((u_int16_t) ireq->i_val) << 16) | 2546 ((u_int16_t) ireq->i_len); | 2189 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) | 2190 ((uint16_t) ireq->i_len); |
2547 break; 2548 case IEEE80211_IOC_KEYMGTALGS: 2549 /* XXX check */ 2550 rsn->rsn_keymgmtset = ireq->i_val; 2551 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2552 break; 2553 case IEEE80211_IOC_RSNCAPS: 2554 /* XXX check */ --- 6 unchanged lines hidden (view full) --- 2561 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2562 if (error) 2563 break; 2564 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2565 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2566 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2567 else 2568 ic->ic_flags |= IEEE80211_F_DESBSSID; | 2191 break; 2192 case IEEE80211_IOC_KEYMGTALGS: 2193 /* XXX check */ 2194 rsn->rsn_keymgmtset = ireq->i_val; 2195 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2196 break; 2197 case IEEE80211_IOC_RSNCAPS: 2198 /* XXX check */ --- 6 unchanged lines hidden (view full) --- 2205 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2206 if (error) 2207 break; 2208 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2209 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2210 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2211 else 2212 ic->ic_flags |= IEEE80211_F_DESBSSID; |
2569 error = ENETRESET; | 2213 if (IS_UP_AUTO(ic)) 2214 error = ieee80211_init(ic, RESCAN); |
2570 break; 2571 case IEEE80211_IOC_CHANLIST: 2572 error = ieee80211_ioctl_setchanlist(ic, ireq); 2573 break; 2574 case IEEE80211_IOC_SCAN_REQ: | 2215 break; 2216 case IEEE80211_IOC_CHANLIST: 2217 error = ieee80211_ioctl_setchanlist(ic, ireq); 2218 break; 2219 case IEEE80211_IOC_SCAN_REQ: |
2575 if (ic->ic_opmode == IEEE80211_M_HOSTAP) /* XXX ignore */ 2576 break; 2577 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 2578 if (error == 0) /* XXX background scan */ 2579 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); | 2220 if (!IS_UP(ic)) 2221 return EINVAL; 2222 (void) ieee80211_start_scan(ic, 2223 IEEE80211_SCAN_ACTIVE | 2224 IEEE80211_SCAN_NOPICK | 2225 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER, 2226 /* XXX use ioctl params */ 2227 ic->ic_des_nssid, ic->ic_des_ssid); |
2580 break; 2581 case IEEE80211_IOC_ADDMAC: 2582 case IEEE80211_IOC_DELMAC: 2583 error = ieee80211_ioctl_macmac(ic, ireq); 2584 break; 2585 case IEEE80211_IOC_MACCMD: 2586 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2587 break; --- 34 unchanged lines hidden (view full) --- 2622 error = EINVAL; 2623 break; 2624 case IEEE80211_IOC_PUREG: 2625 if (ireq->i_val) 2626 ic->ic_flags |= IEEE80211_F_PUREG; 2627 else 2628 ic->ic_flags &= ~IEEE80211_F_PUREG; 2629 /* NB: reset only if we're operating on an 11g channel */ | 2228 break; 2229 case IEEE80211_IOC_ADDMAC: 2230 case IEEE80211_IOC_DELMAC: 2231 error = ieee80211_ioctl_macmac(ic, ireq); 2232 break; 2233 case IEEE80211_IOC_MACCMD: 2234 error = ieee80211_ioctl_setmaccmd(ic, ireq); 2235 break; --- 34 unchanged lines hidden (view full) --- 2270 error = EINVAL; 2271 break; 2272 case IEEE80211_IOC_PUREG: 2273 if (ireq->i_val) 2274 ic->ic_flags |= IEEE80211_F_PUREG; 2275 else 2276 ic->ic_flags &= ~IEEE80211_F_PUREG; 2277 /* NB: reset only if we're operating on an 11g channel */ |
2630 if (ic->ic_curmode == IEEE80211_MODE_11G) | 2278 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2279 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) |
2631 error = ENETRESET; 2632 break; | 2280 error = ENETRESET; 2281 break; |
2282 case IEEE80211_IOC_FF: 2283 if (ireq->i_val) { 2284 if ((ic->ic_caps & IEEE80211_C_FF) == 0) 2285 return EINVAL; 2286 ic->ic_flags |= IEEE80211_F_FF; 2287 } else 2288 ic->ic_flags &= ~IEEE80211_F_FF; 2289 error = ENETRESET; 2290 break; 2291 case IEEE80211_IOC_TURBOP: 2292 if (ireq->i_val) { 2293 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0) 2294 return EINVAL; 2295 ic->ic_flags |= IEEE80211_F_TURBOP; 2296 } else 2297 ic->ic_flags &= ~IEEE80211_F_TURBOP; 2298 error = ENETRESET; 2299 break; 2300 case IEEE80211_IOC_BGSCAN: 2301 if (ireq->i_val) { 2302 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0) 2303 return EINVAL; 2304 ic->ic_flags |= IEEE80211_F_BGSCAN; 2305 } else 2306 ic->ic_flags &= ~IEEE80211_F_BGSCAN; 2307 break; 2308 case IEEE80211_IOC_BGSCAN_IDLE: 2309 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN) 2310 ic->ic_bgscanidle = ireq->i_val*hz/1000; 2311 else 2312 error = EINVAL; 2313 break; 2314 case IEEE80211_IOC_BGSCAN_INTERVAL: 2315 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN) 2316 ic->ic_bgscanintvl = ireq->i_val*hz; 2317 else 2318 error = EINVAL; 2319 break; 2320 case IEEE80211_IOC_SCANVALID: 2321 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN) 2322 ic->ic_scanvalid = ireq->i_val*hz; 2323 else 2324 error = EINVAL; 2325 break; 2326 case IEEE80211_IOC_ROAM_RSSI_11A: 2327 ic->ic_roam.rssi11a = ireq->i_val; 2328 break; 2329 case IEEE80211_IOC_ROAM_RSSI_11B: 2330 ic->ic_roam.rssi11bOnly = ireq->i_val; 2331 break; 2332 case IEEE80211_IOC_ROAM_RSSI_11G: 2333 ic->ic_roam.rssi11b = ireq->i_val; 2334 break; 2335 case IEEE80211_IOC_ROAM_RATE_11A: 2336 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL; 2337 break; 2338 case IEEE80211_IOC_ROAM_RATE_11B: 2339 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL; 2340 break; 2341 case IEEE80211_IOC_ROAM_RATE_11G: 2342 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL; 2343 break; |
|
2633 case IEEE80211_IOC_MCAST_RATE: 2634 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2635 break; 2636 case IEEE80211_IOC_FRAGTHRESHOLD: 2637 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2638 ireq->i_val != IEEE80211_FRAG_MAX) 2639 return EINVAL; 2640 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && --- 13 unchanged lines hidden (view full) --- 2654 break; 2655 case IEEE80211_IOC_BMISSTHRESHOLD: 2656 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val && 2657 ireq->i_val <= IEEE80211_HWBMISS_MAX)) 2658 return EINVAL; 2659 ic->ic_bmissthreshold = ireq->i_val; 2660 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2661 break; | 2344 case IEEE80211_IOC_MCAST_RATE: 2345 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL; 2346 break; 2347 case IEEE80211_IOC_FRAGTHRESHOLD: 2348 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 && 2349 ireq->i_val != IEEE80211_FRAG_MAX) 2350 return EINVAL; 2351 if (!(IEEE80211_FRAG_MIN <= ireq->i_val && --- 13 unchanged lines hidden (view full) --- 2365 break; 2366 case IEEE80211_IOC_BMISSTHRESHOLD: 2367 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val && 2368 ireq->i_val <= IEEE80211_HWBMISS_MAX)) 2369 return EINVAL; 2370 ic->ic_bmissthreshold = ireq->i_val; 2371 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2372 break; |
2373 case IEEE80211_IOC_CURCHAN: 2374 error = ieee80211_ioctl_setcurchan(ic, ireq); 2375 break; 2376 case IEEE80211_IOC_SHORTGI: 2377 if (ireq->i_val) { 2378#define IEEE80211_HTCAP_SHORTGI \ 2379 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) 2380 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0) 2381 return EINVAL; 2382 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20) 2383 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20; 2384 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40) 2385 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40; 2386#undef IEEE80211_HTCAP_SHORTGI 2387 } else 2388 ic->ic_flags_ext &= 2389 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40); 2390 /* XXX kick state machine? */ 2391 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2392 break; 2393 case IEEE80211_IOC_AMPDU: 2394 if (ireq->i_val) { 2395 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0) 2396 return EINVAL; 2397 if (ireq->i_val & 1) 2398 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX; 2399 if (ireq->i_val & 2) 2400 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX; 2401 } else 2402 ic->ic_flags_ext &= 2403 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX); 2404 /* NB: reset only if we're operating on an 11n channel */ 2405 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2406 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2407 error = ENETRESET; 2408 break; 2409 case IEEE80211_IOC_AMPDU_LIMIT: 2410 /* XXX validate */ 2411 ic->ic_ampdu_limit = ireq->i_val; 2412 break; 2413 case IEEE80211_IOC_AMPDU_DENSITY: 2414 /* XXX validate */ 2415 ic->ic_ampdu_density = ireq->i_val; 2416 break; 2417 case IEEE80211_IOC_AMSDU: 2418 if (ireq->i_val) { 2419 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0) 2420 return EINVAL; 2421 if (ireq->i_val & 1) 2422 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX; 2423 if (ireq->i_val & 2) 2424 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX; 2425 } else 2426 ic->ic_flags_ext &= 2427 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX); 2428 /* NB: reset only if we're operating on an 11n channel */ 2429 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2430 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2431 error = ENETRESET; 2432 break; 2433 case IEEE80211_IOC_AMSDU_LIMIT: 2434 /* XXX validate */ 2435 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */ 2436 break; 2437 case IEEE80211_IOC_PUREN: 2438 if (ireq->i_val) { 2439 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2440 return EINVAL; 2441 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN; 2442 } else 2443 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN; 2444 /* NB: reset only if we're operating on an 11n channel */ 2445 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2446 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2447 error = ENETRESET; 2448 break; 2449 case IEEE80211_IOC_DOTH: 2450 if (ireq->i_val) { 2451#if 0 2452 /* XXX no capability */ 2453 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0) 2454 return EINVAL; 2455#endif 2456 ic->ic_flags |= IEEE80211_F_DOTH; 2457 } else 2458 ic->ic_flags &= ~IEEE80211_F_DOTH; 2459 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2460 break; 2461 case IEEE80211_IOC_HTCOMPAT: 2462 if (ireq->i_val) { 2463 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0) 2464 return EINVAL; 2465 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT; 2466 } else 2467 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT; 2468 /* NB: reset only if we're operating on an 11n channel */ 2469 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 2470 IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) 2471 error = ENETRESET; 2472 break; |
|
2662 default: 2663 error = EINVAL; 2664 break; 2665 } | 2473 default: 2474 error = EINVAL; 2475 break; 2476 } |
2666 if (error == ENETRESET && !IS_UP_AUTO(ic)) 2667 error = 0; | 2477 if (error == ENETRESET) 2478 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0; |
2668 return error; 2669} 2670 2671int 2672ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2673{ 2674 struct ifnet *ifp = ic->ic_ifp; 2675 int error = 0; --- 11 unchanged lines hidden (view full) --- 2687 (struct ieee80211req *) data); 2688 break; 2689 case SIOCS80211: 2690 error = priv_check(curthread, PRIV_NET80211_MANAGE); 2691 if (error == 0) 2692 error = ieee80211_ioctl_set80211(ic, cmd, 2693 (struct ieee80211req *) data); 2694 break; | 2479 return error; 2480} 2481 2482int 2483ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2484{ 2485 struct ifnet *ifp = ic->ic_ifp; 2486 int error = 0; --- 11 unchanged lines hidden (view full) --- 2498 (struct ieee80211req *) data); 2499 break; 2500 case SIOCS80211: 2501 error = priv_check(curthread, PRIV_NET80211_MANAGE); 2502 if (error == 0) 2503 error = ieee80211_ioctl_set80211(ic, cmd, 2504 (struct ieee80211req *) data); 2505 break; |
2695 case SIOCGIFGENERIC: 2696 error = ieee80211_cfgget(ic, cmd, data); 2697 break; 2698 case SIOCSIFGENERIC: 2699 error = priv_check(curthread, PRIV_NET80211_MANAGE); 2700 if (error) 2701 break; 2702 error = ieee80211_cfgset(ic, cmd, data); 2703 break; | |
2704 case SIOCG80211STATS: 2705 ifr = (struct ifreq *)data; 2706 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2707 break; 2708 case SIOCSIFMTU: 2709 ifr = (struct ifreq *)data; 2710 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2711 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) --- 55 unchanged lines hidden --- | 2506 case SIOCG80211STATS: 2507 ifr = (struct ifreq *)data; 2508 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2509 break; 2510 case SIOCSIFMTU: 2511 ifr = (struct ifreq *)data; 2512 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2513 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) --- 55 unchanged lines hidden --- |