2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include "opt_compat.h"
33 * IEEE 802.11 ioctl support (FreeBSD-specific)
39 #include <sys/endian.h>
40 #include <sys/param.h>
41 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/systm.h>
48 #include <net/if_dl.h>
49 #include <net/if_media.h>
50 #include <net/ethernet.h>
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
58 #include <netipx/ipx.h>
59 #include <netipx/ipx_if.h>
62 #include <net80211/ieee80211_var.h>
63 #include <net80211/ieee80211_ioctl.h>
66 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
67 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
68 #define IS_UP_AUTO(_ic) \
69 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
72 static struct ieee80211_channel *findchannel(struct ieee80211com *,
79 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP;
80 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB;
81 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM;
82 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP;
83 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP;
89 ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq)
91 struct ieee80211_node *ni;
92 struct ieee80211req_key ik;
93 struct ieee80211_key *wk;
94 const struct ieee80211_cipher *cip;
98 if (ireq->i_len != sizeof(ik))
100 error = copyin(ireq->i_data, &ik, sizeof(ik));
104 if (kid == IEEE80211_KEYIX_NONE) {
105 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
107 return EINVAL; /* XXX */
108 wk = &ni->ni_ucastkey;
110 if (kid >= IEEE80211_WEP_NKID)
112 wk = &ic->ic_nw_keys[kid];
113 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr);
117 ik.ik_type = cip->ic_cipher;
118 ik.ik_keylen = wk->wk_keylen;
119 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
120 if (wk->wk_keyix == ic->ic_def_txkey)
121 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
122 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
123 /* NB: only root can read key data */
124 ik.ik_keyrsc = wk->wk_keyrsc;
125 ik.ik_keytsc = wk->wk_keytsc;
126 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
127 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
128 memcpy(ik.ik_keydata+wk->wk_keylen,
129 wk->wk_key + IEEE80211_KEYBUF_SIZE,
130 IEEE80211_MICBUF_SIZE);
131 ik.ik_keylen += IEEE80211_MICBUF_SIZE;
136 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
139 ieee80211_free_node(ni);
140 return copyout(&ik, ireq->i_data, sizeof(ik));
144 ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
147 if (sizeof(ic->ic_chan_active) < ireq->i_len)
148 ireq->i_len = sizeof(ic->ic_chan_active);
149 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
153 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
157 space = __offsetof(struct ieee80211req_chaninfo,
158 ic_chans[ic->ic_nchans]);
159 if (space > ireq->i_len)
161 /* XXX assumes compatible layout */
162 return copyout(&ic->ic_nchans, ireq->i_data, space);
166 ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req)
168 struct ieee80211_node *ni;
169 struct ieee80211req_wpaie2 wpaie;
172 if (ireq->i_len < IEEE80211_ADDR_LEN)
174 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
177 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
179 return ENOENT; /* XXX */
180 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
181 if (ni->ni_wpa_ie != NULL) {
182 int ielen = ni->ni_wpa_ie[1] + 2;
183 if (ielen > sizeof(wpaie.wpa_ie))
184 ielen = sizeof(wpaie.wpa_ie);
185 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
187 if (req == IEEE80211_IOC_WPAIE2) {
188 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
189 if (ni->ni_rsn_ie != NULL) {
190 int ielen = ni->ni_rsn_ie[1] + 2;
191 if (ielen > sizeof(wpaie.rsn_ie))
192 ielen = sizeof(wpaie.rsn_ie);
193 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
195 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
196 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
198 /* compatibility op, may overwrite wpa ie */
199 /* XXX check ic_flags? */
200 if (ni->ni_rsn_ie != NULL) {
201 int ielen = ni->ni_rsn_ie[1] + 2;
202 if (ielen > sizeof(wpaie.wpa_ie))
203 ielen = sizeof(wpaie.wpa_ie);
204 memcpy(wpaie.wpa_ie, ni->ni_rsn_ie, ielen);
206 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
207 ireq->i_len = sizeof(struct ieee80211req_wpaie);
209 ieee80211_free_node(ni);
210 return copyout(&wpaie, ireq->i_data, ireq->i_len);
214 ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
216 struct ieee80211_node *ni;
217 uint8_t macaddr[IEEE80211_ADDR_LEN];
218 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
221 if (ireq->i_len < off)
223 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
226 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
229 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
230 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
231 /* NB: copy out only the statistics */
232 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
234 ieee80211_free_node(ni);
238 static __inline uint8_t *
239 copyie(uint8_t *cp, const uint8_t *ie)
242 memcpy(cp, ie, 2+ie[1]);
248 #ifdef COMPAT_FREEBSD6
249 #define IEEE80211_IOC_SCAN_RESULTS_OLD 24
251 struct scan_result_old {
252 uint16_t isr_len; /* length (mult of 4) */
253 uint16_t isr_freq; /* MHz */
254 uint16_t isr_flags; /* channel flags */
257 uint8_t isr_intval; /* beacon interval */
258 uint8_t isr_capinfo; /* capabilities */
259 uint8_t isr_erp; /* ERP element */
260 uint8_t isr_bssid[IEEE80211_ADDR_LEN];
262 uint8_t isr_rates[IEEE80211_RATE_MAXSIZE];
263 uint8_t isr_ssid_len; /* SSID length */
264 uint8_t isr_ie_len; /* IE length */
266 /* variable length SSID followed by IE data */
270 struct scan_result_old *sr;
275 old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
280 if (se->se_wpa_ie != NULL)
281 *ielen += 2+se->se_wpa_ie[1];
282 if (se->se_wme_ie != NULL)
283 *ielen += 2+se->se_wme_ie[1];
285 * NB: ie's can be no more than 255 bytes and the max 802.11
286 * packet is <3Kbytes so we are sure this doesn't overflow
287 * 16-bits; if this is a concern we can drop the ie's.
289 len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen;
290 return roundup(len, sizeof(uint32_t));
294 old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
296 struct oscanreq *req = arg;
299 req->space += old_scan_space(se, &ielen);
303 old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
305 struct oscanreq *req = arg;
306 struct scan_result_old *sr;
307 int ielen, len, nr, nxr;
310 len = old_scan_space(se, &ielen);
311 if (len > req->space)
315 memset(sr, 0, sizeof(*sr));
316 sr->isr_ssid_len = se->se_ssid[1];
317 /* NB: beware of overflow, isr_ie_len is 8 bits */
318 sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
320 sr->isr_freq = se->se_chan->ic_freq;
321 sr->isr_flags = se->se_chan->ic_flags;
322 sr->isr_rssi = se->se_rssi;
323 sr->isr_noise = se->se_noise;
324 sr->isr_intval = se->se_intval;
325 sr->isr_capinfo = se->se_capinfo;
326 sr->isr_erp = se->se_erp;
327 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
328 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
329 memcpy(sr->isr_rates, se->se_rates+2, nr);
330 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
331 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
332 sr->isr_nrates = nr + nxr;
334 cp = (uint8_t *)(sr+1);
335 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
336 cp += sr->isr_ssid_len;
337 if (sr->isr_ie_len) {
338 cp = copyie(cp, se->se_wpa_ie);
339 cp = copyie(cp, se->se_wme_ie);
343 req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len);
347 old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
352 if (ireq->i_len < sizeof(struct scan_result_old))
357 ieee80211_scan_iterate(ic, old_get_scan_space, &req);
358 if (req.space > ireq->i_len)
359 req.space = ireq->i_len;
365 /* XXX M_WAITOK after driver lock released */
366 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
370 ieee80211_scan_iterate(ic, old_get_scan_result, &req);
371 ireq->i_len = space - req.space;
372 error = copyout(p, ireq->i_data, ireq->i_len);
379 #endif /* COMPAT_FREEBSD6 */
382 struct ieee80211req_scan_result *sr;
387 scan_space(const struct ieee80211_scan_entry *se, int *ielen)
392 if (se->se_wpa_ie != NULL)
393 *ielen += 2+se->se_wpa_ie[1];
394 if (se->se_rsn_ie != NULL)
395 *ielen += 2+se->se_rsn_ie[1];
396 if (se->se_wme_ie != NULL)
397 *ielen += 2+se->se_wme_ie[1];
398 if (se->se_ath_ie != NULL)
399 *ielen += 2+se->se_ath_ie[1];
401 * NB: ie's can be no more than 255 bytes and the max 802.11
402 * packet is <3Kbytes so we are sure this doesn't overflow
403 * 16-bits; if this is a concern we can drop the ie's.
405 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
406 return roundup(len, sizeof(uint32_t));
410 get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
412 struct scanreq *req = arg;
415 req->space += scan_space(se, &ielen);
419 get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
421 struct scanreq *req = arg;
422 struct ieee80211req_scan_result *sr;
423 int ielen, len, nr, nxr;
426 len = scan_space(se, &ielen);
427 if (len > req->space)
431 KASSERT(len <= 65535 && ielen <= 65535,
432 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
433 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
434 sr->isr_ie_len = ielen;
436 sr->isr_freq = se->se_chan->ic_freq;
437 sr->isr_flags = se->se_chan->ic_flags;
438 sr->isr_rssi = se->se_rssi;
439 sr->isr_noise = se->se_noise;
440 sr->isr_intval = se->se_intval;
441 sr->isr_capinfo = se->se_capinfo;
442 sr->isr_erp = se->se_erp;
443 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
444 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
445 memcpy(sr->isr_rates, se->se_rates+2, nr);
446 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
447 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
448 sr->isr_nrates = nr + nxr;
450 sr->isr_ssid_len = se->se_ssid[1];
451 cp = ((uint8_t *)sr) + sr->isr_ie_off;
452 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
455 cp += sr->isr_ssid_len;
456 cp = copyie(cp, se->se_wpa_ie);
457 cp = copyie(cp, se->se_rsn_ie);
458 cp = copyie(cp, se->se_wme_ie);
459 cp = copyie(cp, se->se_ath_ie);
460 cp = copyie(cp, se->se_htcap_ie);
464 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
468 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
473 if (ireq->i_len < sizeof(struct ieee80211req_scan_result))
478 ieee80211_scan_iterate(ic, get_scan_space, &req);
479 if (req.space > ireq->i_len)
480 req.space = ireq->i_len;
486 /* XXX M_WAITOK after driver lock released */
487 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
491 ieee80211_scan_iterate(ic, get_scan_result, &req);
492 ireq->i_len = space - req.space;
493 error = copyout(p, ireq->i_data, ireq->i_len);
502 struct ieee80211com *ic;
503 struct ieee80211req_sta_info *si;
508 sta_space(const struct ieee80211_node *ni, size_t *ielen)
511 if (ni->ni_wpa_ie != NULL)
512 *ielen += 2+ni->ni_wpa_ie[1];
513 if (ni->ni_rsn_ie != NULL)
514 *ielen += 2+ni->ni_rsn_ie[1];
515 if (ni->ni_wme_ie != NULL)
516 *ielen += 2+ni->ni_wme_ie[1];
517 if (ni->ni_ath_ie != NULL)
518 *ielen += 2+ni->ni_ath_ie[1];
519 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
524 get_sta_space(void *arg, struct ieee80211_node *ni)
526 struct stainforeq *req = arg;
527 struct ieee80211com *ic = ni->ni_ic;
530 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
531 ni->ni_associd == 0) /* only associated stations */
533 req->space += sta_space(ni, &ielen);
537 get_sta_info(void *arg, struct ieee80211_node *ni)
539 struct stainforeq *req = arg;
540 struct ieee80211com *ic = ni->ni_ic;
541 struct ieee80211req_sta_info *si;
545 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
546 ni->ni_associd == 0) /* only associated stations */
548 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
550 len = sta_space(ni, &ielen);
551 if (len > req->space)
555 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
556 si->isi_ie_len = ielen;
557 si->isi_freq = ni->ni_chan->ic_freq;
558 si->isi_flags = ni->ni_chan->ic_flags;
559 si->isi_state = ni->ni_flags;
560 si->isi_authmode = ni->ni_authmode;
561 ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
562 si->isi_noise = 0; /* XXX */
563 si->isi_capinfo = ni->ni_capinfo;
564 si->isi_erp = ni->ni_erp;
565 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
566 si->isi_nrates = ni->ni_rates.rs_nrates;
567 if (si->isi_nrates > 15)
569 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
570 si->isi_txrate = ni->ni_txrate;
571 si->isi_ie_len = ielen;
572 si->isi_associd = ni->ni_associd;
573 si->isi_txpower = ni->ni_txpower;
574 si->isi_vlan = ni->ni_vlan;
575 if (ni->ni_flags & IEEE80211_NODE_QOS) {
576 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
577 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
579 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
580 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
582 /* NB: leave all cases in case we relax ni_associd == 0 check */
583 if (ieee80211_node_is_authorized(ni))
584 si->isi_inact = ic->ic_inact_run;
585 else if (ni->ni_associd != 0)
586 si->isi_inact = ic->ic_inact_auth;
588 si->isi_inact = ic->ic_inact_init;
589 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
592 cp = ((uint8_t *)si) + si->isi_ie_off;
593 cp = copyie(cp, ni->ni_wpa_ie);
594 cp = copyie(cp, ni->ni_rsn_ie);
595 cp = copyie(cp, ni->ni_wme_ie);
596 cp = copyie(cp, ni->ni_ath_ie);
599 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
604 getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq,
605 struct ieee80211_node *ni, int off)
607 struct stainforeq req;
615 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
617 get_sta_space(&req, ni);
618 if (req.space > ireq->i_len)
619 req.space = ireq->i_len;
622 /* XXX M_WAITOK after driver lock released */
623 MALLOC(p, void *, space, M_TEMP, M_NOWAIT);
630 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
632 get_sta_info(&req, ni);
633 ireq->i_len = space - req.space;
634 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
640 ieee80211_free_node(ni);
645 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
647 uint8_t macaddr[IEEE80211_ADDR_LEN];
648 const int off = __offsetof(struct ieee80211req_sta_req, info);
649 struct ieee80211_node *ni;
652 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
654 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
657 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) {
660 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
664 return getstainfo_common(ic, ireq, ni, off);
667 #ifdef COMPAT_FREEBSD6
668 #define IEEE80211_IOC_STA_INFO_OLD 45
671 old_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
673 if (ireq->i_len < sizeof(struct ieee80211req_sta_info))
675 return getstainfo_common(ic, ireq, NULL, 0);
677 #endif /* COMPAT_FREEBSD6 */
680 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
682 struct ieee80211_node *ni;
683 struct ieee80211req_sta_txpow txpow;
686 if (ireq->i_len != sizeof(txpow))
688 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
691 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
693 return EINVAL; /* XXX */
694 txpow.it_txpow = ni->ni_txpower;
695 error = copyout(&txpow, ireq->i_data, sizeof(txpow));
696 ieee80211_free_node(ni);
701 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
703 struct ieee80211_wme_state *wme = &ic->ic_wme;
704 struct wmeParams *wmep;
707 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
710 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
711 if (ac >= WME_NUM_AC)
713 if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
714 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
716 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
717 switch (ireq->i_type) {
718 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
719 ireq->i_val = wmep->wmep_logcwmin;
721 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
722 ireq->i_val = wmep->wmep_logcwmax;
724 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
725 ireq->i_val = wmep->wmep_aifsn;
727 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
728 ireq->i_val = wmep->wmep_txopLimit;
730 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
731 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
732 ireq->i_val = wmep->wmep_acm;
734 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
735 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
736 ireq->i_val = !wmep->wmep_noackPolicy;
743 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
745 const struct ieee80211_aclator *acl = ic->ic_acl;
747 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
751 * Return the current ``state'' of an Atheros capbility.
752 * If associated in station mode report the negotiated
753 * setting. Otherwise report the current setting.
756 getathcap(struct ieee80211com *ic, int cap)
758 if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN)
759 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0;
761 return (ic->ic_flags & cap) != 0;
765 ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq)
767 if (ireq->i_len != sizeof(struct ieee80211_channel))
769 return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan));
773 * When building the kernel with -O2 on the i386 architecture, gcc
774 * seems to want to inline this function into ieee80211_ioctl()
775 * (which is the only routine that calls it). When this happens,
776 * ieee80211_ioctl() ends up consuming an additional 2K of stack
777 * space. (Exactly why it needs so much is unclear.) The problem
778 * is that it's possible for ieee80211_ioctl() to invoke other
779 * routines (including driver init functions) which could then find
780 * themselves perilously close to exhausting the stack.
782 * To avoid this, we deliberately prevent gcc from inlining this
783 * routine. Another way to avoid this is to use less agressive
784 * optimization when compiling this file (i.e. -O instead of -O2)
785 * but special-casing the compilation of this one module in the
786 * build system would be awkward.
789 __attribute__ ((noinline))
792 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
794 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
797 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
798 char tmpssid[IEEE80211_NWID_LEN];
800 switch (ireq->i_type) {
801 case IEEE80211_IOC_SSID:
802 switch (ic->ic_state) {
803 case IEEE80211_S_INIT:
804 case IEEE80211_S_SCAN:
805 ireq->i_len = ic->ic_des_ssid[0].len;
806 memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len);
809 ireq->i_len = ic->ic_bss->ni_esslen;
810 memcpy(tmpssid, ic->ic_bss->ni_essid,
814 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
816 case IEEE80211_IOC_NUMSSIDS:
819 case IEEE80211_IOC_WEP:
820 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
821 ireq->i_val = IEEE80211_WEP_OFF;
822 else if (ic->ic_flags & IEEE80211_F_DROPUNENC)
823 ireq->i_val = IEEE80211_WEP_ON;
825 ireq->i_val = IEEE80211_WEP_MIXED;
827 case IEEE80211_IOC_WEPKEY:
828 kid = (u_int) ireq->i_val;
829 if (kid >= IEEE80211_WEP_NKID)
831 len = (u_int) ic->ic_nw_keys[kid].wk_keylen;
832 /* NB: only root can read WEP keys */
833 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
834 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
839 error = copyout(tmpkey, ireq->i_data, len);
841 case IEEE80211_IOC_NUMWEPKEYS:
842 ireq->i_val = IEEE80211_WEP_NKID;
844 case IEEE80211_IOC_WEPTXKEY:
845 ireq->i_val = ic->ic_def_txkey;
847 case IEEE80211_IOC_AUTHMODE:
848 if (ic->ic_flags & IEEE80211_F_WPA)
849 ireq->i_val = IEEE80211_AUTH_WPA;
851 ireq->i_val = ic->ic_bss->ni_authmode;
853 case IEEE80211_IOC_CHANNEL:
854 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
856 case IEEE80211_IOC_POWERSAVE:
857 if (ic->ic_flags & IEEE80211_F_PMGTON)
858 ireq->i_val = IEEE80211_POWERSAVE_ON;
860 ireq->i_val = IEEE80211_POWERSAVE_OFF;
862 case IEEE80211_IOC_POWERSAVESLEEP:
863 ireq->i_val = ic->ic_lintval;
865 case IEEE80211_IOC_RTSTHRESHOLD:
866 ireq->i_val = ic->ic_rtsthreshold;
868 case IEEE80211_IOC_PROTMODE:
869 ireq->i_val = ic->ic_protmode;
871 case IEEE80211_IOC_TXPOWER:
872 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
874 ireq->i_val = ic->ic_txpowlimit;
876 case IEEE80211_IOC_MCASTCIPHER:
877 ireq->i_val = rsn->rsn_mcastcipher;
879 case IEEE80211_IOC_MCASTKEYLEN:
880 ireq->i_val = rsn->rsn_mcastkeylen;
882 case IEEE80211_IOC_UCASTCIPHERS:
884 for (m = 0x1; m != 0; m <<= 1)
885 if (rsn->rsn_ucastcipherset & m)
886 ireq->i_val |= 1<<cap2cipher(m);
888 case IEEE80211_IOC_UCASTCIPHER:
889 ireq->i_val = rsn->rsn_ucastcipher;
891 case IEEE80211_IOC_UCASTKEYLEN:
892 ireq->i_val = rsn->rsn_ucastkeylen;
894 case IEEE80211_IOC_KEYMGTALGS:
895 ireq->i_val = rsn->rsn_keymgmtset;
897 case IEEE80211_IOC_RSNCAPS:
898 ireq->i_val = rsn->rsn_caps;
900 case IEEE80211_IOC_WPA:
901 switch (ic->ic_flags & IEEE80211_F_WPA) {
902 case IEEE80211_F_WPA1:
905 case IEEE80211_F_WPA2:
908 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
916 case IEEE80211_IOC_CHANLIST:
917 error = ieee80211_ioctl_getchanlist(ic, ireq);
919 case IEEE80211_IOC_ROAMING:
920 ireq->i_val = ic->ic_roaming;
922 case IEEE80211_IOC_PRIVACY:
923 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0;
925 case IEEE80211_IOC_DROPUNENCRYPTED:
926 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0;
928 case IEEE80211_IOC_COUNTERMEASURES:
929 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0;
931 case IEEE80211_IOC_DRIVER_CAPS:
932 ireq->i_val = ic->ic_caps>>16;
933 ireq->i_len = ic->ic_caps&0xffff;
935 case IEEE80211_IOC_WME:
936 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0;
938 case IEEE80211_IOC_HIDESSID:
939 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0;
941 case IEEE80211_IOC_APBRIDGE:
942 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0;
944 case IEEE80211_IOC_OPTIE:
945 if (ic->ic_opt_ie == NULL)
947 /* NB: truncate, caller can check length */
948 if (ireq->i_len > ic->ic_opt_ie_len)
949 ireq->i_len = ic->ic_opt_ie_len;
950 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len);
952 case IEEE80211_IOC_WPAKEY:
953 error = ieee80211_ioctl_getkey(ic, ireq);
955 case IEEE80211_IOC_CHANINFO:
956 error = ieee80211_ioctl_getchaninfo(ic, ireq);
958 case IEEE80211_IOC_BSSID:
959 if (ireq->i_len != IEEE80211_ADDR_LEN)
961 error = copyout(ic->ic_state == IEEE80211_S_RUN ?
962 ic->ic_bss->ni_bssid :
964 ireq->i_data, ireq->i_len);
966 case IEEE80211_IOC_WPAIE:
967 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
969 case IEEE80211_IOC_WPAIE2:
970 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
972 #ifdef COMPAT_FREEBSD6
973 case IEEE80211_IOC_SCAN_RESULTS_OLD:
974 error = old_getscanresults(ic, ireq);
977 case IEEE80211_IOC_SCAN_RESULTS:
978 error = ieee80211_ioctl_getscanresults(ic, ireq);
980 case IEEE80211_IOC_STA_STATS:
981 error = ieee80211_ioctl_getstastats(ic, ireq);
983 case IEEE80211_IOC_TXPOWMAX:
984 ireq->i_val = ic->ic_bss->ni_txpower;
986 case IEEE80211_IOC_STA_TXPOW:
987 error = ieee80211_ioctl_getstatxpow(ic, ireq);
989 #ifdef COMPAT_FREEBSD6
990 case IEEE80211_IOC_STA_INFO_OLD:
991 error = old_getstainfo(ic, ireq);
994 case IEEE80211_IOC_STA_INFO:
995 error = ieee80211_ioctl_getstainfo(ic, ireq);
997 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
998 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
999 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1000 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1001 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1002 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
1003 error = ieee80211_ioctl_getwmeparam(ic, ireq);
1005 case IEEE80211_IOC_DTIM_PERIOD:
1006 ireq->i_val = ic->ic_dtim_period;
1008 case IEEE80211_IOC_BEACON_INTERVAL:
1009 /* NB: get from ic_bss for station mode */
1010 ireq->i_val = ic->ic_bss->ni_intval;
1012 case IEEE80211_IOC_PUREG:
1013 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
1015 case IEEE80211_IOC_FF:
1016 ireq->i_val = getathcap(ic, IEEE80211_F_FF);
1018 case IEEE80211_IOC_TURBOP:
1019 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP);
1021 case IEEE80211_IOC_BGSCAN:
1022 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0;
1024 case IEEE80211_IOC_BGSCAN_IDLE:
1025 ireq->i_val = ic->ic_bgscanidle*hz/1000; /* ms */
1027 case IEEE80211_IOC_BGSCAN_INTERVAL:
1028 ireq->i_val = ic->ic_bgscanintvl/hz; /* seconds */
1030 case IEEE80211_IOC_SCANVALID:
1031 ireq->i_val = ic->ic_scanvalid/hz; /* seconds */
1033 case IEEE80211_IOC_ROAM_RSSI_11A:
1034 ireq->i_val = ic->ic_roam.rssi11a;
1036 case IEEE80211_IOC_ROAM_RSSI_11B:
1037 ireq->i_val = ic->ic_roam.rssi11bOnly;
1039 case IEEE80211_IOC_ROAM_RSSI_11G:
1040 ireq->i_val = ic->ic_roam.rssi11b;
1042 case IEEE80211_IOC_ROAM_RATE_11A:
1043 ireq->i_val = ic->ic_roam.rate11a;
1045 case IEEE80211_IOC_ROAM_RATE_11B:
1046 ireq->i_val = ic->ic_roam.rate11bOnly;
1048 case IEEE80211_IOC_ROAM_RATE_11G:
1049 ireq->i_val = ic->ic_roam.rate11b;
1051 case IEEE80211_IOC_MCAST_RATE:
1052 ireq->i_val = ic->ic_mcast_rate;
1054 case IEEE80211_IOC_FRAGTHRESHOLD:
1055 ireq->i_val = ic->ic_fragthreshold;
1057 case IEEE80211_IOC_MACCMD:
1058 error = ieee80211_ioctl_getmaccmd(ic, ireq);
1060 case IEEE80211_IOC_BURST:
1061 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0;
1063 case IEEE80211_IOC_BMISSTHRESHOLD:
1064 ireq->i_val = ic->ic_bmissthreshold;
1066 case IEEE80211_IOC_CURCHAN:
1067 error = ieee80211_ioctl_getcurchan(ic, ireq);
1069 case IEEE80211_IOC_SHORTGI:
1071 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20)
1072 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1073 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40)
1074 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1076 case IEEE80211_IOC_AMPDU:
1078 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)
1080 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1083 case IEEE80211_IOC_AMPDU_LIMIT:
1084 ireq->i_val = ic->ic_ampdu_limit; /* XXX truncation? */
1086 case IEEE80211_IOC_AMPDU_DENSITY:
1087 ireq->i_val = ic->ic_ampdu_density;
1089 case IEEE80211_IOC_AMSDU:
1091 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1093 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1096 case IEEE80211_IOC_AMSDU_LIMIT:
1097 ireq->i_val = ic->ic_amsdu_limit; /* XXX truncation? */
1099 case IEEE80211_IOC_PUREN:
1100 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1102 case IEEE80211_IOC_DOTH:
1103 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
1105 case IEEE80211_IOC_HTCOMPAT:
1106 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1108 case IEEE80211_IOC_INACTIVITY:
1109 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_INACT) != 0;
1119 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq)
1125 * NB: Doing this for ap operation could be useful (e.g. for
1126 * WPA and/or WME) except that it typically is worthless
1127 * without being able to intervene when processing
1128 * association response frames--so disallow it for now.
1130 if (ic->ic_opmode != IEEE80211_M_STA)
1132 if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1134 /* NB: data.length is validated by the wireless extensions code */
1135 /* XXX M_WAITOK after driver lock released */
1136 if (ireq->i_len > 0) {
1137 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1140 error = copyin(ireq->i_data, ie, ireq->i_len);
1149 /* XXX sanity check data? */
1150 oie = ic->ic_opt_ie;
1152 ic->ic_opt_ie_len = ireq->i_len;
1154 FREE(oie, M_DEVBUF);
1159 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1161 struct ieee80211req_key ik;
1162 struct ieee80211_node *ni;
1163 struct ieee80211_key *wk;
1167 if (ireq->i_len != sizeof(ik))
1169 error = copyin(ireq->i_data, &ik, sizeof(ik));
1172 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1173 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1174 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1177 if (kid == IEEE80211_KEYIX_NONE) {
1178 /* XXX unicast keys currently must be tx/rx */
1179 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1181 if (ic->ic_opmode == IEEE80211_M_STA) {
1182 ni = ieee80211_ref_node(ic->ic_bss);
1183 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1184 ieee80211_free_node(ni);
1185 return EADDRNOTAVAIL;
1188 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
1192 wk = &ni->ni_ucastkey;
1194 if (kid >= IEEE80211_WEP_NKID)
1196 wk = &ic->ic_nw_keys[kid];
1198 * Global slots start off w/o any assigned key index.
1199 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1201 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1206 ieee80211_key_update_begin(ic);
1207 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) {
1208 wk->wk_keylen = ik.ik_keylen;
1209 /* NB: MIC presence is implied by cipher type */
1210 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1211 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1212 wk->wk_keyrsc = ik.ik_keyrsc;
1213 wk->wk_keytsc = 0; /* new key, reset */
1214 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1215 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1216 if (!ieee80211_crypto_setkey(ic, wk,
1217 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr))
1219 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1220 ic->ic_def_txkey = kid;
1223 ieee80211_key_update_end(ic);
1225 ieee80211_free_node(ni);
1230 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1232 struct ieee80211req_del_key dk;
1235 if (ireq->i_len != sizeof(dk))
1237 error = copyin(ireq->i_data, &dk, sizeof(dk));
1241 /* XXX uint8_t -> uint16_t */
1242 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1243 struct ieee80211_node *ni;
1245 if (ic->ic_opmode == IEEE80211_M_STA) {
1246 ni = ieee80211_ref_node(ic->ic_bss);
1247 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1248 ieee80211_free_node(ni);
1249 return EADDRNOTAVAIL;
1252 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr);
1256 /* XXX error return */
1257 ieee80211_node_delucastkey(ni);
1258 ieee80211_free_node(ni);
1260 if (kid >= IEEE80211_WEP_NKID)
1262 /* XXX error return */
1263 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]);
1269 domlme(void *arg, struct ieee80211_node *ni)
1271 struct ieee80211com *ic = ni->ni_ic;
1272 struct ieee80211req_mlme *mlme = arg;
1274 if (ni->ni_associd != 0) {
1275 IEEE80211_SEND_MGMT(ic, ni,
1276 mlme->im_op == IEEE80211_MLME_DEAUTH ?
1277 IEEE80211_FC0_SUBTYPE_DEAUTH :
1278 IEEE80211_FC0_SUBTYPE_DISASSOC,
1281 ieee80211_node_leave(ic, ni);
1287 const uint8_t *essid;
1288 const struct ieee80211_scan_entry *se;
1292 * Match mac address and any ssid.
1295 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1297 struct scanlookup *look = arg;
1299 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1301 if (look->esslen != 0) {
1302 if (se->se_ssid[1] != look->esslen)
1304 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1311 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1313 struct ieee80211req_mlme mlme;
1314 struct ieee80211_node *ni;
1317 if (ireq->i_len != sizeof(mlme))
1319 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1322 switch (mlme.im_op) {
1323 case IEEE80211_MLME_ASSOC:
1324 /* XXX ibss/ahdemo */
1325 if (ic->ic_opmode == IEEE80211_M_STA) {
1326 struct scanlookup lookup;
1329 lookup.mac = mlme.im_macaddr;
1330 /* XXX use revised api w/ explicit ssid */
1331 lookup.esslen = ic->ic_des_ssid[0].len;
1332 lookup.essid = ic->ic_des_ssid[0].ssid;
1333 ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1334 if (lookup.se != NULL &&
1335 ieee80211_sta_join(ic, lookup.se))
1339 case IEEE80211_MLME_DISASSOC:
1340 case IEEE80211_MLME_DEAUTH:
1341 switch (ic->ic_opmode) {
1342 case IEEE80211_M_STA:
1343 /* XXX not quite right */
1344 ieee80211_new_state(ic, IEEE80211_S_INIT,
1347 case IEEE80211_M_HOSTAP:
1348 /* NB: the broadcast address means do 'em all */
1349 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) {
1350 if ((ni = ieee80211_find_node(&ic->ic_sta,
1351 mlme.im_macaddr)) == NULL)
1354 ieee80211_free_node(ni);
1356 ieee80211_iterate_nodes(&ic->ic_sta,
1364 case IEEE80211_MLME_AUTHORIZE:
1365 case IEEE80211_MLME_UNAUTHORIZE:
1366 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1368 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr);
1371 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
1372 ieee80211_node_authorize(ni);
1374 ieee80211_node_unauthorize(ni);
1375 ieee80211_free_node(ni);
1384 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1386 uint8_t mac[IEEE80211_ADDR_LEN];
1387 const struct ieee80211_aclator *acl = ic->ic_acl;
1390 if (ireq->i_len != sizeof(mac))
1392 error = copyin(ireq->i_data, mac, ireq->i_len);
1396 acl = ieee80211_aclator_get("mac");
1397 if (acl == NULL || !acl->iac_attach(ic))
1401 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1402 acl->iac_add(ic, mac);
1404 acl->iac_remove(ic, mac);
1409 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1411 const struct ieee80211_aclator *acl = ic->ic_acl;
1413 switch (ireq->i_val) {
1414 case IEEE80211_MACCMD_POLICY_OPEN:
1415 case IEEE80211_MACCMD_POLICY_ALLOW:
1416 case IEEE80211_MACCMD_POLICY_DENY:
1418 acl = ieee80211_aclator_get("mac");
1419 if (acl == NULL || !acl->iac_attach(ic))
1423 acl->iac_setpolicy(ic, ireq->i_val);
1425 case IEEE80211_MACCMD_FLUSH:
1428 /* NB: silently ignore when not in use */
1430 case IEEE80211_MACCMD_DETACH:
1433 acl->iac_detach(ic);
1440 return acl->iac_setioctl(ic, ireq);
1446 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1448 struct ieee80211req_chanlist list;
1449 u_char chanlist[IEEE80211_CHAN_BYTES];
1450 int i, j, nchan, error;
1452 if (ireq->i_len != sizeof(list))
1454 error = copyin(ireq->i_data, &list, sizeof(list));
1457 memset(chanlist, 0, sizeof(chanlist));
1459 * Since channel 0 is not available for DS, channel 1
1460 * is assigned to LSB on WaveLAN.
1462 if (ic->ic_phytype == IEEE80211_T_DS)
1467 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1469 * NB: silently discard unavailable channels so users
1470 * can specify 1-255 to get all available channels.
1472 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
1473 setbit(chanlist, i);
1479 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1480 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1481 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1482 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1483 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
1487 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1489 struct ieee80211_node *ni;
1490 uint8_t macaddr[IEEE80211_ADDR_LEN];
1494 * NB: we could copyin ieee80211req_sta_stats so apps
1495 * could make selective changes but that's overkill;
1496 * just clear all stats for now.
1498 if (ireq->i_len < IEEE80211_ADDR_LEN)
1500 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1503 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1505 return EINVAL; /* XXX */
1506 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1507 ieee80211_free_node(ni);
1512 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
1514 struct ieee80211_node *ni;
1515 struct ieee80211req_sta_txpow txpow;
1518 if (ireq->i_len != sizeof(txpow))
1520 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1523 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
1525 return EINVAL; /* XXX */
1526 ni->ni_txpower = txpow.it_txpow;
1527 ieee80211_free_node(ni);
1532 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
1534 struct ieee80211_wme_state *wme = &ic->ic_wme;
1535 struct wmeParams *wmep, *chanp;
1538 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1541 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1542 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1543 if (ac >= WME_NUM_AC)
1546 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1547 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1549 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1550 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1552 switch (ireq->i_type) {
1553 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1555 wmep->wmep_logcwmin = ireq->i_val;
1556 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1557 chanp->wmep_logcwmin = ireq->i_val;
1559 wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1563 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1565 wmep->wmep_logcwmax = ireq->i_val;
1566 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1567 chanp->wmep_logcwmax = ireq->i_val;
1569 wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1573 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1575 wmep->wmep_aifsn = ireq->i_val;
1576 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1577 chanp->wmep_aifsn = ireq->i_val;
1579 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1582 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1584 wmep->wmep_txopLimit = ireq->i_val;
1585 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1586 chanp->wmep_txopLimit = ireq->i_val;
1588 wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1592 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1593 wmep->wmep_acm = ireq->i_val;
1594 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1595 chanp->wmep_acm = ireq->i_val;
1597 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1598 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1602 ieee80211_wme_updateparams(ic);
1607 cipher2cap(int cipher)
1610 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP;
1611 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES;
1612 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM;
1613 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP;
1614 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP;
1620 find11gchannel(struct ieee80211com *ic, int start, int freq)
1622 const struct ieee80211_channel *c;
1625 for (i = start+1; i < ic->ic_nchans; i++) {
1626 c = &ic->ic_channels[i];
1627 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1630 /* NB: should not be needed but in case things are mis-sorted */
1631 for (i = 0; i < start; i++) {
1632 c = &ic->ic_channels[i];
1633 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1639 static struct ieee80211_channel *
1640 findchannel(struct ieee80211com *ic, int ieee, int mode)
1642 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1643 0, /* IEEE80211_MODE_AUTO */
1644 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
1645 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
1646 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */
1647 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
1648 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */
1649 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */
1650 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */
1651 /* NB: handled specially below */
1652 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */
1653 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */
1658 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1659 modeflags = chanflags[mode];
1660 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1661 ("no chanflags for mode %u", mode));
1662 for (i = 0; i < ic->ic_nchans; i++) {
1663 struct ieee80211_channel *c = &ic->ic_channels[i];
1665 if (c->ic_ieee != ieee)
1667 if (mode == IEEE80211_MODE_AUTO) {
1668 /* ignore turbo channels for autoselect */
1669 if (IEEE80211_IS_CHAN_TURBO(c))
1672 * XXX special-case 11b/g channels so we
1673 * always select the g channel if both
1675 * XXX prefer HT to non-HT?
1677 if (!IEEE80211_IS_CHAN_B(c) ||
1678 !find11gchannel(ic, i, c->ic_freq))
1681 /* must check HT specially */
1682 if ((mode == IEEE80211_MODE_11NA ||
1683 mode == IEEE80211_MODE_11NG) &&
1684 !IEEE80211_IS_CHAN_HT(c))
1686 if ((c->ic_flags & modeflags) == modeflags)
1694 * Check the specified against any desired mode (aka netband).
1695 * This is only used (presently) when operating in hostap mode
1696 * to enforce consistency.
1699 check_mode_consistency(const struct ieee80211_channel *c, int mode)
1701 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1704 case IEEE80211_MODE_11B:
1705 return (IEEE80211_IS_CHAN_B(c));
1706 case IEEE80211_MODE_11G:
1707 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1708 case IEEE80211_MODE_11A:
1709 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1710 case IEEE80211_MODE_STURBO_A:
1711 return (IEEE80211_IS_CHAN_STURBO(c));
1712 case IEEE80211_MODE_11NA:
1713 return (IEEE80211_IS_CHAN_HTA(c));
1714 case IEEE80211_MODE_11NG:
1715 return (IEEE80211_IS_CHAN_HTG(c));
1722 * Common code to set the current channel. If the device
1723 * is up and running this may result in an immediate channel
1724 * change or a kick of the state machine.
1727 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1731 if (c != IEEE80211_CHAN_ANYC) {
1732 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1733 !check_mode_consistency(c, ic->ic_des_mode))
1735 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1736 return 0; /* NB: nothing to do */
1738 ic->ic_des_chan = c;
1741 if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1742 ic->ic_opmode == IEEE80211_M_WDS) &&
1743 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1745 * Monitor and wds modes can switch directly.
1747 ic->ic_curchan = ic->ic_des_chan;
1748 if (ic->ic_state == IEEE80211_S_RUN)
1749 ic->ic_set_channel(ic);
1752 * Need to go through the state machine in case we
1753 * need to reassociate or the like. The state machine
1754 * will pickup the desired channel and avoid scanning.
1757 error = ieee80211_init(ic, RESCAN);
1758 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1760 * When not up+running and a real channel has
1761 * been specified fix the current channel so
1762 * there is immediate feedback; e.g. via ifconfig.
1764 ic->ic_curchan = ic->ic_des_chan;
1771 * Old api for setting the current channel; this is
1772 * deprecated because channel numbers are ambiguous.
1775 ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1776 const struct ieee80211req *ireq)
1778 struct ieee80211_channel *c;
1780 /* XXX 0xffff overflows 16-bit signed */
1781 if (ireq->i_val == 0 ||
1782 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1783 c = IEEE80211_CHAN_ANYC;
1784 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1787 struct ieee80211_channel *c2;
1789 c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1791 c = findchannel(ic, ireq->i_val,
1792 IEEE80211_MODE_AUTO);
1797 * Fine tune channel selection based on desired mode:
1798 * if 11b is requested, find the 11b version of any
1799 * 11g channel returned,
1800 * if static turbo, find the turbo version of any
1801 * 11a channel return,
1802 * if 11na is requested, find the ht version of any
1803 * 11a channel returned,
1804 * if 11ng is requested, find the ht version of any
1805 * 11g channel returned,
1806 * otherwise we should be ok with what we've got.
1808 switch (ic->ic_des_mode) {
1809 case IEEE80211_MODE_11B:
1810 if (IEEE80211_IS_CHAN_ANYG(c)) {
1811 c2 = findchannel(ic, ireq->i_val,
1812 IEEE80211_MODE_11B);
1813 /* NB: should not happen, =>'s 11g w/o 11b */
1818 case IEEE80211_MODE_TURBO_A:
1819 if (IEEE80211_IS_CHAN_A(c)) {
1820 c2 = findchannel(ic, ireq->i_val,
1821 IEEE80211_MODE_TURBO_A);
1826 case IEEE80211_MODE_11NA:
1827 if (IEEE80211_IS_CHAN_A(c)) {
1828 c2 = findchannel(ic, ireq->i_val,
1829 IEEE80211_MODE_11NA);
1834 case IEEE80211_MODE_11NG:
1835 if (IEEE80211_IS_CHAN_ANYG(c)) {
1836 c2 = findchannel(ic, ireq->i_val,
1837 IEEE80211_MODE_11NG);
1842 default: /* NB: no static turboG */
1846 return setcurchan(ic, c);
1850 * New/current api for setting the current channel; a complete
1851 * channel description is provide so there is no ambiguity in
1852 * identifying the channel.
1855 ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1856 const struct ieee80211req *ireq)
1858 struct ieee80211_channel chan, *c;
1861 if (ireq->i_len != sizeof(chan))
1863 error = copyin(ireq->i_data, &chan, sizeof(chan));
1866 /* XXX 0xffff overflows 16-bit signed */
1867 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1868 c = IEEE80211_CHAN_ANYC;
1870 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1874 return setcurchan(ic, c);
1878 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1880 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1881 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1883 const struct ieee80211_authenticator *auth;
1884 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1885 char tmpssid[IEEE80211_NWID_LEN];
1886 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
1887 struct ieee80211_key *k;
1892 switch (ireq->i_type) {
1893 case IEEE80211_IOC_SSID:
1894 if (ireq->i_val != 0 ||
1895 ireq->i_len > IEEE80211_NWID_LEN)
1897 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1900 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1901 ic->ic_des_ssid[0].len = ireq->i_len;
1902 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1903 ic->ic_des_nssid = (ireq->i_len > 0);
1905 error = ieee80211_init(ic, RESCAN);
1907 case IEEE80211_IOC_WEP:
1908 switch (ireq->i_val) {
1909 case IEEE80211_WEP_OFF:
1910 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1911 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1913 case IEEE80211_WEP_ON:
1914 ic->ic_flags |= IEEE80211_F_PRIVACY;
1915 ic->ic_flags |= IEEE80211_F_DROPUNENC;
1917 case IEEE80211_WEP_MIXED:
1918 ic->ic_flags |= IEEE80211_F_PRIVACY;
1919 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1923 error = ieee80211_init(ic, RESCAN);
1925 case IEEE80211_IOC_WEPKEY:
1926 kid = (u_int) ireq->i_val;
1927 if (kid >= IEEE80211_WEP_NKID)
1929 k = &ic->ic_nw_keys[kid];
1930 if (ireq->i_len == 0) {
1931 /* zero-len =>'s delete any existing key */
1932 (void) ieee80211_crypto_delkey(ic, k);
1935 if (ireq->i_len > sizeof(tmpkey))
1937 memset(tmpkey, 0, sizeof(tmpkey));
1938 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
1941 ieee80211_key_update_begin(ic);
1942 k->wk_keyix = kid; /* NB: force fixed key id */
1943 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP,
1944 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1945 k->wk_keylen = ireq->i_len;
1946 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1947 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1951 ieee80211_key_update_end(ic);
1953 case IEEE80211_IOC_WEPTXKEY:
1954 kid = (u_int) ireq->i_val;
1955 if (kid >= IEEE80211_WEP_NKID &&
1956 (uint16_t) kid != IEEE80211_KEYIX_NONE)
1958 ic->ic_def_txkey = kid;
1960 case IEEE80211_IOC_AUTHMODE:
1961 switch (ireq->i_val) {
1962 case IEEE80211_AUTH_WPA:
1963 case IEEE80211_AUTH_8021X: /* 802.1x */
1964 case IEEE80211_AUTH_OPEN: /* open */
1965 case IEEE80211_AUTH_SHARED: /* shared-key */
1966 case IEEE80211_AUTH_AUTO: /* auto */
1967 auth = ieee80211_authenticator_get(ireq->i_val);
1974 switch (ireq->i_val) {
1975 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
1976 ic->ic_flags |= IEEE80211_F_PRIVACY;
1977 ireq->i_val = IEEE80211_AUTH_8021X;
1979 case IEEE80211_AUTH_OPEN: /* open */
1980 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
1982 case IEEE80211_AUTH_SHARED: /* shared-key */
1983 case IEEE80211_AUTH_8021X: /* 802.1x */
1984 ic->ic_flags &= ~IEEE80211_F_WPA;
1985 /* both require a key so mark the PRIVACY capability */
1986 ic->ic_flags |= IEEE80211_F_PRIVACY;
1988 case IEEE80211_AUTH_AUTO: /* auto */
1989 ic->ic_flags &= ~IEEE80211_F_WPA;
1990 /* XXX PRIVACY handling? */
1991 /* XXX what's the right way to do this? */
1994 /* NB: authenticator attach/detach happens on state change */
1995 ic->ic_bss->ni_authmode = ireq->i_val;
1996 /* XXX mixed/mode/usage? */
1999 error = ieee80211_init(ic, RESCAN);
2001 case IEEE80211_IOC_CHANNEL:
2002 error = ieee80211_ioctl_setchannel(ic, ireq);
2004 case IEEE80211_IOC_POWERSAVE:
2005 switch (ireq->i_val) {
2006 case IEEE80211_POWERSAVE_OFF:
2007 if (ic->ic_flags & IEEE80211_F_PMGTON) {
2008 ic->ic_flags &= ~IEEE80211_F_PMGTON;
2012 case IEEE80211_POWERSAVE_ON:
2013 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
2015 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
2016 ic->ic_flags |= IEEE80211_F_PMGTON;
2024 if (error == ENETRESET) {
2026 * Switching in+out of power save mode
2027 * should not require a state change.
2029 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2032 case IEEE80211_IOC_POWERSAVESLEEP:
2033 if (ireq->i_val < 0)
2035 ic->ic_lintval = ireq->i_val;
2036 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2038 case IEEE80211_IOC_RTSTHRESHOLD:
2039 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2040 ireq->i_val <= IEEE80211_RTS_MAX))
2042 ic->ic_rtsthreshold = ireq->i_val;
2043 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2045 case IEEE80211_IOC_PROTMODE:
2046 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2048 ic->ic_protmode = ireq->i_val;
2049 /* NB: if not operating in 11g this can wait */
2050 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2051 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2052 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2054 case IEEE80211_IOC_TXPOWER:
2055 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2057 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2058 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2060 ic->ic_txpowlimit = ireq->i_val;
2061 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2063 case IEEE80211_IOC_ROAMING:
2064 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2065 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2067 ic->ic_roaming = ireq->i_val;
2070 case IEEE80211_IOC_PRIVACY:
2072 /* XXX check for key state? */
2073 ic->ic_flags |= IEEE80211_F_PRIVACY;
2075 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2077 case IEEE80211_IOC_DROPUNENCRYPTED:
2079 ic->ic_flags |= IEEE80211_F_DROPUNENC;
2081 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2083 case IEEE80211_IOC_WPAKEY:
2084 error = ieee80211_ioctl_setkey(ic, ireq);
2086 case IEEE80211_IOC_DELKEY:
2087 error = ieee80211_ioctl_delkey(ic, ireq);
2089 case IEEE80211_IOC_MLME:
2090 error = ieee80211_ioctl_setmlme(ic, ireq);
2092 case IEEE80211_IOC_OPTIE:
2093 error = ieee80211_ioctl_setoptie(ic, ireq);
2095 case IEEE80211_IOC_COUNTERMEASURES:
2097 if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
2099 ic->ic_flags |= IEEE80211_F_COUNTERM;
2101 ic->ic_flags &= ~IEEE80211_F_COUNTERM;
2103 case IEEE80211_IOC_WPA:
2104 if (ireq->i_val > 3)
2106 /* XXX verify ciphers available */
2107 ic->ic_flags &= ~IEEE80211_F_WPA;
2108 switch (ireq->i_val) {
2110 ic->ic_flags |= IEEE80211_F_WPA1;
2113 ic->ic_flags |= IEEE80211_F_WPA2;
2116 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2121 case IEEE80211_IOC_WME:
2123 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2125 ic->ic_flags |= IEEE80211_F_WME;
2127 ic->ic_flags &= ~IEEE80211_F_WME;
2129 error = ieee80211_init(ic, 0);
2131 case IEEE80211_IOC_HIDESSID:
2133 ic->ic_flags |= IEEE80211_F_HIDESSID;
2135 ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2138 case IEEE80211_IOC_APBRIDGE:
2139 if (ireq->i_val == 0)
2140 ic->ic_flags |= IEEE80211_F_NOBRIDGE;
2142 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE;
2144 case IEEE80211_IOC_MCASTCIPHER:
2145 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 &&
2146 !ieee80211_crypto_available(ireq->i_val))
2148 rsn->rsn_mcastcipher = ireq->i_val;
2149 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2151 case IEEE80211_IOC_MCASTKEYLEN:
2152 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2154 /* XXX no way to verify driver capability */
2155 rsn->rsn_mcastkeylen = ireq->i_val;
2156 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2158 case IEEE80211_IOC_UCASTCIPHERS:
2160 * Convert user-specified cipher set to the set
2161 * we can support (via hardware or software).
2162 * NB: this logic intentionally ignores unknown and
2163 * unsupported ciphers so folks can specify 0xff or
2164 * similar and get all available ciphers.
2167 for (j = 1; j < 32; j++) /* NB: skip WEP */
2168 if ((ireq->i_val & (1<<j)) &&
2169 ((ic->ic_caps & cipher2cap(j)) ||
2170 ieee80211_crypto_available(j)))
2172 if (caps == 0) /* nothing available */
2174 /* XXX verify ciphers ok for unicast use? */
2175 /* XXX disallow if running as it'll have no effect */
2176 rsn->rsn_ucastcipherset = caps;
2177 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2179 case IEEE80211_IOC_UCASTCIPHER:
2180 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0)
2182 rsn->rsn_ucastcipher = ireq->i_val;
2184 case IEEE80211_IOC_UCASTKEYLEN:
2185 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2187 /* XXX no way to verify driver capability */
2188 rsn->rsn_ucastkeylen = ireq->i_val;
2190 case IEEE80211_IOC_DRIVER_CAPS:
2191 /* NB: for testing */
2192 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2193 ((uint16_t) ireq->i_len);
2195 case IEEE80211_IOC_KEYMGTALGS:
2197 rsn->rsn_keymgmtset = ireq->i_val;
2198 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2200 case IEEE80211_IOC_RSNCAPS:
2202 rsn->rsn_caps = ireq->i_val;
2203 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2205 case IEEE80211_IOC_BSSID:
2206 if (ireq->i_len != sizeof(tmpbssid))
2208 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2211 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2212 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2213 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2215 ic->ic_flags |= IEEE80211_F_DESBSSID;
2217 error = ieee80211_init(ic, RESCAN);
2219 case IEEE80211_IOC_CHANLIST:
2220 error = ieee80211_ioctl_setchanlist(ic, ireq);
2222 case IEEE80211_IOC_SCAN_REQ:
2225 (void) ieee80211_start_scan(ic,
2226 IEEE80211_SCAN_ACTIVE |
2227 IEEE80211_SCAN_NOPICK |
2228 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2229 /* XXX use ioctl params */
2230 ic->ic_des_nssid, ic->ic_des_ssid);
2232 case IEEE80211_IOC_ADDMAC:
2233 case IEEE80211_IOC_DELMAC:
2234 error = ieee80211_ioctl_macmac(ic, ireq);
2236 case IEEE80211_IOC_MACCMD:
2237 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2239 case IEEE80211_IOC_STA_STATS:
2240 error = ieee80211_ioctl_setstastats(ic, ireq);
2242 case IEEE80211_IOC_STA_TXPOW:
2243 error = ieee80211_ioctl_setstatxpow(ic, ireq);
2245 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
2246 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
2247 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
2248 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
2249 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
2250 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
2251 error = ieee80211_ioctl_setwmeparam(ic, ireq);
2253 case IEEE80211_IOC_DTIM_PERIOD:
2254 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2255 ic->ic_opmode != IEEE80211_M_IBSS)
2257 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2258 ireq->i_val <= IEEE80211_DTIM_MAX) {
2259 ic->ic_dtim_period = ireq->i_val;
2260 error = ENETRESET; /* requires restart */
2264 case IEEE80211_IOC_BEACON_INTERVAL:
2265 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2266 ic->ic_opmode != IEEE80211_M_IBSS)
2268 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2269 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2270 ic->ic_bintval = ireq->i_val;
2271 error = ENETRESET; /* requires restart */
2275 case IEEE80211_IOC_PUREG:
2277 ic->ic_flags |= IEEE80211_F_PUREG;
2279 ic->ic_flags &= ~IEEE80211_F_PUREG;
2280 /* NB: reset only if we're operating on an 11g channel */
2281 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2282 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2285 case IEEE80211_IOC_FF:
2287 if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2289 ic->ic_flags |= IEEE80211_F_FF;
2291 ic->ic_flags &= ~IEEE80211_F_FF;
2294 case IEEE80211_IOC_TURBOP:
2296 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2298 ic->ic_flags |= IEEE80211_F_TURBOP;
2300 ic->ic_flags &= ~IEEE80211_F_TURBOP;
2303 case IEEE80211_IOC_BGSCAN:
2305 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2307 ic->ic_flags |= IEEE80211_F_BGSCAN;
2309 ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2311 case IEEE80211_IOC_BGSCAN_IDLE:
2312 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2313 ic->ic_bgscanidle = ireq->i_val*hz/1000;
2317 case IEEE80211_IOC_BGSCAN_INTERVAL:
2318 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2319 ic->ic_bgscanintvl = ireq->i_val*hz;
2323 case IEEE80211_IOC_SCANVALID:
2324 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2325 ic->ic_scanvalid = ireq->i_val*hz;
2329 case IEEE80211_IOC_ROAM_RSSI_11A:
2330 ic->ic_roam.rssi11a = ireq->i_val;
2332 case IEEE80211_IOC_ROAM_RSSI_11B:
2333 ic->ic_roam.rssi11bOnly = ireq->i_val;
2335 case IEEE80211_IOC_ROAM_RSSI_11G:
2336 ic->ic_roam.rssi11b = ireq->i_val;
2338 case IEEE80211_IOC_ROAM_RATE_11A:
2339 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2341 case IEEE80211_IOC_ROAM_RATE_11B:
2342 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2344 case IEEE80211_IOC_ROAM_RATE_11G:
2345 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2347 case IEEE80211_IOC_MCAST_RATE:
2348 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2350 case IEEE80211_IOC_FRAGTHRESHOLD:
2351 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2352 ireq->i_val != IEEE80211_FRAG_MAX)
2354 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2355 ireq->i_val <= IEEE80211_FRAG_MAX))
2357 ic->ic_fragthreshold = ireq->i_val;
2358 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2360 case IEEE80211_IOC_BURST:
2362 if ((ic->ic_caps & IEEE80211_C_BURST) == 0)
2364 ic->ic_flags |= IEEE80211_F_BURST;
2366 ic->ic_flags &= ~IEEE80211_F_BURST;
2367 error = ENETRESET; /* XXX maybe not for station? */
2369 case IEEE80211_IOC_BMISSTHRESHOLD:
2370 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2371 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2373 ic->ic_bmissthreshold = ireq->i_val;
2374 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2376 case IEEE80211_IOC_CURCHAN:
2377 error = ieee80211_ioctl_setcurchan(ic, ireq);
2379 case IEEE80211_IOC_SHORTGI:
2381 #define IEEE80211_HTCAP_SHORTGI \
2382 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2383 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2385 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2386 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2387 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2388 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2389 #undef IEEE80211_HTCAP_SHORTGI
2392 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2393 /* XXX kick state machine? */
2394 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2396 case IEEE80211_IOC_AMPDU:
2398 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2400 if (ireq->i_val & 1)
2401 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2402 if (ireq->i_val & 2)
2403 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2406 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2407 /* NB: reset only if we're operating on an 11n channel */
2408 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2409 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2412 case IEEE80211_IOC_AMPDU_LIMIT:
2414 ic->ic_ampdu_limit = ireq->i_val;
2416 case IEEE80211_IOC_AMPDU_DENSITY:
2418 ic->ic_ampdu_density = ireq->i_val;
2420 case IEEE80211_IOC_AMSDU:
2422 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2424 if (ireq->i_val & 1)
2425 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2426 if (ireq->i_val & 2)
2427 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2430 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2431 /* NB: reset only if we're operating on an 11n channel */
2432 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2433 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2436 case IEEE80211_IOC_AMSDU_LIMIT:
2438 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */
2440 case IEEE80211_IOC_PUREN:
2442 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2444 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2446 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2447 /* NB: reset only if we're operating on an 11n channel */
2448 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2449 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2452 case IEEE80211_IOC_DOTH:
2455 /* XXX no capability */
2456 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2459 ic->ic_flags |= IEEE80211_F_DOTH;
2461 ic->ic_flags &= ~IEEE80211_F_DOTH;
2462 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2464 case IEEE80211_IOC_HTCOMPAT:
2466 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2468 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2470 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2471 /* NB: reset only if we're operating on an 11n channel */
2472 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2473 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2476 case IEEE80211_IOC_INACTIVITY:
2478 ic->ic_flags_ext |= IEEE80211_FEXT_INACT;
2480 ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT;
2486 if (error == ENETRESET)
2487 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2492 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2494 struct ifnet *ifp = ic->ic_ifp;
2497 struct ifaddr *ifa; /* XXX */
2502 error = ifmedia_ioctl(ifp, (struct ifreq *) data,
2503 &ic->ic_media, cmd);
2506 error = ieee80211_ioctl_get80211(ic, cmd,
2507 (struct ieee80211req *) data);
2510 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2512 error = ieee80211_ioctl_set80211(ic, cmd,
2513 (struct ieee80211req *) data);
2515 case SIOCG80211STATS:
2516 ifr = (struct ifreq *)data;
2517 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2520 ifr = (struct ifreq *)data;
2521 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2522 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
2525 ifp->if_mtu = ifr->ifr_mtu;
2529 * XXX Handle this directly so we can supress if_init calls.
2530 * XXX This should be done in ether_ioctl but for the moment
2531 * XXX there are too many other parts of the system that
2532 * XXX set IFF_UP and so supress if_init being called when
2535 ifa = (struct ifaddr *) data;
2536 switch (ifa->ifa_addr->sa_family) {
2539 if ((ifp->if_flags & IFF_UP) == 0) {
2540 ifp->if_flags |= IFF_UP;
2541 ifp->if_init(ifp->if_softc);
2543 arp_ifinit(ifp, ifa);
2548 * XXX - This code is probably wrong,
2549 * but has been copied many times.
2552 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2554 if (ipx_nullhost(*ina))
2555 ina->x_host = *(union ipx_host *)
2558 bcopy((caddr_t) ina->x_host.c_host,
2559 (caddr_t) IF_LLADDR(ifp),
2565 if ((ifp->if_flags & IFF_UP) == 0) {
2566 ifp->if_flags |= IFF_UP;
2567 ifp->if_init(ifp->if_softc);
2573 error = ether_ioctl(ifp, cmd, data);