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