1 /* $OpenBSD: ieee80211_ioctl.c,v 1.24 2008/08/29 12:14:53 damien Exp $ */ 2 /* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */ 3 4 /*- 5 * Copyright (c) 2001 Atsushi Onoe 6 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * IEEE 802.11 ioctl support 34 */ 35 36 #include <sys/param.h> 37 #include <sys/kernel.h> 38 #include <sys/socket.h> 39 #include <sys/sockio.h> 40 #include <sys/systm.h> 41 #include <sys/endian.h> 42 #include <sys/proc.h> 43 #include <sys/tree.h> 44 45 #include <net/if.h> 46 #include <net/if_arp.h> 47 #include <net/if_media.h> 48 49 #ifdef INET 50 #include <netinet/in.h> 51 #include <netinet/if_ether.h> 52 #endif 53 54 #include <net80211/ieee80211_var.h> 55 #include <net80211/ieee80211_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 /* Node address and name information */ 67 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr); 68 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid); 69 nr->nr_nwid_len = ni->ni_esslen; 70 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN); 71 72 /* Channel and rates */ 73 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan); 74 nr->nr_chan_flags = ni->ni_chan->ic_flags; 75 nr->nr_nrates = ni->ni_rates.rs_nrates; 76 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE); 77 78 /* Node status information */ 79 nr->nr_rssi = (*ic->ic_node_getrssi)(ic, ni); 80 nr->nr_max_rssi = ic->ic_max_rssi; 81 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp)); 82 nr->nr_intval = ni->ni_intval; 83 nr->nr_capinfo = ni->ni_capinfo; 84 nr->nr_erp = ni->ni_erp; 85 nr->nr_pwrsave = ni->ni_pwrsave; 86 nr->nr_associd = ni->ni_associd; 87 nr->nr_txseq = ni->ni_txseq; 88 nr->nr_rxseq = ni->ni_rxseq; 89 nr->nr_fails = ni->ni_fails; 90 nr->nr_inact = ni->ni_inact; 91 nr->nr_txrate = ni->ni_txrate; 92 nr->nr_state = ni->ni_state; 93 /* XXX RSN */ 94 95 /* Node flags */ 96 nr->nr_flags = 0; 97 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0) 98 nr->nr_flags |= IEEE80211_NODEREQ_AP; 99 if (ni == ic->ic_bss) 100 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS; 101 } 102 103 void 104 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr, 105 struct ieee80211_node *ni) 106 { 107 /* Node address and name information */ 108 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr); 109 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid); 110 ni->ni_esslen = nr->nr_nwid_len; 111 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN); 112 113 /* Rates */ 114 ni->ni_rates.rs_nrates = nr->nr_nrates; 115 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE); 116 117 /* Node information */ 118 ni->ni_intval = nr->nr_intval; 119 ni->ni_capinfo = nr->nr_capinfo; 120 ni->ni_erp = nr->nr_erp; 121 ni->ni_pwrsave = nr->nr_pwrsave; 122 ni->ni_associd = nr->nr_associd; 123 ni->ni_txseq = nr->nr_txseq; 124 ni->ni_rxseq = nr->nr_rxseq; 125 ni->ni_fails = nr->nr_fails; 126 ni->ni_inact = nr->nr_inact; 127 ni->ni_txrate = nr->nr_txrate; 128 ni->ni_state = nr->nr_state; 129 } 130 131 static int 132 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic, 133 const struct ieee80211_nwkey *nwkey) 134 { 135 struct ieee80211_key *k; 136 int error, i; 137 138 if (!(ic->ic_caps & IEEE80211_C_WEP)) 139 return ENODEV; 140 141 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) { 142 if (!(ic->ic_flags & IEEE80211_F_WEPON)) 143 return 0; 144 ic->ic_flags &= ~IEEE80211_F_WEPON; 145 return ENETRESET; 146 } 147 if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID) 148 return EINVAL; 149 150 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 151 if (nwkey->i_key[i].i_keylen == 0 || 152 nwkey->i_key[i].i_keydat == NULL) 153 continue; /* entry not set */ 154 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE) 155 return EINVAL; 156 157 /* map wep key to ieee80211_key */ 158 k = &ic->ic_nw_keys[i]; 159 if (k->k_cipher != IEEE80211_CIPHER_NONE) 160 (*ic->ic_delete_key)(ic, NULL, k); 161 memset(k, 0, sizeof(*k)); 162 if (nwkey->i_key[i].i_keylen <= 5) 163 k->k_cipher = IEEE80211_CIPHER_WEP40; 164 else 165 k->k_cipher = IEEE80211_CIPHER_WEP104; 166 k->k_len = nwkey->i_key[i].i_keylen; 167 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; 168 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, 169 nwkey->i_key[i].i_keylen); 170 if (error != 0) 171 return error; 172 if ((error = (*ic->ic_set_key)(ic, NULL, k)) != 0) 173 return error; 174 } 175 176 ic->ic_def_txkey = nwkey->i_defkid - 1; 177 ic->ic_flags |= IEEE80211_F_WEPON; 178 179 return ENETRESET; 180 } 181 182 static int 183 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic, 184 struct ieee80211_nwkey *nwkey) 185 { 186 struct ieee80211_key *k; 187 int error, i; 188 189 if (ic->ic_flags & IEEE80211_F_WEPON) 190 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 191 else 192 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 193 194 nwkey->i_defkid = ic->ic_wep_txkey + 1; 195 196 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 197 if (nwkey->i_key[i].i_keydat == NULL) 198 continue; 199 /* do not show any keys to non-root user */ 200 if ((error = suser(curproc, 0)) != 0) 201 return error; 202 k = &ic->ic_nw_keys[i]; 203 if (k->k_cipher != IEEE80211_CIPHER_WEP40 && 204 k->k_cipher != IEEE80211_CIPHER_WEP104) 205 nwkey->i_key[i].i_keylen = 0; 206 else 207 nwkey->i_key[i].i_keylen = k->k_len; 208 error = copyout(k->k_key, nwkey->i_key[i].i_keydat, 209 nwkey->i_key[i].i_keylen); 210 if (error != 0) 211 return error; 212 } 213 return 0; 214 } 215 216 static int 217 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic, 218 const struct ieee80211_wpaparams *wpa) 219 { 220 if (!(ic->ic_caps & IEEE80211_C_RSN)) 221 return ENODEV; 222 223 if (!wpa->i_enabled) { 224 if (!(ic->ic_flags & IEEE80211_F_RSNON)) 225 return 0; 226 ic->ic_flags &= ~IEEE80211_F_RSNON; 227 return ENETRESET; 228 } 229 230 ic->ic_rsnprotos = 0; 231 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1) 232 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA; 233 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2) 234 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN; 235 if (ic->ic_rsnprotos == 0) /* set to default (WPA+RSN) */ 236 ic->ic_rsnprotos = IEEE80211_PROTO_WPA | IEEE80211_PROTO_RSN; 237 238 ic->ic_rsnakms = 0; 239 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK) 240 ic->ic_rsnakms |= IEEE80211_AKM_PSK; 241 if (wpa->i_akms & IEEE80211_WPA_AKM_IEEE8021X) 242 ic->ic_rsnakms |= IEEE80211_AKM_8021X; 243 if (ic->ic_rsnakms == 0) /* set to default (PSK+802.1X) */ 244 ic->ic_rsnakms = IEEE80211_AKM_PSK | IEEE80211_AKM_8021X; 245 246 if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40) 247 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40; 248 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP) 249 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 250 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP) 251 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 252 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104) 253 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104; 254 else { /* set to default */ 255 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 256 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP; 257 else 258 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP; 259 } 260 261 ic->ic_rsnciphers = 0; 262 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP) 263 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP; 264 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP) 265 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP; 266 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP) 267 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP; 268 if (ic->ic_rsnciphers == 0) /* set to default (TKIP+CCMP) */ 269 ic->ic_rsnciphers = IEEE80211_CIPHER_TKIP | 270 IEEE80211_CIPHER_CCMP; 271 272 ic->ic_flags |= IEEE80211_F_RSNON; 273 274 return ENETRESET; 275 } 276 277 static int 278 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic, 279 struct ieee80211_wpaparams *wpa) 280 { 281 wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0; 282 283 wpa->i_protos = 0; 284 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA) 285 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1; 286 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN) 287 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2; 288 289 wpa->i_akms = 0; 290 if (ic->ic_rsnakms & IEEE80211_AKM_PSK) 291 wpa->i_akms |= IEEE80211_WPA_AKM_PSK; 292 if (ic->ic_rsnakms & IEEE80211_AKM_8021X) 293 wpa->i_akms |= IEEE80211_WPA_AKM_IEEE8021X; 294 295 if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40) 296 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40; 297 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP) 298 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP; 299 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP) 300 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP; 301 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104) 302 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104; 303 else 304 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE; 305 306 wpa->i_ciphers = 0; 307 if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP) 308 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP; 309 if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP) 310 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP; 311 if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP) 312 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP; 313 314 return 0; 315 } 316 317 int 318 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 319 { 320 struct ieee80211com *ic = (void *)ifp; 321 struct ifreq *ifr = (struct ifreq *)data; 322 int i, error = 0; 323 struct ieee80211_nwid nwid; 324 struct ieee80211_wpapsk *psk; 325 struct ieee80211_wmmparams *wmm; 326 struct ieee80211_power *power; 327 struct ieee80211_bssid *bssid; 328 struct ieee80211chanreq *chanreq; 329 struct ieee80211_channel *chan; 330 struct ieee80211_txpower *txpower; 331 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 333 }; 334 struct ieee80211_nodereq *nr, nrbuf; 335 struct ieee80211_nodereq_all *na; 336 struct ieee80211_node *ni; 337 u_int32_t flags; 338 339 switch (cmd) { 340 case SIOCSIFADDR: 341 case SIOCGIFADDR: 342 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data); 343 break; 344 case SIOCSIFMEDIA: 345 case SIOCGIFMEDIA: 346 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 347 break; 348 case SIOCS80211NWID: 349 if ((error = suser(curproc, 0)) != 0) 350 break; 351 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0) 352 break; 353 if (nwid.i_len > IEEE80211_NWID_LEN) { 354 error = EINVAL; 355 break; 356 } 357 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 358 ic->ic_des_esslen = nwid.i_len; 359 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len); 360 error = ENETRESET; 361 break; 362 case SIOCG80211NWID: 363 memset(&nwid, 0, sizeof(nwid)); 364 switch (ic->ic_state) { 365 case IEEE80211_S_INIT: 366 case IEEE80211_S_SCAN: 367 nwid.i_len = ic->ic_des_esslen; 368 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); 369 break; 370 default: 371 nwid.i_len = ic->ic_bss->ni_esslen; 372 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len); 373 break; 374 } 375 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 376 break; 377 case SIOCS80211NWKEY: 378 if ((error = suser(curproc, 0)) != 0) 379 break; 380 error = ieee80211_ioctl_setnwkeys(ic, (void *)data); 381 break; 382 case SIOCG80211NWKEY: 383 error = ieee80211_ioctl_getnwkeys(ic, (void *)data); 384 break; 385 case SIOCS80211WMMPARMS: 386 if ((error = suser(curproc, 0)) != 0) 387 break; 388 if (!(ic->ic_flags & IEEE80211_C_QOS)) { 389 error = ENODEV; 390 break; 391 } 392 wmm = (struct ieee80211_wmmparams *)data; 393 if (wmm->i_enabled) 394 ic->ic_flags |= IEEE80211_F_QOS; 395 else 396 ic->ic_flags &= ~IEEE80211_F_QOS; 397 error = ENETRESET; 398 break; 399 case SIOCG80211WMMPARMS: 400 wmm = (struct ieee80211_wmmparams *)data; 401 wmm->i_enabled = (ic->ic_flags & IEEE80211_F_QOS) ? 1 : 0; 402 break; 403 case SIOCS80211WPAPARMS: 404 if ((error = suser(curproc, 0)) != 0) 405 break; 406 error = ieee80211_ioctl_setwpaparms(ic, (void *)data); 407 break; 408 case SIOCG80211WPAPARMS: 409 error = ieee80211_ioctl_getwpaparms(ic, (void *)data); 410 break; 411 case SIOCS80211WPAPSK: 412 if ((error = suser(curproc, 0)) != 0) 413 break; 414 psk = (struct ieee80211_wpapsk *)data; 415 if (psk->i_enabled) { 416 ic->ic_flags |= IEEE80211_F_PSK; 417 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk)); 418 } else { 419 ic->ic_flags &= ~IEEE80211_F_PSK; 420 memset(ic->ic_psk, 0, sizeof(ic->ic_psk)); 421 } 422 error = ENETRESET; 423 break; 424 case SIOCG80211WPAPSK: 425 psk = (struct ieee80211_wpapsk *)data; 426 if (ic->ic_flags & IEEE80211_F_PSK) { 427 psk->i_enabled = 1; 428 /* do not show any keys to non-root user */ 429 if (suser(curproc, 0) != 0) { 430 psk->i_enabled = 2; 431 memset(psk->i_psk, 0, sizeof(psk->i_psk)); 432 break; /* return ok but w/o key */ 433 } 434 memcpy(psk->i_psk, ic->ic_psk, sizeof(psk->i_psk)); 435 } else 436 psk->i_enabled = 0; 437 break; 438 case SIOCS80211POWER: 439 if ((error = suser(curproc, 0)) != 0) 440 break; 441 power = (struct ieee80211_power *)data; 442 ic->ic_lintval = power->i_maxsleep; 443 if (power->i_enabled != 0) { 444 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 445 error = EINVAL; 446 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 447 ic->ic_flags |= IEEE80211_F_PMGTON; 448 error = ENETRESET; 449 } 450 } else { 451 if (ic->ic_flags & IEEE80211_F_PMGTON) { 452 ic->ic_flags &= ~IEEE80211_F_PMGTON; 453 error = ENETRESET; 454 } 455 } 456 break; 457 case SIOCG80211POWER: 458 power = (struct ieee80211_power *)data; 459 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; 460 power->i_maxsleep = ic->ic_lintval; 461 break; 462 case SIOCS80211BSSID: 463 if ((error = suser(curproc, 0)) != 0) 464 break; 465 bssid = (struct ieee80211_bssid *)data; 466 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) 467 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 468 else { 469 ic->ic_flags |= IEEE80211_F_DESBSSID; 470 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); 471 } 472 #ifndef IEEE80211_STA_ONLY 473 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 474 break; 475 #endif 476 switch (ic->ic_state) { 477 case IEEE80211_S_INIT: 478 case IEEE80211_S_SCAN: 479 error = ENETRESET; 480 break; 481 default: 482 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 483 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, 484 ic->ic_bss->ni_bssid)) 485 error = ENETRESET; 486 break; 487 } 488 break; 489 case SIOCG80211BSSID: 490 bssid = (struct ieee80211_bssid *)data; 491 switch (ic->ic_state) { 492 case IEEE80211_S_INIT: 493 case IEEE80211_S_SCAN: 494 #ifndef IEEE80211_STA_ONLY 495 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 496 IEEE80211_ADDR_COPY(bssid->i_bssid, 497 ic->ic_myaddr); 498 else 499 #endif 500 if (ic->ic_flags & IEEE80211_F_DESBSSID) 501 IEEE80211_ADDR_COPY(bssid->i_bssid, 502 ic->ic_des_bssid); 503 else 504 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); 505 break; 506 default: 507 IEEE80211_ADDR_COPY(bssid->i_bssid, 508 ic->ic_bss->ni_bssid); 509 break; 510 } 511 break; 512 case SIOCS80211CHANNEL: 513 if ((error = suser(curproc, 0)) != 0) 514 break; 515 chanreq = (struct ieee80211chanreq *)data; 516 if (chanreq->i_channel == IEEE80211_CHAN_ANY) 517 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 518 else if (chanreq->i_channel > IEEE80211_CHAN_MAX || 519 isclr(ic->ic_chan_active, chanreq->i_channel)) { 520 error = EINVAL; 521 break; 522 } else 523 ic->ic_ibss_chan = ic->ic_des_chan = 524 &ic->ic_channels[chanreq->i_channel]; 525 switch (ic->ic_state) { 526 case IEEE80211_S_INIT: 527 case IEEE80211_S_SCAN: 528 error = ENETRESET; 529 break; 530 default: 531 if (ic->ic_opmode == IEEE80211_M_STA) { 532 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 533 ic->ic_bss->ni_chan != ic->ic_des_chan) 534 error = ENETRESET; 535 } else { 536 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 537 error = ENETRESET; 538 } 539 break; 540 } 541 break; 542 case SIOCG80211CHANNEL: 543 chanreq = (struct ieee80211chanreq *)data; 544 switch (ic->ic_state) { 545 case IEEE80211_S_INIT: 546 case IEEE80211_S_SCAN: 547 if (ic->ic_opmode == IEEE80211_M_STA) 548 chan = ic->ic_des_chan; 549 else 550 chan = ic->ic_ibss_chan; 551 break; 552 default: 553 chan = ic->ic_bss->ni_chan; 554 break; 555 } 556 chanreq->i_channel = ieee80211_chan2ieee(ic, chan); 557 break; 558 #if 0 559 case SIOCG80211ZSTATS: 560 #endif 561 case SIOCG80211STATS: 562 ifr = (struct ifreq *)data; 563 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 564 #if 0 565 if (cmd == SIOCG80211ZSTATS) 566 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats)); 567 #endif 568 break; 569 case SIOCS80211TXPOWER: 570 if ((error = suser(curproc, 0)) != 0) 571 break; 572 txpower = (struct ieee80211_txpower *)data; 573 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 574 error = EINVAL; 575 break; 576 } 577 if (!(IEEE80211_TXPOWER_MIN < txpower->i_val && 578 txpower->i_val < IEEE80211_TXPOWER_MAX)) { 579 error = EINVAL; 580 break; 581 } 582 ic->ic_txpower = txpower->i_val; 583 error = ENETRESET; 584 break; 585 case SIOCG80211TXPOWER: 586 txpower = (struct ieee80211_txpower *)data; 587 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 588 error = EINVAL; 589 else 590 txpower->i_val = ic->ic_txpower; 591 break; 592 case SIOCSIFMTU: 593 ifr = (struct ifreq *)data; 594 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 595 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 596 error = EINVAL; 597 else 598 ifp->if_mtu = ifr->ifr_mtu; 599 break; 600 case SIOCS80211SCAN: 601 if ((error = suser(curproc, 0)) != 0) 602 break; 603 #ifndef IEEE80211_STA_ONLY 604 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 605 break; 606 #endif 607 if ((ifp->if_flags & IFF_UP) == 0) { 608 error = ENETDOWN; 609 break; 610 } 611 if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) { 612 if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED) 613 ic->ic_scan_lock |= IEEE80211_SCAN_RESUME; 614 ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST; 615 if (ic->ic_state != IEEE80211_S_SCAN) 616 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 617 } 618 /* Let the userspace process wait for completion */ 619 error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan", 620 hz * IEEE80211_SCAN_TIMEOUT); 621 break; 622 case SIOCG80211NODE: 623 nr = (struct ieee80211_nodereq *)data; 624 ni = ieee80211_find_node(ic, nr->nr_macaddr); 625 if (ni == NULL) { 626 error = ENOENT; 627 break; 628 } 629 ieee80211_node2req(ic, ni, nr); 630 break; 631 case SIOCS80211NODE: 632 if ((error = suser(curproc, 0)) != 0) 633 break; 634 #ifndef IEEE80211_STA_ONLY 635 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 636 error = EINVAL; 637 break; 638 } 639 #endif 640 nr = (struct ieee80211_nodereq *)data; 641 642 ni = ieee80211_find_node(ic, nr->nr_macaddr); 643 if (ni == NULL) 644 ni = ieee80211_alloc_node(ic, nr->nr_macaddr); 645 if (ni == NULL) { 646 error = ENOENT; 647 break; 648 } 649 650 if (nr->nr_flags & IEEE80211_NODEREQ_COPY) 651 ieee80211_req2node(ic, nr, ni); 652 break; 653 case SIOCS80211DELNODE: 654 if ((error = suser(curproc, 0)) != 0) 655 break; 656 nr = (struct ieee80211_nodereq *)data; 657 ni = ieee80211_find_node(ic, nr->nr_macaddr); 658 if (ni == NULL) 659 error = ENOENT; 660 else if (ni == ic->ic_bss) 661 error = EPERM; 662 else { 663 if (ni->ni_state == IEEE80211_STA_COLLECT) 664 break; 665 666 /* Disassociate station. */ 667 if (ni->ni_state == IEEE80211_STA_ASSOC) 668 IEEE80211_SEND_MGMT(ic, ni, 669 IEEE80211_FC0_SUBTYPE_DISASSOC, 670 IEEE80211_REASON_ASSOC_LEAVE); 671 672 /* Deauth station. */ 673 if (ni->ni_state >= IEEE80211_STA_AUTH) 674 IEEE80211_SEND_MGMT(ic, ni, 675 IEEE80211_FC0_SUBTYPE_DEAUTH, 676 IEEE80211_REASON_AUTH_LEAVE); 677 678 ieee80211_release_node(ic, ni); 679 } 680 break; 681 case SIOCG80211ALLNODES: 682 na = (struct ieee80211_nodereq_all *)data; 683 na->na_nodes = i = 0; 684 ni = RB_MIN(ieee80211_tree, &ic->ic_tree); 685 while (ni && na->na_size >= 686 i + sizeof(struct ieee80211_nodereq)) { 687 ieee80211_node2req(ic, ni, &nrbuf); 688 error = copyout(&nrbuf, (caddr_t)na->na_node + i, 689 sizeof(struct ieee80211_nodereq)); 690 if (error) 691 break; 692 i += sizeof(struct ieee80211_nodereq); 693 na->na_nodes++; 694 ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); 695 } 696 break; 697 case SIOCG80211FLAGS: 698 flags = ic->ic_flags; 699 #ifndef IEEE80211_STA_ONLY 700 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 701 #endif 702 flags &= ~IEEE80211_F_HOSTAPMASK; 703 ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT; 704 break; 705 case SIOCS80211FLAGS: 706 if ((error = suser(curproc, 0)) != 0) 707 break; 708 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT; 709 #ifndef IEEE80211_STA_ONLY 710 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 711 (flags & IEEE80211_F_HOSTAPMASK)) { 712 error = EINVAL; 713 break; 714 } 715 #endif 716 ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags; 717 error = ENETRESET; 718 break; 719 default: 720 error = ENOTTY; 721 break; 722 } 723 return error; 724 } 725