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