1 /*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 /* 37 * IEEE 802.11 ioctl support (FreeBSD-specific) 38 */ 39 40 #include "opt_inet.h" 41 #include "opt_ipx.h" 42 43 #include <sys/endian.h> 44 #include <sys/param.h> 45 #include <sys/kernel.h> 46 #include <sys/socket.h> 47 #include <sys/sockio.h> 48 #include <sys/systm.h> 49 50 #include <net/if.h> 51 #include <net/if_arp.h> 52 #include <net/if_media.h> 53 #include <net/ethernet.h> 54 55 #ifdef INET 56 #include <netinet/in.h> 57 #include <netinet/if_ether.h> 58 #endif 59 60 #ifdef IPX 61 #include <netipx/ipx.h> 62 #include <netipx/ipx_if.h> 63 #endif 64 65 #include <net80211/ieee80211_var.h> 66 #include <net80211/ieee80211_ioctl.h> 67 68 #include <dev/wi/if_wavelan_ieee.h> 69 70 /* 71 * XXX 72 * Wireless LAN specific configuration interface, which is compatible 73 * with wicontrol(8). 74 */ 75 76 int 77 ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) 78 { 79 struct ieee80211com *ic = (void *)ifp; 80 int i, j, error; 81 struct ifreq *ifr = (struct ifreq *)data; 82 struct wi_req wreq; 83 struct wi_ltv_keys *keys; 84 struct wi_apinfo *ap; 85 struct ieee80211_node *ni; 86 struct ieee80211_rateset *rs; 87 struct wi_sigcache wsc; 88 struct wi_scan_p2_hdr *p2; 89 struct wi_scan_res *res; 90 91 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 92 if (error) 93 return error; 94 wreq.wi_len = 0; 95 switch (wreq.wi_type) { 96 case WI_RID_SERIALNO: 97 /* nothing appropriate */ 98 break; 99 case WI_RID_NODENAME: 100 strcpy((char *)&wreq.wi_val[1], hostname); 101 wreq.wi_val[0] = htole16(strlen(hostname)); 102 wreq.wi_len = (1 + strlen(hostname) + 1) / 2; 103 break; 104 case WI_RID_CURRENT_SSID: 105 if (ic->ic_state != IEEE80211_S_RUN) { 106 wreq.wi_val[0] = 0; 107 wreq.wi_len = 1; 108 break; 109 } 110 wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen); 111 memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid, 112 ic->ic_bss->ni_esslen); 113 wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2; 114 break; 115 case WI_RID_OWN_SSID: 116 case WI_RID_DESIRED_SSID: 117 wreq.wi_val[0] = htole16(ic->ic_des_esslen); 118 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen); 119 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2; 120 break; 121 case WI_RID_CURRENT_BSSID: 122 if (ic->ic_state == IEEE80211_S_RUN) 123 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid); 124 else 125 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); 126 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 127 break; 128 case WI_RID_CHANNEL_LIST: 129 memset(wreq.wi_val, 0, sizeof(wreq.wi_val)); 130 /* 131 * Since channel 0 is not available for DS, channel 1 132 * is assigned to LSB on WaveLAN. 133 */ 134 if (ic->ic_phytype == IEEE80211_T_DS) 135 i = 1; 136 else 137 i = 0; 138 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) 139 if (isset(ic->ic_chan_active, i)) { 140 setbit((u_int8_t *)wreq.wi_val, j); 141 wreq.wi_len = j / 16 + 1; 142 } 143 break; 144 case WI_RID_OWN_CHNL: 145 wreq.wi_val[0] = htole16( 146 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 147 wreq.wi_len = 1; 148 break; 149 case WI_RID_CURRENT_CHAN: 150 wreq.wi_val[0] = htole16( 151 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)); 152 wreq.wi_len = 1; 153 break; 154 case WI_RID_COMMS_QUALITY: 155 wreq.wi_val[0] = 0; /* quality */ 156 wreq.wi_val[1] = 157 htole16((*ic->ic_node_getrssi)(ic, ic->ic_bss)); 158 wreq.wi_val[2] = 0; /* noise */ 159 wreq.wi_len = 3; 160 break; 161 case WI_RID_PROMISC: 162 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0); 163 wreq.wi_len = 1; 164 break; 165 case WI_RID_PORTTYPE: 166 wreq.wi_val[0] = htole16(ic->ic_opmode); 167 wreq.wi_len = 1; 168 break; 169 case WI_RID_MAC_NODE: 170 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); 171 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 172 break; 173 case WI_RID_TX_RATE: 174 if (ic->ic_fixed_rate == -1) 175 wreq.wi_val[0] = 0; /* auto */ 176 else 177 wreq.wi_val[0] = htole16( 178 (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] & 179 IEEE80211_RATE_VAL) / 2); 180 wreq.wi_len = 1; 181 break; 182 case WI_RID_CUR_TX_RATE: 183 wreq.wi_val[0] = htole16( 184 (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] & 185 IEEE80211_RATE_VAL) / 2); 186 wreq.wi_len = 1; 187 break; 188 case WI_RID_RTS_THRESH: 189 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); 190 wreq.wi_len = 1; 191 break; 192 case WI_RID_CREATE_IBSS: 193 wreq.wi_val[0] = 194 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0); 195 wreq.wi_len = 1; 196 break; 197 case WI_RID_MICROWAVE_OVEN: 198 wreq.wi_val[0] = 0; /* no ... not supported */ 199 wreq.wi_len = 1; 200 break; 201 case WI_RID_ROAMING_MODE: 202 wreq.wi_val[0] = htole16(1); /* enabled ... not supported */ 203 wreq.wi_len = 1; 204 break; 205 case WI_RID_SYSTEM_SCALE: 206 wreq.wi_val[0] = htole16(1); /* low density ... not supp */ 207 wreq.wi_len = 1; 208 break; 209 case WI_RID_PM_ENABLED: 210 wreq.wi_val[0] = 211 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); 212 wreq.wi_len = 1; 213 break; 214 case WI_RID_MAX_SLEEP: 215 wreq.wi_val[0] = htole16(ic->ic_lintval); 216 wreq.wi_len = 1; 217 break; 218 case WI_RID_CUR_BEACON_INT: 219 wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval); 220 wreq.wi_len = 1; 221 break; 222 case WI_RID_WEP_AVAIL: 223 wreq.wi_val[0] = 224 htole16((ic->ic_caps & IEEE80211_C_WEP) ? 1 : 0); 225 wreq.wi_len = 1; 226 break; 227 case WI_RID_CNFAUTHMODE: 228 wreq.wi_val[0] = htole16(1); /* TODO: open system only */ 229 wreq.wi_len = 1; 230 break; 231 case WI_RID_ENCRYPTION: 232 wreq.wi_val[0] = 233 htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0); 234 wreq.wi_len = 1; 235 break; 236 case WI_RID_TX_CRYPT_KEY: 237 wreq.wi_val[0] = htole16(ic->ic_wep_txkey); 238 wreq.wi_len = 1; 239 break; 240 case WI_RID_DEFLT_CRYPT_KEYS: 241 keys = (struct wi_ltv_keys *)&wreq; 242 /* do not show keys to non-root user */ 243 error = suser(curthread); 244 if (error) { 245 memset(keys, 0, sizeof(*keys)); 246 error = 0; 247 break; 248 } 249 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 250 keys->wi_keys[i].wi_keylen = 251 htole16(ic->ic_nw_keys[i].wk_len); 252 memcpy(keys->wi_keys[i].wi_keydat, 253 ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len); 254 } 255 wreq.wi_len = sizeof(*keys) / 2; 256 break; 257 case WI_RID_MAX_DATALEN: 258 wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: frag */ 259 wreq.wi_len = 1; 260 break; 261 case WI_RID_IFACE_STATS: 262 /* XXX: should be implemented in lower drivers */ 263 break; 264 case WI_RID_READ_APS: 265 if (ic->ic_opmode != IEEE80211_M_HOSTAP) { 266 /* 267 * Don't return results until active scan completes. 268 */ 269 if (ic->ic_state == IEEE80211_S_SCAN && 270 (ic->ic_flags & IEEE80211_F_ASCAN)) { 271 error = EINPROGRESS; 272 break; 273 } 274 } 275 i = 0; 276 ap = (void *)((char *)wreq.wi_val + sizeof(i)); 277 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 278 if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1)) 279 break; 280 memset(ap, 0, sizeof(*ap)); 281 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 282 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); 283 ap->namelen = ic->ic_des_esslen; 284 if (ic->ic_des_esslen) 285 memcpy(ap->name, ic->ic_des_essid, 286 ic->ic_des_esslen); 287 } else { 288 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); 289 ap->namelen = ni->ni_esslen; 290 if (ni->ni_esslen) 291 memcpy(ap->name, ni->ni_essid, 292 ni->ni_esslen); 293 } 294 ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); 295 ap->signal = (*ic->ic_node_getrssi)(ic, ni); 296 ap->capinfo = ni->ni_capinfo; 297 ap->interval = ni->ni_intval; 298 rs = &ni->ni_rates; 299 for (j = 0; j < rs->rs_nrates; j++) { 300 if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) { 301 ap->rate = (rs->rs_rates[j] & 302 IEEE80211_RATE_VAL) * 5; /* XXX */ 303 } 304 } 305 i++; 306 ap++; 307 } 308 memcpy(wreq.wi_val, &i, sizeof(i)); 309 wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2; 310 break; 311 case WI_RID_PRISM2: 312 wreq.wi_val[0] = 1; /* XXX lie so SCAN_RES can give rates */ 313 wreq.wi_len = sizeof(u_int16_t) / 2; 314 break; 315 case WI_RID_SCAN_RES: /* compatibility interface */ 316 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 317 ic->ic_state == IEEE80211_S_SCAN && 318 (ic->ic_flags & IEEE80211_F_ASCAN)) { 319 error = EINPROGRESS; 320 break; 321 } 322 /* NB: we use the Prism2 format so we can return rate info */ 323 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; 324 res = (void *)&p2[1]; 325 i = 0; 326 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 327 if ((caddr_t)(res + 1) > (caddr_t)(&wreq + 1)) 328 break; 329 res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); 330 res->wi_noise = 0; 331 res->wi_signal = (*ic->ic_node_getrssi)(ic, ni); 332 IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); 333 res->wi_interval = ni->ni_intval; 334 res->wi_capinfo = ni->ni_capinfo; 335 res->wi_ssid_len = ni->ni_esslen; 336 memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN); 337 /* NB: assumes wi_srates holds <= ni->ni_rates */ 338 memcpy(res->wi_srates, ni->ni_rates.rs_rates, 339 sizeof(res->wi_srates)); 340 if (ni->ni_rates.rs_nrates < 10) 341 res->wi_srates[ni->ni_rates.rs_nrates] = 0; 342 res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate]; 343 res->wi_rsvd = 0; 344 res++, i++; 345 } 346 p2->wi_rsvd = 0; 347 p2->wi_reason = i; 348 wreq.wi_len = (sizeof(*p2) + sizeof(*res) * i) / 2; 349 break; 350 case WI_RID_READ_CACHE: 351 i = 0; 352 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 353 if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1) 354 break; 355 IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr); 356 memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc)); 357 wsc.signal = (*ic->ic_node_getrssi)(ic, ni); 358 wsc.noise = 0; 359 wsc.quality = 0; 360 memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i, 361 &wsc, sizeof(wsc)); 362 i++; 363 } 364 wreq.wi_len = sizeof(wsc) * i / 2; 365 break; 366 case WI_RID_SCAN_APS: 367 error = EINVAL; 368 break; 369 default: 370 error = EINVAL; 371 break; 372 } 373 if (error == 0) { 374 wreq.wi_len++; 375 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 376 } 377 return error; 378 } 379 380 static int 381 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) 382 { 383 #define IEEERATE(_ic,_m,_i) \ 384 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) 385 int i, nrates = ic->ic_sup_rates[mode].rs_nrates; 386 for (i = 0; i < nrates; i++) 387 if (IEEERATE(ic, mode, i) == rate) 388 return i; 389 return -1; 390 #undef IEEERATE 391 } 392 393 /* 394 * Prepare to do a user-initiated scan for AP's. If no 395 * current/default channel is setup or the current channel 396 * is invalid then pick the first available channel from 397 * the active list as the place to start the scan. 398 */ 399 static int 400 ieee80211_setupscan(struct ieee80211com *ic) 401 { 402 u_char *chanlist = ic->ic_chan_active; 403 int i; 404 405 if (ic->ic_ibss_chan == NULL || 406 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 407 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 408 if (isset(chanlist, i)) { 409 ic->ic_ibss_chan = &ic->ic_channels[i]; 410 goto found; 411 } 412 return EINVAL; /* no active channels */ 413 found: 414 ; 415 } 416 if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC || 417 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan))) 418 ic->ic_bss->ni_chan = ic->ic_ibss_chan; 419 /* 420 * XXX don't permit a scan to be started unless we 421 * know the device is ready. For the moment this means 422 * the device is marked up as this is the required to 423 * initialize the hardware. It would be better to permit 424 * scanning prior to being up but that'll require some 425 * changes to the infrastructure. 426 */ 427 return (ic->ic_if.if_flags & IFF_UP) ? 0 : ENETRESET; 428 } 429 430 int 431 ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) 432 { 433 struct ieee80211com *ic = (void *)ifp; 434 int i, j, len, error, rate; 435 struct ifreq *ifr = (struct ifreq *)data; 436 struct wi_ltv_keys *keys; 437 struct wi_req wreq; 438 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)]; 439 440 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 441 if (error) 442 return error; 443 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0; 444 switch (wreq.wi_type) { 445 case WI_RID_SERIALNO: 446 case WI_RID_NODENAME: 447 return EPERM; 448 case WI_RID_CURRENT_SSID: 449 return EPERM; 450 case WI_RID_OWN_SSID: 451 case WI_RID_DESIRED_SSID: 452 if (le16toh(wreq.wi_val[0]) * 2 > len || 453 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) { 454 error = ENOSPC; 455 break; 456 } 457 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); 458 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2; 459 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen); 460 error = ENETRESET; 461 break; 462 case WI_RID_CURRENT_BSSID: 463 return EPERM; 464 case WI_RID_OWN_CHNL: 465 if (len != 2) 466 return EINVAL; 467 i = le16toh(wreq.wi_val[0]); 468 if (i < 0 || 469 i > IEEE80211_CHAN_MAX || 470 isclr(ic->ic_chan_active, i)) 471 return EINVAL; 472 ic->ic_ibss_chan = &ic->ic_channels[i]; 473 if (ic->ic_flags & IEEE80211_F_SIBSS) 474 error = ENETRESET; 475 break; 476 case WI_RID_CURRENT_CHAN: 477 return EPERM; 478 case WI_RID_COMMS_QUALITY: 479 return EPERM; 480 case WI_RID_PROMISC: 481 if (len != 2) 482 return EINVAL; 483 if (ifp->if_flags & IFF_PROMISC) { 484 if (wreq.wi_val[0] == 0) { 485 ifp->if_flags &= ~IFF_PROMISC; 486 error = ENETRESET; 487 } 488 } else { 489 if (wreq.wi_val[0] != 0) { 490 ifp->if_flags |= IFF_PROMISC; 491 error = ENETRESET; 492 } 493 } 494 break; 495 case WI_RID_PORTTYPE: 496 if (len != 2) 497 return EINVAL; 498 switch (le16toh(wreq.wi_val[0])) { 499 case IEEE80211_M_STA: 500 break; 501 case IEEE80211_M_IBSS: 502 if (!(ic->ic_caps & IEEE80211_C_IBSS)) 503 return EINVAL; 504 break; 505 case IEEE80211_M_AHDEMO: 506 if (ic->ic_phytype != IEEE80211_T_DS || 507 !(ic->ic_caps & IEEE80211_C_AHDEMO)) 508 return EINVAL; 509 break; 510 case IEEE80211_M_HOSTAP: 511 if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) 512 return EINVAL; 513 break; 514 default: 515 return EINVAL; 516 } 517 if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { 518 ic->ic_opmode = le16toh(wreq.wi_val[0]); 519 error = ENETRESET; 520 } 521 break; 522 #if 0 523 case WI_RID_MAC_NODE: 524 if (len != IEEE80211_ADDR_LEN) 525 return EINVAL; 526 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val); 527 /* if_init will copy lladdr into ic_myaddr */ 528 error = ENETRESET; 529 break; 530 #endif 531 case WI_RID_TX_RATE: 532 if (len != 2) 533 return EINVAL; 534 if (wreq.wi_val[0] == 0) { 535 /* auto */ 536 ic->ic_fixed_rate = -1; 537 break; 538 } 539 rate = 2 * le16toh(wreq.wi_val[0]); 540 if (ic->ic_curmode == IEEE80211_MODE_AUTO) { 541 /* 542 * In autoselect mode search for the rate. We take 543 * the first instance which may not be right, but we 544 * are limited by the interface. Note that we also 545 * lock the mode to insure the rate is meaningful 546 * when it is used. 547 */ 548 for (j = IEEE80211_MODE_11A; 549 j < IEEE80211_MODE_MAX; j++) { 550 if ((ic->ic_modecaps & (1<<j)) == 0) 551 continue; 552 i = findrate(ic, j, rate); 553 if (i != -1) { 554 /* lock mode too */ 555 ic->ic_curmode = j; 556 goto setrate; 557 } 558 } 559 } else { 560 i = findrate(ic, ic->ic_curmode, rate); 561 if (i != -1) 562 goto setrate; 563 } 564 return EINVAL; 565 setrate: 566 ic->ic_fixed_rate = i; 567 error = ENETRESET; 568 break; 569 case WI_RID_CUR_TX_RATE: 570 return EPERM; 571 case WI_RID_RTS_THRESH: 572 if (len != 2) 573 return EINVAL; 574 if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN) 575 return EINVAL; /* TODO: RTS */ 576 break; 577 case WI_RID_CREATE_IBSS: 578 if (len != 2) 579 return EINVAL; 580 if (wreq.wi_val[0] != 0) { 581 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) 582 return EINVAL; 583 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 584 ic->ic_flags |= IEEE80211_F_IBSSON; 585 if (ic->ic_opmode == IEEE80211_M_IBSS && 586 ic->ic_state == IEEE80211_S_SCAN) 587 error = ENETRESET; 588 } 589 } else { 590 if (ic->ic_flags & IEEE80211_F_IBSSON) { 591 ic->ic_flags &= ~IEEE80211_F_IBSSON; 592 if (ic->ic_flags & IEEE80211_F_SIBSS) { 593 ic->ic_flags &= ~IEEE80211_F_SIBSS; 594 error = ENETRESET; 595 } 596 } 597 } 598 break; 599 case WI_RID_MICROWAVE_OVEN: 600 if (len != 2) 601 return EINVAL; 602 if (wreq.wi_val[0] != 0) 603 return EINVAL; /* not supported */ 604 break; 605 case WI_RID_ROAMING_MODE: 606 if (len != 2) 607 return EINVAL; 608 if (le16toh(wreq.wi_val[0]) != 1) 609 return EINVAL; /* not supported */ 610 break; 611 case WI_RID_SYSTEM_SCALE: 612 if (len != 2) 613 return EINVAL; 614 if (le16toh(wreq.wi_val[0]) != 1) 615 return EINVAL; /* not supported */ 616 break; 617 case WI_RID_PM_ENABLED: 618 if (len != 2) 619 return EINVAL; 620 if (wreq.wi_val[0] != 0) { 621 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 622 return EINVAL; 623 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 624 ic->ic_flags |= IEEE80211_F_PMGTON; 625 error = ENETRESET; 626 } 627 } else { 628 if (ic->ic_flags & IEEE80211_F_PMGTON) { 629 ic->ic_flags &= ~IEEE80211_F_PMGTON; 630 error = ENETRESET; 631 } 632 } 633 break; 634 case WI_RID_MAX_SLEEP: 635 if (len != 2) 636 return EINVAL; 637 ic->ic_lintval = le16toh(wreq.wi_val[0]); 638 if (ic->ic_flags & IEEE80211_F_PMGTON) 639 error = ENETRESET; 640 break; 641 case WI_RID_CUR_BEACON_INT: 642 return EPERM; 643 case WI_RID_WEP_AVAIL: 644 return EPERM; 645 case WI_RID_CNFAUTHMODE: 646 if (len != 2) 647 return EINVAL; 648 if (le16toh(wreq.wi_val[0]) != 1) 649 return EINVAL; /* TODO: shared key auth */ 650 break; 651 case WI_RID_ENCRYPTION: 652 if (len != 2) 653 return EINVAL; 654 if (wreq.wi_val[0] != 0) { 655 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 656 return EINVAL; 657 if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) { 658 ic->ic_flags |= IEEE80211_F_WEPON; 659 error = ENETRESET; 660 } 661 } else { 662 if (ic->ic_flags & IEEE80211_F_WEPON) { 663 ic->ic_flags &= ~IEEE80211_F_WEPON; 664 error = ENETRESET; 665 } 666 } 667 break; 668 case WI_RID_TX_CRYPT_KEY: 669 if (len != 2) 670 return EINVAL; 671 i = le16toh(wreq.wi_val[0]); 672 if (i >= IEEE80211_WEP_NKID) 673 return EINVAL; 674 ic->ic_wep_txkey = i; 675 break; 676 case WI_RID_DEFLT_CRYPT_KEYS: 677 if (len != sizeof(struct wi_ltv_keys)) 678 return EINVAL; 679 keys = (struct wi_ltv_keys *)&wreq; 680 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 681 len = le16toh(keys->wi_keys[i].wi_keylen); 682 if (len != 0 && len < IEEE80211_WEP_KEYLEN) 683 return EINVAL; 684 if (len > sizeof(ic->ic_nw_keys[i].wk_key)) 685 return EINVAL; 686 } 687 memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys)); 688 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 689 len = le16toh(keys->wi_keys[i].wi_keylen); 690 ic->ic_nw_keys[i].wk_len = len; 691 memcpy(ic->ic_nw_keys[i].wk_key, 692 keys->wi_keys[i].wi_keydat, len); 693 } 694 error = ENETRESET; 695 break; 696 case WI_RID_MAX_DATALEN: 697 if (len != 2) 698 return EINVAL; 699 len = le16toh(wreq.wi_val[0]); 700 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) 701 return EINVAL; 702 if (len != IEEE80211_MAX_LEN) 703 return EINVAL; /* TODO: fragment */ 704 ic->ic_fragthreshold = len; 705 error = ENETRESET; 706 break; 707 case WI_RID_IFACE_STATS: 708 error = EPERM; 709 break; 710 case WI_RID_SCAN_REQ: /* XXX wicontrol */ 711 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 712 break; 713 error = ieee80211_setupscan(ic); 714 if (error == 0) 715 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 716 break; 717 case WI_RID_SCAN_APS: 718 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 719 break; 720 len--; /* XXX: tx rate? */ 721 /* FALLTHRU */ 722 case WI_RID_CHANNEL_LIST: 723 memset(chanlist, 0, sizeof(chanlist)); 724 /* 725 * Since channel 0 is not available for DS, channel 1 726 * is assigned to LSB on WaveLAN. 727 */ 728 if (ic->ic_phytype == IEEE80211_T_DS) 729 i = 1; 730 else 731 i = 0; 732 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 733 if ((j / 8) >= len) 734 break; 735 if (isclr((u_int8_t *)wreq.wi_val, j)) 736 continue; 737 if (isclr(ic->ic_chan_active, i)) { 738 if (wreq.wi_type != WI_RID_CHANNEL_LIST) 739 continue; 740 if (isclr(ic->ic_chan_avail, i)) 741 return EPERM; 742 } 743 setbit(chanlist, i); 744 } 745 memcpy(ic->ic_chan_active, chanlist, 746 sizeof(ic->ic_chan_active)); 747 error = ieee80211_setupscan(ic); 748 if (wreq.wi_type == WI_RID_CHANNEL_LIST) { 749 /* NB: ignore error from ieee80211_setupscan */ 750 error = ENETRESET; 751 } else if (error == 0) 752 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 753 break; 754 default: 755 error = EINVAL; 756 break; 757 } 758 return error; 759 } 760 761 int 762 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 763 { 764 struct ieee80211com *ic = (void *)ifp; 765 int error = 0; 766 u_int kid, len; 767 struct ieee80211req *ireq; 768 struct ifreq *ifr; 769 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 770 char tmpssid[IEEE80211_NWID_LEN]; 771 struct ieee80211_channel *chan; 772 struct ifaddr *ifa; /* XXX */ 773 774 switch (cmd) { 775 case SIOCSIFMEDIA: 776 case SIOCGIFMEDIA: 777 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 778 &ic->ic_media, cmd); 779 break; 780 case SIOCG80211: 781 ireq = (struct ieee80211req *) data; 782 switch (ireq->i_type) { 783 case IEEE80211_IOC_SSID: 784 switch (ic->ic_state) { 785 case IEEE80211_S_INIT: 786 case IEEE80211_S_SCAN: 787 ireq->i_len = ic->ic_des_esslen; 788 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len); 789 break; 790 default: 791 ireq->i_len = ic->ic_bss->ni_esslen; 792 memcpy(tmpssid, ic->ic_bss->ni_essid, 793 ireq->i_len); 794 break; 795 } 796 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 797 break; 798 case IEEE80211_IOC_NUMSSIDS: 799 ireq->i_val = 1; 800 break; 801 case IEEE80211_IOC_WEP: 802 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 803 ireq->i_val = IEEE80211_WEP_NOSUP; 804 } else { 805 if (ic->ic_flags & IEEE80211_F_WEPON) { 806 ireq->i_val = 807 IEEE80211_WEP_MIXED; 808 } else { 809 ireq->i_val = 810 IEEE80211_WEP_OFF; 811 } 812 } 813 break; 814 case IEEE80211_IOC_WEPKEY: 815 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 816 error = EINVAL; 817 break; 818 } 819 kid = (u_int) ireq->i_val; 820 if (kid >= IEEE80211_WEP_NKID) { 821 error = EINVAL; 822 break; 823 } 824 len = (u_int) ic->ic_nw_keys[kid].wk_len; 825 /* NB: only root can read WEP keys */ 826 if (suser(curthread) == 0) { 827 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); 828 } else { 829 bzero(tmpkey, len); 830 } 831 ireq->i_len = len; 832 error = copyout(tmpkey, ireq->i_data, len); 833 break; 834 case IEEE80211_IOC_NUMWEPKEYS: 835 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 836 error = EINVAL; 837 else 838 ireq->i_val = IEEE80211_WEP_NKID; 839 break; 840 case IEEE80211_IOC_WEPTXKEY: 841 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 842 error = EINVAL; 843 else 844 ireq->i_val = ic->ic_wep_txkey; 845 break; 846 case IEEE80211_IOC_AUTHMODE: 847 ireq->i_val = IEEE80211_AUTH_OPEN; 848 break; 849 case IEEE80211_IOC_CHANNEL: 850 switch (ic->ic_state) { 851 case IEEE80211_S_INIT: 852 case IEEE80211_S_SCAN: 853 if (ic->ic_opmode == IEEE80211_M_STA) 854 chan = ic->ic_des_chan; 855 else 856 chan = ic->ic_ibss_chan; 857 break; 858 default: 859 chan = ic->ic_bss->ni_chan; 860 break; 861 } 862 ireq->i_val = ieee80211_chan2ieee(ic, chan); 863 break; 864 case IEEE80211_IOC_POWERSAVE: 865 if (ic->ic_flags & IEEE80211_F_PMGTON) 866 ireq->i_val = IEEE80211_POWERSAVE_ON; 867 else 868 ireq->i_val = IEEE80211_POWERSAVE_OFF; 869 break; 870 case IEEE80211_IOC_POWERSAVESLEEP: 871 ireq->i_val = ic->ic_lintval; 872 break; 873 case IEEE80211_IOC_RTSTHRESHOLD: 874 ireq->i_val = ic->ic_rtsthreshold; 875 break; 876 case IEEE80211_IOC_PROTMODE: 877 ireq->i_val = ic->ic_protmode; 878 break; 879 case IEEE80211_IOC_TXPOWER: 880 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 881 error = EINVAL; 882 else 883 ireq->i_val = ic->ic_txpower; 884 break; 885 default: 886 error = EINVAL; 887 break; 888 } 889 break; 890 case SIOCS80211: 891 error = suser(curthread); 892 if (error) 893 break; 894 ireq = (struct ieee80211req *) data; 895 switch (ireq->i_type) { 896 case IEEE80211_IOC_SSID: 897 if (ireq->i_val != 0 || 898 ireq->i_len > IEEE80211_NWID_LEN) { 899 error = EINVAL; 900 break; 901 } 902 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 903 if (error) 904 break; 905 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 906 ic->ic_des_esslen = ireq->i_len; 907 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); 908 error = ENETRESET; 909 break; 910 case IEEE80211_IOC_WEP: 911 /* 912 * These cards only support one mode so 913 * we just turn wep on if what ever is 914 * passed in is not OFF. 915 */ 916 if (ireq->i_val == IEEE80211_WEP_OFF) { 917 ic->ic_flags &= ~IEEE80211_F_WEPON; 918 } else { 919 ic->ic_flags |= IEEE80211_F_WEPON; 920 } 921 error = ENETRESET; 922 break; 923 case IEEE80211_IOC_WEPKEY: 924 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 925 error = EINVAL; 926 break; 927 } 928 kid = (u_int) ireq->i_val; 929 if (kid >= IEEE80211_WEP_NKID) { 930 error = EINVAL; 931 break; 932 } 933 if (ireq->i_len > sizeof(tmpkey)) { 934 error = EINVAL; 935 break; 936 } 937 memset(tmpkey, 0, sizeof(tmpkey)); 938 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 939 if (error) 940 break; 941 memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey, 942 sizeof(tmpkey)); 943 ic->ic_nw_keys[kid].wk_len = ireq->i_len; 944 error = ENETRESET; 945 break; 946 case IEEE80211_IOC_WEPTXKEY: 947 kid = (u_int) ireq->i_val; 948 if (kid >= IEEE80211_WEP_NKID) { 949 error = EINVAL; 950 break; 951 } 952 ic->ic_wep_txkey = kid; 953 error = ENETRESET; 954 break; 955 #if 0 956 case IEEE80211_IOC_AUTHMODE: 957 sc->wi_authmode = ireq->i_val; 958 break; 959 #endif 960 case IEEE80211_IOC_CHANNEL: 961 /* XXX 0xffff overflows 16-bit signed */ 962 if (ireq->i_val == 0 || 963 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 964 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 965 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 966 isclr(ic->ic_chan_active, ireq->i_val)) { 967 error = EINVAL; 968 break; 969 } else 970 ic->ic_ibss_chan = ic->ic_des_chan = 971 &ic->ic_channels[ireq->i_val]; 972 switch (ic->ic_state) { 973 case IEEE80211_S_INIT: 974 case IEEE80211_S_SCAN: 975 error = ENETRESET; 976 break; 977 default: 978 if (ic->ic_opmode == IEEE80211_M_STA) { 979 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 980 ic->ic_bss->ni_chan != ic->ic_des_chan) 981 error = ENETRESET; 982 } else { 983 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 984 error = ENETRESET; 985 } 986 break; 987 } 988 break; 989 case IEEE80211_IOC_POWERSAVE: 990 switch (ireq->i_val) { 991 case IEEE80211_POWERSAVE_OFF: 992 if (ic->ic_flags & IEEE80211_F_PMGTON) { 993 ic->ic_flags &= ~IEEE80211_F_PMGTON; 994 error = ENETRESET; 995 } 996 break; 997 case IEEE80211_POWERSAVE_ON: 998 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 999 error = EINVAL; 1000 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 1001 ic->ic_flags |= IEEE80211_F_PMGTON; 1002 error = ENETRESET; 1003 } 1004 break; 1005 default: 1006 error = EINVAL; 1007 break; 1008 } 1009 break; 1010 case IEEE80211_IOC_POWERSAVESLEEP: 1011 if (ireq->i_val < 0) { 1012 error = EINVAL; 1013 break; 1014 } 1015 ic->ic_lintval = ireq->i_val; 1016 error = ENETRESET; 1017 break; 1018 case IEEE80211_IOC_RTSTHRESHOLD: 1019 if (!(IEEE80211_RTS_MIN < ireq->i_val && 1020 ireq->i_val < IEEE80211_RTS_MAX)) { 1021 error = EINVAL; 1022 break; 1023 } 1024 ic->ic_rtsthreshold = ireq->i_val; 1025 error = ENETRESET; 1026 break; 1027 case IEEE80211_IOC_PROTMODE: 1028 if (ireq->i_val > IEEE80211_PROT_RTSCTS) { 1029 error = EINVAL; 1030 break; 1031 } 1032 ic->ic_protmode = ireq->i_val; 1033 /* NB: if not operating in 11g this can wait */ 1034 if (ic->ic_curmode == IEEE80211_MODE_11G) 1035 error = ENETRESET; 1036 break; 1037 case IEEE80211_IOC_TXPOWER: 1038 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 1039 error = EINVAL; 1040 break; 1041 } 1042 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 1043 ireq->i_val < IEEE80211_TXPOWER_MAX)) { 1044 error = EINVAL; 1045 break; 1046 } 1047 ic->ic_txpower = ireq->i_val; 1048 error = ENETRESET; 1049 break; 1050 default: 1051 error = EINVAL; 1052 break; 1053 } 1054 break; 1055 case SIOCGIFGENERIC: 1056 error = ieee80211_cfgget(ifp, cmd, data); 1057 break; 1058 case SIOCSIFGENERIC: 1059 error = suser(curthread); 1060 if (error) 1061 break; 1062 error = ieee80211_cfgset(ifp, cmd, data); 1063 break; 1064 case SIOCG80211STATS: 1065 ifr = (struct ifreq *)data; 1066 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 1067 break; 1068 case SIOCSIFMTU: 1069 ifr = (struct ifreq *)data; 1070 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 1071 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 1072 error = EINVAL; 1073 else 1074 ifp->if_mtu = ifr->ifr_mtu; 1075 break; 1076 case SIOCSIFADDR: 1077 /* 1078 * XXX Handle this directly so we can supress if_init calls. 1079 * XXX This should be done in ether_ioctl but for the moment 1080 * XXX there are too many other parts of the system that 1081 * XXX set IFF_UP and so supress if_init being called when 1082 * XXX it should be. 1083 */ 1084 ifa = (struct ifaddr *) data; 1085 switch (ifa->ifa_addr->sa_family) { 1086 #ifdef INET 1087 case AF_INET: 1088 if ((ifp->if_flags & IFF_UP) == 0) { 1089 ifp->if_flags |= IFF_UP; 1090 ifp->if_init(ifp->if_softc); 1091 } 1092 arp_ifinit(ifp, ifa); 1093 break; 1094 #endif 1095 #ifdef IPX 1096 /* 1097 * XXX - This code is probably wrong, 1098 * but has been copied many times. 1099 */ 1100 case AF_IPX: { 1101 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 1102 struct arpcom *ac = (struct arpcom *)ifp; 1103 1104 if (ipx_nullhost(*ina)) 1105 ina->x_host = *(union ipx_host *) ac->ac_enaddr; 1106 else 1107 bcopy((caddr_t) ina->x_host.c_host, 1108 (caddr_t) ac->ac_enaddr, 1109 sizeof(ac->ac_enaddr)); 1110 /* fall thru... */ 1111 } 1112 #endif 1113 default: 1114 if ((ifp->if_flags & IFF_UP) == 0) { 1115 ifp->if_flags |= IFF_UP; 1116 ifp->if_init(ifp->if_softc); 1117 } 1118 break; 1119 } 1120 break; 1121 default: 1122 error = ether_ioctl(ifp, cmd, data); 1123 break; 1124 } 1125 return error; 1126 } 1127