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