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