2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2009 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.
26 * $FreeBSD: head/sys/net80211/ieee80211_ioctl.c 202935 2010-01-24 16:17:58Z syrinx $
30 * IEEE 802.11 ioctl support (DragonFlyBSD-specific)
37 #include <sys/endian.h>
38 #include <sys/param.h>
39 #include <sys/kernel.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
43 #include <sys/systm.h>
46 #include <net/if_var.h>
47 #include <net/if_dl.h>
48 #include <net/if_media.h>
49 #include <net/ethernet.h>
50 #include <net/route.h>
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
58 #include <netproto/ipx/ipx.h>
59 #include <netproto/ipx/ipx_if.h>
62 #include <netproto/802_11/ieee80211_var.h>
63 #include <netproto/802_11/ieee80211_ioctl.h>
64 #include <netproto/802_11/ieee80211_regdomain.h>
65 #include <netproto/802_11/ieee80211_input.h>
67 #define IS_UP_AUTO(_vap) \
68 (IFNET_IS_UP_RUNNING((_vap)->iv_ifp) && \
69 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO)
71 static const uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
72 static struct ieee80211_channel
*findchannel(struct ieee80211com
*,
76 ieee80211_ioctl_getkey(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
78 struct ieee80211com
*ic
= vap
->iv_ic
;
79 struct ieee80211_node
*ni
;
80 struct ieee80211req_key ik
;
81 struct ieee80211_key
*wk
;
82 const struct ieee80211_cipher
*cip
;
86 if (ireq
->i_len
!= sizeof(ik
))
88 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
92 if (kid
== IEEE80211_KEYIX_NONE
) {
93 ni
= ieee80211_find_vap_node(&ic
->ic_sta
, vap
, ik
.ik_macaddr
);
96 wk
= &ni
->ni_ucastkey
;
98 if (kid
>= IEEE80211_WEP_NKID
)
100 wk
= &vap
->iv_nw_keys
[kid
];
101 IEEE80211_ADDR_COPY(&ik
.ik_macaddr
, vap
->iv_bss
->ni_macaddr
);
105 ik
.ik_type
= cip
->ic_cipher
;
106 ik
.ik_keylen
= wk
->wk_keylen
;
107 ik
.ik_flags
= wk
->wk_flags
& (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
);
108 if (wk
->wk_keyix
== vap
->iv_def_txkey
)
109 ik
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
110 if (priv_check(curthread
, PRIV_NET80211_GETKEY
) == 0) {
111 /* NB: only root can read key data */
112 ik
.ik_keyrsc
= wk
->wk_keyrsc
[IEEE80211_NONQOS_TID
];
113 ik
.ik_keytsc
= wk
->wk_keytsc
;
114 memcpy(ik
.ik_keydata
, wk
->wk_key
, wk
->wk_keylen
);
115 if (cip
->ic_cipher
== IEEE80211_CIPHER_TKIP
) {
116 memcpy(ik
.ik_keydata
+wk
->wk_keylen
,
117 wk
->wk_key
+ IEEE80211_KEYBUF_SIZE
,
118 IEEE80211_MICBUF_SIZE
);
119 ik
.ik_keylen
+= IEEE80211_MICBUF_SIZE
;
124 memset(ik
.ik_keydata
, 0, sizeof(ik
.ik_keydata
));
127 ieee80211_free_node(ni
);
128 return copyout(&ik
, ireq
->i_data
, sizeof(ik
));
131 static __noinline
int
132 ieee80211_ioctl_getchanlist(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
134 struct ieee80211com
*ic
= vap
->iv_ic
;
136 if (sizeof(ic
->ic_chan_active
) < ireq
->i_len
)
137 ireq
->i_len
= sizeof(ic
->ic_chan_active
);
138 return copyout(&ic
->ic_chan_active
, ireq
->i_data
, ireq
->i_len
);
141 static __noinline
int
142 ieee80211_ioctl_getchaninfo(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
144 struct ieee80211com
*ic
= vap
->iv_ic
;
147 space
= __offsetof(struct ieee80211req_chaninfo
,
148 ic_chans
[ic
->ic_nchans
]);
149 if (space
> ireq
->i_len
)
151 /* XXX assumes compatible layout */
152 return copyout(&ic
->ic_nchans
, ireq
->i_data
, space
);
155 static __noinline
int
156 ieee80211_ioctl_getwpaie(struct ieee80211vap
*vap
,
157 struct ieee80211req
*ireq
, int req
)
159 struct ieee80211_node
*ni
;
160 struct ieee80211req_wpaie2 wpaie
;
163 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
165 error
= copyin(ireq
->i_data
, wpaie
.wpa_macaddr
, IEEE80211_ADDR_LEN
);
168 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, wpaie
.wpa_macaddr
);
171 memset(wpaie
.wpa_ie
, 0, sizeof(wpaie
.wpa_ie
));
172 if (ni
->ni_ies
.wpa_ie
!= NULL
) {
173 int ielen
= ni
->ni_ies
.wpa_ie
[1] + 2;
174 if (ielen
> sizeof(wpaie
.wpa_ie
))
175 ielen
= sizeof(wpaie
.wpa_ie
);
176 memcpy(wpaie
.wpa_ie
, ni
->ni_ies
.wpa_ie
, ielen
);
178 if (req
== IEEE80211_IOC_WPAIE2
) {
179 memset(wpaie
.rsn_ie
, 0, sizeof(wpaie
.rsn_ie
));
180 if (ni
->ni_ies
.rsn_ie
!= NULL
) {
181 int ielen
= ni
->ni_ies
.rsn_ie
[1] + 2;
182 if (ielen
> sizeof(wpaie
.rsn_ie
))
183 ielen
= sizeof(wpaie
.rsn_ie
);
184 memcpy(wpaie
.rsn_ie
, ni
->ni_ies
.rsn_ie
, ielen
);
186 if (ireq
->i_len
> sizeof(struct ieee80211req_wpaie2
))
187 ireq
->i_len
= sizeof(struct ieee80211req_wpaie2
);
189 /* compatibility op, may overwrite wpa ie */
190 /* XXX check ic_flags? */
191 if (ni
->ni_ies
.rsn_ie
!= NULL
) {
192 int ielen
= ni
->ni_ies
.rsn_ie
[1] + 2;
193 if (ielen
> sizeof(wpaie
.wpa_ie
))
194 ielen
= sizeof(wpaie
.wpa_ie
);
195 memcpy(wpaie
.wpa_ie
, ni
->ni_ies
.rsn_ie
, ielen
);
197 if (ireq
->i_len
> sizeof(struct ieee80211req_wpaie
))
198 ireq
->i_len
= sizeof(struct ieee80211req_wpaie
);
200 ieee80211_free_node(ni
);
201 return copyout(&wpaie
, ireq
->i_data
, ireq
->i_len
);
204 static __noinline
int
205 ieee80211_ioctl_getstastats(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
207 struct ieee80211_node
*ni
;
208 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
209 const int off
= __offsetof(struct ieee80211req_sta_stats
, is_stats
);
212 if (ireq
->i_len
< off
)
214 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
217 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
220 if (ireq
->i_len
> sizeof(struct ieee80211req_sta_stats
))
221 ireq
->i_len
= sizeof(struct ieee80211req_sta_stats
);
222 /* NB: copy out only the statistics */
223 error
= copyout(&ni
->ni_stats
, (uint8_t *) ireq
->i_data
+ off
,
225 ieee80211_free_node(ni
);
230 struct ieee80211req_scan_result
*sr
;
235 scan_space(const struct ieee80211_scan_entry
*se
, int *ielen
)
239 *ielen
= se
->se_ies
.len
;
241 * NB: ie's can be no more than 255 bytes and the max 802.11
242 * packet is <3Kbytes so we are sure this doesn't overflow
243 * 16-bits; if this is a concern we can drop the ie's.
245 len
= sizeof(struct ieee80211req_scan_result
) + se
->se_ssid
[1] +
246 se
->se_meshid
[1] + *ielen
;
247 return roundup(len
, sizeof(uint32_t));
251 get_scan_space(void *arg
, const struct ieee80211_scan_entry
*se
)
253 struct scanreq
*req
= arg
;
256 req
->space
+= scan_space(se
, &ielen
);
259 static __noinline
void
260 get_scan_result(void *arg
, const struct ieee80211_scan_entry
*se
)
262 struct scanreq
*req
= arg
;
263 struct ieee80211req_scan_result
*sr
;
264 int ielen
, len
, nr
, nxr
;
267 len
= scan_space(se
, &ielen
);
268 if (len
> req
->space
)
272 KASSERT(len
<= 65535 && ielen
<= 65535,
273 ("len %u ssid %u ie %u", len
, se
->se_ssid
[1], ielen
));
275 sr
->isr_ie_off
= sizeof(struct ieee80211req_scan_result
);
276 sr
->isr_ie_len
= ielen
;
277 sr
->isr_freq
= se
->se_chan
->ic_freq
;
278 sr
->isr_flags
= se
->se_chan
->ic_flags
;
279 sr
->isr_rssi
= se
->se_rssi
;
280 sr
->isr_noise
= se
->se_noise
;
281 sr
->isr_intval
= se
->se_intval
;
282 sr
->isr_capinfo
= se
->se_capinfo
;
283 sr
->isr_erp
= se
->se_erp
;
284 IEEE80211_ADDR_COPY(sr
->isr_bssid
, se
->se_bssid
);
285 nr
= min(se
->se_rates
[1], IEEE80211_RATE_MAXSIZE
);
286 memcpy(sr
->isr_rates
, se
->se_rates
+2, nr
);
287 nxr
= min(se
->se_xrates
[1], IEEE80211_RATE_MAXSIZE
- nr
);
288 memcpy(sr
->isr_rates
+nr
, se
->se_xrates
+2, nxr
);
289 sr
->isr_nrates
= nr
+ nxr
;
292 sr
->isr_ssid_len
= se
->se_ssid
[1];
293 cp
= ((uint8_t *)sr
) + sr
->isr_ie_off
;
294 memcpy(cp
, se
->se_ssid
+2, sr
->isr_ssid_len
);
297 cp
+= sr
->isr_ssid_len
;
298 sr
->isr_meshid_len
= se
->se_meshid
[1];
299 memcpy(cp
, se
->se_meshid
+2, sr
->isr_meshid_len
);
300 cp
+= sr
->isr_meshid_len
;
303 memcpy(cp
, se
->se_ies
.data
, ielen
);
306 req
->sr
= (struct ieee80211req_scan_result
*)(((uint8_t *)sr
) + len
);
309 static __noinline
int
310 ieee80211_ioctl_getscanresults(struct ieee80211vap
*vap
,
311 struct ieee80211req
*ireq
)
316 if (ireq
->i_len
< sizeof(struct scanreq
))
321 ieee80211_scan_iterate(vap
, get_scan_space
, &req
);
322 if (req
.space
> ireq
->i_len
)
323 req
.space
= ireq
->i_len
;
329 /* XXX M_WAITOK after driver lock released */
330 p
= kmalloc(space
, M_TEMP
, M_INTWAIT
| M_ZERO
);
334 ieee80211_scan_iterate(vap
, get_scan_result
, &req
);
335 ireq
->i_len
= space
- req
.space
;
336 error
= copyout(p
, ireq
->i_data
, ireq
->i_len
);
345 struct ieee80211vap
*vap
;
346 struct ieee80211req_sta_info
*si
;
351 sta_space(const struct ieee80211_node
*ni
, size_t *ielen
)
353 *ielen
= ni
->ni_ies
.len
;
354 return roundup(sizeof(struct ieee80211req_sta_info
) + *ielen
,
359 get_sta_space(void *arg
, struct ieee80211_node
*ni
)
361 struct stainforeq
*req
= arg
;
364 if (req
->vap
!= ni
->ni_vap
)
366 if (ni
->ni_vap
->iv_opmode
== IEEE80211_M_HOSTAP
&&
367 ni
->ni_associd
== 0) /* only associated stations */
369 req
->space
+= sta_space(ni
, &ielen
);
372 static __noinline
void
373 get_sta_info(void *arg
, struct ieee80211_node
*ni
)
375 struct stainforeq
*req
= arg
;
376 struct ieee80211vap
*vap
= ni
->ni_vap
;
377 struct ieee80211req_sta_info
*si
;
381 if (req
->vap
!= ni
->ni_vap
)
383 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
&&
384 ni
->ni_associd
== 0) /* only associated stations */
386 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
) /* XXX bogus entry */
388 len
= sta_space(ni
, &ielen
);
389 if (len
> req
->space
)
393 si
->isi_ie_off
= sizeof(struct ieee80211req_sta_info
);
394 si
->isi_ie_len
= ielen
;
395 si
->isi_freq
= ni
->ni_chan
->ic_freq
;
396 si
->isi_flags
= ni
->ni_chan
->ic_flags
;
397 si
->isi_state
= ni
->ni_flags
;
398 si
->isi_authmode
= ni
->ni_authmode
;
399 vap
->iv_ic
->ic_node_getsignal(ni
, &si
->isi_rssi
, &si
->isi_noise
);
400 vap
->iv_ic
->ic_node_getmimoinfo(ni
, &si
->isi_mimo
);
401 si
->isi_capinfo
= ni
->ni_capinfo
;
402 si
->isi_erp
= ni
->ni_erp
;
403 IEEE80211_ADDR_COPY(si
->isi_macaddr
, ni
->ni_macaddr
);
404 si
->isi_nrates
= ni
->ni_rates
.rs_nrates
;
405 if (si
->isi_nrates
> 15)
407 memcpy(si
->isi_rates
, ni
->ni_rates
.rs_rates
, si
->isi_nrates
);
408 si
->isi_txrate
= ni
->ni_txrate
;
409 if (si
->isi_txrate
& IEEE80211_RATE_MCS
) {
410 const struct ieee80211_mcs_rates
*mcs
=
411 &ieee80211_htrates
[ni
->ni_txrate
&~ IEEE80211_RATE_MCS
];
412 if (IEEE80211_IS_CHAN_HT40(ni
->ni_chan
)) {
413 if (ni
->ni_flags
& IEEE80211_NODE_SGI40
)
414 si
->isi_txmbps
= mcs
->ht40_rate_800ns
;
416 si
->isi_txmbps
= mcs
->ht40_rate_400ns
;
418 if (ni
->ni_flags
& IEEE80211_NODE_SGI20
)
419 si
->isi_txmbps
= mcs
->ht20_rate_800ns
;
421 si
->isi_txmbps
= mcs
->ht20_rate_400ns
;
424 si
->isi_txmbps
= si
->isi_txrate
;
425 si
->isi_associd
= ni
->ni_associd
;
426 si
->isi_txpower
= ni
->ni_txpower
;
427 si
->isi_vlan
= ni
->ni_vlan
;
428 if (ni
->ni_flags
& IEEE80211_NODE_QOS
) {
429 memcpy(si
->isi_txseqs
, ni
->ni_txseqs
, sizeof(ni
->ni_txseqs
));
430 memcpy(si
->isi_rxseqs
, ni
->ni_rxseqs
, sizeof(ni
->ni_rxseqs
));
432 si
->isi_txseqs
[0] = ni
->ni_txseqs
[IEEE80211_NONQOS_TID
];
433 si
->isi_rxseqs
[0] = ni
->ni_rxseqs
[IEEE80211_NONQOS_TID
];
435 /* NB: leave all cases in case we relax ni_associd == 0 check */
436 if (ieee80211_node_is_authorized(ni
))
437 si
->isi_inact
= vap
->iv_inact_run
;
438 else if (ni
->ni_associd
!= 0 ||
439 (vap
->iv_opmode
== IEEE80211_M_WDS
&&
440 (vap
->iv_flags_ext
& IEEE80211_FEXT_WDSLEGACY
)))
441 si
->isi_inact
= vap
->iv_inact_auth
;
443 si
->isi_inact
= vap
->iv_inact_init
;
444 si
->isi_inact
= (si
->isi_inact
- ni
->ni_inact
) * IEEE80211_INACT_WAIT
;
445 si
->isi_localid
= ni
->ni_mllid
;
446 si
->isi_peerid
= ni
->ni_mlpid
;
447 si
->isi_peerstate
= ni
->ni_mlstate
;
450 cp
= ((uint8_t *)si
) + si
->isi_ie_off
;
451 memcpy(cp
, ni
->ni_ies
.data
, ielen
);
454 req
->si
= (struct ieee80211req_sta_info
*)(((uint8_t *)si
) + len
);
458 static __noinline
int
459 getstainfo_common(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
,
460 struct ieee80211_node
*ni
, int off
)
462 struct ieee80211com
*ic
= vap
->iv_ic
;
463 struct stainforeq req
;
472 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_space
, &req
);
474 get_sta_space(&req
, ni
);
475 if (req
.space
> ireq
->i_len
)
476 req
.space
= ireq
->i_len
;
479 /* XXX M_WAITOK after driver lock released */
480 p
= kmalloc(space
, M_TEMP
, M_INTWAIT
| M_ZERO
);
487 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_info
, &req
);
489 get_sta_info(&req
, ni
);
490 ireq
->i_len
= space
- req
.space
;
491 error
= copyout(p
, (uint8_t *) ireq
->i_data
+off
, ireq
->i_len
);
497 ieee80211_free_node(ni
);
501 static __noinline
int
502 ieee80211_ioctl_getstainfo(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
504 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
505 const int off
= __offsetof(struct ieee80211req_sta_req
, info
);
506 struct ieee80211_node
*ni
;
509 if (ireq
->i_len
< sizeof(struct ieee80211req_sta_req
))
511 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
514 if (IEEE80211_ADDR_EQ(macaddr
, vap
->iv_ifp
->if_broadcastaddr
)) {
517 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
521 return getstainfo_common(vap
, ireq
, ni
, off
);
524 static __noinline
int
525 ieee80211_ioctl_getstatxpow(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
527 struct ieee80211_node
*ni
;
528 struct ieee80211req_sta_txpow txpow
;
531 if (ireq
->i_len
!= sizeof(txpow
))
533 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
536 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, txpow
.it_macaddr
);
539 txpow
.it_txpow
= ni
->ni_txpower
;
540 error
= copyout(&txpow
, ireq
->i_data
, sizeof(txpow
));
541 ieee80211_free_node(ni
);
545 static __noinline
int
546 ieee80211_ioctl_getwmeparam(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
548 struct ieee80211com
*ic
= vap
->iv_ic
;
549 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
550 struct wmeParams
*wmep
;
553 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
556 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
557 if (ac
>= WME_NUM_AC
)
559 if (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
)
560 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
562 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
563 switch (ireq
->i_type
) {
564 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
565 ireq
->i_val
= wmep
->wmep_logcwmin
;
567 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
568 ireq
->i_val
= wmep
->wmep_logcwmax
;
570 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
571 ireq
->i_val
= wmep
->wmep_aifsn
;
573 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
574 ireq
->i_val
= wmep
->wmep_txopLimit
;
576 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
577 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
578 ireq
->i_val
= wmep
->wmep_acm
;
580 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
581 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
582 ireq
->i_val
= !wmep
->wmep_noackPolicy
;
588 static __noinline
int
589 ieee80211_ioctl_getmaccmd(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
591 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
593 return (acl
== NULL
? EINVAL
: acl
->iac_getioctl(vap
, ireq
));
596 static __noinline
int
597 ieee80211_ioctl_getcurchan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
599 struct ieee80211com
*ic
= vap
->iv_ic
;
600 struct ieee80211_channel
*c
;
602 if (ireq
->i_len
!= sizeof(struct ieee80211_channel
))
605 * vap's may have different operating channels when HT is
606 * in use. When in RUN state report the vap-specific channel.
607 * Otherwise return curchan.
609 if (vap
->iv_state
== IEEE80211_S_RUN
)
610 c
= vap
->iv_bss
->ni_chan
;
613 return copyout(c
, ireq
->i_data
, sizeof(*c
));
617 getappie(const struct ieee80211_appie
*aie
, struct ieee80211req
*ireq
)
621 /* NB: truncate, caller can check length */
622 if (ireq
->i_len
> aie
->ie_len
)
623 ireq
->i_len
= aie
->ie_len
;
624 return copyout(aie
->ie_data
, ireq
->i_data
, ireq
->i_len
);
628 ieee80211_ioctl_getappie(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
632 fc0
= ireq
->i_val
& 0xff;
633 if ((fc0
& IEEE80211_FC0_TYPE_MASK
) != IEEE80211_FC0_TYPE_MGT
)
635 /* NB: could check iv_opmode and reject but hardly worth the effort */
636 switch (fc0
& IEEE80211_FC0_SUBTYPE_MASK
) {
637 case IEEE80211_FC0_SUBTYPE_BEACON
:
638 return getappie(vap
->iv_appie_beacon
, ireq
);
639 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
640 return getappie(vap
->iv_appie_proberesp
, ireq
);
641 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
642 return getappie(vap
->iv_appie_assocresp
, ireq
);
643 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
644 return getappie(vap
->iv_appie_probereq
, ireq
);
645 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
646 return getappie(vap
->iv_appie_assocreq
, ireq
);
647 case IEEE80211_FC0_SUBTYPE_BEACON
|IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
648 return getappie(vap
->iv_appie_wpa
, ireq
);
653 static __noinline
int
654 ieee80211_ioctl_getregdomain(struct ieee80211vap
*vap
,
655 const struct ieee80211req
*ireq
)
657 struct ieee80211com
*ic
= vap
->iv_ic
;
659 if (ireq
->i_len
!= sizeof(ic
->ic_regdomain
))
661 return copyout(&ic
->ic_regdomain
, ireq
->i_data
,
662 sizeof(ic
->ic_regdomain
));
665 static __noinline
int
666 ieee80211_ioctl_getroam(struct ieee80211vap
*vap
,
667 const struct ieee80211req
*ireq
)
669 size_t len
= ireq
->i_len
;
670 /* NB: accept short requests for backwards compat */
671 if (len
> sizeof(vap
->iv_roamparms
))
672 len
= sizeof(vap
->iv_roamparms
);
673 return copyout(vap
->iv_roamparms
, ireq
->i_data
, len
);
676 static __noinline
int
677 ieee80211_ioctl_gettxparams(struct ieee80211vap
*vap
,
678 const struct ieee80211req
*ireq
)
680 size_t len
= ireq
->i_len
;
681 /* NB: accept short requests for backwards compat */
682 if (len
> sizeof(vap
->iv_txparms
))
683 len
= sizeof(vap
->iv_txparms
);
684 return copyout(vap
->iv_txparms
, ireq
->i_data
, len
);
687 static __noinline
int
688 ieee80211_ioctl_getdevcaps(struct ieee80211com
*ic
,
689 const struct ieee80211req
*ireq
)
691 struct ieee80211_devcaps_req
*dc
;
692 struct ieee80211req_chaninfo
*ci
;
695 maxchans
= 1 + ((ireq
->i_len
- sizeof(struct ieee80211_devcaps_req
)) /
696 sizeof(struct ieee80211_channel
));
697 /* NB: require 1 so we know ic_nchans is accessible */
700 /* constrain max request size, 2K channels is ~24Kbytes */
703 dc
= (struct ieee80211_devcaps_req
*)
704 kmalloc(IEEE80211_DEVCAPS_SIZE(maxchans
), M_TEMP
,
708 dc
->dc_drivercaps
= ic
->ic_caps
;
709 dc
->dc_cryptocaps
= ic
->ic_cryptocaps
;
710 dc
->dc_htcaps
= ic
->ic_htcaps
;
711 ci
= &dc
->dc_chaninfo
;
712 ic
->ic_getradiocaps(ic
, maxchans
, &ci
->ic_nchans
, ci
->ic_chans
);
713 KASSERT(ci
->ic_nchans
<= maxchans
,
714 ("nchans %d maxchans %d", ci
->ic_nchans
, maxchans
));
715 ieee80211_sort_channels(ci
->ic_chans
, ci
->ic_nchans
);
716 error
= copyout(dc
, ireq
->i_data
, IEEE80211_DEVCAPS_SPACE(dc
));
721 static __noinline
int
722 ieee80211_ioctl_getstavlan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
724 struct ieee80211_node
*ni
;
725 struct ieee80211req_sta_vlan vlan
;
728 if (ireq
->i_len
!= sizeof(vlan
))
730 error
= copyin(ireq
->i_data
, &vlan
, sizeof(vlan
));
733 if (!IEEE80211_ADDR_EQ(vlan
.sv_macaddr
, zerobssid
)) {
734 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
739 ni
= ieee80211_ref_node(vap
->iv_bss
);
740 vlan
.sv_vlan
= ni
->ni_vlan
;
741 error
= copyout(&vlan
, ireq
->i_data
, sizeof(vlan
));
742 ieee80211_free_node(ni
);
747 * Dummy ioctl get handler so the linker set is defined.
750 dummy_ioctl_get(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
754 IEEE80211_IOCTL_GET(dummy
, dummy_ioctl_get
);
757 ieee80211_ioctl_getdefault(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
759 ieee80211_ioctl_getfunc
* const *get
;
762 SET_FOREACH(get
, ieee80211_ioctl_getset
) {
763 error
= (*get
)(vap
, ireq
);
771 * When building the kernel with -O2 on the i386 architecture, gcc
772 * seems to want to inline this function into ieee80211_ioctl()
773 * (which is the only routine that calls it). When this happens,
774 * ieee80211_ioctl() ends up consuming an additional 2K of stack
775 * space. (Exactly why it needs so much is unclear.) The problem
776 * is that it's possible for ieee80211_ioctl() to invoke other
777 * routines (including driver init functions) which could then find
778 * themselves perilously close to exhausting the stack.
780 * To avoid this, we deliberately prevent gcc from inlining this
781 * routine. Another way to avoid this is to use less agressive
782 * optimization when compiling this file (i.e. -O instead of -O2)
783 * but special-casing the compilation of this one module in the
784 * build system would be awkward.
786 static __noinline
int
787 ieee80211_ioctl_get80211(struct ieee80211vap
*vap
, u_long cmd
,
788 struct ieee80211req
*ireq
)
790 #define MS(_v, _f) (((_v) & _f) >> _f##_S)
791 struct ieee80211com
*ic
= vap
->iv_ic
;
793 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
794 char tmpssid
[IEEE80211_NWID_LEN
];
797 switch (ireq
->i_type
) {
798 case IEEE80211_IOC_SSID
:
799 switch (vap
->iv_state
) {
800 case IEEE80211_S_INIT
:
801 case IEEE80211_S_SCAN
:
802 ireq
->i_len
= vap
->iv_des_ssid
[0].len
;
803 memcpy(tmpssid
, vap
->iv_des_ssid
[0].ssid
, ireq
->i_len
);
806 ireq
->i_len
= vap
->iv_bss
->ni_esslen
;
807 memcpy(tmpssid
, vap
->iv_bss
->ni_essid
, ireq
->i_len
);
810 error
= copyout(tmpssid
, ireq
->i_data
, ireq
->i_len
);
812 case IEEE80211_IOC_NUMSSIDS
:
815 case IEEE80211_IOC_WEP
:
816 if ((vap
->iv_flags
& IEEE80211_F_PRIVACY
) == 0)
817 ireq
->i_val
= IEEE80211_WEP_OFF
;
818 else if (vap
->iv_flags
& IEEE80211_F_DROPUNENC
)
819 ireq
->i_val
= IEEE80211_WEP_ON
;
821 ireq
->i_val
= IEEE80211_WEP_MIXED
;
823 case IEEE80211_IOC_WEPKEY
:
824 kid
= (u_int
) ireq
->i_val
;
825 if (kid
>= IEEE80211_WEP_NKID
)
827 len
= (u_int
) vap
->iv_nw_keys
[kid
].wk_keylen
;
828 /* NB: only root can read WEP keys */
829 if (priv_check(curthread
, PRIV_NET80211_GETKEY
) == 0) {
830 bcopy(vap
->iv_nw_keys
[kid
].wk_key
, tmpkey
, len
);
835 error
= copyout(tmpkey
, ireq
->i_data
, len
);
837 case IEEE80211_IOC_NUMWEPKEYS
:
838 ireq
->i_val
= IEEE80211_WEP_NKID
;
840 case IEEE80211_IOC_WEPTXKEY
:
841 ireq
->i_val
= vap
->iv_def_txkey
;
843 case IEEE80211_IOC_AUTHMODE
:
844 if (vap
->iv_flags
& IEEE80211_F_WPA
)
845 ireq
->i_val
= IEEE80211_AUTH_WPA
;
847 ireq
->i_val
= vap
->iv_bss
->ni_authmode
;
849 case IEEE80211_IOC_CHANNEL
:
850 ireq
->i_val
= ieee80211_chan2ieee(ic
, ic
->ic_curchan
);
852 case IEEE80211_IOC_POWERSAVE
:
853 if (vap
->iv_flags
& IEEE80211_F_PMGTON
)
854 ireq
->i_val
= IEEE80211_POWERSAVE_ON
;
856 ireq
->i_val
= IEEE80211_POWERSAVE_OFF
;
858 case IEEE80211_IOC_POWERSAVESLEEP
:
859 ireq
->i_val
= ic
->ic_lintval
;
861 case IEEE80211_IOC_RTSTHRESHOLD
:
862 ireq
->i_val
= vap
->iv_rtsthreshold
;
864 case IEEE80211_IOC_PROTMODE
:
865 ireq
->i_val
= ic
->ic_protmode
;
867 case IEEE80211_IOC_TXPOWER
:
869 * Tx power limit is the min of max regulatory
870 * power, any user-set limit, and the max the
873 ireq
->i_val
= 2*ic
->ic_curchan
->ic_maxregpower
;
874 if (ireq
->i_val
> ic
->ic_txpowlimit
)
875 ireq
->i_val
= ic
->ic_txpowlimit
;
876 if (ireq
->i_val
> ic
->ic_curchan
->ic_maxpower
)
877 ireq
->i_val
= ic
->ic_curchan
->ic_maxpower
;
879 case IEEE80211_IOC_WPA
:
880 switch (vap
->iv_flags
& IEEE80211_F_WPA
) {
881 case IEEE80211_F_WPA1
:
884 case IEEE80211_F_WPA2
:
887 case IEEE80211_F_WPA1
| IEEE80211_F_WPA2
:
895 case IEEE80211_IOC_CHANLIST
:
896 error
= ieee80211_ioctl_getchanlist(vap
, ireq
);
898 case IEEE80211_IOC_ROAMING
:
899 ireq
->i_val
= vap
->iv_roaming
;
901 case IEEE80211_IOC_PRIVACY
:
902 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_PRIVACY
) != 0;
904 case IEEE80211_IOC_DROPUNENCRYPTED
:
905 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_DROPUNENC
) != 0;
907 case IEEE80211_IOC_COUNTERMEASURES
:
908 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_COUNTERM
) != 0;
910 case IEEE80211_IOC_WME
:
911 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_WME
) != 0;
913 case IEEE80211_IOC_HIDESSID
:
914 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_HIDESSID
) != 0;
916 case IEEE80211_IOC_APBRIDGE
:
917 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_NOBRIDGE
) == 0;
919 case IEEE80211_IOC_WPAKEY
:
920 error
= ieee80211_ioctl_getkey(vap
, ireq
);
922 case IEEE80211_IOC_CHANINFO
:
923 error
= ieee80211_ioctl_getchaninfo(vap
, ireq
);
925 case IEEE80211_IOC_BSSID
:
926 if (ireq
->i_len
!= IEEE80211_ADDR_LEN
)
928 if (vap
->iv_state
== IEEE80211_S_RUN
) {
929 error
= copyout(vap
->iv_opmode
== IEEE80211_M_WDS
?
930 vap
->iv_bss
->ni_macaddr
: vap
->iv_bss
->ni_bssid
,
931 ireq
->i_data
, ireq
->i_len
);
933 error
= copyout(vap
->iv_des_bssid
, ireq
->i_data
,
936 case IEEE80211_IOC_WPAIE
:
937 error
= ieee80211_ioctl_getwpaie(vap
, ireq
, ireq
->i_type
);
939 case IEEE80211_IOC_WPAIE2
:
940 error
= ieee80211_ioctl_getwpaie(vap
, ireq
, ireq
->i_type
);
942 case IEEE80211_IOC_SCAN_RESULTS
:
943 error
= ieee80211_ioctl_getscanresults(vap
, ireq
);
945 case IEEE80211_IOC_STA_STATS
:
946 error
= ieee80211_ioctl_getstastats(vap
, ireq
);
948 case IEEE80211_IOC_TXPOWMAX
:
949 ireq
->i_val
= vap
->iv_bss
->ni_txpower
;
951 case IEEE80211_IOC_STA_TXPOW
:
952 error
= ieee80211_ioctl_getstatxpow(vap
, ireq
);
954 case IEEE80211_IOC_STA_INFO
:
955 error
= ieee80211_ioctl_getstainfo(vap
, ireq
);
957 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
958 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
959 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
960 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
961 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
962 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
963 error
= ieee80211_ioctl_getwmeparam(vap
, ireq
);
965 case IEEE80211_IOC_DTIM_PERIOD
:
966 ireq
->i_val
= vap
->iv_dtim_period
;
968 case IEEE80211_IOC_BEACON_INTERVAL
:
969 /* NB: get from ic_bss for station mode */
970 ireq
->i_val
= vap
->iv_bss
->ni_intval
;
972 case IEEE80211_IOC_PUREG
:
973 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_PUREG
) != 0;
975 case IEEE80211_IOC_BGSCAN
:
976 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_BGSCAN
) != 0;
978 case IEEE80211_IOC_BGSCAN_IDLE
:
979 ireq
->i_val
= vap
->iv_bgscanidle
*hz
/1000; /* ms */
981 case IEEE80211_IOC_BGSCAN_INTERVAL
:
982 ireq
->i_val
= vap
->iv_bgscanintvl
/hz
; /* seconds */
984 case IEEE80211_IOC_SCANVALID
:
985 ireq
->i_val
= vap
->iv_scanvalid
/hz
; /* seconds */
987 case IEEE80211_IOC_FRAGTHRESHOLD
:
988 ireq
->i_val
= vap
->iv_fragthreshold
;
990 case IEEE80211_IOC_MACCMD
:
991 error
= ieee80211_ioctl_getmaccmd(vap
, ireq
);
993 case IEEE80211_IOC_BURST
:
994 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_BURST
) != 0;
996 case IEEE80211_IOC_BMISSTHRESHOLD
:
997 ireq
->i_val
= vap
->iv_bmissthreshold
;
999 case IEEE80211_IOC_CURCHAN
:
1000 error
= ieee80211_ioctl_getcurchan(vap
, ireq
);
1002 case IEEE80211_IOC_SHORTGI
:
1004 if (vap
->iv_flags_ht
& IEEE80211_FHT_SHORTGI20
)
1005 ireq
->i_val
|= IEEE80211_HTCAP_SHORTGI20
;
1006 if (vap
->iv_flags_ht
& IEEE80211_FHT_SHORTGI40
)
1007 ireq
->i_val
|= IEEE80211_HTCAP_SHORTGI40
;
1009 case IEEE80211_IOC_AMPDU
:
1011 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMPDU_TX
)
1013 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMPDU_RX
)
1016 case IEEE80211_IOC_AMPDU_LIMIT
:
1017 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
1018 ireq
->i_val
= vap
->iv_ampdu_rxmax
;
1019 else if (vap
->iv_state
== IEEE80211_S_RUN
)
1020 ireq
->i_val
= MS(vap
->iv_bss
->ni_htparam
,
1021 IEEE80211_HTCAP_MAXRXAMPDU
);
1023 ireq
->i_val
= vap
->iv_ampdu_limit
;
1025 case IEEE80211_IOC_AMPDU_DENSITY
:
1026 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1027 vap
->iv_state
== IEEE80211_S_RUN
)
1028 ireq
->i_val
= MS(vap
->iv_bss
->ni_htparam
,
1029 IEEE80211_HTCAP_MPDUDENSITY
);
1031 ireq
->i_val
= vap
->iv_ampdu_density
;
1033 case IEEE80211_IOC_AMSDU
:
1035 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMSDU_TX
)
1037 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMSDU_RX
)
1040 case IEEE80211_IOC_AMSDU_LIMIT
:
1041 ireq
->i_val
= vap
->iv_amsdu_limit
; /* XXX truncation? */
1043 case IEEE80211_IOC_PUREN
:
1044 ireq
->i_val
= (vap
->iv_flags_ht
& IEEE80211_FHT_PUREN
) != 0;
1046 case IEEE80211_IOC_DOTH
:
1047 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_DOTH
) != 0;
1049 case IEEE80211_IOC_REGDOMAIN
:
1050 error
= ieee80211_ioctl_getregdomain(vap
, ireq
);
1052 case IEEE80211_IOC_ROAM
:
1053 error
= ieee80211_ioctl_getroam(vap
, ireq
);
1055 case IEEE80211_IOC_TXPARAMS
:
1056 error
= ieee80211_ioctl_gettxparams(vap
, ireq
);
1058 case IEEE80211_IOC_HTCOMPAT
:
1059 ireq
->i_val
= (vap
->iv_flags_ht
& IEEE80211_FHT_HTCOMPAT
) != 0;
1061 case IEEE80211_IOC_DWDS
:
1062 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_DWDS
) != 0;
1064 case IEEE80211_IOC_INACTIVITY
:
1065 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_INACT
) != 0;
1067 case IEEE80211_IOC_APPIE
:
1068 error
= ieee80211_ioctl_getappie(vap
, ireq
);
1070 case IEEE80211_IOC_WPS
:
1071 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_WPS
) != 0;
1073 case IEEE80211_IOC_TSN
:
1074 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_TSN
) != 0;
1076 case IEEE80211_IOC_DFS
:
1077 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_DFS
) != 0;
1079 case IEEE80211_IOC_DOTD
:
1080 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_DOTD
) != 0;
1082 case IEEE80211_IOC_DEVCAPS
:
1083 error
= ieee80211_ioctl_getdevcaps(ic
, ireq
);
1085 case IEEE80211_IOC_HTPROTMODE
:
1086 ireq
->i_val
= ic
->ic_htprotmode
;
1088 case IEEE80211_IOC_HTCONF
:
1089 if (vap
->iv_flags_ht
& IEEE80211_FHT_HT
) {
1091 if (vap
->iv_flags_ht
& IEEE80211_FHT_USEHT40
)
1096 case IEEE80211_IOC_STA_VLAN
:
1097 error
= ieee80211_ioctl_getstavlan(vap
, ireq
);
1099 case IEEE80211_IOC_SMPS
:
1100 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1101 vap
->iv_state
== IEEE80211_S_RUN
) {
1102 if (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_MIMO_RTS
)
1103 ireq
->i_val
= IEEE80211_HTCAP_SMPS_DYNAMIC
;
1104 else if (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_MIMO_PS
)
1105 ireq
->i_val
= IEEE80211_HTCAP_SMPS_ENA
;
1107 ireq
->i_val
= IEEE80211_HTCAP_SMPS_OFF
;
1109 ireq
->i_val
= vap
->iv_htcaps
& IEEE80211_HTCAP_SMPS
;
1111 case IEEE80211_IOC_RIFS
:
1112 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1113 vap
->iv_state
== IEEE80211_S_RUN
)
1115 (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_RIFS
) != 0;
1118 (vap
->iv_flags_ht
& IEEE80211_FHT_RIFS
) != 0;
1121 error
= ieee80211_ioctl_getdefault(vap
, ireq
);
1128 static __noinline
int
1129 ieee80211_ioctl_setkey(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1131 struct ieee80211req_key ik
;
1132 struct ieee80211_node
*ni
;
1133 struct ieee80211_key
*wk
;
1137 if (ireq
->i_len
!= sizeof(ik
))
1139 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
1142 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1143 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1144 if (ik
.ik_keylen
> sizeof(ik
.ik_keydata
))
1147 if (kid
== IEEE80211_KEYIX_NONE
) {
1148 /* XXX unicast keys currently must be tx/rx */
1149 if (ik
.ik_flags
!= (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
))
1151 if (vap
->iv_opmode
== IEEE80211_M_STA
) {
1152 ni
= ieee80211_ref_node(vap
->iv_bss
);
1153 if (!IEEE80211_ADDR_EQ(ik
.ik_macaddr
, ni
->ni_bssid
)) {
1154 ieee80211_free_node(ni
);
1155 return EADDRNOTAVAIL
;
1158 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
1163 wk
= &ni
->ni_ucastkey
;
1165 if (kid
>= IEEE80211_WEP_NKID
)
1167 wk
= &vap
->iv_nw_keys
[kid
];
1169 * Global slots start off w/o any assigned key index.
1170 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1172 if (wk
->wk_keyix
== IEEE80211_KEYIX_NONE
)
1177 ieee80211_key_update_begin(vap
);
1178 if (ieee80211_crypto_newkey(vap
, ik
.ik_type
, ik
.ik_flags
, wk
)) {
1179 wk
->wk_keylen
= ik
.ik_keylen
;
1180 /* NB: MIC presence is implied by cipher type */
1181 if (wk
->wk_keylen
> IEEE80211_KEYBUF_SIZE
)
1182 wk
->wk_keylen
= IEEE80211_KEYBUF_SIZE
;
1183 for (i
= 0; i
< IEEE80211_TID_SIZE
; i
++)
1184 wk
->wk_keyrsc
[i
] = ik
.ik_keyrsc
;
1185 wk
->wk_keytsc
= 0; /* new key, reset */
1186 memset(wk
->wk_key
, 0, sizeof(wk
->wk_key
));
1187 memcpy(wk
->wk_key
, ik
.ik_keydata
, ik
.ik_keylen
);
1188 IEEE80211_ADDR_COPY(wk
->wk_macaddr
,
1189 ni
!= NULL
? ni
->ni_macaddr
: ik
.ik_macaddr
);
1190 if (!ieee80211_crypto_setkey(vap
, wk
))
1192 else if ((ik
.ik_flags
& IEEE80211_KEY_DEFAULT
))
1193 vap
->iv_def_txkey
= kid
;
1196 ieee80211_key_update_end(vap
);
1198 ieee80211_free_node(ni
);
1202 static __noinline
int
1203 ieee80211_ioctl_delkey(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1205 struct ieee80211req_del_key dk
;
1208 if (ireq
->i_len
!= sizeof(dk
))
1210 error
= copyin(ireq
->i_data
, &dk
, sizeof(dk
));
1214 /* XXX uint8_t -> uint16_t */
1215 if (dk
.idk_keyix
== (uint8_t) IEEE80211_KEYIX_NONE
) {
1216 struct ieee80211_node
*ni
;
1218 if (vap
->iv_opmode
== IEEE80211_M_STA
) {
1219 ni
= ieee80211_ref_node(vap
->iv_bss
);
1220 if (!IEEE80211_ADDR_EQ(dk
.idk_macaddr
, ni
->ni_bssid
)) {
1221 ieee80211_free_node(ni
);
1222 return EADDRNOTAVAIL
;
1225 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
1230 /* XXX error return */
1231 ieee80211_node_delucastkey(ni
);
1232 ieee80211_free_node(ni
);
1234 if (kid
>= IEEE80211_WEP_NKID
)
1236 /* XXX error return */
1237 ieee80211_crypto_delkey(vap
, &vap
->iv_nw_keys
[kid
]);
1243 struct ieee80211vap
*vap
;
1249 mlmedebug(struct ieee80211vap
*vap
, const uint8_t mac
[IEEE80211_ADDR_LEN
],
1252 #ifdef IEEE80211_DEBUG
1253 static const struct {
1258 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1259 IEEE80211_MSG_ASSOC
, "assoc" },
1260 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1261 IEEE80211_MSG_ASSOC
, "disassoc" },
1262 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1263 IEEE80211_MSG_AUTH
, "deauth" },
1264 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1265 IEEE80211_MSG_AUTH
, "authorize" },
1266 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1267 IEEE80211_MSG_AUTH
, "unauthorize" },
1270 if (op
== IEEE80211_MLME_AUTH
) {
1271 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_IOCTL
|
1272 IEEE80211_MSG_STATE
| IEEE80211_MSG_AUTH
, mac
,
1273 "station authenticate %s via MLME (reason %d)",
1274 reason
== IEEE80211_STATUS_SUCCESS
? "ACCEPT" : "REJECT",
1276 } else if (!(IEEE80211_MLME_ASSOC
<= op
&& op
<= IEEE80211_MLME_AUTH
)) {
1277 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_ANY
, mac
,
1278 "unknown MLME request %d (reason %d)", op
, reason
);
1279 } else if (reason
== IEEE80211_STATUS_SUCCESS
) {
1280 IEEE80211_NOTE_MAC(vap
, ops
[op
].mask
, mac
,
1281 "station %s via MLME", ops
[op
].opstr
);
1283 IEEE80211_NOTE_MAC(vap
, ops
[op
].mask
, mac
,
1284 "station %s via MLME (reason %d)", ops
[op
].opstr
, reason
);
1286 #endif /* IEEE80211_DEBUG */
1290 domlme(void *arg
, struct ieee80211_node
*ni
)
1292 struct mlmeop
*mop
= arg
;
1293 struct ieee80211vap
*vap
= ni
->ni_vap
;
1295 if (vap
!= mop
->vap
)
1298 * NB: if ni_associd is zero then the node is already cleaned
1299 * up and we don't need to do this (we're safely holding a
1300 * reference but should otherwise not modify it's state).
1302 if (ni
->ni_associd
== 0)
1304 mlmedebug(vap
, ni
->ni_macaddr
, mop
->op
, mop
->reason
);
1305 if (mop
->op
== IEEE80211_MLME_DEAUTH
) {
1306 IEEE80211_SEND_MGMT(ni
, IEEE80211_FC0_SUBTYPE_DEAUTH
,
1309 IEEE80211_SEND_MGMT(ni
, IEEE80211_FC0_SUBTYPE_DISASSOC
,
1312 ieee80211_node_leave(ni
);
1316 setmlme_dropsta(struct ieee80211vap
*vap
,
1317 const uint8_t mac
[IEEE80211_ADDR_LEN
], struct mlmeop
*mlmeop
)
1319 struct ieee80211com
*ic
= vap
->iv_ic
;
1320 struct ieee80211_node_table
*nt
= &ic
->ic_sta
;
1321 struct ieee80211_node
*ni
;
1324 /* NB: the broadcast address means do 'em all */
1325 if (!IEEE80211_ADDR_EQ(mac
, ic
->ic_ifp
->if_broadcastaddr
)) {
1326 ni
= ieee80211_find_node_locked(nt
, mac
);
1329 ieee80211_free_node(ni
);
1333 ieee80211_iterate_nodes(nt
, domlme
, mlmeop
);
1338 static __noinline
int
1339 setmlme_common(struct ieee80211vap
*vap
, int op
,
1340 const uint8_t mac
[IEEE80211_ADDR_LEN
], int reason
)
1342 struct ieee80211com
*ic
= vap
->iv_ic
;
1343 struct ieee80211_node_table
*nt
= &ic
->ic_sta
;
1344 struct ieee80211_node
*ni
;
1345 struct mlmeop mlmeop
;
1350 case IEEE80211_MLME_DISASSOC
:
1351 case IEEE80211_MLME_DEAUTH
:
1352 switch (vap
->iv_opmode
) {
1353 case IEEE80211_M_STA
:
1354 mlmedebug(vap
, vap
->iv_bss
->ni_macaddr
, op
, reason
);
1355 /* XXX not quite right */
1356 ieee80211_new_state(vap
, IEEE80211_S_INIT
, reason
);
1358 case IEEE80211_M_HOSTAP
:
1361 mlmeop
.reason
= reason
;
1362 error
= setmlme_dropsta(vap
, mac
, &mlmeop
);
1364 case IEEE80211_M_WDS
:
1365 /* XXX user app should send raw frame? */
1366 if (op
!= IEEE80211_MLME_DEAUTH
) {
1371 /* XXX accept any address, simplifies user code */
1372 if (!IEEE80211_ADDR_EQ(mac
, vap
->iv_bss
->ni_macaddr
)) {
1377 mlmedebug(vap
, vap
->iv_bss
->ni_macaddr
, op
, reason
);
1378 ni
= ieee80211_ref_node(vap
->iv_bss
);
1379 IEEE80211_SEND_MGMT(ni
,
1380 IEEE80211_FC0_SUBTYPE_DEAUTH
, reason
);
1381 ieee80211_free_node(ni
);
1388 case IEEE80211_MLME_AUTHORIZE
:
1389 case IEEE80211_MLME_UNAUTHORIZE
:
1390 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
1391 vap
->iv_opmode
!= IEEE80211_M_WDS
) {
1395 ni
= ieee80211_find_vap_node_locked(nt
, vap
, mac
);
1397 mlmedebug(vap
, mac
, op
, reason
);
1398 if (op
== IEEE80211_MLME_AUTHORIZE
)
1399 ieee80211_node_authorize(ni
);
1401 ieee80211_node_unauthorize(ni
);
1402 ieee80211_free_node(ni
);
1406 case IEEE80211_MLME_AUTH
:
1407 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
) {
1411 ni
= ieee80211_find_vap_node_locked(nt
, vap
, mac
);
1413 mlmedebug(vap
, mac
, op
, reason
);
1414 if (reason
== IEEE80211_STATUS_SUCCESS
) {
1415 IEEE80211_SEND_MGMT(ni
,
1416 IEEE80211_FC0_SUBTYPE_AUTH
, 2);
1418 * For shared key auth, just continue the
1419 * exchange. Otherwise when 802.1x is not in
1420 * use mark the port authorized at this point
1421 * so traffic can flow.
1423 if (ni
->ni_authmode
!= IEEE80211_AUTH_8021X
&&
1424 ni
->ni_challenge
== NULL
)
1425 ieee80211_node_authorize(ni
);
1427 vap
->iv_stats
.is_rx_acl
++;
1428 ieee80211_send_error(ni
, ni
->ni_macaddr
,
1429 IEEE80211_FC0_SUBTYPE_AUTH
, 2|(reason
<<16));
1430 ieee80211_node_leave(ni
);
1432 ieee80211_free_node(ni
);
1446 const uint8_t *essid
;
1447 const struct ieee80211_scan_entry
*se
;
1451 * Match mac address and any ssid.
1454 mlmelookup(void *arg
, const struct ieee80211_scan_entry
*se
)
1456 struct scanlookup
*look
= arg
;
1458 if (!IEEE80211_ADDR_EQ(look
->mac
, se
->se_macaddr
))
1460 if (look
->esslen
!= 0) {
1461 if (se
->se_ssid
[1] != look
->esslen
)
1463 if (memcmp(look
->essid
, se
->se_ssid
+2, look
->esslen
))
1469 static __noinline
int
1470 setmlme_assoc(struct ieee80211vap
*vap
, const uint8_t mac
[IEEE80211_ADDR_LEN
],
1471 int ssid_len
, const uint8_t ssid
[IEEE80211_NWID_LEN
])
1473 struct scanlookup lookup
;
1475 /* XXX ibss/ahdemo */
1476 if (vap
->iv_opmode
!= IEEE80211_M_STA
)
1479 /* NB: this is racey if roaming is !manual */
1482 lookup
.esslen
= ssid_len
;
1483 lookup
.essid
= ssid
;
1484 ieee80211_scan_iterate(vap
, mlmelookup
, &lookup
);
1485 if (lookup
.se
== NULL
)
1487 mlmedebug(vap
, mac
, IEEE80211_MLME_ASSOC
, 0);
1488 if (!ieee80211_sta_join(vap
, lookup
.se
->se_chan
, lookup
.se
))
1489 return EIO
; /* XXX unique but could be better */
1493 static __noinline
int
1494 ieee80211_ioctl_setmlme(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1496 struct ieee80211req_mlme mlme
;
1499 if (ireq
->i_len
!= sizeof(mlme
))
1501 error
= copyin(ireq
->i_data
, &mlme
, sizeof(mlme
));
1504 if (mlme
.im_op
== IEEE80211_MLME_ASSOC
)
1505 return setmlme_assoc(vap
, mlme
.im_macaddr
,
1506 vap
->iv_des_ssid
[0].len
, vap
->iv_des_ssid
[0].ssid
);
1508 return setmlme_common(vap
, mlme
.im_op
,
1509 mlme
.im_macaddr
, mlme
.im_reason
);
1512 static __noinline
int
1513 ieee80211_ioctl_macmac(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1515 uint8_t mac
[IEEE80211_ADDR_LEN
];
1516 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
1519 if (ireq
->i_len
!= sizeof(mac
))
1521 error
= copyin(ireq
->i_data
, mac
, ireq
->i_len
);
1525 acl
= ieee80211_aclator_get("mac");
1526 if (acl
== NULL
|| !acl
->iac_attach(vap
))
1530 if (ireq
->i_type
== IEEE80211_IOC_ADDMAC
)
1531 acl
->iac_add(vap
, mac
);
1533 acl
->iac_remove(vap
, mac
);
1537 static __noinline
int
1538 ieee80211_ioctl_setmaccmd(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1540 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
1542 switch (ireq
->i_val
) {
1543 case IEEE80211_MACCMD_POLICY_OPEN
:
1544 case IEEE80211_MACCMD_POLICY_ALLOW
:
1545 case IEEE80211_MACCMD_POLICY_DENY
:
1546 case IEEE80211_MACCMD_POLICY_RADIUS
:
1548 acl
= ieee80211_aclator_get("mac");
1549 if (acl
== NULL
|| !acl
->iac_attach(vap
))
1553 acl
->iac_setpolicy(vap
, ireq
->i_val
);
1555 case IEEE80211_MACCMD_FLUSH
:
1557 acl
->iac_flush(vap
);
1558 /* NB: silently ignore when not in use */
1560 case IEEE80211_MACCMD_DETACH
:
1563 acl
->iac_detach(vap
);
1570 return acl
->iac_setioctl(vap
, ireq
);
1575 static __noinline
int
1576 ieee80211_ioctl_setchanlist(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1578 struct ieee80211com
*ic
= vap
->iv_ic
;
1579 uint8_t *chanlist
, *list
;
1580 int i
, nchan
, maxchan
, error
;
1582 if (ireq
->i_len
> sizeof(ic
->ic_chan_active
))
1583 ireq
->i_len
= sizeof(ic
->ic_chan_active
);
1584 list
= kmalloc(ireq
->i_len
+ IEEE80211_CHAN_BYTES
, M_TEMP
,
1585 M_INTWAIT
| M_ZERO
);
1588 error
= copyin(ireq
->i_data
, list
, ireq
->i_len
);
1590 kfree(list
, M_TEMP
);
1594 chanlist
= list
+ ireq
->i_len
; /* NB: zero'd already */
1595 maxchan
= ireq
->i_len
* NBBY
;
1596 for (i
= 0; i
< ic
->ic_nchans
; i
++) {
1597 const struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
1599 * Calculate the intersection of the user list and the
1600 * available channels so users can do things like specify
1601 * 1-255 to get all available channels.
1603 if (c
->ic_ieee
< maxchan
&& isset(list
, c
->ic_ieee
)) {
1604 setbit(chanlist
, c
->ic_ieee
);
1609 kfree(list
, M_TEMP
);
1612 if (ic
->ic_bsschan
!= IEEE80211_CHAN_ANYC
&& /* XXX */
1613 isclr(chanlist
, ic
->ic_bsschan
->ic_ieee
))
1614 ic
->ic_bsschan
= IEEE80211_CHAN_ANYC
;
1615 memcpy(ic
->ic_chan_active
, chanlist
, IEEE80211_CHAN_BYTES
);
1616 ieee80211_scan_flush(vap
);
1617 kfree(list
, M_TEMP
);
1621 static __noinline
int
1622 ieee80211_ioctl_setstastats(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1624 struct ieee80211_node
*ni
;
1625 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
1629 * NB: we could copyin ieee80211req_sta_stats so apps
1630 * could make selective changes but that's overkill;
1631 * just clear all stats for now.
1633 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
1635 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
1638 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
1641 /* XXX require ni_vap == vap? */
1642 memset(&ni
->ni_stats
, 0, sizeof(ni
->ni_stats
));
1643 ieee80211_free_node(ni
);
1647 static __noinline
int
1648 ieee80211_ioctl_setstatxpow(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1650 struct ieee80211_node
*ni
;
1651 struct ieee80211req_sta_txpow txpow
;
1654 if (ireq
->i_len
!= sizeof(txpow
))
1656 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1659 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, txpow
.it_macaddr
);
1662 ni
->ni_txpower
= txpow
.it_txpow
;
1663 ieee80211_free_node(ni
);
1667 static __noinline
int
1668 ieee80211_ioctl_setwmeparam(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1670 struct ieee80211com
*ic
= vap
->iv_ic
;
1671 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1672 struct wmeParams
*wmep
, *chanp
;
1675 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1678 isbss
= (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
);
1679 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1680 if (ac
>= WME_NUM_AC
)
1683 chanp
= &wme
->wme_bssChanParams
.cap_wmeParams
[ac
];
1684 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1686 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[ac
];
1687 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1689 switch (ireq
->i_type
) {
1690 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1692 wmep
->wmep_logcwmin
= ireq
->i_val
;
1693 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1694 chanp
->wmep_logcwmin
= ireq
->i_val
;
1696 wmep
->wmep_logcwmin
= chanp
->wmep_logcwmin
=
1700 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1702 wmep
->wmep_logcwmax
= ireq
->i_val
;
1703 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1704 chanp
->wmep_logcwmax
= ireq
->i_val
;
1706 wmep
->wmep_logcwmax
= chanp
->wmep_logcwmax
=
1710 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1712 wmep
->wmep_aifsn
= ireq
->i_val
;
1713 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1714 chanp
->wmep_aifsn
= ireq
->i_val
;
1716 wmep
->wmep_aifsn
= chanp
->wmep_aifsn
= ireq
->i_val
;
1719 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1721 wmep
->wmep_txopLimit
= ireq
->i_val
;
1722 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1723 chanp
->wmep_txopLimit
= ireq
->i_val
;
1725 wmep
->wmep_txopLimit
= chanp
->wmep_txopLimit
=
1729 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1730 wmep
->wmep_acm
= ireq
->i_val
;
1731 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1732 chanp
->wmep_acm
= ireq
->i_val
;
1734 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
1735 wmep
->wmep_noackPolicy
= chanp
->wmep_noackPolicy
=
1739 ieee80211_wme_updateparams(vap
);
1744 find11gchannel(struct ieee80211com
*ic
, int start
, int freq
)
1746 const struct ieee80211_channel
*c
;
1749 for (i
= start
+1; i
< ic
->ic_nchans
; i
++) {
1750 c
= &ic
->ic_channels
[i
];
1751 if (c
->ic_freq
== freq
&& IEEE80211_IS_CHAN_ANYG(c
))
1754 /* NB: should not be needed but in case things are mis-sorted */
1755 for (i
= 0; i
< start
; i
++) {
1756 c
= &ic
->ic_channels
[i
];
1757 if (c
->ic_freq
== freq
&& IEEE80211_IS_CHAN_ANYG(c
))
1763 static struct ieee80211_channel
*
1764 findchannel(struct ieee80211com
*ic
, int ieee
, int mode
)
1766 static const u_int chanflags
[IEEE80211_MODE_MAX
] = {
1767 [IEEE80211_MODE_AUTO
] = 0,
1768 [IEEE80211_MODE_11A
] = IEEE80211_CHAN_A
,
1769 [IEEE80211_MODE_11B
] = IEEE80211_CHAN_B
,
1770 [IEEE80211_MODE_11G
] = IEEE80211_CHAN_G
,
1771 [IEEE80211_MODE_FH
] = IEEE80211_CHAN_FHSS
,
1772 [IEEE80211_MODE_TURBO_A
] = IEEE80211_CHAN_108A
,
1773 [IEEE80211_MODE_TURBO_G
] = IEEE80211_CHAN_108G
,
1774 [IEEE80211_MODE_STURBO_A
] = IEEE80211_CHAN_STURBO
,
1775 [IEEE80211_MODE_HALF
] = IEEE80211_CHAN_HALF
,
1776 [IEEE80211_MODE_QUARTER
] = IEEE80211_CHAN_QUARTER
,
1777 /* NB: handled specially below */
1778 [IEEE80211_MODE_11NA
] = IEEE80211_CHAN_A
,
1779 [IEEE80211_MODE_11NG
] = IEEE80211_CHAN_G
,
1784 modeflags
= chanflags
[mode
];
1785 for (i
= 0; i
< ic
->ic_nchans
; i
++) {
1786 struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
1788 if (c
->ic_ieee
!= ieee
)
1790 if (mode
== IEEE80211_MODE_AUTO
) {
1791 /* ignore turbo channels for autoselect */
1792 if (IEEE80211_IS_CHAN_TURBO(c
))
1795 * XXX special-case 11b/g channels so we
1796 * always select the g channel if both
1798 * XXX prefer HT to non-HT?
1800 if (!IEEE80211_IS_CHAN_B(c
) ||
1801 !find11gchannel(ic
, i
, c
->ic_freq
))
1804 /* must check HT specially */
1805 if ((mode
== IEEE80211_MODE_11NA
||
1806 mode
== IEEE80211_MODE_11NG
) &&
1807 !IEEE80211_IS_CHAN_HT(c
))
1809 if ((c
->ic_flags
& modeflags
) == modeflags
)
1817 * Check the specified against any desired mode (aka netband).
1818 * This is only used (presently) when operating in hostap mode
1819 * to enforce consistency.
1822 check_mode_consistency(const struct ieee80211_channel
*c
, int mode
)
1824 KASSERT(c
!= IEEE80211_CHAN_ANYC
, ("oops, no channel"));
1827 case IEEE80211_MODE_11B
:
1828 return (IEEE80211_IS_CHAN_B(c
));
1829 case IEEE80211_MODE_11G
:
1830 return (IEEE80211_IS_CHAN_ANYG(c
) && !IEEE80211_IS_CHAN_HT(c
));
1831 case IEEE80211_MODE_11A
:
1832 return (IEEE80211_IS_CHAN_A(c
) && !IEEE80211_IS_CHAN_HT(c
));
1833 case IEEE80211_MODE_STURBO_A
:
1834 return (IEEE80211_IS_CHAN_STURBO(c
));
1835 case IEEE80211_MODE_11NA
:
1836 return (IEEE80211_IS_CHAN_HTA(c
));
1837 case IEEE80211_MODE_11NG
:
1838 return (IEEE80211_IS_CHAN_HTG(c
));
1845 * Common code to set the current channel. If the device
1846 * is up and running this may result in an immediate channel
1847 * change or a kick of the state machine.
1850 setcurchan(struct ieee80211vap
*vap
, struct ieee80211_channel
*c
)
1852 struct ieee80211com
*ic
= vap
->iv_ic
;
1855 if (c
!= IEEE80211_CHAN_ANYC
) {
1856 if (IEEE80211_IS_CHAN_RADAR(c
))
1857 return EBUSY
; /* XXX better code? */
1858 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
) {
1859 if (IEEE80211_IS_CHAN_NOHOSTAP(c
))
1861 if (!check_mode_consistency(c
, vap
->iv_des_mode
))
1863 } else if (vap
->iv_opmode
== IEEE80211_M_IBSS
) {
1864 if (IEEE80211_IS_CHAN_NOADHOC(c
))
1867 if (vap
->iv_state
== IEEE80211_S_RUN
&&
1868 vap
->iv_bss
->ni_chan
== c
)
1869 return 0; /* NB: nothing to do */
1871 vap
->iv_des_chan
= c
;
1874 if (vap
->iv_opmode
== IEEE80211_M_MONITOR
&&
1875 vap
->iv_des_chan
!= IEEE80211_CHAN_ANYC
) {
1877 * Monitor mode can switch directly.
1879 if (IFNET_IS_UP_RUNNING(vap
->iv_ifp
)) {
1880 /* XXX need state machine for other vap's to follow */
1881 ieee80211_setcurchan(ic
, vap
->iv_des_chan
);
1882 vap
->iv_bss
->ni_chan
= ic
->ic_curchan
;
1884 ic
->ic_curchan
= vap
->iv_des_chan
;
1885 ic
->ic_rt
= ieee80211_get_ratetable(ic
->ic_curchan
);
1888 * Need to go through the state machine in case we
1889 * need to reassociate or the like. The state machine
1890 * will pickup the desired channel and avoid scanning.
1892 if (IS_UP_AUTO(vap
))
1893 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
1894 else if (vap
->iv_des_chan
!= IEEE80211_CHAN_ANYC
) {
1896 * When not up+running and a real channel has
1897 * been specified fix the current channel so
1898 * there is immediate feedback; e.g. via ifconfig.
1900 ic
->ic_curchan
= vap
->iv_des_chan
;
1901 ic
->ic_rt
= ieee80211_get_ratetable(ic
->ic_curchan
);
1908 * Old api for setting the current channel; this is
1909 * deprecated because channel numbers are ambiguous.
1911 static __noinline
int
1912 ieee80211_ioctl_setchannel(struct ieee80211vap
*vap
,
1913 const struct ieee80211req
*ireq
)
1915 struct ieee80211com
*ic
= vap
->iv_ic
;
1916 struct ieee80211_channel
*c
;
1918 /* XXX 0xffff overflows 16-bit signed */
1919 if (ireq
->i_val
== 0 ||
1920 ireq
->i_val
== (int16_t) IEEE80211_CHAN_ANY
) {
1921 c
= IEEE80211_CHAN_ANYC
;
1923 struct ieee80211_channel
*c2
;
1925 c
= findchannel(ic
, ireq
->i_val
, vap
->iv_des_mode
);
1927 c
= findchannel(ic
, ireq
->i_val
,
1928 IEEE80211_MODE_AUTO
);
1933 * Fine tune channel selection based on desired mode:
1934 * if 11b is requested, find the 11b version of any
1935 * 11g channel returned,
1936 * if static turbo, find the turbo version of any
1937 * 11a channel return,
1938 * if 11na is requested, find the ht version of any
1939 * 11a channel returned,
1940 * if 11ng is requested, find the ht version of any
1941 * 11g channel returned,
1942 * otherwise we should be ok with what we've got.
1944 switch (vap
->iv_des_mode
) {
1945 case IEEE80211_MODE_11B
:
1946 if (IEEE80211_IS_CHAN_ANYG(c
)) {
1947 c2
= findchannel(ic
, ireq
->i_val
,
1948 IEEE80211_MODE_11B
);
1949 /* NB: should not happen, =>'s 11g w/o 11b */
1954 case IEEE80211_MODE_TURBO_A
:
1955 if (IEEE80211_IS_CHAN_A(c
)) {
1956 c2
= findchannel(ic
, ireq
->i_val
,
1957 IEEE80211_MODE_TURBO_A
);
1962 case IEEE80211_MODE_11NA
:
1963 if (IEEE80211_IS_CHAN_A(c
)) {
1964 c2
= findchannel(ic
, ireq
->i_val
,
1965 IEEE80211_MODE_11NA
);
1970 case IEEE80211_MODE_11NG
:
1971 if (IEEE80211_IS_CHAN_ANYG(c
)) {
1972 c2
= findchannel(ic
, ireq
->i_val
,
1973 IEEE80211_MODE_11NG
);
1978 default: /* NB: no static turboG */
1982 return setcurchan(vap
, c
);
1986 * New/current api for setting the current channel; a complete
1987 * channel description is provide so there is no ambiguity in
1988 * identifying the channel.
1990 static __noinline
int
1991 ieee80211_ioctl_setcurchan(struct ieee80211vap
*vap
,
1992 const struct ieee80211req
*ireq
)
1994 struct ieee80211com
*ic
= vap
->iv_ic
;
1995 struct ieee80211_channel chan
, *c
;
1998 if (ireq
->i_len
!= sizeof(chan
))
2000 error
= copyin(ireq
->i_data
, &chan
, sizeof(chan
));
2003 /* XXX 0xffff overflows 16-bit signed */
2004 if (chan
.ic_freq
== 0 || chan
.ic_freq
== IEEE80211_CHAN_ANY
) {
2005 c
= IEEE80211_CHAN_ANYC
;
2007 c
= ieee80211_find_channel(ic
, chan
.ic_freq
, chan
.ic_flags
);
2011 return setcurchan(vap
, c
);
2014 static __noinline
int
2015 ieee80211_ioctl_setregdomain(struct ieee80211vap
*vap
,
2016 const struct ieee80211req
*ireq
)
2018 struct ieee80211_regdomain_req
*reg
;
2021 nchans
= 1 + ((ireq
->i_len
- sizeof(struct ieee80211_regdomain_req
)) /
2022 sizeof(struct ieee80211_channel
));
2023 if (!(1 <= nchans
&& nchans
<= IEEE80211_CHAN_MAX
)) {
2024 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2025 "%s: bad # chans, i_len %d nchans %d\n", __func__
,
2026 ireq
->i_len
, nchans
);
2029 reg
= (struct ieee80211_regdomain_req
*)
2030 kmalloc(IEEE80211_REGDOMAIN_SIZE(nchans
), M_TEMP
, M_INTWAIT
);
2032 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2033 "%s: no memory, nchans %d\n", __func__
, nchans
);
2036 error
= copyin(ireq
->i_data
, reg
, IEEE80211_REGDOMAIN_SIZE(nchans
));
2038 /* NB: validate inline channel count against storage size */
2039 if (reg
->chaninfo
.ic_nchans
!= nchans
) {
2040 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2041 "%s: chan cnt mismatch, %d != %d\n", __func__
,
2042 reg
->chaninfo
.ic_nchans
, nchans
);
2045 error
= ieee80211_setregdomain(vap
, reg
);
2049 return (error
== 0 ? ENETRESET
: error
);
2053 ieee80211_ioctl_setroam(struct ieee80211vap
*vap
,
2054 const struct ieee80211req
*ireq
)
2056 if (ireq
->i_len
!= sizeof(vap
->iv_roamparms
))
2058 /* XXX validate params */
2059 /* XXX? ENETRESET to push to device? */
2060 return copyin(ireq
->i_data
, vap
->iv_roamparms
,
2061 sizeof(vap
->iv_roamparms
));
2065 checkrate(const struct ieee80211_rateset
*rs
, int rate
)
2069 if (rate
== IEEE80211_FIXED_RATE_NONE
)
2071 for (i
= 0; i
< rs
->rs_nrates
; i
++)
2072 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
) == rate
)
2080 if (mcs
== IEEE80211_FIXED_RATE_NONE
)
2082 if ((mcs
& IEEE80211_RATE_MCS
) == 0) /* MCS always have 0x80 set */
2084 return (mcs
& 0x7f) <= 15; /* XXX could search ht rate set */
2087 static __noinline
int
2088 ieee80211_ioctl_settxparams(struct ieee80211vap
*vap
,
2089 const struct ieee80211req
*ireq
)
2091 struct ieee80211com
*ic
= vap
->iv_ic
;
2092 struct ieee80211_txparams_req parms
; /* XXX stack use? */
2093 struct ieee80211_txparam
*src
, *dst
;
2094 const struct ieee80211_rateset
*rs
;
2095 int error
, mode
, changed
, is11n
, nmodes
;
2097 /* NB: accept short requests for backwards compat */
2098 if (ireq
->i_len
> sizeof(parms
))
2100 error
= copyin(ireq
->i_data
, &parms
, ireq
->i_len
);
2103 nmodes
= ireq
->i_len
/ sizeof(struct ieee80211_txparam
);
2105 /* validate parameters and check if anything changed */
2106 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2107 if (isclr(ic
->ic_modecaps
, mode
))
2109 src
= &parms
.params
[mode
];
2110 dst
= &vap
->iv_txparms
[mode
];
2111 rs
= &ic
->ic_sup_rates
[mode
]; /* NB: 11n maps to legacy */
2112 is11n
= (mode
== IEEE80211_MODE_11NA
||
2113 mode
== IEEE80211_MODE_11NG
);
2114 if (src
->ucastrate
!= dst
->ucastrate
) {
2115 if (!checkrate(rs
, src
->ucastrate
) &&
2116 (!is11n
|| !checkmcs(src
->ucastrate
)))
2120 if (src
->mcastrate
!= dst
->mcastrate
) {
2121 if (!checkrate(rs
, src
->mcastrate
) &&
2122 (!is11n
|| !checkmcs(src
->mcastrate
)))
2126 if (src
->mgmtrate
!= dst
->mgmtrate
) {
2127 if (!checkrate(rs
, src
->mgmtrate
) &&
2128 (!is11n
|| !checkmcs(src
->mgmtrate
)))
2132 if (src
->maxretry
!= dst
->maxretry
) /* NB: no bounds */
2137 * Copy new parameters in place and notify the
2138 * driver so it can push state to the device.
2140 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2141 if (isset(ic
->ic_modecaps
, mode
))
2142 vap
->iv_txparms
[mode
] = parms
.params
[mode
];
2144 /* XXX could be more intelligent,
2145 e.g. don't reset if setting not being used */
2152 * Application Information Element support.
2155 setappie(struct ieee80211_appie
**aie
, const struct ieee80211req
*ireq
)
2157 struct ieee80211_appie
*app
= *aie
;
2158 struct ieee80211_appie
*napp
;
2161 if (ireq
->i_len
== 0) { /* delete any existing ie */
2163 *aie
= NULL
; /* XXX racey */
2164 kfree(app
, M_80211_NODE_IE
);
2168 if (!(2 <= ireq
->i_len
&& ireq
->i_len
<= IEEE80211_MAX_APPIE
))
2171 * Allocate a new appie structure and copy in the user data.
2172 * When done swap in the new structure. Note that we do not
2173 * guard against users holding a ref to the old structure;
2174 * this must be handled outside this code.
2178 napp
= (struct ieee80211_appie
*) kmalloc(
2179 sizeof(struct ieee80211_appie
) + ireq
->i_len
, M_80211_NODE_IE
,
2183 /* XXX holding ic lock */
2184 error
= copyin(ireq
->i_data
, napp
->ie_data
, ireq
->i_len
);
2186 kfree(napp
, M_80211_NODE_IE
);
2189 napp
->ie_len
= ireq
->i_len
;
2192 kfree(app
, M_80211_NODE_IE
);
2197 setwparsnie(struct ieee80211vap
*vap
, uint8_t *ie
, int space
)
2199 /* validate data is present as best we can */
2200 if (space
== 0 || 2+ie
[1] > space
)
2202 if (ie
[0] == IEEE80211_ELEMID_VENDOR
)
2203 vap
->iv_wpa_ie
= ie
;
2204 else if (ie
[0] == IEEE80211_ELEMID_RSN
)
2205 vap
->iv_rsn_ie
= ie
;
2208 static __noinline
int
2209 ieee80211_ioctl_setappie_locked(struct ieee80211vap
*vap
,
2210 const struct ieee80211req
*ireq
, int fc0
)
2214 switch (fc0
& IEEE80211_FC0_SUBTYPE_MASK
) {
2215 case IEEE80211_FC0_SUBTYPE_BEACON
:
2216 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
2217 vap
->iv_opmode
!= IEEE80211_M_IBSS
) {
2221 error
= setappie(&vap
->iv_appie_beacon
, ireq
);
2223 ieee80211_beacon_notify(vap
, IEEE80211_BEACON_APPIE
);
2225 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
2226 error
= setappie(&vap
->iv_appie_proberesp
, ireq
);
2228 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
2229 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
2230 error
= setappie(&vap
->iv_appie_assocresp
, ireq
);
2234 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
2235 error
= setappie(&vap
->iv_appie_probereq
, ireq
);
2237 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
2238 if (vap
->iv_opmode
== IEEE80211_M_STA
)
2239 error
= setappie(&vap
->iv_appie_assocreq
, ireq
);
2243 case (IEEE80211_APPIE_WPA
& IEEE80211_FC0_SUBTYPE_MASK
):
2244 error
= setappie(&vap
->iv_appie_wpa
, ireq
);
2247 * Must split single blob of data into separate
2248 * WPA and RSN ie's because they go in different
2249 * locations in the mgt frames.
2250 * XXX use IEEE80211_IOC_WPA2 so user code does split
2252 vap
->iv_wpa_ie
= NULL
;
2253 vap
->iv_rsn_ie
= NULL
;
2254 if (vap
->iv_appie_wpa
!= NULL
) {
2255 struct ieee80211_appie
*appie
=
2257 uint8_t *data
= appie
->ie_data
;
2259 /* XXX ie length validate is painful, cheat */
2260 setwparsnie(vap
, data
, appie
->ie_len
);
2261 setwparsnie(vap
, data
+ 2 + data
[1],
2262 appie
->ie_len
- (2 + data
[1]));
2264 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
||
2265 vap
->iv_opmode
== IEEE80211_M_IBSS
) {
2267 * Must rebuild beacon frame as the update
2268 * mechanism doesn't handle WPA/RSN ie's.
2269 * Could extend it but it doesn't normally
2270 * change; this is just to deal with hostapd
2271 * plumbing the ie after the interface is up.
2284 static __noinline
int
2285 ieee80211_ioctl_setappie(struct ieee80211vap
*vap
,
2286 const struct ieee80211req
*ireq
)
2288 struct ieee80211com
*ic
= vap
->iv_ic
;
2293 fc0
= ireq
->i_val
& 0xff;
2294 if ((fc0
& IEEE80211_FC0_TYPE_MASK
) != IEEE80211_FC0_TYPE_MGT
)
2296 /* NB: could check iv_opmode and reject but hardly worth the effort */
2297 error
= ieee80211_ioctl_setappie_locked(vap
, ireq
, fc0
);
2301 static __noinline
int
2302 ieee80211_ioctl_chanswitch(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2304 struct ieee80211com
*ic
= vap
->iv_ic
;
2305 struct ieee80211_chanswitch_req csr
;
2306 struct ieee80211_channel
*c
;
2309 if (ireq
->i_len
!= sizeof(csr
))
2311 error
= copyin(ireq
->i_data
, &csr
, sizeof(csr
));
2314 /* XXX adhoc mode not supported */
2315 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
||
2316 (vap
->iv_flags
& IEEE80211_F_DOTH
) == 0)
2318 c
= ieee80211_find_channel(ic
,
2319 csr
.csa_chan
.ic_freq
, csr
.csa_chan
.ic_flags
);
2322 if ((ic
->ic_flags
& IEEE80211_F_CSAPENDING
) == 0)
2323 ieee80211_csa_startswitch(ic
, c
, csr
.csa_mode
, csr
.csa_count
);
2324 else if (csr
.csa_count
== 0)
2325 ieee80211_csa_cancelswitch(ic
);
2331 static __noinline
int
2332 ieee80211_ioctl_scanreq(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2334 #define IEEE80211_IOC_SCAN_FLAGS \
2335 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \
2336 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \
2337 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \
2338 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \
2339 IEEE80211_IOC_SCAN_CHECK)
2340 struct ieee80211com
*ic
= vap
->iv_ic
;
2341 struct ieee80211_scan_req sr
; /* XXX off stack? */
2344 /* NB: parent must be running */
2345 if ((ic
->ic_ifp
->if_flags
& IFF_RUNNING
) == 0)
2348 if (ireq
->i_len
!= sizeof(sr
))
2350 error
= copyin(ireq
->i_data
, &sr
, sizeof(sr
));
2353 /* convert duration */
2354 if (sr
.sr_duration
== IEEE80211_IOC_SCAN_FOREVER
)
2355 sr
.sr_duration
= IEEE80211_SCAN_FOREVER
;
2357 if (sr
.sr_duration
< IEEE80211_IOC_SCAN_DURATION_MIN
||
2358 sr
.sr_duration
> IEEE80211_IOC_SCAN_DURATION_MAX
)
2360 sr
.sr_duration
= msecs_to_ticks(sr
.sr_duration
);
2361 if (sr
.sr_duration
< 1)
2364 /* convert min/max channel dwell */
2365 if (sr
.sr_mindwell
!= 0) {
2366 sr
.sr_mindwell
= msecs_to_ticks(sr
.sr_mindwell
);
2367 if (sr
.sr_mindwell
< 1)
2370 if (sr
.sr_maxdwell
!= 0) {
2371 sr
.sr_maxdwell
= msecs_to_ticks(sr
.sr_maxdwell
);
2372 if (sr
.sr_maxdwell
< 1)
2375 /* NB: silently reduce ssid count to what is supported */
2376 if (sr
.sr_nssid
> IEEE80211_SCAN_MAX_SSID
)
2377 sr
.sr_nssid
= IEEE80211_SCAN_MAX_SSID
;
2378 for (i
= 0; i
< sr
.sr_nssid
; i
++)
2379 if (sr
.sr_ssid
[i
].len
> IEEE80211_NWID_LEN
)
2381 /* cleanse flags just in case, could reject if invalid flags */
2382 sr
.sr_flags
&= IEEE80211_IOC_SCAN_FLAGS
;
2384 * Add an implicit NOPICK if the vap is not marked UP. This
2385 * allows applications to scan without joining a bss (or picking
2386 * a channel and setting up a bss) and without forcing manual
2387 * roaming mode--you just need to mark the parent device UP.
2389 if ((vap
->iv_ifp
->if_flags
& IFF_UP
) == 0)
2390 sr
.sr_flags
|= IEEE80211_IOC_SCAN_NOPICK
;
2392 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
2393 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n",
2394 __func__
, sr
.sr_flags
,
2395 (vap
->iv_ifp
->if_flags
& IFF_UP
) == 0 ? " (!IFF_UP)" : "",
2396 sr
.sr_duration
, sr
.sr_mindwell
, sr
.sr_maxdwell
, sr
.sr_nssid
);
2398 * If we are in INIT state then the driver has never had a chance
2399 * to setup hardware state to do a scan; we must use the state
2400 * machine to get us up to the SCAN state but once we reach SCAN
2401 * state we then want to use the supplied params. Stash the
2402 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the
2403 * state machines will recognize this and use the stashed params
2404 * to issue the scan request.
2406 * Otherwise just invoke the scan machinery directly.
2408 if (vap
->iv_state
== IEEE80211_S_INIT
) {
2409 /* NB: clobbers previous settings */
2410 vap
->iv_scanreq_flags
= sr
.sr_flags
;
2411 vap
->iv_scanreq_duration
= sr
.sr_duration
;
2412 vap
->iv_scanreq_nssid
= sr
.sr_nssid
;
2413 for (i
= 0; i
< sr
.sr_nssid
; i
++) {
2414 vap
->iv_scanreq_ssid
[i
].len
= sr
.sr_ssid
[i
].len
;
2415 memcpy(vap
->iv_scanreq_ssid
[i
].ssid
, sr
.sr_ssid
[i
].ssid
,
2418 vap
->iv_flags_ext
|= IEEE80211_FEXT_SCANREQ
;
2419 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
2421 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_SCANREQ
;
2422 /* XXX neeed error return codes */
2423 if (sr
.sr_flags
& IEEE80211_IOC_SCAN_CHECK
) {
2424 (void) ieee80211_check_scan(vap
, sr
.sr_flags
,
2425 sr
.sr_duration
, sr
.sr_mindwell
, sr
.sr_maxdwell
,
2427 /* NB: cheat, we assume structures are compatible */
2428 (const struct ieee80211_scan_ssid
*) &sr
.sr_ssid
[0]);
2430 (void) ieee80211_start_scan(vap
, sr
.sr_flags
,
2431 sr
.sr_duration
, sr
.sr_mindwell
, sr
.sr_maxdwell
,
2433 /* NB: cheat, we assume structures are compatible */
2434 (const struct ieee80211_scan_ssid
*) &sr
.sr_ssid
[0]);
2438 #undef IEEE80211_IOC_SCAN_FLAGS
2441 static __noinline
int
2442 ieee80211_ioctl_setstavlan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2444 struct ieee80211_node
*ni
;
2445 struct ieee80211req_sta_vlan vlan
;
2448 if (ireq
->i_len
!= sizeof(vlan
))
2450 error
= copyin(ireq
->i_data
, &vlan
, sizeof(vlan
));
2453 if (!IEEE80211_ADDR_EQ(vlan
.sv_macaddr
, zerobssid
)) {
2454 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
2459 ni
= ieee80211_ref_node(vap
->iv_bss
);
2460 ni
->ni_vlan
= vlan
.sv_vlan
;
2461 ieee80211_free_node(ni
);
2466 isvap11g(const struct ieee80211vap
*vap
)
2468 const struct ieee80211_node
*bss
= vap
->iv_bss
;
2469 return bss
->ni_chan
!= IEEE80211_CHAN_ANYC
&&
2470 IEEE80211_IS_CHAN_ANYG(bss
->ni_chan
);
2474 isvapht(const struct ieee80211vap
*vap
)
2476 const struct ieee80211_node
*bss
= vap
->iv_bss
;
2477 return bss
->ni_chan
!= IEEE80211_CHAN_ANYC
&&
2478 IEEE80211_IS_CHAN_HT(bss
->ni_chan
);
2482 * Dummy ioctl set handler so the linker set is defined.
2485 dummy_ioctl_set(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2489 IEEE80211_IOCTL_SET(dummy
, dummy_ioctl_set
);
2492 ieee80211_ioctl_setdefault(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2494 ieee80211_ioctl_setfunc
* const *set
;
2497 SET_FOREACH(set
, ieee80211_ioctl_setset
) {
2498 error
= (*set
)(vap
, ireq
);
2499 if (error
!= ENOSYS
)
2505 static __noinline
int
2506 ieee80211_ioctl_set80211(struct ieee80211vap
*vap
, u_long cmd
, struct ieee80211req
*ireq
)
2508 struct ieee80211com
*ic
= vap
->iv_ic
;
2510 const struct ieee80211_authenticator
*auth
;
2511 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
2512 char tmpssid
[IEEE80211_NWID_LEN
];
2513 uint8_t tmpbssid
[IEEE80211_ADDR_LEN
];
2514 struct ieee80211_key
*k
;
2519 switch (ireq
->i_type
) {
2520 case IEEE80211_IOC_SSID
:
2521 if (ireq
->i_val
!= 0 ||
2522 ireq
->i_len
> IEEE80211_NWID_LEN
)
2524 error
= copyin(ireq
->i_data
, tmpssid
, ireq
->i_len
);
2527 memset(vap
->iv_des_ssid
[0].ssid
, 0, IEEE80211_NWID_LEN
);
2528 vap
->iv_des_ssid
[0].len
= ireq
->i_len
;
2529 memcpy(vap
->iv_des_ssid
[0].ssid
, tmpssid
, ireq
->i_len
);
2530 vap
->iv_des_nssid
= (ireq
->i_len
> 0);
2533 case IEEE80211_IOC_WEP
:
2534 switch (ireq
->i_val
) {
2535 case IEEE80211_WEP_OFF
:
2536 vap
->iv_flags
&= ~IEEE80211_F_PRIVACY
;
2537 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2539 case IEEE80211_WEP_ON
:
2540 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2541 vap
->iv_flags
|= IEEE80211_F_DROPUNENC
;
2543 case IEEE80211_WEP_MIXED
:
2544 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2545 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2550 case IEEE80211_IOC_WEPKEY
:
2551 kid
= (u_int
) ireq
->i_val
;
2552 if (kid
>= IEEE80211_WEP_NKID
)
2554 k
= &vap
->iv_nw_keys
[kid
];
2555 if (ireq
->i_len
== 0) {
2556 /* zero-len =>'s delete any existing key */
2557 (void) ieee80211_crypto_delkey(vap
, k
);
2560 if (ireq
->i_len
> sizeof(tmpkey
))
2562 memset(tmpkey
, 0, sizeof(tmpkey
));
2563 error
= copyin(ireq
->i_data
, tmpkey
, ireq
->i_len
);
2566 ieee80211_key_update_begin(vap
);
2567 k
->wk_keyix
= kid
; /* NB: force fixed key id */
2568 if (ieee80211_crypto_newkey(vap
, IEEE80211_CIPHER_WEP
,
2569 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, k
)) {
2570 k
->wk_keylen
= ireq
->i_len
;
2571 memcpy(k
->wk_key
, tmpkey
, sizeof(tmpkey
));
2572 IEEE80211_ADDR_COPY(k
->wk_macaddr
, vap
->iv_myaddr
);
2573 if (!ieee80211_crypto_setkey(vap
, k
))
2577 ieee80211_key_update_end(vap
);
2579 case IEEE80211_IOC_WEPTXKEY
:
2580 kid
= (u_int
) ireq
->i_val
;
2581 if (kid
>= IEEE80211_WEP_NKID
&&
2582 (uint16_t) kid
!= IEEE80211_KEYIX_NONE
)
2584 vap
->iv_def_txkey
= kid
;
2586 case IEEE80211_IOC_AUTHMODE
:
2587 switch (ireq
->i_val
) {
2588 case IEEE80211_AUTH_WPA
:
2589 case IEEE80211_AUTH_8021X
: /* 802.1x */
2590 case IEEE80211_AUTH_OPEN
: /* open */
2591 case IEEE80211_AUTH_SHARED
: /* shared-key */
2592 case IEEE80211_AUTH_AUTO
: /* auto */
2593 auth
= ieee80211_authenticator_get(ireq
->i_val
);
2600 switch (ireq
->i_val
) {
2601 case IEEE80211_AUTH_WPA
: /* WPA w/ 802.1x */
2602 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2603 ireq
->i_val
= IEEE80211_AUTH_8021X
;
2605 case IEEE80211_AUTH_OPEN
: /* open */
2606 vap
->iv_flags
&= ~(IEEE80211_F_WPA
|IEEE80211_F_PRIVACY
);
2608 case IEEE80211_AUTH_SHARED
: /* shared-key */
2609 case IEEE80211_AUTH_8021X
: /* 802.1x */
2610 vap
->iv_flags
&= ~IEEE80211_F_WPA
;
2611 /* both require a key so mark the PRIVACY capability */
2612 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2614 case IEEE80211_AUTH_AUTO
: /* auto */
2615 vap
->iv_flags
&= ~IEEE80211_F_WPA
;
2616 /* XXX PRIVACY handling? */
2617 /* XXX what's the right way to do this? */
2620 /* NB: authenticator attach/detach happens on state change */
2621 vap
->iv_bss
->ni_authmode
= ireq
->i_val
;
2622 /* XXX mixed/mode/usage? */
2623 vap
->iv_auth
= auth
;
2626 case IEEE80211_IOC_CHANNEL
:
2627 error
= ieee80211_ioctl_setchannel(vap
, ireq
);
2629 case IEEE80211_IOC_POWERSAVE
:
2630 switch (ireq
->i_val
) {
2631 case IEEE80211_POWERSAVE_OFF
:
2632 if (vap
->iv_flags
& IEEE80211_F_PMGTON
) {
2633 ieee80211_syncflag(vap
, -IEEE80211_F_PMGTON
);
2637 case IEEE80211_POWERSAVE_ON
:
2638 if ((vap
->iv_caps
& IEEE80211_C_PMGT
) == 0)
2640 else if ((vap
->iv_flags
& IEEE80211_F_PMGTON
) == 0) {
2641 ieee80211_syncflag(vap
, IEEE80211_F_PMGTON
);
2650 case IEEE80211_IOC_POWERSAVESLEEP
:
2651 if (ireq
->i_val
< 0)
2653 ic
->ic_lintval
= ireq
->i_val
;
2656 case IEEE80211_IOC_RTSTHRESHOLD
:
2657 if (!(IEEE80211_RTS_MIN
<= ireq
->i_val
&&
2658 ireq
->i_val
<= IEEE80211_RTS_MAX
))
2660 vap
->iv_rtsthreshold
= ireq
->i_val
;
2663 case IEEE80211_IOC_PROTMODE
:
2664 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
2666 ic
->ic_protmode
= ireq
->i_val
;
2667 /* NB: if not operating in 11g this can wait */
2668 if (ic
->ic_bsschan
!= IEEE80211_CHAN_ANYC
&&
2669 IEEE80211_IS_CHAN_ANYG(ic
->ic_bsschan
))
2672 case IEEE80211_IOC_TXPOWER
:
2673 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
2675 if (!(IEEE80211_TXPOWER_MIN
<= ireq
->i_val
&&
2676 ireq
->i_val
<= IEEE80211_TXPOWER_MAX
))
2678 ic
->ic_txpowlimit
= ireq
->i_val
;
2681 case IEEE80211_IOC_ROAMING
:
2682 if (!(IEEE80211_ROAMING_DEVICE
<= ireq
->i_val
&&
2683 ireq
->i_val
<= IEEE80211_ROAMING_MANUAL
))
2685 vap
->iv_roaming
= ireq
->i_val
;
2688 case IEEE80211_IOC_PRIVACY
:
2690 /* XXX check for key state? */
2691 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2693 vap
->iv_flags
&= ~IEEE80211_F_PRIVACY
;
2696 case IEEE80211_IOC_DROPUNENCRYPTED
:
2698 vap
->iv_flags
|= IEEE80211_F_DROPUNENC
;
2700 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2703 case IEEE80211_IOC_WPAKEY
:
2704 error
= ieee80211_ioctl_setkey(vap
, ireq
);
2706 case IEEE80211_IOC_DELKEY
:
2707 error
= ieee80211_ioctl_delkey(vap
, ireq
);
2709 case IEEE80211_IOC_MLME
:
2710 error
= ieee80211_ioctl_setmlme(vap
, ireq
);
2712 case IEEE80211_IOC_COUNTERMEASURES
:
2714 if ((vap
->iv_flags
& IEEE80211_F_WPA
) == 0)
2716 vap
->iv_flags
|= IEEE80211_F_COUNTERM
;
2718 vap
->iv_flags
&= ~IEEE80211_F_COUNTERM
;
2721 case IEEE80211_IOC_WPA
:
2722 if (ireq
->i_val
> 3)
2724 /* XXX verify ciphers available */
2725 flags
= vap
->iv_flags
& ~IEEE80211_F_WPA
;
2726 switch (ireq
->i_val
) {
2728 if (!(vap
->iv_caps
& IEEE80211_C_WPA1
))
2730 flags
|= IEEE80211_F_WPA1
;
2733 if (!(vap
->iv_caps
& IEEE80211_C_WPA2
))
2735 flags
|= IEEE80211_F_WPA2
;
2738 if ((vap
->iv_caps
& IEEE80211_C_WPA
) != IEEE80211_C_WPA
)
2740 flags
|= IEEE80211_F_WPA1
| IEEE80211_F_WPA2
;
2742 default: /* Can't set any -> error */
2745 vap
->iv_flags
= flags
;
2746 error
= ERESTART
; /* NB: can change beacon frame */
2748 case IEEE80211_IOC_WME
:
2750 if ((vap
->iv_caps
& IEEE80211_C_WME
) == 0)
2752 ieee80211_syncflag(vap
, IEEE80211_F_WME
);
2754 ieee80211_syncflag(vap
, -IEEE80211_F_WME
);
2755 error
= ERESTART
; /* NB: can change beacon frame */
2757 case IEEE80211_IOC_HIDESSID
:
2759 vap
->iv_flags
|= IEEE80211_F_HIDESSID
;
2761 vap
->iv_flags
&= ~IEEE80211_F_HIDESSID
;
2762 error
= ERESTART
; /* XXX ENETRESET? */
2764 case IEEE80211_IOC_APBRIDGE
:
2765 if (ireq
->i_val
== 0)
2766 vap
->iv_flags
|= IEEE80211_F_NOBRIDGE
;
2768 vap
->iv_flags
&= ~IEEE80211_F_NOBRIDGE
;
2770 case IEEE80211_IOC_BSSID
:
2771 if (ireq
->i_len
!= sizeof(tmpbssid
))
2773 error
= copyin(ireq
->i_data
, tmpbssid
, ireq
->i_len
);
2776 IEEE80211_ADDR_COPY(vap
->iv_des_bssid
, tmpbssid
);
2777 if (IEEE80211_ADDR_EQ(vap
->iv_des_bssid
, zerobssid
))
2778 vap
->iv_flags
&= ~IEEE80211_F_DESBSSID
;
2780 vap
->iv_flags
|= IEEE80211_F_DESBSSID
;
2783 case IEEE80211_IOC_CHANLIST
:
2784 error
= ieee80211_ioctl_setchanlist(vap
, ireq
);
2786 #define OLD_IEEE80211_IOC_SCAN_REQ 23
2787 #ifdef OLD_IEEE80211_IOC_SCAN_REQ
2788 case OLD_IEEE80211_IOC_SCAN_REQ
:
2789 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
2790 "%s: active scan request\n", __func__
);
2792 * If we are in INIT state then the driver has never
2793 * had a chance to setup hardware state to do a scan;
2794 * use the state machine to get us up the SCAN state.
2795 * Otherwise just invoke the scan machinery to start
2798 if (vap
->iv_state
== IEEE80211_S_INIT
)
2799 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
2801 (void) ieee80211_start_scan(vap
,
2802 IEEE80211_SCAN_ACTIVE
|
2803 IEEE80211_SCAN_NOPICK
|
2804 IEEE80211_SCAN_ONCE
,
2805 IEEE80211_SCAN_FOREVER
, 0, 0,
2806 /* XXX use ioctl params */
2807 vap
->iv_des_nssid
, vap
->iv_des_ssid
);
2809 #endif /* OLD_IEEE80211_IOC_SCAN_REQ */
2810 case IEEE80211_IOC_SCAN_REQ
:
2811 error
= ieee80211_ioctl_scanreq(vap
, ireq
);
2813 case IEEE80211_IOC_SCAN_CANCEL
:
2814 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
2815 "%s: cancel scan\n", __func__
);
2816 ieee80211_cancel_scan(vap
);
2818 case IEEE80211_IOC_HTCONF
:
2819 if (ireq
->i_val
& 1)
2820 ieee80211_syncflag_ht(vap
, IEEE80211_FHT_HT
);
2822 ieee80211_syncflag_ht(vap
, -IEEE80211_FHT_HT
);
2823 if (ireq
->i_val
& 2)
2824 ieee80211_syncflag_ht(vap
, IEEE80211_FHT_USEHT40
);
2826 ieee80211_syncflag_ht(vap
, -IEEE80211_FHT_USEHT40
);
2829 case IEEE80211_IOC_ADDMAC
:
2830 case IEEE80211_IOC_DELMAC
:
2831 error
= ieee80211_ioctl_macmac(vap
, ireq
);
2833 case IEEE80211_IOC_MACCMD
:
2834 error
= ieee80211_ioctl_setmaccmd(vap
, ireq
);
2836 case IEEE80211_IOC_STA_STATS
:
2837 error
= ieee80211_ioctl_setstastats(vap
, ireq
);
2839 case IEEE80211_IOC_STA_TXPOW
:
2840 error
= ieee80211_ioctl_setstatxpow(vap
, ireq
);
2842 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
2843 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
2844 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
2845 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
2846 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
2847 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
2848 error
= ieee80211_ioctl_setwmeparam(vap
, ireq
);
2850 case IEEE80211_IOC_DTIM_PERIOD
:
2851 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
2852 vap
->iv_opmode
!= IEEE80211_M_MBSS
&&
2853 vap
->iv_opmode
!= IEEE80211_M_IBSS
)
2855 if (IEEE80211_DTIM_MIN
<= ireq
->i_val
&&
2856 ireq
->i_val
<= IEEE80211_DTIM_MAX
) {
2857 vap
->iv_dtim_period
= ireq
->i_val
;
2858 error
= ENETRESET
; /* requires restart */
2862 case IEEE80211_IOC_BEACON_INTERVAL
:
2863 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
2864 vap
->iv_opmode
!= IEEE80211_M_MBSS
&&
2865 vap
->iv_opmode
!= IEEE80211_M_IBSS
)
2867 if (IEEE80211_BINTVAL_MIN
<= ireq
->i_val
&&
2868 ireq
->i_val
<= IEEE80211_BINTVAL_MAX
) {
2869 ic
->ic_bintval
= ireq
->i_val
;
2870 error
= ENETRESET
; /* requires restart */
2874 case IEEE80211_IOC_PUREG
:
2876 vap
->iv_flags
|= IEEE80211_F_PUREG
;
2878 vap
->iv_flags
&= ~IEEE80211_F_PUREG
;
2879 /* NB: reset only if we're operating on an 11g channel */
2883 case IEEE80211_IOC_BGSCAN
:
2885 if ((vap
->iv_caps
& IEEE80211_C_BGSCAN
) == 0)
2887 vap
->iv_flags
|= IEEE80211_F_BGSCAN
;
2889 vap
->iv_flags
&= ~IEEE80211_F_BGSCAN
;
2891 case IEEE80211_IOC_BGSCAN_IDLE
:
2892 if (ireq
->i_val
>= IEEE80211_BGSCAN_IDLE_MIN
)
2893 vap
->iv_bgscanidle
= ireq
->i_val
*hz
/1000;
2897 case IEEE80211_IOC_BGSCAN_INTERVAL
:
2898 if (ireq
->i_val
>= IEEE80211_BGSCAN_INTVAL_MIN
)
2899 vap
->iv_bgscanintvl
= ireq
->i_val
*hz
;
2903 case IEEE80211_IOC_SCANVALID
:
2904 if (ireq
->i_val
>= IEEE80211_SCAN_VALID_MIN
)
2905 vap
->iv_scanvalid
= ireq
->i_val
*hz
;
2909 case IEEE80211_IOC_FRAGTHRESHOLD
:
2910 if ((vap
->iv_caps
& IEEE80211_C_TXFRAG
) == 0 &&
2911 ireq
->i_val
!= IEEE80211_FRAG_MAX
)
2913 if (!(IEEE80211_FRAG_MIN
<= ireq
->i_val
&&
2914 ireq
->i_val
<= IEEE80211_FRAG_MAX
))
2916 vap
->iv_fragthreshold
= ireq
->i_val
;
2919 case IEEE80211_IOC_BURST
:
2921 if ((vap
->iv_caps
& IEEE80211_C_BURST
) == 0)
2923 ieee80211_syncflag(vap
, IEEE80211_F_BURST
);
2925 ieee80211_syncflag(vap
, -IEEE80211_F_BURST
);
2928 case IEEE80211_IOC_BMISSTHRESHOLD
:
2929 if (!(IEEE80211_HWBMISS_MIN
<= ireq
->i_val
&&
2930 ireq
->i_val
<= IEEE80211_HWBMISS_MAX
))
2932 vap
->iv_bmissthreshold
= ireq
->i_val
;
2935 case IEEE80211_IOC_CURCHAN
:
2936 error
= ieee80211_ioctl_setcurchan(vap
, ireq
);
2938 case IEEE80211_IOC_SHORTGI
:
2940 #define IEEE80211_HTCAP_SHORTGI \
2941 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2942 if (((ireq
->i_val
^ vap
->iv_htcaps
) & IEEE80211_HTCAP_SHORTGI
) != 0)
2944 if (ireq
->i_val
& IEEE80211_HTCAP_SHORTGI20
)
2945 vap
->iv_flags_ht
|= IEEE80211_FHT_SHORTGI20
;
2946 if (ireq
->i_val
& IEEE80211_HTCAP_SHORTGI40
)
2947 vap
->iv_flags_ht
|= IEEE80211_FHT_SHORTGI40
;
2948 #undef IEEE80211_HTCAP_SHORTGI
2951 ~(IEEE80211_FHT_SHORTGI20
| IEEE80211_FHT_SHORTGI40
);
2954 case IEEE80211_IOC_AMPDU
:
2955 if (ireq
->i_val
&& (vap
->iv_htcaps
& IEEE80211_HTC_AMPDU
) == 0)
2957 if (ireq
->i_val
& 1)
2958 vap
->iv_flags_ht
|= IEEE80211_FHT_AMPDU_TX
;
2960 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMPDU_TX
;
2961 if (ireq
->i_val
& 2)
2962 vap
->iv_flags_ht
|= IEEE80211_FHT_AMPDU_RX
;
2964 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMPDU_RX
;
2965 /* NB: reset only if we're operating on an 11n channel */
2969 case IEEE80211_IOC_AMPDU_LIMIT
:
2970 if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K
<= ireq
->i_val
&&
2971 ireq
->i_val
<= IEEE80211_HTCAP_MAXRXAMPDU_64K
))
2973 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
2974 vap
->iv_ampdu_rxmax
= ireq
->i_val
;
2976 vap
->iv_ampdu_limit
= ireq
->i_val
;
2979 case IEEE80211_IOC_AMPDU_DENSITY
:
2980 if (!(IEEE80211_HTCAP_MPDUDENSITY_NA
<= ireq
->i_val
&&
2981 ireq
->i_val
<= IEEE80211_HTCAP_MPDUDENSITY_16
))
2983 vap
->iv_ampdu_density
= ireq
->i_val
;
2986 case IEEE80211_IOC_AMSDU
:
2987 if (ireq
->i_val
&& (vap
->iv_htcaps
& IEEE80211_HTC_AMSDU
) == 0)
2989 if (ireq
->i_val
& 1)
2990 vap
->iv_flags_ht
|= IEEE80211_FHT_AMSDU_TX
;
2992 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMSDU_TX
;
2993 if (ireq
->i_val
& 2)
2994 vap
->iv_flags_ht
|= IEEE80211_FHT_AMSDU_RX
;
2996 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMSDU_RX
;
2997 /* NB: reset only if we're operating on an 11n channel */
3001 case IEEE80211_IOC_AMSDU_LIMIT
:
3003 vap
->iv_amsdu_limit
= ireq
->i_val
; /* XXX truncation? */
3005 case IEEE80211_IOC_PUREN
:
3007 if ((vap
->iv_flags_ht
& IEEE80211_FHT_HT
) == 0)
3009 vap
->iv_flags_ht
|= IEEE80211_FHT_PUREN
;
3011 vap
->iv_flags_ht
&= ~IEEE80211_FHT_PUREN
;
3012 /* NB: reset only if we're operating on an 11n channel */
3016 case IEEE80211_IOC_DOTH
:
3019 /* XXX no capability */
3020 if ((vap
->iv_caps
& IEEE80211_C_DOTH
) == 0)
3023 vap
->iv_flags
|= IEEE80211_F_DOTH
;
3025 vap
->iv_flags
&= ~IEEE80211_F_DOTH
;
3028 case IEEE80211_IOC_REGDOMAIN
:
3029 error
= ieee80211_ioctl_setregdomain(vap
, ireq
);
3031 case IEEE80211_IOC_ROAM
:
3032 error
= ieee80211_ioctl_setroam(vap
, ireq
);
3034 case IEEE80211_IOC_TXPARAMS
:
3035 error
= ieee80211_ioctl_settxparams(vap
, ireq
);
3037 case IEEE80211_IOC_HTCOMPAT
:
3039 if ((vap
->iv_flags_ht
& IEEE80211_FHT_HT
) == 0)
3041 vap
->iv_flags_ht
|= IEEE80211_FHT_HTCOMPAT
;
3043 vap
->iv_flags_ht
&= ~IEEE80211_FHT_HTCOMPAT
;
3044 /* NB: reset only if we're operating on an 11n channel */
3048 case IEEE80211_IOC_DWDS
:
3050 /* NB: DWDS only makes sense for WDS-capable devices */
3051 if ((ic
->ic_caps
& IEEE80211_C_WDS
) == 0)
3053 /* NB: DWDS is used only with ap+sta vaps */
3054 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
3055 vap
->iv_opmode
!= IEEE80211_M_STA
)
3057 vap
->iv_flags
|= IEEE80211_F_DWDS
;
3058 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3059 vap
->iv_flags_ext
|= IEEE80211_FEXT_4ADDR
;
3061 vap
->iv_flags
&= ~IEEE80211_F_DWDS
;
3062 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3063 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_4ADDR
;
3066 case IEEE80211_IOC_INACTIVITY
:
3068 vap
->iv_flags_ext
|= IEEE80211_FEXT_INACT
;
3070 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_INACT
;
3072 case IEEE80211_IOC_APPIE
:
3073 error
= ieee80211_ioctl_setappie(vap
, ireq
);
3075 case IEEE80211_IOC_WPS
:
3077 if ((vap
->iv_caps
& IEEE80211_C_WPA
) == 0)
3079 vap
->iv_flags_ext
|= IEEE80211_FEXT_WPS
;
3081 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_WPS
;
3083 case IEEE80211_IOC_TSN
:
3085 if ((vap
->iv_caps
& IEEE80211_C_WPA
) == 0)
3087 vap
->iv_flags_ext
|= IEEE80211_FEXT_TSN
;
3089 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_TSN
;
3091 case IEEE80211_IOC_CHANSWITCH
:
3092 error
= ieee80211_ioctl_chanswitch(vap
, ireq
);
3094 case IEEE80211_IOC_DFS
:
3096 if ((vap
->iv_caps
& IEEE80211_C_DFS
) == 0)
3098 /* NB: DFS requires 11h support */
3099 if ((vap
->iv_flags
& IEEE80211_F_DOTH
) == 0)
3101 vap
->iv_flags_ext
|= IEEE80211_FEXT_DFS
;
3103 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_DFS
;
3105 case IEEE80211_IOC_DOTD
:
3107 vap
->iv_flags_ext
|= IEEE80211_FEXT_DOTD
;
3109 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_DOTD
;
3110 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3113 case IEEE80211_IOC_HTPROTMODE
:
3114 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
3116 ic
->ic_htprotmode
= ireq
->i_val
?
3117 IEEE80211_PROT_RTSCTS
: IEEE80211_PROT_NONE
;
3118 /* NB: if not operating in 11n this can wait */
3122 case IEEE80211_IOC_STA_VLAN
:
3123 error
= ieee80211_ioctl_setstavlan(vap
, ireq
);
3125 case IEEE80211_IOC_SMPS
:
3126 if ((ireq
->i_val
&~ IEEE80211_HTCAP_SMPS
) != 0 ||
3127 ireq
->i_val
== 0x0008) /* value of 2 is reserved */
3129 if (ireq
->i_val
!= IEEE80211_HTCAP_SMPS_OFF
&&
3130 (vap
->iv_htcaps
& IEEE80211_HTC_SMPS
) == 0)
3132 vap
->iv_htcaps
= (vap
->iv_htcaps
&~ IEEE80211_HTCAP_SMPS
) |
3134 /* NB: if not operating in 11n this can wait */
3138 case IEEE80211_IOC_RIFS
:
3139 if (ireq
->i_val
!= 0) {
3140 if ((vap
->iv_htcaps
& IEEE80211_HTC_RIFS
) == 0)
3142 vap
->iv_flags_ht
|= IEEE80211_FHT_RIFS
;
3144 vap
->iv_flags_ht
&= ~IEEE80211_FHT_RIFS
;
3145 /* NB: if not operating in 11n this can wait */
3150 error
= ieee80211_ioctl_setdefault(vap
, ireq
);
3154 * The convention is that ENETRESET means an operation
3155 * requires a complete re-initialization of the device (e.g.
3156 * changing something that affects the association state).
3157 * ERESTART means the request may be handled with only a
3158 * reload of the hardware state. We hand ERESTART requests
3159 * to the iv_reset callback so the driver can decide. If
3160 * a device does not fillin iv_reset then it defaults to one
3161 * that returns ENETRESET. Otherwise a driver may return
3162 * ENETRESET (in which case a full reset will be done) or
3163 * 0 to mean there's no need to do anything (e.g. when the
3164 * change has no effect on the driver/device).
3166 if (error
== ERESTART
)
3167 error
= IFNET_IS_UP_RUNNING(vap
->iv_ifp
) ?
3168 vap
->iv_reset(vap
, ireq
->i_type
) : 0;
3169 if (error
== ENETRESET
) {
3170 /* XXX need to re-think AUTO handling */
3171 if (IS_UP_AUTO(vap
))
3172 ieee80211_init(vap
);
3179 * Rebuild the parent's multicast address list after an add/del
3180 * of a multicast address for a vap. We have no way to tell
3181 * what happened above to optimize the work so we purge the entire
3182 * list and rebuild from scratch. This is way expensive.
3183 * Note also the half-baked workaround for if_addmulti calling
3184 * back to the parent device; there's no way to insert mcast
3185 * entries quietly and/or cheaply.
3188 ieee80211_ioctl_updatemulti(struct ieee80211com
*ic
)
3190 struct ifnet
*parent
= ic
->ic_ifp
;
3191 struct ieee80211vap
*vap
;
3194 if_delallmulti(parent
);
3195 ioctl
= parent
->if_ioctl
; /* XXX WAR if_allmulti */
3196 parent
->if_ioctl
= NULL
;
3197 TAILQ_FOREACH(vap
, &ic
->ic_vaps
, iv_next
) {
3198 struct ifnet
*ifp
= vap
->iv_ifp
;
3199 struct ifmultiaddr
*ifma
;
3201 TAILQ_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
3202 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
3204 (void) if_addmulti(parent
, ifma
->ifma_addr
, NULL
);
3207 parent
->if_ioctl
= ioctl
;
3208 ieee80211_runtask(ic
, &ic
->ic_mcast_task
);
3212 ieee80211_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*ucred
)
3214 struct ieee80211vap
*vap
= ifp
->if_softc
;
3215 struct ieee80211com
*ic
= vap
->iv_ic
;
3218 struct ifaddr
*ifa
; /* XXX */
3222 ieee80211_syncifflag_locked(ic
, IFF_PROMISC
);
3223 ieee80211_syncifflag_locked(ic
, IFF_ALLMULTI
);
3224 if (ifp
->if_flags
& IFF_UP
) {
3226 * Bring ourself up unless we're already operational.
3227 * If we're the first vap and the parent is not up
3228 * then it will automatically be brought up as a
3229 * side-effect of bringing ourself up.
3231 if (vap
->iv_state
== IEEE80211_S_INIT
)
3232 ieee80211_start_locked(vap
);
3233 } else if (ifp
->if_flags
& IFF_RUNNING
) {
3235 * Stop ourself. If we are the last vap to be
3236 * marked down the parent will also be taken down.
3238 ieee80211_stop_locked(vap
);
3240 /* Wait for parent ioctl handler if it was queued */
3241 ieee80211_waitfor_parent(ic
);
3245 ieee80211_ioctl_updatemulti(ic
);
3249 ifr
= (struct ifreq
*)data
;
3250 error
= ifmedia_ioctl(ifp
, ifr
, &vap
->iv_media
, cmd
);
3253 error
= ieee80211_ioctl_get80211(vap
, cmd
,
3254 (struct ieee80211req
*) data
);
3257 error
= priv_check(curthread
, PRIV_NET80211_MANAGE
);
3259 error
= ieee80211_ioctl_set80211(vap
, cmd
,
3260 (struct ieee80211req
*) data
);
3262 case SIOCG80211STATS
:
3263 ifr
= (struct ifreq
*)data
;
3264 copyout(&vap
->iv_stats
, ifr
->ifr_data
, sizeof (vap
->iv_stats
));
3267 ifr
= (struct ifreq
*)data
;
3268 if (!(IEEE80211_MTU_MIN
<= ifr
->ifr_mtu
&&
3269 ifr
->ifr_mtu
<= IEEE80211_MTU_MAX
))
3272 ifp
->if_mtu
= ifr
->ifr_mtu
;
3276 * XXX Handle this directly so we can supress if_init calls.
3277 * XXX This should be done in ether_ioctl but for the moment
3278 * XXX there are too many other parts of the system that
3279 * XXX set IFF_UP and so supress if_init being called when
3282 ifa
= (struct ifaddr
*) data
;
3283 switch (ifa
->ifa_addr
->sa_family
) {
3286 if ((ifp
->if_flags
& IFF_UP
) == 0) {
3287 ifp
->if_flags
|= IFF_UP
;
3288 ifp
->if_init(ifp
->if_softc
);
3290 arp_ifinit(ifp
, ifa
);
3295 * XXX - This code is probably wrong,
3296 * but has been copied many times.
3299 struct ipx_addr
*ina
= &(IA_SIPX(ifa
)->sipx_addr
);
3301 if (ipx_nullhost(*ina
))
3302 ina
->x_host
= *(union ipx_host
*)
3305 bcopy((caddr_t
) ina
->x_host
.c_host
,
3306 (caddr_t
) IF_LLADDR(ifp
),
3312 if ((ifp
->if_flags
& IFF_UP
) == 0) {
3313 ifp
->if_flags
|= IFF_UP
;
3314 ifp
->if_init(ifp
->if_softc
);
3319 /* Pass NDIS ioctls up to the driver */
3322 case SIOCGPRIVATE_0
: {
3323 struct ifnet
*parent
= vap
->iv_ic
->ic_ifp
;
3324 error
= parent
->if_ioctl(parent
, cmd
, data
, ucred
);
3328 error
= ether_ioctl(ifp
, cmd
, data
);