1 /* $OpenBSD: ieee80211_ioctl.c,v 1.34 2010/09/29 20:00:51 kettenis Exp $ */ 2 /* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */ 3 4 /*- 5 * Copyright (c) 2001 Atsushi Onoe 6 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * IEEE 802.11 ioctl support 34 */ 35 36 #include <sys/param.h> 37 #include <sys/kernel.h> 38 #include <sys/socket.h> 39 #include <sys/sockio.h> 40 #include <sys/systm.h> 41 #include <sys/endian.h> 42 #include <sys/proc.h> 43 #include <sys/tree.h> 44 45 #include <net/if.h> 46 #include <net/if_arp.h> 47 #include <net/if_media.h> 48 49 #ifdef INET 50 #include <netinet/in.h> 51 #include <netinet/if_ether.h> 52 #endif 53 54 #include <net80211/ieee80211_var.h> 55 #include <net80211/ieee80211_crypto.h> 56 #include <net80211/ieee80211_ioctl.h> 57 58 void ieee80211_node2req(struct ieee80211com *, 59 const struct ieee80211_node *, struct ieee80211_nodereq *); 60 void ieee80211_req2node(struct ieee80211com *, 61 const struct ieee80211_nodereq *, struct ieee80211_node *); 62 63 void 64 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, 65 struct ieee80211_nodereq *nr) 66 { 67 /* Node address and name information */ 68 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr); 69 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid); 70 nr->nr_nwid_len = ni->ni_esslen; 71 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN); 72 73 /* Channel and rates */ 74 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan); 75 nr->nr_chan_flags = ni->ni_chan->ic_flags; 76 nr->nr_nrates = ni->ni_rates.rs_nrates; 77 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE); 78 79 /* Node status information */ 80 nr->nr_rssi = (*ic->ic_node_getrssi)(ic, ni); 81 nr->nr_max_rssi = ic->ic_max_rssi; 82 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp)); 83 nr->nr_intval = ni->ni_intval; 84 nr->nr_capinfo = ni->ni_capinfo; 85 nr->nr_erp = ni->ni_erp; 86 nr->nr_pwrsave = ni->ni_pwrsave; 87 nr->nr_associd = ni->ni_associd; 88 nr->nr_txseq = ni->ni_txseq; 89 nr->nr_rxseq = ni->ni_rxseq; 90 nr->nr_fails = ni->ni_fails; 91 nr->nr_inact = ni->ni_inact; 92 nr->nr_txrate = ni->ni_txrate; 93 nr->nr_state = ni->ni_state; 94 /* XXX RSN */ 95 96 /* Node flags */ 97 nr->nr_flags = 0; 98 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0) 99 nr->nr_flags |= IEEE80211_NODEREQ_AP; 100 if (ni == ic->ic_bss) 101 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS; 102 } 103 104 void 105 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr, 106 struct ieee80211_node *ni) 107 { 108 /* Node address and name information */ 109 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr); 110 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid); 111 ni->ni_esslen = nr->nr_nwid_len; 112 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN); 113 114 /* Rates */ 115 ni->ni_rates.rs_nrates = nr->nr_nrates; 116 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE); 117 118 /* Node information */ 119 ni->ni_intval = nr->nr_intval; 120 ni->ni_capinfo = nr->nr_capinfo; 121 ni->ni_erp = nr->nr_erp; 122 ni->ni_pwrsave = nr->nr_pwrsave; 123 ni->ni_associd = nr->nr_associd; 124 ni->ni_txseq = nr->nr_txseq; 125 ni->ni_rxseq = nr->nr_rxseq; 126 ni->ni_fails = nr->nr_fails; 127 ni->ni_inact = nr->nr_inact; 128 ni->ni_txrate = nr->nr_txrate; 129 ni->ni_state = nr->nr_state; 130 } 131 132 static int 133 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic, 134 const struct ieee80211_nwkey *nwkey) 135 { 136 struct ieee80211_key *k; 137 int error, i; 138 139 if (!(ic->ic_caps & IEEE80211_C_WEP)) 140 return ENODEV; 141 142 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) { 143 if (!(ic->ic_flags & IEEE80211_F_WEPON)) 144 return 0; 145 ic->ic_flags &= ~IEEE80211_F_WEPON; 146 return ENETRESET; 147 } 148 if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID) 149 return EINVAL; 150 151 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 152 if (nwkey->i_key[i].i_keylen == 0 || 153 nwkey->i_key[i].i_keydat == NULL) 154 continue; /* entry not set */ 155 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE) 156 return EINVAL; 157 158 /* map wep key to ieee80211_key */ 159 k = &ic->ic_nw_keys[i]; 160 if (k->k_cipher != IEEE80211_CIPHER_NONE) 161 (*ic->ic_delete_key)(ic, NULL, k); 162 memset(k, 0, sizeof(*k)); 163 if (nwkey->i_key[i].i_keylen <= 5) 164 k->k_cipher = IEEE80211_CIPHER_WEP40; 165 else 166 k->k_cipher = IEEE80211_CIPHER_WEP104; 167 k->k_len = ieee80211_cipher_keylen(k->k_cipher); 168 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; 169 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len); 170 if (error != 0) 171 return error; 172 if ((error = (*ic->ic_set_key)(ic, NULL, k)) != 0) 173 return error; 174 } 175 176 ic->ic_def_txkey = nwkey->i_defkid - 1; 177 ic->ic_flags |= IEEE80211_F_WEPON; 178 179 return ENETRESET; 180 } 181 182 static int 183 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic, 184 struct ieee80211_nwkey *nwkey) 185 { 186 struct ieee80211_key *k; 187 int error, i; 188 189 if (ic->ic_flags & IEEE80211_F_WEPON) 190 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 191 else 192 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 193 194 nwkey->i_defkid = ic->ic_wep_txkey + 1; 195 196 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 197 if (nwkey->i_key[i].i_keydat == NULL) 198 continue; 199 /* do not show any keys to non-root user */ 200 if ((error = suser(curproc, 0)) != 0) 201 return error; 202 k = &ic->ic_nw_keys[i]; 203 if (k->k_cipher != IEEE80211_CIPHER_WEP40 && 204 k->k_cipher != IEEE80211_CIPHER_WEP104) 205 nwkey->i_key[i].i_keylen = 0; 206 else 207 nwkey->i_key[i].i_keylen = k->k_len; 208 error = copyout(k->k_key, nwkey->i_key[i].i_keydat, 209 nwkey->i_key[i].i_keylen); 210 if (error != 0) 211 return error; 212 } 213 return 0; 214 } 215 216 static int 217 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic, 218 const struct ieee80211_wpaparams *wpa) 219 { 220 if (!(ic->ic_caps & IEEE80211_C_RSN)) 221 return ENODEV; 222 223 if (!wpa->i_enabled) { 224 if (!(ic->ic_flags & IEEE80211_F_RSNON)) 225 return 0; 226 ic->ic_flags &= ~IEEE80211_F_RSNON; 227 return ENETRESET; 228 } 229 230 ic->ic_rsnprotos = 0; 231 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1) 232 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA; 233 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2) 234 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN; 235 if (ic->ic_rsnprotos == 0) /* set to default (WPA+RSN) */ 236 ic->ic_rsnprotos = IEEE80211_PROTO_WPA | IEEE80211_PROTO_RSN; 237 238 ic->ic_rsnakms = 0; 239 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK) 240 ic->ic_rsnakms |= IEEE80211_AKM_PSK; 241 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK) 242 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK; 243 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X) 244 ic->ic_rsnakms |= IEEE80211_AKM_8021X; 245 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X) 246 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X; 247 if (ic->ic_rsnakms == 0) /* set to default (PSK) */ 248 ic->ic_rsnakms = IEEE80211_AKM_PSK; 249 250 if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40) 251 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40; 252 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP) 253 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 254 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP) 255 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 256 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104) 257 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104; 258 else { /* set to default */ 259 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 260 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 261 else 262 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 263 } 264 265 ic->ic_rsnciphers = 0; 266 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP) 267 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 268 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP) 269 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP; 270 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP) 271 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP; 272 if (ic->ic_rsnciphers == 0) /* set to default (TKIP+CCMP) */ 273 ic->ic_rsnciphers = IEEE80211_CIPHER_TKIP | 274 IEEE80211_CIPHER_CCMP; 275 276 ic->ic_flags |= IEEE80211_F_RSNON; 277 278 return ENETRESET; 279 } 280 281 static int 282 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic, 283 struct ieee80211_wpaparams *wpa) 284 { 285 wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0; 286 287 wpa->i_protos = 0; 288 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 289 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1; 290 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN) 291 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2; 292 293 wpa->i_akms = 0; 294 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 295 wpa->i_akms |= IEEE80211_WPA_AKM_PSK; 296 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK) 297 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK; 298 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 299 wpa->i_akms |= IEEE80211_WPA_AKM_8021X; 300 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X) 301 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X; 302 303 if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40) 304 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40; 305 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP) 306 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP; 307 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP) 308 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP; 309 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104) 310 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104; 311 else 312 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE; 313 314 wpa->i_ciphers = 0; 315 if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP) 316 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP; 317 if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP) 318 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP; 319 if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP) 320 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP; 321 322 return 0; 323 } 324 325 int 326 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 327 { 328 struct ieee80211com *ic = (void *)ifp; 329 struct ifreq *ifr = (struct ifreq *)data; 330 int i, error = 0; 331 struct ieee80211_nwid nwid; 332 struct ieee80211_wpapsk *psk; 333 struct ieee80211_wmmparams *wmm; 334 struct ieee80211_keyavail *ka; 335 struct ieee80211_keyrun *kr; 336 struct ieee80211_power *power; 337 struct ieee80211_bssid *bssid; 338 struct ieee80211chanreq *chanreq; 339 struct ieee80211_channel *chan; 340 struct ieee80211_txpower *txpower; 341 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 343 }; 344 struct ieee80211_nodereq *nr, nrbuf; 345 struct ieee80211_nodereq_all *na; 346 struct ieee80211_node *ni; 347 u_int32_t flags; 348 349 switch (cmd) { 350 case SIOCSIFMEDIA: 351 case SIOCGIFMEDIA: 352 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 353 break; 354 case SIOCS80211NWID: 355 if ((error = suser(curproc, 0)) != 0) 356 break; 357 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 358 break; 359 if (nwid.i_len > IEEE80211_NWID_LEN) { 360 error = EINVAL; 361 break; 362 } 363 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 364 ic->ic_des_esslen = nwid.i_len; 365 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 366 error = ENETRESET; 367 break; 368 case SIOCG80211NWID: 369 memset(&nwid, 0, sizeof(nwid)); 370 switch (ic->ic_state) { 371 case IEEE80211_S_INIT: 372 case IEEE80211_S_SCAN: 373 nwid.i_len = ic->ic_des_esslen; 374 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 375 break; 376 default: 377 nwid.i_len = ic->ic_bss->ni_esslen; 378 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 379 break; 380 } 381 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 382 break; 383 case SIOCS80211NWKEY: 384 if ((error = suser(curproc, 0)) != 0) 385 break; 386 error = ieee80211_ioctl_setnwkeys(ic, (void *)data); 387 break; 388 case SIOCG80211NWKEY: 389 error = ieee80211_ioctl_getnwkeys(ic, (void *)data); 390 break; 391 case SIOCS80211WMMPARMS: 392 if ((error = suser(curproc, 0)) != 0) 393 break; 394 if (!(ic->ic_flags & IEEE80211_C_QOS)) { 395 error = ENODEV; 396 break; 397 } 398 wmm = (struct ieee80211_wmmparams *)data; 399 if (wmm->i_enabled) 400 ic->ic_flags |= IEEE80211_F_QOS; 401 else 402 ic->ic_flags &= ~IEEE80211_F_QOS; 403 error = ENETRESET; 404 break; 405 case SIOCG80211WMMPARMS: 406 wmm = (struct ieee80211_wmmparams *)data; 407 wmm->i_enabled = (ic->ic_flags & IEEE80211_F_QOS) ? 1 : 0; 408 break; 409 case SIOCS80211WPAPARMS: 410 if ((error = suser(curproc, 0)) != 0) 411 break; 412 error = ieee80211_ioctl_setwpaparms(ic, (void *)data); 413 break; 414 case SIOCG80211WPAPARMS: 415 error = ieee80211_ioctl_getwpaparms(ic, (void *)data); 416 break; 417 case SIOCS80211WPAPSK: 418 if ((error = suser(curproc, 0)) != 0) 419 break; 420 psk = (struct ieee80211_wpapsk *)data; 421 if (psk->i_enabled) { 422 ic->ic_flags |= IEEE80211_F_PSK; 423 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk)); 424 } else { 425 ic->ic_flags &= ~IEEE80211_F_PSK; 426 memset(ic->ic_psk, 0, sizeof(ic->ic_psk)); 427 } 428 error = ENETRESET; 429 break; 430 case SIOCG80211WPAPSK: 431 psk = (struct ieee80211_wpapsk *)data; 432 if (ic->ic_flags & IEEE80211_F_PSK) { 433 psk->i_enabled = 1; 434 /* do not show any keys to non-root user */ 435 if (suser(curproc, 0) != 0) { 436 psk->i_enabled = 2; 437 memset(psk->i_psk, 0, sizeof(psk->i_psk)); 438 break; /* return ok but w/o key */ 439 } 440 memcpy(psk->i_psk, ic->ic_psk, sizeof(psk->i_psk)); 441 } else 442 psk->i_enabled = 0; 443 break; 444 case SIOCS80211KEYAVAIL: 445 if ((error = suser(curproc, 0)) != 0) 446 break; 447 ka = (struct ieee80211_keyavail *)data; 448 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X, 449 ka->i_macaddr, ka->i_key, ka->i_lifetime); 450 break; 451 case SIOCS80211KEYRUN: 452 if ((error = suser(curproc, 0)) != 0) 453 break; 454 kr = (struct ieee80211_keyrun *)data; 455 error = ieee80211_keyrun(ic, kr->i_macaddr); 456 break; 457 case SIOCS80211POWER: 458 if ((error = suser(curproc, 0)) != 0) 459 break; 460 power = (struct ieee80211_power *)data; 461 ic->ic_lintval = power->i_maxsleep; 462 if (power->i_enabled != 0) { 463 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 464 error = EINVAL; 465 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 466 ic->ic_flags |= IEEE80211_F_PMGTON; 467 error = ENETRESET; 468 } 469 } else { 470 if (ic->ic_flags & IEEE80211_F_PMGTON) { 471 ic->ic_flags &= ~IEEE80211_F_PMGTON; 472 error = ENETRESET; 473 } 474 } 475 break; 476 case SIOCG80211POWER: 477 power = (struct ieee80211_power *)data; 478 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 479 power->i_maxsleep = ic->ic_lintval; 480 break; 481 case SIOCS80211BSSID: 482 if ((error = suser(curproc, 0)) != 0) 483 break; 484 bssid = (struct ieee80211_bssid *)data; 485 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) 486 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 487 else { 488 ic->ic_flags |= IEEE80211_F_DESBSSID; 489 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 490 } 491 #ifndef IEEE80211_STA_ONLY 492 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 493 break; 494 #endif 495 switch (ic->ic_state) { 496 case IEEE80211_S_INIT: 497 case IEEE80211_S_SCAN: 498 error = ENETRESET; 499 break; 500 default: 501 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 502 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, 503 ic->ic_bss->ni_bssid)) 504 error = ENETRESET; 505 break; 506 } 507 break; 508 case SIOCG80211BSSID: 509 bssid = (struct ieee80211_bssid *)data; 510 switch (ic->ic_state) { 511 case IEEE80211_S_INIT: 512 case IEEE80211_S_SCAN: 513 #ifndef IEEE80211_STA_ONLY 514 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 515 IEEE80211_ADDR_COPY(bssid->i_bssid, 516 ic->ic_myaddr); 517 else 518 #endif 519 if (ic->ic_flags & IEEE80211_F_DESBSSID) 520 IEEE80211_ADDR_COPY(bssid->i_bssid, 521 ic->ic_des_bssid); 522 else 523 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 524 break; 525 default: 526 IEEE80211_ADDR_COPY(bssid->i_bssid, 527 ic->ic_bss->ni_bssid); 528 break; 529 } 530 break; 531 case SIOCS80211CHANNEL: 532 if ((error = suser(curproc, 0)) != 0) 533 break; 534 chanreq = (struct ieee80211chanreq *)data; 535 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 536 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 537 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 538 isclr(ic->ic_chan_active, chanreq->i_channel)) { 539 error = EINVAL; 540 break; 541 } else 542 ic->ic_ibss_chan = ic->ic_des_chan = 543 &ic->ic_channels[chanreq->i_channel]; 544 switch (ic->ic_state) { 545 case IEEE80211_S_INIT: 546 case IEEE80211_S_SCAN: 547 error = ENETRESET; 548 break; 549 default: 550 if (ic->ic_opmode == IEEE80211_M_STA) { 551 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 552 ic->ic_bss->ni_chan != ic->ic_des_chan) 553 error = ENETRESET; 554 } else { 555 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 556 error = ENETRESET; 557 } 558 break; 559 } 560 break; 561 case SIOCG80211CHANNEL: 562 chanreq = (struct ieee80211chanreq *)data; 563 switch (ic->ic_state) { 564 case IEEE80211_S_INIT: 565 case IEEE80211_S_SCAN: 566 if (ic->ic_opmode == IEEE80211_M_STA) 567 chan = ic->ic_des_chan; 568 else 569 chan = ic->ic_ibss_chan; 570 break; 571 default: 572 chan = ic->ic_bss->ni_chan; 573 break; 574 } 575 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 576 break; 577 case SIOCG80211ALLCHANS: 578 error = copyout(ic->ic_channels, 579 ((struct ieee80211_chanreq_all *)data)->i_chans, 580 sizeof(ic->ic_channels)); 581 break; 582 #if 0 583 case SIOCG80211ZSTATS: 584 #endif 585 case SIOCG80211STATS: 586 ifr = (struct ifreq *)data; 587 error = copyout(&ic->ic_stats, ifr->ifr_data, 588 sizeof(ic->ic_stats)); 589 #if 0 590 if (cmd == SIOCG80211ZSTATS) 591 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 592 #endif 593 break; 594 case SIOCS80211TXPOWER: 595 if ((error = suser(curproc, 0)) != 0) 596 break; 597 txpower = (struct ieee80211_txpower *)data; 598 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 599 error = EINVAL; 600 break; 601 } 602 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val && 603 txpower->i_val <= IEEE80211_TXPOWER_MAX)) { 604 error = EINVAL; 605 break; 606 } 607 ic->ic_txpower = txpower->i_val; 608 error = ENETRESET; 609 break; 610 case SIOCG80211TXPOWER: 611 txpower = (struct ieee80211_txpower *)data; 612 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 613 error = EINVAL; 614 else 615 txpower->i_val = ic->ic_txpower; 616 break; 617 case SIOCSIFMTU: 618 ifr = (struct ifreq *)data; 619 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 620 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 621 error = EINVAL; 622 else 623 ifp->if_mtu = ifr->ifr_mtu; 624 break; 625 case SIOCS80211SCAN: 626 if ((error = suser(curproc, 0)) != 0) 627 break; 628 #ifndef IEEE80211_STA_ONLY 629 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 630 break; 631 #endif 632 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 633 (IFF_UP | IFF_RUNNING)) { 634 error = ENETDOWN; 635 break; 636 } 637 if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) { 638 if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED) 639 ic->ic_scan_lock |= IEEE80211_SCAN_RESUME; 640 ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST; 641 if (ic->ic_state != IEEE80211_S_SCAN) 642 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 643 } 644 /* Let the userspace process wait for completion */ 645 error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan", 646 hz * IEEE80211_SCAN_TIMEOUT); 647 break; 648 case SIOCG80211NODE: 649 nr = (struct ieee80211_nodereq *)data; 650 ni = ieee80211_find_node(ic, nr->nr_macaddr); 651 if (ni == NULL) { 652 error = ENOENT; 653 break; 654 } 655 ieee80211_node2req(ic, ni, nr); 656 break; 657 case SIOCS80211NODE: 658 if ((error = suser(curproc, 0)) != 0) 659 break; 660 #ifndef IEEE80211_STA_ONLY 661 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 662 error = EINVAL; 663 break; 664 } 665 #endif 666 nr = (struct ieee80211_nodereq *)data; 667 668 ni = ieee80211_find_node(ic, nr->nr_macaddr); 669 if (ni == NULL) 670 ni = ieee80211_alloc_node(ic, nr->nr_macaddr); 671 if (ni == NULL) { 672 error = ENOENT; 673 break; 674 } 675 676 if (nr->nr_flags & IEEE80211_NODEREQ_COPY) 677 ieee80211_req2node(ic, nr, ni); 678 break; 679 #ifndef IEEE80211_STA_ONLY 680 case SIOCS80211DELNODE: 681 if ((error = suser(curproc, 0)) != 0) 682 break; 683 nr = (struct ieee80211_nodereq *)data; 684 ni = ieee80211_find_node(ic, nr->nr_macaddr); 685 if (ni == NULL) 686 error = ENOENT; 687 else if (ni == ic->ic_bss) 688 error = EPERM; 689 else { 690 if (ni->ni_state == IEEE80211_STA_COLLECT) 691 break; 692 693 /* Disassociate station. */ 694 if (ni->ni_state == IEEE80211_STA_ASSOC) 695 IEEE80211_SEND_MGMT(ic, ni, 696 IEEE80211_FC0_SUBTYPE_DISASSOC, 697 IEEE80211_REASON_ASSOC_LEAVE); 698 699 /* Deauth station. */ 700 if (ni->ni_state >= IEEE80211_STA_AUTH) 701 IEEE80211_SEND_MGMT(ic, ni, 702 IEEE80211_FC0_SUBTYPE_DEAUTH, 703 IEEE80211_REASON_AUTH_LEAVE); 704 705 ieee80211_node_leave(ic, ni); 706 } 707 break; 708 #endif 709 case SIOCG80211ALLNODES: 710 na = (struct ieee80211_nodereq_all *)data; 711 na->na_nodes = i = 0; 712 ni = RB_MIN(ieee80211_tree, &ic->ic_tree); 713 while (ni && na->na_size >= 714 i + sizeof(struct ieee80211_nodereq)) { 715 ieee80211_node2req(ic, ni, &nrbuf); 716 error = copyout(&nrbuf, (caddr_t)na->na_node + i, 717 sizeof(struct ieee80211_nodereq)); 718 if (error) 719 break; 720 i += sizeof(struct ieee80211_nodereq); 721 na->na_nodes++; 722 ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); 723 } 724 break; 725 case SIOCG80211FLAGS: 726 flags = ic->ic_flags; 727 #ifndef IEEE80211_STA_ONLY 728 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 729 #endif 730 flags &= ~IEEE80211_F_HOSTAPMASK; 731 ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT; 732 break; 733 case SIOCS80211FLAGS: 734 if ((error = suser(curproc, 0)) != 0) 735 break; 736 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT; 737 if ( 738 #ifndef IEEE80211_STA_ONLY 739 ic->ic_opmode != IEEE80211_M_HOSTAP && 740 #endif 741 (flags & IEEE80211_F_HOSTAPMASK)) { 742 error = EINVAL; 743 break; 744 } 745 ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags; 746 error = ENETRESET; 747 break; 748 default: 749 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data); 750 } 751 752 return error; 753 } 754