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