1 /* $OpenBSD: ieee80211_ioctl.c,v 1.59 2018/02/19 08:59:52 mpi 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/tree.h> 43 44 #include <net/if.h> 45 #include <net/if_media.h> 46 47 #include <netinet/in.h> 48 #include <netinet/if_ether.h> 49 50 #include <net80211/ieee80211_var.h> 51 #include <net80211/ieee80211_crypto.h> 52 #include <net80211/ieee80211_ioctl.h> 53 54 void ieee80211_node2req(struct ieee80211com *, 55 const struct ieee80211_node *, struct ieee80211_nodereq *); 56 void ieee80211_req2node(struct ieee80211com *, 57 const struct ieee80211_nodereq *, struct ieee80211_node *); 58 59 void 60 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, 61 struct ieee80211_nodereq *nr) 62 { 63 uint8_t rssi; 64 65 memset(nr, 0, sizeof(*nr)); 66 67 strlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname)); 68 69 /* Node address and name information */ 70 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr); 71 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid); 72 nr->nr_nwid_len = ni->ni_esslen; 73 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN); 74 75 /* Channel and rates */ 76 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan); 77 nr->nr_chan_flags = ni->ni_chan->ic_flags; 78 if (ic->ic_curmode != IEEE80211_MODE_11N) 79 nr->nr_chan_flags &= ~IEEE80211_CHAN_HT; 80 nr->nr_nrates = ni->ni_rates.rs_nrates; 81 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE); 82 83 /* Node status information */ 84 rssi = (*ic->ic_node_getrssi)(ic, ni); 85 if (ic->ic_max_rssi) { 86 /* Driver reports RSSI relative to ic_max_rssi. */ 87 nr->nr_rssi = rssi; 88 } else { 89 /* 90 * Driver reports RSSI value in dBm. 91 * Convert from unsigned to signed. 92 * Some drivers report a negative value, some don't. 93 * Reasonable range is -20dBm to -80dBm. 94 */ 95 nr->nr_rssi = (rssi < 128) ? -rssi : rssi; 96 } 97 nr->nr_max_rssi = ic->ic_max_rssi; 98 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp)); 99 nr->nr_intval = ni->ni_intval; 100 nr->nr_capinfo = ni->ni_capinfo; 101 nr->nr_erp = ni->ni_erp; 102 nr->nr_pwrsave = ni->ni_pwrsave; 103 nr->nr_associd = ni->ni_associd; 104 nr->nr_txseq = ni->ni_txseq; 105 nr->nr_rxseq = ni->ni_rxseq; 106 nr->nr_fails = ni->ni_fails; 107 nr->nr_inact = ni->ni_inact; 108 nr->nr_txrate = ni->ni_txrate; 109 nr->nr_state = ni->ni_state; 110 111 /* RSN */ 112 nr->nr_rsnciphers = ni->ni_rsnciphers; 113 nr->nr_rsnakms = 0; 114 nr->nr_rsnprotos = 0; 115 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN) 116 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2; 117 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA) 118 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1; 119 if (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X) 120 nr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X; 121 if (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK) 122 nr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK; 123 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X) 124 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X; 125 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK) 126 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK; 127 128 /* Node flags */ 129 nr->nr_flags = 0; 130 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0) 131 nr->nr_flags |= IEEE80211_NODEREQ_AP; 132 if (ni == ic->ic_bss) 133 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS; 134 135 /* HT */ 136 nr->nr_htcaps = ni->ni_htcaps; 137 memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs)); 138 nr->nr_max_rxrate = ni->ni_max_rxrate; 139 nr->nr_tx_mcs_set = ni->ni_tx_mcs_set; 140 nr->nr_txmcs = ni->ni_txmcs; 141 if (ni->ni_flags & IEEE80211_NODE_HT) 142 nr->nr_flags |= IEEE80211_NODEREQ_HT; 143 } 144 145 void 146 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr, 147 struct ieee80211_node *ni) 148 { 149 /* Node address and name information */ 150 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr); 151 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid); 152 ni->ni_esslen = nr->nr_nwid_len; 153 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN); 154 155 /* Rates */ 156 ni->ni_rates.rs_nrates = nr->nr_nrates; 157 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE); 158 159 /* Node information */ 160 ni->ni_intval = nr->nr_intval; 161 ni->ni_capinfo = nr->nr_capinfo; 162 ni->ni_erp = nr->nr_erp; 163 ni->ni_pwrsave = nr->nr_pwrsave; 164 ni->ni_associd = nr->nr_associd; 165 ni->ni_txseq = nr->nr_txseq; 166 ni->ni_rxseq = nr->nr_rxseq; 167 ni->ni_fails = nr->nr_fails; 168 ni->ni_inact = nr->nr_inact; 169 ni->ni_txrate = nr->nr_txrate; 170 ni->ni_state = nr->nr_state; 171 } 172 173 void 174 ieee80211_disable_wep(struct ieee80211com *ic) 175 { 176 struct ieee80211_key *k; 177 int i; 178 179 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 180 k = &ic->ic_nw_keys[i]; 181 if (k->k_cipher != IEEE80211_CIPHER_NONE) 182 (*ic->ic_delete_key)(ic, NULL, k); 183 explicit_bzero(k, sizeof(*k)); 184 } 185 ic->ic_flags &= ~IEEE80211_F_WEPON; 186 } 187 188 void 189 ieee80211_disable_rsn(struct ieee80211com *ic) 190 { 191 ic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON); 192 explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk)); 193 ic->ic_rsnprotos = 0; 194 ic->ic_rsnakms = 0; 195 ic->ic_rsngroupcipher = 0; 196 ic->ic_rsnciphers = 0; 197 } 198 199 static int 200 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic, 201 const struct ieee80211_nwkey *nwkey) 202 { 203 struct ieee80211_key *k; 204 int error, i; 205 206 if (!(ic->ic_caps & IEEE80211_C_WEP)) 207 return ENODEV; 208 209 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) { 210 if (!(ic->ic_flags & IEEE80211_F_WEPON)) 211 return 0; 212 ic->ic_flags &= ~IEEE80211_F_WEPON; 213 return ENETRESET; 214 } 215 if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID) 216 return EINVAL; 217 218 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 219 if (nwkey->i_key[i].i_keylen == 0 || 220 nwkey->i_key[i].i_keydat == NULL) 221 continue; /* entry not set */ 222 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE) 223 return EINVAL; 224 225 /* map wep key to ieee80211_key */ 226 k = &ic->ic_nw_keys[i]; 227 if (k->k_cipher != IEEE80211_CIPHER_NONE) 228 (*ic->ic_delete_key)(ic, NULL, k); 229 memset(k, 0, sizeof(*k)); 230 if (nwkey->i_key[i].i_keylen <= 5) 231 k->k_cipher = IEEE80211_CIPHER_WEP40; 232 else 233 k->k_cipher = IEEE80211_CIPHER_WEP104; 234 k->k_len = ieee80211_cipher_keylen(k->k_cipher); 235 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; 236 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len); 237 if (error != 0) 238 return error; 239 if ((error = (*ic->ic_set_key)(ic, NULL, k)) != 0) 240 return error; 241 } 242 243 ic->ic_def_txkey = nwkey->i_defkid - 1; 244 ic->ic_flags |= IEEE80211_F_WEPON; 245 if (ic->ic_flags & IEEE80211_F_RSNON) 246 ieee80211_disable_rsn(ic); 247 248 return ENETRESET; 249 } 250 251 static int 252 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic, 253 struct ieee80211_nwkey *nwkey) 254 { 255 int i; 256 257 if (ic->ic_flags & IEEE80211_F_WEPON) 258 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 259 else 260 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 261 262 nwkey->i_defkid = ic->ic_wep_txkey + 1; 263 264 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 265 if (nwkey->i_key[i].i_keydat == NULL) 266 continue; 267 /* do not show any keys to userland */ 268 return EPERM; 269 } 270 return 0; 271 } 272 273 static int 274 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic, 275 const struct ieee80211_wpaparams *wpa) 276 { 277 if (!(ic->ic_caps & IEEE80211_C_RSN)) 278 return ENODEV; 279 280 if (!wpa->i_enabled) { 281 if (!(ic->ic_flags & IEEE80211_F_RSNON)) 282 return 0; 283 ic->ic_flags &= ~IEEE80211_F_RSNON; 284 ic->ic_rsnprotos = 0; 285 ic->ic_rsnakms = 0; 286 ic->ic_rsngroupcipher = 0; 287 ic->ic_rsnciphers = 0; 288 return ENETRESET; 289 } 290 291 ic->ic_rsnprotos = 0; 292 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1) 293 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA; 294 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2) 295 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN; 296 if (ic->ic_rsnprotos == 0) /* set to default (RSN) */ 297 ic->ic_rsnprotos = IEEE80211_PROTO_RSN; 298 299 ic->ic_rsnakms = 0; 300 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK) 301 ic->ic_rsnakms |= IEEE80211_AKM_PSK; 302 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK) 303 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK; 304 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X) 305 ic->ic_rsnakms |= IEEE80211_AKM_8021X; 306 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X) 307 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X; 308 if (ic->ic_rsnakms == 0) /* set to default (PSK) */ 309 ic->ic_rsnakms = IEEE80211_AKM_PSK; 310 311 if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40) 312 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40; 313 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP) 314 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 315 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP) 316 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 317 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104) 318 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104; 319 else { /* set to default */ 320 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 321 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 322 else 323 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 324 } 325 326 ic->ic_rsnciphers = 0; 327 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP) 328 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 329 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP) 330 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP; 331 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP) 332 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP; 333 if (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */ 334 ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP; 335 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 336 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 337 } 338 339 ic->ic_flags |= IEEE80211_F_RSNON; 340 341 return ENETRESET; 342 } 343 344 static int 345 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic, 346 struct ieee80211_wpaparams *wpa) 347 { 348 wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0; 349 350 wpa->i_protos = 0; 351 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 352 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1; 353 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN) 354 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2; 355 356 wpa->i_akms = 0; 357 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 358 wpa->i_akms |= IEEE80211_WPA_AKM_PSK; 359 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK) 360 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK; 361 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 362 wpa->i_akms |= IEEE80211_WPA_AKM_8021X; 363 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X) 364 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X; 365 366 if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40) 367 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40; 368 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP) 369 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP; 370 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP) 371 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP; 372 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104) 373 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104; 374 else 375 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE; 376 377 wpa->i_ciphers = 0; 378 if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP) 379 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP; 380 if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP) 381 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP; 382 if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP) 383 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP; 384 385 return 0; 386 } 387 388 int 389 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 390 { 391 struct ieee80211com *ic = (void *)ifp; 392 struct ifreq *ifr = (struct ifreq *)data; 393 int i, error = 0; 394 struct ieee80211_nwid nwid; 395 struct ieee80211_wpapsk *psk; 396 struct ieee80211_keyavail *ka; 397 struct ieee80211_keyrun *kr; 398 struct ieee80211_power *power; 399 struct ieee80211_bssid *bssid; 400 struct ieee80211chanreq *chanreq; 401 struct ieee80211_channel *chan; 402 struct ieee80211_txpower *txpower; 403 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 405 }; 406 struct ieee80211_nodereq *nr, nrbuf; 407 struct ieee80211_nodereq_all *na; 408 struct ieee80211_node *ni; 409 u_int32_t flags; 410 411 switch (cmd) { 412 case SIOCSIFMEDIA: 413 case SIOCGIFMEDIA: 414 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 415 break; 416 case SIOCS80211NWID: 417 if ((error = suser(curproc)) != 0) 418 break; 419 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 420 break; 421 if (nwid.i_len > IEEE80211_NWID_LEN) { 422 error = EINVAL; 423 break; 424 } 425 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 426 ic->ic_des_esslen = nwid.i_len; 427 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 428 /* disable WPA/WEP */ 429 ieee80211_disable_rsn(ic); 430 ieee80211_disable_wep(ic); 431 error = ENETRESET; 432 break; 433 case SIOCG80211NWID: 434 memset(&nwid, 0, sizeof(nwid)); 435 switch (ic->ic_state) { 436 case IEEE80211_S_INIT: 437 case IEEE80211_S_SCAN: 438 nwid.i_len = ic->ic_des_esslen; 439 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 440 break; 441 default: 442 nwid.i_len = ic->ic_bss->ni_esslen; 443 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 444 break; 445 } 446 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 447 break; 448 case SIOCS80211NWKEY: 449 if ((error = suser(curproc)) != 0) 450 break; 451 error = ieee80211_ioctl_setnwkeys(ic, (void *)data); 452 break; 453 case SIOCG80211NWKEY: 454 error = ieee80211_ioctl_getnwkeys(ic, (void *)data); 455 break; 456 case SIOCS80211WPAPARMS: 457 if ((error = suser(curproc)) != 0) 458 break; 459 error = ieee80211_ioctl_setwpaparms(ic, (void *)data); 460 break; 461 case SIOCG80211WPAPARMS: 462 error = ieee80211_ioctl_getwpaparms(ic, (void *)data); 463 break; 464 case SIOCS80211WPAPSK: 465 if ((error = suser(curproc)) != 0) 466 break; 467 psk = (struct ieee80211_wpapsk *)data; 468 if (psk->i_enabled) { 469 ic->ic_flags |= IEEE80211_F_PSK; 470 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk)); 471 if (ic->ic_flags & IEEE80211_F_WEPON) 472 ieee80211_disable_wep(ic); 473 } else { 474 ic->ic_flags &= ~IEEE80211_F_PSK; 475 memset(ic->ic_psk, 0, sizeof(ic->ic_psk)); 476 } 477 error = ENETRESET; 478 break; 479 case SIOCG80211WPAPSK: 480 psk = (struct ieee80211_wpapsk *)data; 481 if (ic->ic_flags & IEEE80211_F_PSK) { 482 /* do not show any keys to userland */ 483 psk->i_enabled = 2; 484 memset(psk->i_psk, 0, sizeof(psk->i_psk)); 485 break; /* return ok but w/o key */ 486 } else 487 psk->i_enabled = 0; 488 break; 489 case SIOCS80211KEYAVAIL: 490 if ((error = suser(curproc)) != 0) 491 break; 492 ka = (struct ieee80211_keyavail *)data; 493 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X, 494 ka->i_macaddr, ka->i_key, ka->i_lifetime); 495 break; 496 case SIOCS80211KEYRUN: 497 if ((error = suser(curproc)) != 0) 498 break; 499 kr = (struct ieee80211_keyrun *)data; 500 error = ieee80211_keyrun(ic, kr->i_macaddr); 501 if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON)) 502 ieee80211_disable_wep(ic); 503 break; 504 case SIOCS80211POWER: 505 if ((error = suser(curproc)) != 0) 506 break; 507 power = (struct ieee80211_power *)data; 508 ic->ic_lintval = power->i_maxsleep; 509 if (power->i_enabled != 0) { 510 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 511 error = EINVAL; 512 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 513 ic->ic_flags |= IEEE80211_F_PMGTON; 514 error = ENETRESET; 515 } 516 } else { 517 if (ic->ic_flags & IEEE80211_F_PMGTON) { 518 ic->ic_flags &= ~IEEE80211_F_PMGTON; 519 error = ENETRESET; 520 } 521 } 522 break; 523 case SIOCG80211POWER: 524 power = (struct ieee80211_power *)data; 525 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 526 power->i_maxsleep = ic->ic_lintval; 527 break; 528 case SIOCS80211BSSID: 529 if ((error = suser(curproc)) != 0) 530 break; 531 bssid = (struct ieee80211_bssid *)data; 532 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) 533 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 534 else { 535 ic->ic_flags |= IEEE80211_F_DESBSSID; 536 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 537 } 538 #ifndef IEEE80211_STA_ONLY 539 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 540 break; 541 #endif 542 switch (ic->ic_state) { 543 case IEEE80211_S_INIT: 544 case IEEE80211_S_SCAN: 545 error = ENETRESET; 546 break; 547 default: 548 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 549 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, 550 ic->ic_bss->ni_bssid)) 551 error = ENETRESET; 552 break; 553 } 554 break; 555 case SIOCG80211BSSID: 556 bssid = (struct ieee80211_bssid *)data; 557 switch (ic->ic_state) { 558 case IEEE80211_S_INIT: 559 case IEEE80211_S_SCAN: 560 #ifndef IEEE80211_STA_ONLY 561 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 562 IEEE80211_ADDR_COPY(bssid->i_bssid, 563 ic->ic_myaddr); 564 else 565 #endif 566 if (ic->ic_flags & IEEE80211_F_DESBSSID) 567 IEEE80211_ADDR_COPY(bssid->i_bssid, 568 ic->ic_des_bssid); 569 else 570 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 571 break; 572 default: 573 IEEE80211_ADDR_COPY(bssid->i_bssid, 574 ic->ic_bss->ni_bssid); 575 break; 576 } 577 break; 578 case SIOCS80211CHANNEL: 579 if ((error = suser(curproc)) != 0) 580 break; 581 chanreq = (struct ieee80211chanreq *)data; 582 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 583 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 584 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 585 isclr(ic->ic_chan_active, chanreq->i_channel)) { 586 error = EINVAL; 587 break; 588 } else 589 ic->ic_ibss_chan = ic->ic_des_chan = 590 &ic->ic_channels[chanreq->i_channel]; 591 switch (ic->ic_state) { 592 case IEEE80211_S_INIT: 593 case IEEE80211_S_SCAN: 594 error = ENETRESET; 595 break; 596 default: 597 if (ic->ic_opmode == IEEE80211_M_STA) { 598 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 599 ic->ic_bss->ni_chan != ic->ic_des_chan) 600 error = ENETRESET; 601 } else { 602 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 603 error = ENETRESET; 604 } 605 break; 606 } 607 break; 608 case SIOCG80211CHANNEL: 609 chanreq = (struct ieee80211chanreq *)data; 610 switch (ic->ic_state) { 611 case IEEE80211_S_INIT: 612 case IEEE80211_S_SCAN: 613 if (ic->ic_opmode == IEEE80211_M_STA) 614 chan = ic->ic_des_chan; 615 else 616 chan = ic->ic_ibss_chan; 617 break; 618 default: 619 chan = ic->ic_bss->ni_chan; 620 break; 621 } 622 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 623 break; 624 case SIOCG80211ALLCHANS: 625 error = copyout(ic->ic_channels, 626 ((struct ieee80211_chanreq_all *)data)->i_chans, 627 sizeof(ic->ic_channels)); 628 break; 629 #if 0 630 case SIOCG80211ZSTATS: 631 #endif 632 case SIOCG80211STATS: 633 ifr = (struct ifreq *)data; 634 error = copyout(&ic->ic_stats, ifr->ifr_data, 635 sizeof(ic->ic_stats)); 636 #if 0 637 if (cmd == SIOCG80211ZSTATS) 638 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 639 #endif 640 break; 641 case SIOCS80211TXPOWER: 642 if ((error = suser(curproc)) != 0) 643 break; 644 txpower = (struct ieee80211_txpower *)data; 645 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 646 error = EINVAL; 647 break; 648 } 649 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val && 650 txpower->i_val <= IEEE80211_TXPOWER_MAX)) { 651 error = EINVAL; 652 break; 653 } 654 ic->ic_txpower = txpower->i_val; 655 error = ENETRESET; 656 break; 657 case SIOCG80211TXPOWER: 658 txpower = (struct ieee80211_txpower *)data; 659 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 660 error = EINVAL; 661 else 662 txpower->i_val = ic->ic_txpower; 663 break; 664 case SIOCSIFMTU: 665 ifr = (struct ifreq *)data; 666 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 667 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 668 error = EINVAL; 669 else 670 ifp->if_mtu = ifr->ifr_mtu; 671 break; 672 case SIOCS80211SCAN: 673 if ((error = suser(curproc)) != 0) 674 break; 675 #ifndef IEEE80211_STA_ONLY 676 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 677 break; 678 #endif 679 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 680 (IFF_UP | IFF_RUNNING)) { 681 error = ENETDOWN; 682 break; 683 } 684 if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) { 685 if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED) 686 ic->ic_scan_lock |= IEEE80211_SCAN_RESUME; 687 ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST; 688 if (ic->ic_state != IEEE80211_S_SCAN) { 689 ieee80211_clean_cached(ic); 690 if (ic->ic_opmode == IEEE80211_M_STA && 691 ic->ic_state == IEEE80211_S_RUN && 692 IFM_MODE(ic->ic_media.ifm_cur->ifm_media) 693 == IFM_AUTO) { 694 /* 695 * We're already associated to an AP. 696 * Make the scanning loop start off in 697 * auto mode so all supported bands 698 * get scanned. 699 */ 700 ieee80211_setmode(ic, 701 IEEE80211_MODE_AUTO); 702 } 703 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 704 } 705 } 706 /* Let the userspace process wait for completion */ 707 error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan", 708 hz * IEEE80211_SCAN_TIMEOUT); 709 break; 710 case SIOCG80211NODE: 711 nr = (struct ieee80211_nodereq *)data; 712 ni = ieee80211_find_node(ic, nr->nr_macaddr); 713 if (ni == NULL) { 714 error = ENOENT; 715 break; 716 } 717 ieee80211_node2req(ic, ni, nr); 718 break; 719 case SIOCS80211NODE: 720 if ((error = suser(curproc)) != 0) 721 break; 722 #ifndef IEEE80211_STA_ONLY 723 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 724 error = EINVAL; 725 break; 726 } 727 #endif 728 nr = (struct ieee80211_nodereq *)data; 729 730 ni = ieee80211_find_node(ic, nr->nr_macaddr); 731 if (ni == NULL) 732 ni = ieee80211_alloc_node(ic, nr->nr_macaddr); 733 if (ni == NULL) { 734 error = ENOENT; 735 break; 736 } 737 738 if (nr->nr_flags & IEEE80211_NODEREQ_COPY) 739 ieee80211_req2node(ic, nr, ni); 740 break; 741 #ifndef IEEE80211_STA_ONLY 742 case SIOCS80211DELNODE: 743 if ((error = suser(curproc)) != 0) 744 break; 745 nr = (struct ieee80211_nodereq *)data; 746 ni = ieee80211_find_node(ic, nr->nr_macaddr); 747 if (ni == NULL) 748 error = ENOENT; 749 else if (ni == ic->ic_bss) 750 error = EPERM; 751 else { 752 if (ni->ni_state == IEEE80211_STA_COLLECT) 753 break; 754 755 /* Disassociate station. */ 756 if (ni->ni_state == IEEE80211_STA_ASSOC) 757 IEEE80211_SEND_MGMT(ic, ni, 758 IEEE80211_FC0_SUBTYPE_DISASSOC, 759 IEEE80211_REASON_ASSOC_LEAVE); 760 761 /* Deauth station. */ 762 if (ni->ni_state >= IEEE80211_STA_AUTH) 763 IEEE80211_SEND_MGMT(ic, ni, 764 IEEE80211_FC0_SUBTYPE_DEAUTH, 765 IEEE80211_REASON_AUTH_LEAVE); 766 767 ieee80211_node_leave(ic, ni); 768 } 769 break; 770 #endif 771 case SIOCG80211ALLNODES: 772 na = (struct ieee80211_nodereq_all *)data; 773 na->na_nodes = i = 0; 774 ni = RBT_MIN(ieee80211_tree, &ic->ic_tree); 775 while (ni && na->na_size >= 776 i + sizeof(struct ieee80211_nodereq)) { 777 ieee80211_node2req(ic, ni, &nrbuf); 778 error = copyout(&nrbuf, (caddr_t)na->na_node + i, 779 sizeof(struct ieee80211_nodereq)); 780 if (error) 781 break; 782 i += sizeof(struct ieee80211_nodereq); 783 na->na_nodes++; 784 ni = RBT_NEXT(ieee80211_tree, ni); 785 } 786 break; 787 case SIOCG80211FLAGS: 788 flags = ic->ic_flags; 789 #ifndef IEEE80211_STA_ONLY 790 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 791 #endif 792 flags &= ~IEEE80211_F_HOSTAPMASK; 793 ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT; 794 break; 795 case SIOCS80211FLAGS: 796 if ((error = suser(curproc)) != 0) 797 break; 798 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT; 799 if ( 800 #ifndef IEEE80211_STA_ONLY 801 ic->ic_opmode != IEEE80211_M_HOSTAP && 802 #endif 803 (flags & IEEE80211_F_HOSTAPMASK)) { 804 error = EINVAL; 805 break; 806 } 807 ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags; 808 error = ENETRESET; 809 break; 810 case SIOCADDMULTI: 811 case SIOCDELMULTI: 812 error = (cmd == SIOCADDMULTI) ? 813 ether_addmulti(ifr, &ic->ic_ac) : 814 ether_delmulti(ifr, &ic->ic_ac); 815 if (error == ENETRESET) 816 error = 0; 817 break; 818 default: 819 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data); 820 } 821 822 return error; 823 } 824