1 /* $OpenBSD: ieee80211_ioctl.c,v 1.80 2020/11/19 20:03:33 krw 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 u_int32_t flags; 473 474 switch (cmd) { 475 case SIOCSIFMEDIA: 476 case SIOCGIFMEDIA: 477 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 478 break; 479 case SIOCS80211NWID: 480 if ((error = suser(curproc)) != 0) 481 break; 482 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 483 break; 484 if (nwid.i_len > IEEE80211_NWID_LEN) { 485 error = EINVAL; 486 break; 487 } 488 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 489 ic->ic_des_esslen = nwid.i_len; 490 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 491 if (ic->ic_des_esslen > 0) { 492 /* 'nwid' disables auto-join magic */ 493 ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN; 494 } else if (!TAILQ_EMPTY(&ic->ic_ess)) { 495 /* '-nwid' re-enables auto-join */ 496 ic->ic_flags |= IEEE80211_F_AUTO_JOIN; 497 } 498 /* disable WPA/WEP */ 499 ieee80211_disable_rsn(ic); 500 ieee80211_disable_wep(ic); 501 error = ENETRESET; 502 break; 503 case SIOCG80211NWID: 504 memset(&nwid, 0, sizeof(nwid)); 505 switch (ic->ic_state) { 506 case IEEE80211_S_INIT: 507 case IEEE80211_S_SCAN: 508 nwid.i_len = ic->ic_des_esslen; 509 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 510 break; 511 default: 512 nwid.i_len = ic->ic_bss->ni_esslen; 513 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 514 break; 515 } 516 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 517 break; 518 case SIOCS80211JOIN: 519 if ((error = suser(curproc)) != 0) 520 break; 521 if (ic->ic_opmode != IEEE80211_M_STA) 522 break; 523 if ((error = copyin(ifr->ifr_data, &join, sizeof(join))) != 0) 524 break; 525 if (join.i_len > IEEE80211_NWID_LEN) { 526 error = EINVAL; 527 break; 528 } 529 if (join.i_flags & IEEE80211_JOIN_DEL) { 530 int update_ic = 0; 531 if (ic->ic_des_esslen == join.i_len && 532 memcmp(join.i_nwid, ic->ic_des_essid, 533 join.i_len) == 0) 534 update_ic = 1; 535 if (join.i_flags & IEEE80211_JOIN_DEL_ALL && 536 ieee80211_get_ess(ic, ic->ic_des_essid, 537 ic->ic_des_esslen) != NULL) 538 update_ic = 1; 539 ieee80211_del_ess(ic, join.i_nwid, join.i_len, 540 join.i_flags & IEEE80211_JOIN_DEL_ALL ? 1 : 0); 541 if (update_ic == 1) { 542 /* Unconfigure this essid */ 543 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 544 ic->ic_des_esslen = 0; 545 /* disable WPA/WEP */ 546 ieee80211_disable_rsn(ic); 547 ieee80211_disable_wep(ic); 548 error = ENETRESET; 549 } 550 } else { 551 if (ic->ic_des_esslen == join.i_len && 552 memcmp(join.i_nwid, ic->ic_des_essid, 553 join.i_len) == 0) { 554 struct ieee80211_node *ni; 555 556 ieee80211_deselect_ess(ic); 557 ni = ieee80211_find_node(ic, 558 ic->ic_bss->ni_bssid); 559 if (ni != NULL) 560 ieee80211_free_node(ic, ni); 561 error = ENETRESET; 562 } 563 /* save nwid for auto-join */ 564 if (ieee80211_add_ess(ic, &join) == 0) 565 ic->ic_flags |= IEEE80211_F_AUTO_JOIN; 566 } 567 break; 568 case SIOCG80211JOIN: 569 memset(&join, 0, sizeof(join)); 570 error = ENOENT; 571 if (ic->ic_bss == NULL) 572 break; 573 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) { 574 if (memcmp(ess->essid, ic->ic_bss->ni_essid, 575 IEEE80211_NWID_LEN) == 0) { 576 join.i_len = ic->ic_bss->ni_esslen; 577 memcpy(join.i_nwid, ic->ic_bss->ni_essid, 578 join.i_len); 579 if (ic->ic_flags & IEEE80211_F_AUTO_JOIN) 580 join.i_flags = IEEE80211_JOIN_FOUND; 581 error = copyout(&join, ifr->ifr_data, 582 sizeof(join)); 583 break; 584 } 585 } 586 break; 587 case SIOCG80211JOINALL: 588 ja = (struct ieee80211_joinreq_all *)data; 589 ja->ja_nodes = len = 0; 590 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) { 591 if (len + sizeof(ja->ja_node[0]) >= ja->ja_size) { 592 error = E2BIG; 593 break; 594 } 595 memset(&join, 0, sizeof(join)); 596 join.i_len = ess->esslen; 597 memcpy(&join.i_nwid, ess->essid, join.i_len); 598 if (ess->flags & IEEE80211_F_RSNON) 599 join.i_flags |= IEEE80211_JOIN_WPA; 600 if (ess->flags & IEEE80211_F_PSK) 601 join.i_flags |= IEEE80211_JOIN_WPAPSK; 602 if (ess->flags & IEEE80211_JOIN_8021X) 603 join.i_flags |= IEEE80211_JOIN_8021X; 604 if (ess->flags & IEEE80211_F_WEPON) 605 join.i_flags |= IEEE80211_JOIN_NWKEY; 606 if (ess->flags & IEEE80211_JOIN_ANY) 607 join.i_flags |= IEEE80211_JOIN_ANY; 608 ieee80211_ess_getwpaparms(ess, &join.i_wpaparams); 609 error = copyout(&join, &ja->ja_node[ja->ja_nodes], 610 sizeof(ja->ja_node[0])); 611 if (error) 612 break; 613 len += sizeof(join); 614 ja->ja_nodes++; 615 } 616 break; 617 case SIOCS80211NWKEY: 618 if ((error = suser(curproc)) != 0) 619 break; 620 error = ieee80211_ioctl_setnwkeys(ic, (void *)data); 621 break; 622 case SIOCG80211NWKEY: 623 error = ieee80211_ioctl_getnwkeys(ic, (void *)data); 624 break; 625 case SIOCS80211WPAPARMS: 626 if ((error = suser(curproc)) != 0) 627 break; 628 error = ieee80211_ioctl_setwpaparms(ic, (void *)data); 629 break; 630 case SIOCG80211WPAPARMS: 631 error = ieee80211_ioctl_getwpaparms(ic, (void *)data); 632 break; 633 case SIOCS80211WPAPSK: 634 if ((error = suser(curproc)) != 0) 635 break; 636 psk = (struct ieee80211_wpapsk *)data; 637 if (psk->i_enabled) { 638 ic->ic_flags |= IEEE80211_F_PSK; 639 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk)); 640 if (ic->ic_flags & IEEE80211_F_WEPON) 641 ieee80211_disable_wep(ic); 642 } else { 643 ic->ic_flags &= ~IEEE80211_F_PSK; 644 memset(ic->ic_psk, 0, sizeof(ic->ic_psk)); 645 } 646 error = ENETRESET; 647 break; 648 case SIOCG80211WPAPSK: 649 psk = (struct ieee80211_wpapsk *)data; 650 if (ic->ic_flags & IEEE80211_F_PSK) { 651 /* do not show any keys to userland */ 652 psk->i_enabled = 2; 653 memset(psk->i_psk, 0, sizeof(psk->i_psk)); 654 break; /* return ok but w/o key */ 655 } else 656 psk->i_enabled = 0; 657 break; 658 case SIOCS80211KEYAVAIL: 659 if ((error = suser(curproc)) != 0) 660 break; 661 ka = (struct ieee80211_keyavail *)data; 662 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X, 663 ka->i_macaddr, ka->i_key, ka->i_lifetime); 664 break; 665 case SIOCS80211KEYRUN: 666 if ((error = suser(curproc)) != 0) 667 break; 668 kr = (struct ieee80211_keyrun *)data; 669 error = ieee80211_keyrun(ic, kr->i_macaddr); 670 if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON)) 671 ieee80211_disable_wep(ic); 672 break; 673 case SIOCS80211POWER: 674 if ((error = suser(curproc)) != 0) 675 break; 676 power = (struct ieee80211_power *)data; 677 ic->ic_lintval = power->i_maxsleep; 678 if (power->i_enabled != 0) { 679 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 680 error = EINVAL; 681 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 682 ic->ic_flags |= IEEE80211_F_PMGTON; 683 error = ENETRESET; 684 } 685 } else { 686 if (ic->ic_flags & IEEE80211_F_PMGTON) { 687 ic->ic_flags &= ~IEEE80211_F_PMGTON; 688 error = ENETRESET; 689 } 690 } 691 break; 692 case SIOCG80211POWER: 693 power = (struct ieee80211_power *)data; 694 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 695 power->i_maxsleep = ic->ic_lintval; 696 break; 697 case SIOCS80211BSSID: 698 if ((error = suser(curproc)) != 0) 699 break; 700 bssid = (struct ieee80211_bssid *)data; 701 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) 702 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 703 else { 704 ic->ic_flags |= IEEE80211_F_DESBSSID; 705 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 706 } 707 #ifndef IEEE80211_STA_ONLY 708 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 709 break; 710 #endif 711 switch (ic->ic_state) { 712 case IEEE80211_S_INIT: 713 case IEEE80211_S_SCAN: 714 error = ENETRESET; 715 break; 716 default: 717 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 718 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, 719 ic->ic_bss->ni_bssid)) 720 error = ENETRESET; 721 break; 722 } 723 break; 724 case SIOCG80211BSSID: 725 bssid = (struct ieee80211_bssid *)data; 726 switch (ic->ic_state) { 727 case IEEE80211_S_INIT: 728 case IEEE80211_S_SCAN: 729 #ifndef IEEE80211_STA_ONLY 730 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 731 IEEE80211_ADDR_COPY(bssid->i_bssid, 732 ic->ic_myaddr); 733 else 734 #endif 735 if (ic->ic_flags & IEEE80211_F_DESBSSID) 736 IEEE80211_ADDR_COPY(bssid->i_bssid, 737 ic->ic_des_bssid); 738 else 739 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 740 break; 741 default: 742 IEEE80211_ADDR_COPY(bssid->i_bssid, 743 ic->ic_bss->ni_bssid); 744 break; 745 } 746 break; 747 case SIOCS80211CHANNEL: 748 if ((error = suser(curproc)) != 0) 749 break; 750 chanreq = (struct ieee80211chanreq *)data; 751 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 752 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 753 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 754 isclr(ic->ic_chan_active, chanreq->i_channel)) { 755 error = EINVAL; 756 break; 757 } else 758 ic->ic_ibss_chan = ic->ic_des_chan = 759 &ic->ic_channels[chanreq->i_channel]; 760 switch (ic->ic_state) { 761 case IEEE80211_S_INIT: 762 case IEEE80211_S_SCAN: 763 error = ENETRESET; 764 break; 765 default: 766 if (ic->ic_opmode == IEEE80211_M_STA) { 767 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 768 ic->ic_bss->ni_chan != ic->ic_des_chan) 769 error = ENETRESET; 770 } else { 771 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 772 error = ENETRESET; 773 } 774 break; 775 } 776 break; 777 case SIOCG80211CHANNEL: 778 chanreq = (struct ieee80211chanreq *)data; 779 switch (ic->ic_state) { 780 case IEEE80211_S_INIT: 781 case IEEE80211_S_SCAN: 782 if (ic->ic_opmode == IEEE80211_M_STA) 783 chan = ic->ic_des_chan; 784 else 785 chan = ic->ic_ibss_chan; 786 break; 787 default: 788 chan = ic->ic_bss->ni_chan; 789 break; 790 } 791 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 792 break; 793 case SIOCG80211ALLCHANS: 794 error = copyout(ic->ic_channels, 795 ((struct ieee80211_chanreq_all *)data)->i_chans, 796 sizeof(ic->ic_channels)); 797 break; 798 #if 0 799 case SIOCG80211ZSTATS: 800 #endif 801 case SIOCG80211STATS: 802 ifr = (struct ifreq *)data; 803 error = copyout(&ic->ic_stats, ifr->ifr_data, 804 sizeof(ic->ic_stats)); 805 #if 0 806 if (cmd == SIOCG80211ZSTATS) 807 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 808 #endif 809 break; 810 case SIOCS80211TXPOWER: 811 if ((error = suser(curproc)) != 0) 812 break; 813 txpower = (struct ieee80211_txpower *)data; 814 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 815 error = EINVAL; 816 break; 817 } 818 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val && 819 txpower->i_val <= IEEE80211_TXPOWER_MAX)) { 820 error = EINVAL; 821 break; 822 } 823 ic->ic_txpower = txpower->i_val; 824 error = ENETRESET; 825 break; 826 case SIOCG80211TXPOWER: 827 txpower = (struct ieee80211_txpower *)data; 828 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 829 error = EINVAL; 830 else 831 txpower->i_val = ic->ic_txpower; 832 break; 833 case SIOCSIFMTU: 834 ifr = (struct ifreq *)data; 835 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 836 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 837 error = EINVAL; 838 else 839 ifp->if_mtu = ifr->ifr_mtu; 840 break; 841 case SIOCS80211SCAN: 842 /* Disabled. SIOCG80211ALLNODES is enough. */ 843 break; 844 case SIOCG80211NODE: 845 nr = (struct ieee80211_nodereq *)data; 846 if (ic->ic_bss && 847 IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr)) 848 ni = ic->ic_bss; 849 else 850 ni = ieee80211_find_node(ic, nr->nr_macaddr); 851 if (ni == NULL) { 852 error = ENOENT; 853 break; 854 } 855 ieee80211_node2req(ic, ni, nr); 856 break; 857 case SIOCS80211NODE: 858 if ((error = suser(curproc)) != 0) 859 break; 860 #ifndef IEEE80211_STA_ONLY 861 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 862 error = EINVAL; 863 break; 864 } 865 #endif 866 nr = (struct ieee80211_nodereq *)data; 867 868 ni = ieee80211_find_node(ic, nr->nr_macaddr); 869 if (ni == NULL) 870 ni = ieee80211_alloc_node(ic, nr->nr_macaddr); 871 if (ni == NULL) { 872 error = ENOENT; 873 break; 874 } 875 876 if (nr->nr_flags & IEEE80211_NODEREQ_COPY) 877 ieee80211_req2node(ic, nr, ni); 878 break; 879 #ifndef IEEE80211_STA_ONLY 880 case SIOCS80211DELNODE: 881 if ((error = suser(curproc)) != 0) 882 break; 883 nr = (struct ieee80211_nodereq *)data; 884 ni = ieee80211_find_node(ic, nr->nr_macaddr); 885 if (ni == NULL) 886 error = ENOENT; 887 else if (ni == ic->ic_bss) 888 error = EPERM; 889 else { 890 if (ni->ni_state == IEEE80211_STA_COLLECT) 891 break; 892 893 /* Disassociate station. */ 894 if (ni->ni_state == IEEE80211_STA_ASSOC) 895 IEEE80211_SEND_MGMT(ic, ni, 896 IEEE80211_FC0_SUBTYPE_DISASSOC, 897 IEEE80211_REASON_ASSOC_LEAVE); 898 899 /* Deauth station. */ 900 if (ni->ni_state >= IEEE80211_STA_AUTH) 901 IEEE80211_SEND_MGMT(ic, ni, 902 IEEE80211_FC0_SUBTYPE_DEAUTH, 903 IEEE80211_REASON_AUTH_LEAVE); 904 905 ieee80211_node_leave(ic, ni); 906 } 907 break; 908 #endif 909 case SIOCG80211ALLNODES: 910 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 911 (IFF_UP | IFF_RUNNING)) { 912 error = ENETDOWN; 913 break; 914 } 915 916 na = (struct ieee80211_nodereq_all *)data; 917 na->na_nodes = i = 0; 918 ni = RBT_MIN(ieee80211_tree, &ic->ic_tree); 919 while (ni && na->na_size >= 920 i + sizeof(struct ieee80211_nodereq)) { 921 ieee80211_node2req(ic, ni, &nrbuf); 922 error = copyout(&nrbuf, (caddr_t)na->na_node + i, 923 sizeof(struct ieee80211_nodereq)); 924 if (error) 925 break; 926 i += sizeof(struct ieee80211_nodereq); 927 na->na_nodes++; 928 ni = RBT_NEXT(ieee80211_tree, ni); 929 } 930 if (suser(curproc) == 0) 931 ieee80211_begin_bgscan(ifp); 932 break; 933 case SIOCG80211FLAGS: 934 flags = ic->ic_userflags; 935 #ifndef IEEE80211_STA_ONLY 936 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 937 #endif 938 flags &= ~IEEE80211_F_HOSTAPMASK; 939 ifr->ifr_flags = flags; 940 break; 941 case SIOCS80211FLAGS: 942 if ((error = suser(curproc)) != 0) 943 break; 944 flags = ifr->ifr_flags; 945 if ( 946 #ifndef IEEE80211_STA_ONLY 947 ic->ic_opmode != IEEE80211_M_HOSTAP && 948 #endif 949 (flags & IEEE80211_F_HOSTAPMASK)) { 950 error = EINVAL; 951 break; 952 } 953 ic->ic_userflags = flags; 954 error = ENETRESET; 955 break; 956 case SIOCADDMULTI: 957 case SIOCDELMULTI: 958 error = (cmd == SIOCADDMULTI) ? 959 ether_addmulti(ifr, &ic->ic_ac) : 960 ether_delmulti(ifr, &ic->ic_ac); 961 if (error == ENETRESET) 962 error = 0; 963 break; 964 default: 965 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data); 966 } 967 968 return error; 969 } 970