1 /* $OpenBSD: ieee80211_ioctl.c,v 1.81 2022/03/07 08:13:13 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/tree.h> 43 #ifdef __HAIKU__ 44 #include <sys/ucred.h> 45 #endif 46 47 #include <net/if.h> 48 #include <net/if_media.h> 49 50 #include <netinet/in.h> 51 #include <netinet/if_ether.h> 52 53 #include <net80211/ieee80211_var.h> 54 #include <net80211/ieee80211_crypto.h> 55 #include <net80211/ieee80211_ioctl.h> 56 57 void ieee80211_node2req(struct ieee80211com *, 58 const struct ieee80211_node *, struct ieee80211_nodereq *); 59 void ieee80211_req2node(struct ieee80211com *, 60 const struct ieee80211_nodereq *, struct ieee80211_node *); 61 62 void 63 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, 64 struct ieee80211_nodereq *nr) 65 { 66 uint8_t rssi; 67 68 memset(nr, 0, sizeof(*nr)); 69 70 strlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname)); 71 72 /* Node address and name information */ 73 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr); 74 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid); 75 nr->nr_nwid_len = ni->ni_esslen; 76 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN); 77 78 /* Channel and rates */ 79 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan); 80 if (ni->ni_chan != IEEE80211_CHAN_ANYC) 81 nr->nr_chan_flags = ni->ni_chan->ic_flags; 82 if (ic->ic_curmode != IEEE80211_MODE_11N) 83 nr->nr_chan_flags &= ~IEEE80211_CHAN_HT; 84 nr->nr_nrates = ni->ni_rates.rs_nrates; 85 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE); 86 87 /* Node status information */ 88 rssi = (*ic->ic_node_getrssi)(ic, ni); 89 if (ic->ic_max_rssi) { 90 /* Driver reports RSSI relative to ic_max_rssi. */ 91 nr->nr_rssi = rssi; 92 } else { 93 /* 94 * Driver reports RSSI value in dBm. 95 * Convert from unsigned to signed. 96 * Some drivers report a negative value, some don't. 97 * Reasonable range is -20dBm to -80dBm. 98 */ 99 nr->nr_rssi = (rssi < 128) ? -rssi : rssi; 100 } 101 nr->nr_max_rssi = ic->ic_max_rssi; 102 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp)); 103 nr->nr_intval = ni->ni_intval; 104 nr->nr_capinfo = ni->ni_capinfo; 105 nr->nr_erp = ni->ni_erp; 106 nr->nr_pwrsave = ni->ni_pwrsave; 107 nr->nr_associd = ni->ni_associd; 108 nr->nr_txseq = ni->ni_txseq; 109 nr->nr_rxseq = ni->ni_rxseq; 110 nr->nr_fails = ni->ni_fails; 111 nr->nr_assoc_fail = ni->ni_assoc_fail; /* flag values are the same */ 112 nr->nr_inact = ni->ni_inact; 113 nr->nr_txrate = ni->ni_txrate; 114 nr->nr_state = ni->ni_state; 115 116 /* RSN */ 117 nr->nr_rsnciphers = ni->ni_rsnciphers; 118 nr->nr_rsnakms = 0; 119 nr->nr_rsnprotos = 0; 120 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN) 121 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2; 122 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA) 123 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1; 124 if (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X) 125 nr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X; 126 if (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK) 127 nr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK; 128 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X) 129 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X; 130 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK) 131 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK; 132 #ifdef __FreeBSD_version 133 if (ni->ni_rsnie != NULL) 134 memcpy(nr->nr_rsnie, ni->ni_rsnie, 2 + ni->ni_rsnie[1]); 135 else 136 nr->nr_rsnie[1] = 0; 137 #endif 138 139 /* Node flags */ 140 nr->nr_flags = 0; 141 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0) 142 nr->nr_flags |= IEEE80211_NODEREQ_AP; 143 if (ni == ic->ic_bss) 144 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS; 145 146 /* HT */ 147 nr->nr_htcaps = ni->ni_htcaps; 148 memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs)); 149 nr->nr_max_rxrate = ni->ni_max_rxrate; 150 nr->nr_tx_mcs_set = ni->ni_tx_mcs_set; 151 if (ni->ni_flags & IEEE80211_NODE_HT) 152 nr->nr_flags |= IEEE80211_NODEREQ_HT; 153 154 /* HT / VHT */ 155 nr->nr_txmcs = ni->ni_txmcs; 156 157 /* VHT */ 158 nr->nr_vht_ss = ni->ni_vht_ss; 159 if (ni->ni_flags & IEEE80211_NODE_VHT) 160 nr->nr_flags |= IEEE80211_NODEREQ_VHT; 161 } 162 163 void 164 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr, 165 struct ieee80211_node *ni) 166 { 167 /* Node address and name information */ 168 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr); 169 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid); 170 ni->ni_esslen = nr->nr_nwid_len; 171 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN); 172 173 /* Rates */ 174 ni->ni_rates.rs_nrates = nr->nr_nrates; 175 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE); 176 177 /* Node information */ 178 ni->ni_intval = nr->nr_intval; 179 ni->ni_capinfo = nr->nr_capinfo; 180 ni->ni_erp = nr->nr_erp; 181 ni->ni_pwrsave = nr->nr_pwrsave; 182 ni->ni_associd = nr->nr_associd; 183 ni->ni_txseq = nr->nr_txseq; 184 ni->ni_rxseq = nr->nr_rxseq; 185 ni->ni_fails = nr->nr_fails; 186 ni->ni_inact = nr->nr_inact; 187 ni->ni_txrate = nr->nr_txrate; 188 ni->ni_state = nr->nr_state; 189 } 190 191 void 192 ieee80211_disable_wep(struct ieee80211com *ic) 193 { 194 struct ieee80211_key *k; 195 int i; 196 197 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 198 k = &ic->ic_nw_keys[i]; 199 if (k->k_cipher != IEEE80211_CIPHER_NONE) 200 (*ic->ic_delete_key)(ic, NULL, k); 201 explicit_bzero(k, sizeof(*k)); 202 } 203 ic->ic_flags &= ~IEEE80211_F_WEPON; 204 } 205 206 void 207 ieee80211_disable_rsn(struct ieee80211com *ic) 208 { 209 ic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON); 210 explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk)); 211 ic->ic_rsnprotos = 0; 212 ic->ic_rsnakms = 0; 213 ic->ic_rsngroupcipher = 0; 214 ic->ic_rsnciphers = 0; 215 } 216 217 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setnwkeys() */ 218 static int 219 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic, 220 const struct ieee80211_nwkey *nwkey) 221 { 222 struct ieee80211_key *k; 223 int error, i; 224 225 if (!(ic->ic_caps & IEEE80211_C_WEP)) 226 return ENODEV; 227 228 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) { 229 if (!(ic->ic_flags & IEEE80211_F_WEPON)) 230 return 0; 231 ic->ic_flags &= ~IEEE80211_F_WEPON; 232 return ENETRESET; 233 } 234 if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID) 235 return EINVAL; 236 237 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 238 if (nwkey->i_key[i].i_keylen == 0 || 239 nwkey->i_key[i].i_keydat == NULL) 240 continue; /* entry not set */ 241 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE) 242 return EINVAL; 243 244 /* map wep key to ieee80211_key */ 245 k = &ic->ic_nw_keys[i]; 246 if (k->k_cipher != IEEE80211_CIPHER_NONE) 247 (*ic->ic_delete_key)(ic, NULL, k); 248 memset(k, 0, sizeof(*k)); 249 if (nwkey->i_key[i].i_keylen <= 5) 250 k->k_cipher = IEEE80211_CIPHER_WEP40; 251 else 252 k->k_cipher = IEEE80211_CIPHER_WEP104; 253 k->k_len = ieee80211_cipher_keylen(k->k_cipher); 254 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; 255 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len); 256 if (error != 0) 257 return error; 258 error = (*ic->ic_set_key)(ic, NULL, k); 259 switch (error) { 260 case 0: 261 case EBUSY: 262 break; 263 default: 264 return error; 265 } 266 } 267 268 ic->ic_def_txkey = nwkey->i_defkid - 1; 269 ic->ic_flags |= IEEE80211_F_WEPON; 270 if (ic->ic_flags & IEEE80211_F_RSNON) 271 ieee80211_disable_rsn(ic); 272 273 return ENETRESET; 274 } 275 276 static int 277 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic, 278 struct ieee80211_nwkey *nwkey) 279 { 280 int i; 281 282 if (ic->ic_flags & IEEE80211_F_WEPON) 283 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 284 else 285 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 286 287 nwkey->i_defkid = ic->ic_wep_txkey + 1; 288 289 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 290 if (nwkey->i_key[i].i_keydat == NULL) 291 continue; 292 /* do not show any keys to userland */ 293 return EPERM; 294 } 295 return 0; 296 } 297 298 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setwpaparms() */ 299 static int 300 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic, 301 const struct ieee80211_wpaparams *wpa) 302 { 303 if (!(ic->ic_caps & IEEE80211_C_RSN)) 304 return ENODEV; 305 306 if (!wpa->i_enabled) { 307 if (!(ic->ic_flags & IEEE80211_F_RSNON)) 308 return 0; 309 ic->ic_flags &= ~IEEE80211_F_RSNON; 310 ic->ic_rsnprotos = 0; 311 ic->ic_rsnakms = 0; 312 ic->ic_rsngroupcipher = 0; 313 ic->ic_rsnciphers = 0; 314 return ENETRESET; 315 } 316 317 ic->ic_rsnprotos = 0; 318 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1) 319 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA; 320 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2) 321 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN; 322 if (ic->ic_rsnprotos == 0) /* set to default (RSN) */ 323 ic->ic_rsnprotos = IEEE80211_PROTO_RSN; 324 325 ic->ic_rsnakms = 0; 326 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK) 327 ic->ic_rsnakms |= IEEE80211_AKM_PSK; 328 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK) 329 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK; 330 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X) 331 ic->ic_rsnakms |= IEEE80211_AKM_8021X; 332 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X) 333 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X; 334 if (ic->ic_rsnakms == 0) /* set to default (PSK) */ 335 ic->ic_rsnakms = IEEE80211_AKM_PSK; 336 337 if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40) 338 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40; 339 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP) 340 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 341 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP) 342 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 343 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104) 344 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104; 345 else { /* set to default */ 346 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 347 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 348 else 349 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 350 } 351 352 ic->ic_rsnciphers = 0; 353 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP) 354 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 355 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP) 356 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP; 357 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP) 358 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP; 359 if (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */ 360 ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP; 361 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 362 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 363 } 364 365 ic->ic_flags |= IEEE80211_F_RSNON; 366 367 return ENETRESET; 368 } 369 370 static int 371 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic, 372 struct ieee80211_wpaparams *wpa) 373 { 374 wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0; 375 376 wpa->i_protos = 0; 377 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 378 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1; 379 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN) 380 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2; 381 382 wpa->i_akms = 0; 383 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 384 wpa->i_akms |= IEEE80211_WPA_AKM_PSK; 385 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK) 386 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK; 387 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 388 wpa->i_akms |= IEEE80211_WPA_AKM_8021X; 389 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X) 390 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X; 391 392 if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40) 393 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40; 394 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP) 395 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP; 396 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP) 397 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP; 398 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104) 399 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104; 400 else 401 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE; 402 403 wpa->i_ciphers = 0; 404 if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP) 405 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP; 406 if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP) 407 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP; 408 if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP) 409 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP; 410 411 return 0; 412 } 413 414 static void 415 ieee80211_ess_getwpaparms(struct ieee80211_ess *ess, 416 struct ieee80211_wpaparams *wpa) 417 { 418 wpa->i_enabled = (ess->flags & IEEE80211_F_RSNON) ? 1 : 0; 419 420 wpa->i_protos = 0; 421 if (ess->rsnprotos & IEEE80211_PROTO_WPA) 422 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1; 423 if (ess->rsnprotos & IEEE80211_PROTO_RSN) 424 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2; 425 426 wpa->i_akms = 0; 427 if (ess->rsnakms & IEEE80211_AKM_PSK) 428 wpa->i_akms |= IEEE80211_WPA_AKM_PSK; 429 if (ess->rsnakms & IEEE80211_AKM_SHA256_PSK) 430 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK; 431 if (ess->rsnakms & IEEE80211_AKM_8021X) 432 wpa->i_akms |= IEEE80211_WPA_AKM_8021X; 433 if (ess->rsnakms & IEEE80211_AKM_SHA256_8021X) 434 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X; 435 436 if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP40) 437 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40; 438 else if (ess->rsngroupcipher == IEEE80211_CIPHER_TKIP) 439 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP; 440 else if (ess->rsngroupcipher == IEEE80211_CIPHER_CCMP) 441 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP; 442 else if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP104) 443 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104; 444 else 445 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE; 446 447 wpa->i_ciphers = 0; 448 if (ess->rsnciphers & IEEE80211_CIPHER_TKIP) 449 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP; 450 if (ess->rsnciphers & IEEE80211_CIPHER_CCMP) 451 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP; 452 if (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP) 453 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP; 454 } 455 456 int 457 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 458 { 459 struct ieee80211com *ic = (void *)ifp; 460 struct ifreq *ifr = (struct ifreq *)data; 461 int i, error = 0; 462 size_t len; 463 struct ieee80211_nwid nwid; 464 struct ieee80211_join join; 465 struct ieee80211_joinreq_all *ja; 466 struct ieee80211_ess *ess; 467 struct ieee80211_wpapsk *psk; 468 struct ieee80211_keyavail *ka; 469 struct ieee80211_keyrun *kr; 470 struct ieee80211_power *power; 471 struct ieee80211_bssid *bssid; 472 struct ieee80211chanreq *chanreq; 473 struct ieee80211_channel *chan; 474 struct ieee80211_txpower *txpower; 475 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 477 }; 478 struct ieee80211_nodereq *nr, nrbuf; 479 struct ieee80211_nodereq_all *na; 480 struct ieee80211_node *ni; 481 struct ieee80211_chaninfo chaninfo; 482 struct ieee80211_chanreq_all *allchans; 483 u_int32_t flags; 484 485 switch (cmd) { 486 case SIOCSIFMEDIA: 487 case SIOCGIFMEDIA: 488 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 489 break; 490 case SIOCS80211NWID: 491 if ((error = suser(curproc)) != 0) 492 break; 493 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 494 break; 495 if (nwid.i_len > IEEE80211_NWID_LEN) { 496 error = EINVAL; 497 break; 498 } 499 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 500 ic->ic_des_esslen = nwid.i_len; 501 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 502 if (ic->ic_des_esslen > 0) { 503 /* 'nwid' disables auto-join magic */ 504 ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN; 505 } else if (!TAILQ_EMPTY(&ic->ic_ess)) { 506 /* '-nwid' re-enables auto-join */ 507 ic->ic_flags |= IEEE80211_F_AUTO_JOIN; 508 } 509 /* disable WPA/WEP */ 510 ieee80211_disable_rsn(ic); 511 ieee80211_disable_wep(ic); 512 error = ENETRESET; 513 break; 514 case SIOCG80211NWID: 515 memset(&nwid, 0, sizeof(nwid)); 516 switch (ic->ic_state) { 517 case IEEE80211_S_INIT: 518 case IEEE80211_S_SCAN: 519 nwid.i_len = ic->ic_des_esslen; 520 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 521 break; 522 default: 523 nwid.i_len = ic->ic_bss->ni_esslen; 524 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 525 break; 526 } 527 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 528 break; 529 case SIOCS80211JOIN: 530 if ((error = suser(curproc)) != 0) 531 break; 532 if (ic->ic_opmode != IEEE80211_M_STA) 533 break; 534 if ((error = copyin(ifr->ifr_data, &join, sizeof(join))) != 0) 535 break; 536 if (join.i_len > IEEE80211_NWID_LEN) { 537 error = EINVAL; 538 break; 539 } 540 if (join.i_flags & IEEE80211_JOIN_DEL) { 541 int update_ic = 0; 542 if (ic->ic_des_esslen == join.i_len && 543 memcmp(join.i_nwid, ic->ic_des_essid, 544 join.i_len) == 0) 545 update_ic = 1; 546 if (join.i_flags & IEEE80211_JOIN_DEL_ALL && 547 ieee80211_get_ess(ic, ic->ic_des_essid, 548 ic->ic_des_esslen) != NULL) 549 update_ic = 1; 550 ieee80211_del_ess(ic, join.i_nwid, join.i_len, 551 join.i_flags & IEEE80211_JOIN_DEL_ALL ? 1 : 0); 552 if (update_ic == 1) { 553 /* Unconfigure this essid */ 554 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 555 ic->ic_des_esslen = 0; 556 /* disable WPA/WEP */ 557 ieee80211_disable_rsn(ic); 558 ieee80211_disable_wep(ic); 559 error = ENETRESET; 560 } 561 } else { 562 if (ic->ic_des_esslen == join.i_len && 563 memcmp(join.i_nwid, ic->ic_des_essid, 564 join.i_len) == 0) { 565 struct ieee80211_node *ni; 566 567 ieee80211_deselect_ess(ic); 568 ni = ieee80211_find_node(ic, 569 ic->ic_bss->ni_bssid); 570 if (ni != NULL) 571 ieee80211_free_node(ic, ni); 572 error = ENETRESET; 573 } 574 /* save nwid for auto-join */ 575 if (ieee80211_add_ess(ic, &join) == 0) 576 ic->ic_flags |= IEEE80211_F_AUTO_JOIN; 577 } 578 break; 579 case SIOCG80211JOIN: 580 memset(&join, 0, sizeof(join)); 581 error = ENOENT; 582 if (ic->ic_bss == NULL) 583 break; 584 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) { 585 if (memcmp(ess->essid, ic->ic_bss->ni_essid, 586 IEEE80211_NWID_LEN) == 0) { 587 join.i_len = ic->ic_bss->ni_esslen; 588 memcpy(join.i_nwid, ic->ic_bss->ni_essid, 589 join.i_len); 590 if (ic->ic_flags & IEEE80211_F_AUTO_JOIN) 591 join.i_flags = IEEE80211_JOIN_FOUND; 592 error = copyout(&join, ifr->ifr_data, 593 sizeof(join)); 594 break; 595 } 596 } 597 break; 598 case SIOCG80211JOINALL: 599 ja = (struct ieee80211_joinreq_all *)data; 600 ja->ja_nodes = len = 0; 601 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) { 602 if (len + sizeof(ja->ja_node[0]) >= ja->ja_size) { 603 error = E2BIG; 604 break; 605 } 606 memset(&join, 0, sizeof(join)); 607 join.i_len = ess->esslen; 608 memcpy(&join.i_nwid, ess->essid, join.i_len); 609 if (ess->flags & IEEE80211_F_RSNON) 610 join.i_flags |= IEEE80211_JOIN_WPA; 611 if (ess->flags & IEEE80211_F_PSK) 612 join.i_flags |= IEEE80211_JOIN_WPAPSK; 613 if (ess->flags & IEEE80211_JOIN_8021X) 614 join.i_flags |= IEEE80211_JOIN_8021X; 615 if (ess->flags & IEEE80211_F_WEPON) 616 join.i_flags |= IEEE80211_JOIN_NWKEY; 617 if (ess->flags & IEEE80211_JOIN_ANY) 618 join.i_flags |= IEEE80211_JOIN_ANY; 619 ieee80211_ess_getwpaparms(ess, &join.i_wpaparams); 620 error = copyout(&join, &ja->ja_node[ja->ja_nodes], 621 sizeof(ja->ja_node[0])); 622 if (error) 623 break; 624 len += sizeof(join); 625 ja->ja_nodes++; 626 } 627 break; 628 case SIOCS80211NWKEY: 629 if ((error = suser(curproc)) != 0) 630 break; 631 error = ieee80211_ioctl_setnwkeys(ic, (void *)data); 632 break; 633 case SIOCG80211NWKEY: 634 error = ieee80211_ioctl_getnwkeys(ic, (void *)data); 635 break; 636 case SIOCS80211WPAPARMS: 637 if ((error = suser(curproc)) != 0) 638 break; 639 error = ieee80211_ioctl_setwpaparms(ic, (void *)data); 640 break; 641 case SIOCG80211WPAPARMS: 642 error = ieee80211_ioctl_getwpaparms(ic, (void *)data); 643 break; 644 case SIOCS80211WPAPSK: 645 if ((error = suser(curproc)) != 0) 646 break; 647 psk = (struct ieee80211_wpapsk *)data; 648 if (psk->i_enabled) { 649 ic->ic_flags |= IEEE80211_F_PSK; 650 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk)); 651 if (ic->ic_flags & IEEE80211_F_WEPON) 652 ieee80211_disable_wep(ic); 653 } else { 654 ic->ic_flags &= ~IEEE80211_F_PSK; 655 memset(ic->ic_psk, 0, sizeof(ic->ic_psk)); 656 } 657 error = ENETRESET; 658 break; 659 case SIOCG80211WPAPSK: 660 psk = (struct ieee80211_wpapsk *)data; 661 if (ic->ic_flags & IEEE80211_F_PSK) { 662 /* do not show any keys to userland */ 663 psk->i_enabled = 2; 664 memset(psk->i_psk, 0, sizeof(psk->i_psk)); 665 break; /* return ok but w/o key */ 666 } else 667 psk->i_enabled = 0; 668 break; 669 case SIOCS80211KEYAVAIL: 670 if ((error = suser(curproc)) != 0) 671 break; 672 ka = (struct ieee80211_keyavail *)data; 673 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X, 674 ka->i_macaddr, ka->i_key, ka->i_lifetime); 675 break; 676 case SIOCS80211KEYRUN: 677 if ((error = suser(curproc)) != 0) 678 break; 679 kr = (struct ieee80211_keyrun *)data; 680 error = ieee80211_keyrun(ic, kr->i_macaddr); 681 if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON)) 682 ieee80211_disable_wep(ic); 683 break; 684 case SIOCS80211POWER: 685 if ((error = suser(curproc)) != 0) 686 break; 687 power = (struct ieee80211_power *)data; 688 ic->ic_lintval = power->i_maxsleep; 689 if (power->i_enabled != 0) { 690 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 691 error = EINVAL; 692 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 693 ic->ic_flags |= IEEE80211_F_PMGTON; 694 error = ENETRESET; 695 } 696 } else { 697 if (ic->ic_flags & IEEE80211_F_PMGTON) { 698 ic->ic_flags &= ~IEEE80211_F_PMGTON; 699 error = ENETRESET; 700 } 701 } 702 break; 703 case SIOCG80211POWER: 704 power = (struct ieee80211_power *)data; 705 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 706 power->i_maxsleep = ic->ic_lintval; 707 break; 708 case SIOCS80211BSSID: 709 if ((error = suser(curproc)) != 0) 710 break; 711 bssid = (struct ieee80211_bssid *)data; 712 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) 713 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 714 else { 715 ic->ic_flags |= IEEE80211_F_DESBSSID; 716 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 717 } 718 #ifndef IEEE80211_STA_ONLY 719 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 720 break; 721 #endif 722 switch (ic->ic_state) { 723 case IEEE80211_S_INIT: 724 case IEEE80211_S_SCAN: 725 error = ENETRESET; 726 break; 727 default: 728 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 729 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, 730 ic->ic_bss->ni_bssid)) 731 error = ENETRESET; 732 break; 733 } 734 break; 735 case SIOCG80211BSSID: 736 bssid = (struct ieee80211_bssid *)data; 737 switch (ic->ic_state) { 738 case IEEE80211_S_INIT: 739 case IEEE80211_S_SCAN: 740 #ifndef IEEE80211_STA_ONLY 741 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 742 IEEE80211_ADDR_COPY(bssid->i_bssid, 743 ic->ic_myaddr); 744 else 745 #endif 746 if (ic->ic_flags & IEEE80211_F_DESBSSID) 747 IEEE80211_ADDR_COPY(bssid->i_bssid, 748 ic->ic_des_bssid); 749 else 750 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 751 break; 752 default: 753 IEEE80211_ADDR_COPY(bssid->i_bssid, 754 ic->ic_bss->ni_bssid); 755 break; 756 } 757 break; 758 case SIOCS80211CHANNEL: 759 if ((error = suser(curproc)) != 0) 760 break; 761 chanreq = (struct ieee80211chanreq *)data; 762 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 763 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 764 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 765 isclr(ic->ic_chan_active, chanreq->i_channel)) { 766 error = EINVAL; 767 break; 768 } else 769 ic->ic_ibss_chan = ic->ic_des_chan = 770 &ic->ic_channels[chanreq->i_channel]; 771 switch (ic->ic_state) { 772 case IEEE80211_S_INIT: 773 case IEEE80211_S_SCAN: 774 error = ENETRESET; 775 break; 776 default: 777 if (ic->ic_opmode == IEEE80211_M_STA) { 778 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 779 ic->ic_bss->ni_chan != ic->ic_des_chan) 780 error = ENETRESET; 781 } else { 782 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 783 error = ENETRESET; 784 } 785 break; 786 } 787 break; 788 case SIOCG80211CHANNEL: 789 chanreq = (struct ieee80211chanreq *)data; 790 switch (ic->ic_state) { 791 case IEEE80211_S_INIT: 792 case IEEE80211_S_SCAN: 793 if (ic->ic_opmode == IEEE80211_M_STA) 794 chan = ic->ic_des_chan; 795 else 796 chan = ic->ic_ibss_chan; 797 break; 798 default: 799 chan = ic->ic_bss->ni_chan; 800 break; 801 } 802 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 803 break; 804 case SIOCG80211ALLCHANS: 805 allchans = (struct ieee80211_chanreq_all *)data; 806 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 807 chan = &ic->ic_channels[i]; 808 chaninfo.ic_freq = chan->ic_freq; 809 chaninfo.ic_flags = 0; 810 if (chan->ic_flags & IEEE80211_CHAN_2GHZ) 811 chaninfo.ic_flags |= IEEE80211_CHANINFO_2GHZ; 812 if (chan->ic_flags & IEEE80211_CHAN_5GHZ) 813 chaninfo.ic_flags |= IEEE80211_CHANINFO_5GHZ; 814 if (chan->ic_flags & IEEE80211_CHAN_PASSIVE) 815 chaninfo.ic_flags |= IEEE80211_CHANINFO_PASSIVE; 816 error = copyout(&chaninfo, &allchans->i_chans[i], 817 sizeof(chaninfo)); 818 if (error) 819 break; 820 } 821 break; 822 #if 0 823 case SIOCG80211ZSTATS: 824 #endif 825 case SIOCG80211STATS: 826 ifr = (struct ifreq *)data; 827 error = copyout(&ic->ic_stats, ifr->ifr_data, 828 sizeof(ic->ic_stats)); 829 #if 0 830 if (cmd == SIOCG80211ZSTATS) 831 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 832 #endif 833 break; 834 case SIOCS80211TXPOWER: 835 if ((error = suser(curproc)) != 0) 836 break; 837 txpower = (struct ieee80211_txpower *)data; 838 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 839 error = EINVAL; 840 break; 841 } 842 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val && 843 txpower->i_val <= IEEE80211_TXPOWER_MAX)) { 844 error = EINVAL; 845 break; 846 } 847 ic->ic_txpower = txpower->i_val; 848 error = ENETRESET; 849 break; 850 case SIOCG80211TXPOWER: 851 txpower = (struct ieee80211_txpower *)data; 852 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 853 error = EINVAL; 854 else 855 txpower->i_val = ic->ic_txpower; 856 break; 857 case SIOCSIFMTU: 858 ifr = (struct ifreq *)data; 859 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 860 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 861 error = EINVAL; 862 else 863 ifp->if_mtu = ifr->ifr_mtu; 864 break; 865 case SIOCS80211SCAN: 866 /* Disabled. SIOCG80211ALLNODES is enough. */ 867 break; 868 case SIOCG80211NODE: 869 nr = (struct ieee80211_nodereq *)data; 870 if (ic->ic_bss && 871 IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr)) 872 ni = ic->ic_bss; 873 else 874 ni = ieee80211_find_node(ic, nr->nr_macaddr); 875 if (ni == NULL) { 876 error = ENOENT; 877 break; 878 } 879 ieee80211_node2req(ic, ni, nr); 880 break; 881 case SIOCS80211NODE: 882 if ((error = suser(curproc)) != 0) 883 break; 884 #ifndef IEEE80211_STA_ONLY 885 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 886 error = EINVAL; 887 break; 888 } 889 #endif 890 nr = (struct ieee80211_nodereq *)data; 891 892 ni = ieee80211_find_node(ic, nr->nr_macaddr); 893 if (ni == NULL) 894 ni = ieee80211_alloc_node(ic, nr->nr_macaddr); 895 if (ni == NULL) { 896 error = ENOENT; 897 break; 898 } 899 900 if (nr->nr_flags & IEEE80211_NODEREQ_COPY) 901 ieee80211_req2node(ic, nr, ni); 902 break; 903 #ifndef IEEE80211_STA_ONLY 904 case SIOCS80211DELNODE: 905 if ((error = suser(curproc)) != 0) 906 break; 907 nr = (struct ieee80211_nodereq *)data; 908 ni = ieee80211_find_node(ic, nr->nr_macaddr); 909 if (ni == NULL) 910 error = ENOENT; 911 else if (ni == ic->ic_bss) 912 error = EPERM; 913 else { 914 if (ni->ni_state == IEEE80211_STA_COLLECT) 915 break; 916 917 /* Disassociate station. */ 918 if (ni->ni_state == IEEE80211_STA_ASSOC) 919 IEEE80211_SEND_MGMT(ic, ni, 920 IEEE80211_FC0_SUBTYPE_DISASSOC, 921 IEEE80211_REASON_ASSOC_LEAVE); 922 923 /* Deauth station. */ 924 if (ni->ni_state >= IEEE80211_STA_AUTH) 925 IEEE80211_SEND_MGMT(ic, ni, 926 IEEE80211_FC0_SUBTYPE_DEAUTH, 927 IEEE80211_REASON_AUTH_LEAVE); 928 929 ieee80211_node_leave(ic, ni); 930 } 931 break; 932 #endif 933 case SIOCG80211ALLNODES: 934 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 935 (IFF_UP | IFF_RUNNING)) { 936 error = ENETDOWN; 937 break; 938 } 939 940 na = (struct ieee80211_nodereq_all *)data; 941 na->na_nodes = i = 0; 942 ni = RBT_MIN(ieee80211_tree, &ic->ic_tree); 943 #ifdef __FreeBSD_version 944 while (ni && na->na_startnode) { 945 ni = RBT_NEXT(ieee80211_tree, ni); 946 na->na_startnode--; 947 } 948 #endif 949 while (ni && na->na_size >= 950 i + sizeof(struct ieee80211_nodereq)) { 951 ieee80211_node2req(ic, ni, &nrbuf); 952 error = copyout(&nrbuf, (caddr_t)na->na_node + i, 953 sizeof(struct ieee80211_nodereq)); 954 if (error) 955 break; 956 i += sizeof(struct ieee80211_nodereq); 957 na->na_nodes++; 958 ni = RBT_NEXT(ieee80211_tree, ni); 959 } 960 if (suser(curproc) == 0) 961 ieee80211_begin_bgscan(ifp); 962 break; 963 case SIOCG80211FLAGS: 964 flags = ic->ic_userflags; 965 #ifndef IEEE80211_STA_ONLY 966 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 967 #endif 968 flags &= ~IEEE80211_F_HOSTAPMASK; 969 ifr->ifr_flags = flags; 970 break; 971 case SIOCS80211FLAGS: 972 if ((error = suser(curproc)) != 0) 973 break; 974 flags = ifr->ifr_flags; 975 if ( 976 #ifndef IEEE80211_STA_ONLY 977 ic->ic_opmode != IEEE80211_M_HOSTAP && 978 #endif 979 (flags & IEEE80211_F_HOSTAPMASK)) { 980 error = EINVAL; 981 break; 982 } 983 ic->ic_userflags = flags; 984 error = ENETRESET; 985 break; 986 #ifndef __HAIKU__ 987 case SIOCADDMULTI: 988 case SIOCDELMULTI: 989 error = (cmd == SIOCADDMULTI) ? 990 ether_addmulti(ifr, &ic->ic_ac) : 991 ether_delmulti(ifr, &ic->ic_ac); 992 if (error == ENETRESET) 993 error = 0; 994 break; 995 #endif 996 default: 997 #ifdef __FreeBSD_version 998 error = ether_ioctl(ifp, cmd, data); 999 #else 1000 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data); 1001 #endif 1002 } 1003 1004 return error; 1005 } 1006