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;
1116 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq)
1122 * NB: Doing this for ap operation could be useful (e.g. for
1123 * WPA and/or WME) except that it typically is worthless
1124 * without being able to intervene when processing
1125 * association response frames--so disallow it for now.
1127 if (ic->ic_opmode != IEEE80211_M_STA)
1129 if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1131 /* NB: data.length is validated by the wireless extensions code */
1132 /* XXX M_WAITOK after driver lock released */
1133 if (ireq->i_len > 0) {
1134 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1137 error = copyin(ireq->i_data, ie, ireq->i_len);
1146 /* XXX sanity check data? */
1147 oie = ic->ic_opt_ie;
1149 ic->ic_opt_ie_len = ireq->i_len;
1151 FREE(oie, M_DEVBUF);
1156 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1158 struct ieee80211req_key ik;
1159 struct ieee80211_node *ni;
1160 struct ieee80211_key *wk;
1164 if (ireq->i_len != sizeof(ik))
1166 error = copyin(ireq->i_data, &ik, sizeof(ik));
1169 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1170 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1171 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1174 if (kid == IEEE80211_KEYIX_NONE) {
1175 /* XXX unicast keys currently must be tx/rx */
1176 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1178 if (ic->ic_opmode == IEEE80211_M_STA) {
1179 ni = ieee80211_ref_node(ic->ic_bss);
1180 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1181 ieee80211_free_node(ni);
1182 return EADDRNOTAVAIL;
1185 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
1189 wk = &ni->ni_ucastkey;
1191 if (kid >= IEEE80211_WEP_NKID)
1193 wk = &ic->ic_nw_keys[kid];
1195 * Global slots start off w/o any assigned key index.
1196 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1198 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1203 ieee80211_key_update_begin(ic);
1204 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) {
1205 wk->wk_keylen = ik.ik_keylen;
1206 /* NB: MIC presence is implied by cipher type */
1207 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1208 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1209 wk->wk_keyrsc = ik.ik_keyrsc;
1210 wk->wk_keytsc = 0; /* new key, reset */
1211 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1212 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1213 if (!ieee80211_crypto_setkey(ic, wk,
1214 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr))
1216 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1217 ic->ic_def_txkey = kid;
1220 ieee80211_key_update_end(ic);
1222 ieee80211_free_node(ni);
1227 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1229 struct ieee80211req_del_key dk;
1232 if (ireq->i_len != sizeof(dk))
1234 error = copyin(ireq->i_data, &dk, sizeof(dk));
1238 /* XXX uint8_t -> uint16_t */
1239 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1240 struct ieee80211_node *ni;
1242 if (ic->ic_opmode == IEEE80211_M_STA) {
1243 ni = ieee80211_ref_node(ic->ic_bss);
1244 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1245 ieee80211_free_node(ni);
1246 return EADDRNOTAVAIL;
1249 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr);
1253 /* XXX error return */
1254 ieee80211_node_delucastkey(ni);
1255 ieee80211_free_node(ni);
1257 if (kid >= IEEE80211_WEP_NKID)
1259 /* XXX error return */
1260 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]);
1266 domlme(void *arg, struct ieee80211_node *ni)
1268 struct ieee80211com *ic = ni->ni_ic;
1269 struct ieee80211req_mlme *mlme = arg;
1271 if (ni->ni_associd != 0) {
1272 IEEE80211_SEND_MGMT(ic, ni,
1273 mlme->im_op == IEEE80211_MLME_DEAUTH ?
1274 IEEE80211_FC0_SUBTYPE_DEAUTH :
1275 IEEE80211_FC0_SUBTYPE_DISASSOC,
1278 ieee80211_node_leave(ic, ni);
1284 const uint8_t *essid;
1285 const struct ieee80211_scan_entry *se;
1289 * Match mac address and any ssid.
1292 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1294 struct scanlookup *look = arg;
1296 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1298 if (look->esslen != 0) {
1299 if (se->se_ssid[1] != look->esslen)
1301 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1308 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1310 struct ieee80211req_mlme mlme;
1311 struct ieee80211_node *ni;
1314 if (ireq->i_len != sizeof(mlme))
1316 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1319 switch (mlme.im_op) {
1320 case IEEE80211_MLME_ASSOC:
1321 /* XXX ibss/ahdemo */
1322 if (ic->ic_opmode == IEEE80211_M_STA) {
1323 struct scanlookup lookup;
1326 lookup.mac = mlme.im_macaddr;
1327 /* XXX use revised api w/ explicit ssid */
1328 lookup.esslen = ic->ic_des_ssid[0].len;
1329 lookup.essid = ic->ic_des_ssid[0].ssid;
1330 ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1331 if (lookup.se != NULL &&
1332 ieee80211_sta_join(ic, lookup.se))
1336 case IEEE80211_MLME_DISASSOC:
1337 case IEEE80211_MLME_DEAUTH:
1338 switch (ic->ic_opmode) {
1339 case IEEE80211_M_STA:
1340 /* XXX not quite right */
1341 ieee80211_new_state(ic, IEEE80211_S_INIT,
1344 case IEEE80211_M_HOSTAP:
1345 /* NB: the broadcast address means do 'em all */
1346 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) {
1347 if ((ni = ieee80211_find_node(&ic->ic_sta,
1348 mlme.im_macaddr)) == NULL)
1351 ieee80211_free_node(ni);
1353 ieee80211_iterate_nodes(&ic->ic_sta,
1361 case IEEE80211_MLME_AUTHORIZE:
1362 case IEEE80211_MLME_UNAUTHORIZE:
1363 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1365 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr);
1368 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
1369 ieee80211_node_authorize(ni);
1371 ieee80211_node_unauthorize(ni);
1372 ieee80211_free_node(ni);
1381 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1383 uint8_t mac[IEEE80211_ADDR_LEN];
1384 const struct ieee80211_aclator *acl = ic->ic_acl;
1387 if (ireq->i_len != sizeof(mac))
1389 error = copyin(ireq->i_data, mac, ireq->i_len);
1393 acl = ieee80211_aclator_get("mac");
1394 if (acl == NULL || !acl->iac_attach(ic))
1398 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1399 acl->iac_add(ic, mac);
1401 acl->iac_remove(ic, mac);
1406 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1408 const struct ieee80211_aclator *acl = ic->ic_acl;
1410 switch (ireq->i_val) {
1411 case IEEE80211_MACCMD_POLICY_OPEN:
1412 case IEEE80211_MACCMD_POLICY_ALLOW:
1413 case IEEE80211_MACCMD_POLICY_DENY:
1415 acl = ieee80211_aclator_get("mac");
1416 if (acl == NULL || !acl->iac_attach(ic))
1420 acl->iac_setpolicy(ic, ireq->i_val);
1422 case IEEE80211_MACCMD_FLUSH:
1425 /* NB: silently ignore when not in use */
1427 case IEEE80211_MACCMD_DETACH:
1430 acl->iac_detach(ic);
1437 return acl->iac_setioctl(ic, ireq);
1443 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1445 struct ieee80211req_chanlist list;
1446 u_char chanlist[IEEE80211_CHAN_BYTES];
1447 int i, j, nchan, error;
1449 if (ireq->i_len != sizeof(list))
1451 error = copyin(ireq->i_data, &list, sizeof(list));
1454 memset(chanlist, 0, sizeof(chanlist));
1456 * Since channel 0 is not available for DS, channel 1
1457 * is assigned to LSB on WaveLAN.
1459 if (ic->ic_phytype == IEEE80211_T_DS)
1464 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1466 * NB: silently discard unavailable channels so users
1467 * can specify 1-255 to get all available channels.
1469 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
1470 setbit(chanlist, i);
1476 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1477 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1478 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1479 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1480 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
1484 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1486 struct ieee80211_node *ni;
1487 uint8_t macaddr[IEEE80211_ADDR_LEN];
1491 * NB: we could copyin ieee80211req_sta_stats so apps
1492 * could make selective changes but that's overkill;
1493 * just clear all stats for now.
1495 if (ireq->i_len < IEEE80211_ADDR_LEN)
1497 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1500 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1502 return EINVAL; /* XXX */
1503 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1504 ieee80211_free_node(ni);
1509 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
1511 struct ieee80211_node *ni;
1512 struct ieee80211req_sta_txpow txpow;
1515 if (ireq->i_len != sizeof(txpow))
1517 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1520 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
1522 return EINVAL; /* XXX */
1523 ni->ni_txpower = txpow.it_txpow;
1524 ieee80211_free_node(ni);
1529 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
1531 struct ieee80211_wme_state *wme = &ic->ic_wme;
1532 struct wmeParams *wmep, *chanp;
1535 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1538 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1539 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1540 if (ac >= WME_NUM_AC)
1543 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1544 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1546 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1547 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1549 switch (ireq->i_type) {
1550 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1552 wmep->wmep_logcwmin = ireq->i_val;
1553 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1554 chanp->wmep_logcwmin = ireq->i_val;
1556 wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1560 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1562 wmep->wmep_logcwmax = ireq->i_val;
1563 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1564 chanp->wmep_logcwmax = ireq->i_val;
1566 wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1570 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1572 wmep->wmep_aifsn = ireq->i_val;
1573 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1574 chanp->wmep_aifsn = ireq->i_val;
1576 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1579 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1581 wmep->wmep_txopLimit = ireq->i_val;
1582 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1583 chanp->wmep_txopLimit = ireq->i_val;
1585 wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1589 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1590 wmep->wmep_acm = ireq->i_val;
1591 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1592 chanp->wmep_acm = ireq->i_val;
1594 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1595 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1599 ieee80211_wme_updateparams(ic);
1604 cipher2cap(int cipher)
1607 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP;
1608 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES;
1609 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM;
1610 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP;
1611 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP;
1617 find11gchannel(struct ieee80211com *ic, int start, int freq)
1619 const struct ieee80211_channel *c;
1622 for (i = start+1; i < ic->ic_nchans; i++) {
1623 c = &ic->ic_channels[i];
1624 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1627 /* NB: should not be needed but in case things are mis-sorted */
1628 for (i = 0; i < start; i++) {
1629 c = &ic->ic_channels[i];
1630 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1636 static struct ieee80211_channel *
1637 findchannel(struct ieee80211com *ic, int ieee, int mode)
1639 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1640 0, /* IEEE80211_MODE_AUTO */
1641 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
1642 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
1643 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */
1644 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
1645 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */
1646 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */
1647 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */
1648 /* NB: handled specially below */
1649 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */
1650 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */
1655 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1656 modeflags = chanflags[mode];
1657 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1658 ("no chanflags for mode %u", mode));
1659 for (i = 0; i < ic->ic_nchans; i++) {
1660 struct ieee80211_channel *c = &ic->ic_channels[i];
1662 if (c->ic_ieee != ieee)
1664 if (mode == IEEE80211_MODE_AUTO) {
1665 /* ignore turbo channels for autoselect */
1666 if (IEEE80211_IS_CHAN_TURBO(c))
1669 * XXX special-case 11b/g channels so we
1670 * always select the g channel if both
1672 * XXX prefer HT to non-HT?
1674 if (!IEEE80211_IS_CHAN_B(c) ||
1675 !find11gchannel(ic, i, c->ic_freq))
1678 /* must check HT specially */
1679 if ((mode == IEEE80211_MODE_11NA ||
1680 mode == IEEE80211_MODE_11NG) &&
1681 !IEEE80211_IS_CHAN_HT(c))
1683 if ((c->ic_flags & modeflags) == modeflags)
1691 * Check the specified against any desired mode (aka netband).
1692 * This is only used (presently) when operating in hostap mode
1693 * to enforce consistency.
1696 check_mode_consistency(const struct ieee80211_channel *c, int mode)
1698 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1701 case IEEE80211_MODE_11B:
1702 return (IEEE80211_IS_CHAN_B(c));
1703 case IEEE80211_MODE_11G:
1704 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1705 case IEEE80211_MODE_11A:
1706 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1707 case IEEE80211_MODE_STURBO_A:
1708 return (IEEE80211_IS_CHAN_STURBO(c));
1709 case IEEE80211_MODE_11NA:
1710 return (IEEE80211_IS_CHAN_HTA(c));
1711 case IEEE80211_MODE_11NG:
1712 return (IEEE80211_IS_CHAN_HTG(c));
1719 * Common code to set the current channel. If the device
1720 * is up and running this may result in an immediate channel
1721 * change or a kick of the state machine.
1724 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1728 if (c != IEEE80211_CHAN_ANYC) {
1729 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1730 !check_mode_consistency(c, ic->ic_des_mode))
1732 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1733 return 0; /* NB: nothing to do */
1735 ic->ic_des_chan = c;
1738 if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1739 ic->ic_opmode == IEEE80211_M_WDS) &&
1740 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1742 * Monitor and wds modes can switch directly.
1744 ic->ic_curchan = ic->ic_des_chan;
1745 if (ic->ic_state == IEEE80211_S_RUN)
1746 ic->ic_set_channel(ic);
1749 * Need to go through the state machine in case we
1750 * need to reassociate or the like. The state machine
1751 * will pickup the desired channel and avoid scanning.
1754 error = ieee80211_init(ic, RESCAN);
1755 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1757 * When not up+running and a real channel has
1758 * been specified fix the current channel so
1759 * there is immediate feedback; e.g. via ifconfig.
1761 ic->ic_curchan = ic->ic_des_chan;
1768 * Old api for setting the current channel; this is
1769 * deprecated because channel numbers are ambiguous.
1772 ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1773 const struct ieee80211req *ireq)
1775 struct ieee80211_channel *c;
1777 /* XXX 0xffff overflows 16-bit signed */
1778 if (ireq->i_val == 0 ||
1779 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1780 c = IEEE80211_CHAN_ANYC;
1781 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1784 struct ieee80211_channel *c2;
1786 c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1788 c = findchannel(ic, ireq->i_val,
1789 IEEE80211_MODE_AUTO);
1794 * Fine tune channel selection based on desired mode:
1795 * if 11b is requested, find the 11b version of any
1796 * 11g channel returned,
1797 * if static turbo, find the turbo version of any
1798 * 11a channel return,
1799 * if 11na is requested, find the ht version of any
1800 * 11a channel returned,
1801 * if 11ng is requested, find the ht version of any
1802 * 11g channel returned,
1803 * otherwise we should be ok with what we've got.
1805 switch (ic->ic_des_mode) {
1806 case IEEE80211_MODE_11B:
1807 if (IEEE80211_IS_CHAN_ANYG(c)) {
1808 c2 = findchannel(ic, ireq->i_val,
1809 IEEE80211_MODE_11B);
1810 /* NB: should not happen, =>'s 11g w/o 11b */
1815 case IEEE80211_MODE_TURBO_A:
1816 if (IEEE80211_IS_CHAN_A(c)) {
1817 c2 = findchannel(ic, ireq->i_val,
1818 IEEE80211_MODE_TURBO_A);
1823 case IEEE80211_MODE_11NA:
1824 if (IEEE80211_IS_CHAN_A(c)) {
1825 c2 = findchannel(ic, ireq->i_val,
1826 IEEE80211_MODE_11NA);
1831 case IEEE80211_MODE_11NG:
1832 if (IEEE80211_IS_CHAN_ANYG(c)) {
1833 c2 = findchannel(ic, ireq->i_val,
1834 IEEE80211_MODE_11NG);
1839 default: /* NB: no static turboG */
1843 return setcurchan(ic, c);
1847 * New/current api for setting the current channel; a complete
1848 * channel description is provide so there is no ambiguity in
1849 * identifying the channel.
1852 ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1853 const struct ieee80211req *ireq)
1855 struct ieee80211_channel chan, *c;
1858 if (ireq->i_len != sizeof(chan))
1860 error = copyin(ireq->i_data, &chan, sizeof(chan));
1863 /* XXX 0xffff overflows 16-bit signed */
1864 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1865 c = IEEE80211_CHAN_ANYC;
1867 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1871 return setcurchan(ic, c);
1875 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1877 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1878 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1880 const struct ieee80211_authenticator *auth;
1881 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1882 char tmpssid[IEEE80211_NWID_LEN];
1883 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
1884 struct ieee80211_key *k;
1889 switch (ireq->i_type) {
1890 case IEEE80211_IOC_SSID:
1891 if (ireq->i_val != 0 ||
1892 ireq->i_len > IEEE80211_NWID_LEN)
1894 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1897 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1898 ic->ic_des_ssid[0].len = ireq->i_len;
1899 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1900 ic->ic_des_nssid = (ireq->i_len > 0);
1902 error = ieee80211_init(ic, RESCAN);
1904 case IEEE80211_IOC_WEP:
1905 switch (ireq->i_val) {
1906 case IEEE80211_WEP_OFF:
1907 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1908 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1910 case IEEE80211_WEP_ON:
1911 ic->ic_flags |= IEEE80211_F_PRIVACY;
1912 ic->ic_flags |= IEEE80211_F_DROPUNENC;
1914 case IEEE80211_WEP_MIXED:
1915 ic->ic_flags |= IEEE80211_F_PRIVACY;
1916 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1920 error = ieee80211_init(ic, RESCAN);
1922 case IEEE80211_IOC_WEPKEY:
1923 kid = (u_int) ireq->i_val;
1924 if (kid >= IEEE80211_WEP_NKID)
1926 k = &ic->ic_nw_keys[kid];
1927 if (ireq->i_len == 0) {
1928 /* zero-len =>'s delete any existing key */
1929 (void) ieee80211_crypto_delkey(ic, k);
1932 if (ireq->i_len > sizeof(tmpkey))
1934 memset(tmpkey, 0, sizeof(tmpkey));
1935 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
1938 ieee80211_key_update_begin(ic);
1939 k->wk_keyix = kid; /* NB: force fixed key id */
1940 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP,
1941 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1942 k->wk_keylen = ireq->i_len;
1943 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1944 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1948 ieee80211_key_update_end(ic);
1950 case IEEE80211_IOC_WEPTXKEY:
1951 kid = (u_int) ireq->i_val;
1952 if (kid >= IEEE80211_WEP_NKID &&
1953 (uint16_t) kid != IEEE80211_KEYIX_NONE)
1955 ic->ic_def_txkey = kid;
1957 case IEEE80211_IOC_AUTHMODE:
1958 switch (ireq->i_val) {
1959 case IEEE80211_AUTH_WPA:
1960 case IEEE80211_AUTH_8021X: /* 802.1x */
1961 case IEEE80211_AUTH_OPEN: /* open */
1962 case IEEE80211_AUTH_SHARED: /* shared-key */
1963 case IEEE80211_AUTH_AUTO: /* auto */
1964 auth = ieee80211_authenticator_get(ireq->i_val);
1971 switch (ireq->i_val) {
1972 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
1973 ic->ic_flags |= IEEE80211_F_PRIVACY;
1974 ireq->i_val = IEEE80211_AUTH_8021X;
1976 case IEEE80211_AUTH_OPEN: /* open */
1977 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
1979 case IEEE80211_AUTH_SHARED: /* shared-key */
1980 case IEEE80211_AUTH_8021X: /* 802.1x */
1981 ic->ic_flags &= ~IEEE80211_F_WPA;
1982 /* both require a key so mark the PRIVACY capability */
1983 ic->ic_flags |= IEEE80211_F_PRIVACY;
1985 case IEEE80211_AUTH_AUTO: /* auto */
1986 ic->ic_flags &= ~IEEE80211_F_WPA;
1987 /* XXX PRIVACY handling? */
1988 /* XXX what's the right way to do this? */
1991 /* NB: authenticator attach/detach happens on state change */
1992 ic->ic_bss->ni_authmode = ireq->i_val;
1993 /* XXX mixed/mode/usage? */
1996 error = ieee80211_init(ic, RESCAN);
1998 case IEEE80211_IOC_CHANNEL:
1999 error = ieee80211_ioctl_setchannel(ic, ireq);
2001 case IEEE80211_IOC_POWERSAVE:
2002 switch (ireq->i_val) {
2003 case IEEE80211_POWERSAVE_OFF:
2004 if (ic->ic_flags & IEEE80211_F_PMGTON) {
2005 ic->ic_flags &= ~IEEE80211_F_PMGTON;
2009 case IEEE80211_POWERSAVE_ON:
2010 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
2012 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
2013 ic->ic_flags |= IEEE80211_F_PMGTON;
2021 if (error == ENETRESET) {
2023 * Switching in+out of power save mode
2024 * should not require a state change.
2026 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2029 case IEEE80211_IOC_POWERSAVESLEEP:
2030 if (ireq->i_val < 0)
2032 ic->ic_lintval = ireq->i_val;
2033 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2035 case IEEE80211_IOC_RTSTHRESHOLD:
2036 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2037 ireq->i_val <= IEEE80211_RTS_MAX))
2039 ic->ic_rtsthreshold = ireq->i_val;
2040 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2042 case IEEE80211_IOC_PROTMODE:
2043 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2045 ic->ic_protmode = ireq->i_val;
2046 /* NB: if not operating in 11g this can wait */
2047 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2048 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2049 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2051 case IEEE80211_IOC_TXPOWER:
2052 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2054 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2055 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2057 ic->ic_txpowlimit = ireq->i_val;
2058 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2060 case IEEE80211_IOC_ROAMING:
2061 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2062 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2064 ic->ic_roaming = ireq->i_val;
2067 case IEEE80211_IOC_PRIVACY:
2069 /* XXX check for key state? */
2070 ic->ic_flags |= IEEE80211_F_PRIVACY;
2072 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2074 case IEEE80211_IOC_DROPUNENCRYPTED:
2076 ic->ic_flags |= IEEE80211_F_DROPUNENC;
2078 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2080 case IEEE80211_IOC_WPAKEY:
2081 error = ieee80211_ioctl_setkey(ic, ireq);
2083 case IEEE80211_IOC_DELKEY:
2084 error = ieee80211_ioctl_delkey(ic, ireq);
2086 case IEEE80211_IOC_MLME:
2087 error = ieee80211_ioctl_setmlme(ic, ireq);
2089 case IEEE80211_IOC_OPTIE:
2090 error = ieee80211_ioctl_setoptie(ic, ireq);
2092 case IEEE80211_IOC_COUNTERMEASURES:
2094 if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
2096 ic->ic_flags |= IEEE80211_F_COUNTERM;
2098 ic->ic_flags &= ~IEEE80211_F_COUNTERM;
2100 case IEEE80211_IOC_WPA:
2101 if (ireq->i_val > 3)
2103 /* XXX verify ciphers available */
2104 ic->ic_flags &= ~IEEE80211_F_WPA;
2105 switch (ireq->i_val) {
2107 ic->ic_flags |= IEEE80211_F_WPA1;
2110 ic->ic_flags |= IEEE80211_F_WPA2;
2113 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2118 case IEEE80211_IOC_WME:
2120 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2122 ic->ic_flags |= IEEE80211_F_WME;
2124 ic->ic_flags &= ~IEEE80211_F_WME;
2126 error = ieee80211_init(ic, 0);
2128 case IEEE80211_IOC_HIDESSID:
2130 ic->ic_flags |= IEEE80211_F_HIDESSID;
2132 ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2135 case IEEE80211_IOC_APBRIDGE:
2136 if (ireq->i_val == 0)
2137 ic->ic_flags |= IEEE80211_F_NOBRIDGE;
2139 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE;
2141 case IEEE80211_IOC_MCASTCIPHER:
2142 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 &&
2143 !ieee80211_crypto_available(ireq->i_val))
2145 rsn->rsn_mcastcipher = ireq->i_val;
2146 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2148 case IEEE80211_IOC_MCASTKEYLEN:
2149 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2151 /* XXX no way to verify driver capability */
2152 rsn->rsn_mcastkeylen = ireq->i_val;
2153 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2155 case IEEE80211_IOC_UCASTCIPHERS:
2157 * Convert user-specified cipher set to the set
2158 * we can support (via hardware or software).
2159 * NB: this logic intentionally ignores unknown and
2160 * unsupported ciphers so folks can specify 0xff or
2161 * similar and get all available ciphers.
2164 for (j = 1; j < 32; j++) /* NB: skip WEP */
2165 if ((ireq->i_val & (1<<j)) &&
2166 ((ic->ic_caps & cipher2cap(j)) ||
2167 ieee80211_crypto_available(j)))
2169 if (caps == 0) /* nothing available */
2171 /* XXX verify ciphers ok for unicast use? */
2172 /* XXX disallow if running as it'll have no effect */
2173 rsn->rsn_ucastcipherset = caps;
2174 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2176 case IEEE80211_IOC_UCASTCIPHER:
2177 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0)
2179 rsn->rsn_ucastcipher = ireq->i_val;
2181 case IEEE80211_IOC_UCASTKEYLEN:
2182 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2184 /* XXX no way to verify driver capability */
2185 rsn->rsn_ucastkeylen = ireq->i_val;
2187 case IEEE80211_IOC_DRIVER_CAPS:
2188 /* NB: for testing */
2189 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2190 ((uint16_t) ireq->i_len);
2192 case IEEE80211_IOC_KEYMGTALGS:
2194 rsn->rsn_keymgmtset = ireq->i_val;
2195 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2197 case IEEE80211_IOC_RSNCAPS:
2199 rsn->rsn_caps = ireq->i_val;
2200 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2202 case IEEE80211_IOC_BSSID:
2203 if (ireq->i_len != sizeof(tmpbssid))
2205 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2208 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2209 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2210 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2212 ic->ic_flags |= IEEE80211_F_DESBSSID;
2214 error = ieee80211_init(ic, RESCAN);
2216 case IEEE80211_IOC_CHANLIST:
2217 error = ieee80211_ioctl_setchanlist(ic, ireq);
2219 case IEEE80211_IOC_SCAN_REQ:
2222 (void) ieee80211_start_scan(ic,
2223 IEEE80211_SCAN_ACTIVE |
2224 IEEE80211_SCAN_NOPICK |
2225 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2226 /* XXX use ioctl params */
2227 ic->ic_des_nssid, ic->ic_des_ssid);
2229 case IEEE80211_IOC_ADDMAC:
2230 case IEEE80211_IOC_DELMAC:
2231 error = ieee80211_ioctl_macmac(ic, ireq);
2233 case IEEE80211_IOC_MACCMD:
2234 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2236 case IEEE80211_IOC_STA_STATS:
2237 error = ieee80211_ioctl_setstastats(ic, ireq);
2239 case IEEE80211_IOC_STA_TXPOW:
2240 error = ieee80211_ioctl_setstatxpow(ic, ireq);
2242 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
2243 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
2244 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
2245 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
2246 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
2247 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
2248 error = ieee80211_ioctl_setwmeparam(ic, ireq);
2250 case IEEE80211_IOC_DTIM_PERIOD:
2251 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2252 ic->ic_opmode != IEEE80211_M_IBSS)
2254 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2255 ireq->i_val <= IEEE80211_DTIM_MAX) {
2256 ic->ic_dtim_period = ireq->i_val;
2257 error = ENETRESET; /* requires restart */
2261 case IEEE80211_IOC_BEACON_INTERVAL:
2262 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2263 ic->ic_opmode != IEEE80211_M_IBSS)
2265 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2266 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2267 ic->ic_bintval = ireq->i_val;
2268 error = ENETRESET; /* requires restart */
2272 case IEEE80211_IOC_PUREG:
2274 ic->ic_flags |= IEEE80211_F_PUREG;
2276 ic->ic_flags &= ~IEEE80211_F_PUREG;
2277 /* NB: reset only if we're operating on an 11g channel */
2278 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2279 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2282 case IEEE80211_IOC_FF:
2284 if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2286 ic->ic_flags |= IEEE80211_F_FF;
2288 ic->ic_flags &= ~IEEE80211_F_FF;
2291 case IEEE80211_IOC_TURBOP:
2293 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2295 ic->ic_flags |= IEEE80211_F_TURBOP;
2297 ic->ic_flags &= ~IEEE80211_F_TURBOP;
2300 case IEEE80211_IOC_BGSCAN:
2302 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2304 ic->ic_flags |= IEEE80211_F_BGSCAN;
2306 ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2308 case IEEE80211_IOC_BGSCAN_IDLE:
2309 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2310 ic->ic_bgscanidle = ireq->i_val*hz/1000;
2314 case IEEE80211_IOC_BGSCAN_INTERVAL:
2315 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2316 ic->ic_bgscanintvl = ireq->i_val*hz;
2320 case IEEE80211_IOC_SCANVALID:
2321 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2322 ic->ic_scanvalid = ireq->i_val*hz;
2326 case IEEE80211_IOC_ROAM_RSSI_11A:
2327 ic->ic_roam.rssi11a = ireq->i_val;
2329 case IEEE80211_IOC_ROAM_RSSI_11B:
2330 ic->ic_roam.rssi11bOnly = ireq->i_val;
2332 case IEEE80211_IOC_ROAM_RSSI_11G:
2333 ic->ic_roam.rssi11b = ireq->i_val;
2335 case IEEE80211_IOC_ROAM_RATE_11A:
2336 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2338 case IEEE80211_IOC_ROAM_RATE_11B:
2339 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2341 case IEEE80211_IOC_ROAM_RATE_11G:
2342 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2344 case IEEE80211_IOC_MCAST_RATE:
2345 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2347 case IEEE80211_IOC_FRAGTHRESHOLD:
2348 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2349 ireq->i_val != IEEE80211_FRAG_MAX)
2351 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2352 ireq->i_val <= IEEE80211_FRAG_MAX))
2354 ic->ic_fragthreshold = ireq->i_val;
2355 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2357 case IEEE80211_IOC_BURST:
2359 if ((ic->ic_caps & IEEE80211_C_BURST) == 0)
2361 ic->ic_flags |= IEEE80211_F_BURST;
2363 ic->ic_flags &= ~IEEE80211_F_BURST;
2364 error = ENETRESET; /* XXX maybe not for station? */
2366 case IEEE80211_IOC_BMISSTHRESHOLD:
2367 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2368 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2370 ic->ic_bmissthreshold = ireq->i_val;
2371 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2373 case IEEE80211_IOC_CURCHAN:
2374 error = ieee80211_ioctl_setcurchan(ic, ireq);
2376 case IEEE80211_IOC_SHORTGI:
2378 #define IEEE80211_HTCAP_SHORTGI \
2379 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2380 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2382 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2383 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2384 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2385 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2386 #undef IEEE80211_HTCAP_SHORTGI
2389 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2390 /* XXX kick state machine? */
2391 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2393 case IEEE80211_IOC_AMPDU:
2395 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2397 if (ireq->i_val & 1)
2398 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2399 if (ireq->i_val & 2)
2400 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2403 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2404 /* NB: reset only if we're operating on an 11n channel */
2405 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2406 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2409 case IEEE80211_IOC_AMPDU_LIMIT:
2411 ic->ic_ampdu_limit = ireq->i_val;
2413 case IEEE80211_IOC_AMPDU_DENSITY:
2415 ic->ic_ampdu_density = ireq->i_val;
2417 case IEEE80211_IOC_AMSDU:
2419 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2421 if (ireq->i_val & 1)
2422 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2423 if (ireq->i_val & 2)
2424 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2427 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2428 /* NB: reset only if we're operating on an 11n channel */
2429 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2430 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2433 case IEEE80211_IOC_AMSDU_LIMIT:
2435 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */
2437 case IEEE80211_IOC_PUREN:
2439 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2441 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2443 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2444 /* NB: reset only if we're operating on an 11n channel */
2445 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2446 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2449 case IEEE80211_IOC_DOTH:
2452 /* XXX no capability */
2453 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2456 ic->ic_flags |= IEEE80211_F_DOTH;
2458 ic->ic_flags &= ~IEEE80211_F_DOTH;
2459 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2461 case IEEE80211_IOC_HTCOMPAT:
2463 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2465 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2467 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2468 /* NB: reset only if we're operating on an 11n channel */
2469 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2470 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2477 if (error == ENETRESET)
2478 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2483 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2485 struct ifnet *ifp = ic->ic_ifp;
2488 struct ifaddr *ifa; /* XXX */
2493 error = ifmedia_ioctl(ifp, (struct ifreq *) data,
2494 &ic->ic_media, cmd);
2497 error = ieee80211_ioctl_get80211(ic, cmd,
2498 (struct ieee80211req *) data);
2501 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2503 error = ieee80211_ioctl_set80211(ic, cmd,
2504 (struct ieee80211req *) data);
2506 case SIOCG80211STATS:
2507 ifr = (struct ifreq *)data;
2508 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2511 ifr = (struct ifreq *)data;
2512 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2513 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
2516 ifp->if_mtu = ifr->ifr_mtu;
2520 * XXX Handle this directly so we can supress if_init calls.
2521 * XXX This should be done in ether_ioctl but for the moment
2522 * XXX there are too many other parts of the system that
2523 * XXX set IFF_UP and so supress if_init being called when
2526 ifa = (struct ifaddr *) data;
2527 switch (ifa->ifa_addr->sa_family) {
2530 if ((ifp->if_flags & IFF_UP) == 0) {
2531 ifp->if_flags |= IFF_UP;
2532 ifp->if_init(ifp->if_softc);
2534 arp_ifinit(ifp, ifa);
2539 * XXX - This code is probably wrong,
2540 * but has been copied many times.
2543 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2545 if (ipx_nullhost(*ina))
2546 ina->x_host = *(union ipx_host *)
2549 bcopy((caddr_t) ina->x_host.c_host,
2550 (caddr_t) IF_LLADDR(ifp),
2556 if ((ifp->if_flags & IFF_UP) == 0) {
2557 ifp->if_flags |= IFF_UP;
2558 ifp->if_init(ifp->if_softc);
2564 error = ether_ioctl(ifp, cmd, data);