2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2001 Atsushi Onoe
5 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
31 * IEEE 802.11 ioctl support (FreeBSD-specific)
37 #include <sys/endian.h>
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.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/if_private.h>
50 #include <net/ethernet.h>
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
57 #include <net80211/ieee80211_var.h>
58 #include <net80211/ieee80211_ioctl.h>
59 #include <net80211/ieee80211_regdomain.h>
60 #include <net80211/ieee80211_input.h>
62 #define IS_UP_AUTO(_vap) \
63 (IFNET_IS_UP_RUNNING((_vap)->iv_ifp) && \
64 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO)
66 static const uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
67 static struct ieee80211_channel
*findchannel(struct ieee80211com
*,
69 static int ieee80211_scanreq(struct ieee80211vap
*,
70 struct ieee80211_scan_req
*);
73 ieee80211_ioctl_getkey(u_long cmd
, struct ieee80211vap
*vap
,
74 struct ieee80211req
*ireq
)
76 struct ieee80211com
*ic
= vap
->iv_ic
;
77 struct ieee80211_node
*ni
;
78 struct ieee80211req_key ik
;
79 struct ieee80211_key
*wk
;
80 const struct ieee80211_cipher
*cip
;
84 if (ireq
->i_len
!= sizeof(ik
))
86 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
90 if (kid
== IEEE80211_KEYIX_NONE
) {
91 ni
= ieee80211_find_vap_node(&ic
->ic_sta
, vap
, ik
.ik_macaddr
);
94 wk
= &ni
->ni_ucastkey
;
96 if (kid
>= IEEE80211_WEP_NKID
)
98 wk
= &vap
->iv_nw_keys
[kid
];
99 IEEE80211_ADDR_COPY(&ik
.ik_macaddr
, vap
->iv_bss
->ni_macaddr
);
103 ik
.ik_type
= cip
->ic_cipher
;
104 ik
.ik_keylen
= wk
->wk_keylen
;
105 ik
.ik_flags
= wk
->wk_flags
& (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
);
106 if (wk
->wk_keyix
== vap
->iv_def_txkey
)
107 ik
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
108 if (ieee80211_priv_check_vap_getkey(cmd
, vap
, NULL
) == 0) {
109 /* NB: only root can read key data */
110 ik
.ik_keyrsc
= wk
->wk_keyrsc
[IEEE80211_NONQOS_TID
];
111 ik
.ik_keytsc
= wk
->wk_keytsc
;
112 memcpy(ik
.ik_keydata
, wk
->wk_key
, wk
->wk_keylen
);
113 if (cip
->ic_cipher
== IEEE80211_CIPHER_TKIP
) {
114 memcpy(ik
.ik_keydata
+wk
->wk_keylen
,
115 wk
->wk_key
+ IEEE80211_KEYBUF_SIZE
,
116 IEEE80211_MICBUF_SIZE
);
117 ik
.ik_keylen
+= IEEE80211_MICBUF_SIZE
;
122 memset(ik
.ik_keydata
, 0, sizeof(ik
.ik_keydata
));
125 ieee80211_free_node(ni
);
126 return copyout(&ik
, ireq
->i_data
, sizeof(ik
));
130 ieee80211_ioctl_getchanlist(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
132 struct ieee80211com
*ic
= vap
->iv_ic
;
134 if (sizeof(ic
->ic_chan_active
) < ireq
->i_len
)
135 ireq
->i_len
= sizeof(ic
->ic_chan_active
);
136 return copyout(&ic
->ic_chan_active
, ireq
->i_data
, ireq
->i_len
);
140 ieee80211_ioctl_getchaninfo(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
142 struct ieee80211com
*ic
= vap
->iv_ic
;
145 space
= __offsetof(struct ieee80211req_chaninfo
,
146 ic_chans
[ic
->ic_nchans
]);
147 if (space
> ireq
->i_len
)
149 /* XXX assumes compatible layout */
150 return copyout(&ic
->ic_nchans
, ireq
->i_data
, space
);
154 ieee80211_ioctl_getwpaie(struct ieee80211vap
*vap
,
155 struct ieee80211req
*ireq
, int req
)
157 struct ieee80211_node
*ni
;
158 struct ieee80211req_wpaie2
*wpaie
;
161 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
163 wpaie
= IEEE80211_MALLOC(sizeof(*wpaie
), M_TEMP
,
164 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
167 error
= copyin(ireq
->i_data
, wpaie
->wpa_macaddr
, IEEE80211_ADDR_LEN
);
170 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, wpaie
->wpa_macaddr
);
175 if (ni
->ni_ies
.wpa_ie
!= NULL
) {
176 int ielen
= ni
->ni_ies
.wpa_ie
[1] + 2;
177 if (ielen
> sizeof(wpaie
->wpa_ie
))
178 ielen
= sizeof(wpaie
->wpa_ie
);
179 memcpy(wpaie
->wpa_ie
, ni
->ni_ies
.wpa_ie
, ielen
);
181 if (req
== IEEE80211_IOC_WPAIE2
) {
182 if (ni
->ni_ies
.rsn_ie
!= NULL
) {
183 int ielen
= ni
->ni_ies
.rsn_ie
[1] + 2;
184 if (ielen
> sizeof(wpaie
->rsn_ie
))
185 ielen
= sizeof(wpaie
->rsn_ie
);
186 memcpy(wpaie
->rsn_ie
, ni
->ni_ies
.rsn_ie
, ielen
);
188 if (ireq
->i_len
> sizeof(struct ieee80211req_wpaie2
))
189 ireq
->i_len
= sizeof(struct ieee80211req_wpaie2
);
191 /* compatibility op, may overwrite wpa ie */
192 /* XXX check ic_flags? */
193 if (ni
->ni_ies
.rsn_ie
!= NULL
) {
194 int ielen
= ni
->ni_ies
.rsn_ie
[1] + 2;
195 if (ielen
> sizeof(wpaie
->wpa_ie
))
196 ielen
= sizeof(wpaie
->wpa_ie
);
197 memcpy(wpaie
->wpa_ie
, ni
->ni_ies
.rsn_ie
, ielen
);
199 if (ireq
->i_len
> sizeof(struct ieee80211req_wpaie
))
200 ireq
->i_len
= sizeof(struct ieee80211req_wpaie
);
202 ieee80211_free_node(ni
);
203 error
= copyout(wpaie
, ireq
->i_data
, ireq
->i_len
);
205 IEEE80211_FREE(wpaie
, M_TEMP
);
210 ieee80211_ioctl_getstastats(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
212 struct ieee80211_node
*ni
;
213 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
214 const size_t off
= __offsetof(struct ieee80211req_sta_stats
, is_stats
);
217 if (ireq
->i_len
< off
)
219 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
222 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
225 if (ireq
->i_len
> sizeof(struct ieee80211req_sta_stats
))
226 ireq
->i_len
= sizeof(struct ieee80211req_sta_stats
);
227 /* NB: copy out only the statistics */
228 error
= copyout(&ni
->ni_stats
, (uint8_t *) ireq
->i_data
+ off
,
230 ieee80211_free_node(ni
);
235 struct ieee80211req_scan_result
*sr
;
240 scan_space(const struct ieee80211_scan_entry
*se
, int *ielen
)
244 *ielen
= se
->se_ies
.len
;
246 * NB: ie's can be no more than 255 bytes and the max 802.11
247 * packet is <3Kbytes so we are sure this doesn't overflow
248 * 16-bits; if this is a concern we can drop the ie's.
250 len
= sizeof(struct ieee80211req_scan_result
) + se
->se_ssid
[1] +
251 se
->se_meshid
[1] + *ielen
;
252 return roundup(len
, sizeof(uint32_t));
256 get_scan_space(void *arg
, const struct ieee80211_scan_entry
*se
)
258 struct scanreq
*req
= arg
;
261 req
->space
+= scan_space(se
, &ielen
);
265 get_scan_result(void *arg
, const struct ieee80211_scan_entry
*se
)
267 struct scanreq
*req
= arg
;
268 struct ieee80211req_scan_result
*sr
;
269 int ielen
, len
, nr
, nxr
;
272 len
= scan_space(se
, &ielen
);
273 if (len
> req
->space
)
277 KASSERT(len
<= 65535 && ielen
<= 65535,
278 ("len %u ssid %u ie %u", len
, se
->se_ssid
[1], ielen
));
280 sr
->isr_ie_off
= sizeof(struct ieee80211req_scan_result
);
281 sr
->isr_ie_len
= ielen
;
282 sr
->isr_freq
= se
->se_chan
->ic_freq
;
283 sr
->isr_flags
= se
->se_chan
->ic_flags
;
284 sr
->isr_rssi
= se
->se_rssi
;
285 sr
->isr_noise
= se
->se_noise
;
286 sr
->isr_intval
= se
->se_intval
;
287 sr
->isr_capinfo
= se
->se_capinfo
;
288 sr
->isr_erp
= se
->se_erp
;
289 IEEE80211_ADDR_COPY(sr
->isr_bssid
, se
->se_bssid
);
290 nr
= min(se
->se_rates
[1], IEEE80211_RATE_MAXSIZE
);
291 memcpy(sr
->isr_rates
, se
->se_rates
+2, nr
);
292 nxr
= min(se
->se_xrates
[1], IEEE80211_RATE_MAXSIZE
- nr
);
293 memcpy(sr
->isr_rates
+nr
, se
->se_xrates
+2, nxr
);
294 sr
->isr_nrates
= nr
+ nxr
;
297 sr
->isr_ssid_len
= se
->se_ssid
[1];
298 cp
= ((uint8_t *)sr
) + sr
->isr_ie_off
;
299 memcpy(cp
, se
->se_ssid
+2, sr
->isr_ssid_len
);
302 cp
+= sr
->isr_ssid_len
;
303 sr
->isr_meshid_len
= se
->se_meshid
[1];
304 memcpy(cp
, se
->se_meshid
+2, sr
->isr_meshid_len
);
305 cp
+= sr
->isr_meshid_len
;
308 memcpy(cp
, se
->se_ies
.data
, ielen
);
311 req
->sr
= (struct ieee80211req_scan_result
*)(((uint8_t *)sr
) + len
);
315 ieee80211_ioctl_getscanresults(struct ieee80211vap
*vap
,
316 struct ieee80211req
*ireq
)
321 if (ireq
->i_len
< sizeof(struct scanreq
))
326 ieee80211_scan_iterate(vap
, get_scan_space
, &req
);
327 if (req
.space
> ireq
->i_len
)
328 req
.space
= ireq
->i_len
;
334 /* XXX IEEE80211_M_WAITOK after driver lock released */
335 p
= IEEE80211_MALLOC(space
, M_TEMP
,
336 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
340 ieee80211_scan_iterate(vap
, get_scan_result
, &req
);
341 ireq
->i_len
= space
- req
.space
;
342 error
= copyout(p
, ireq
->i_data
, ireq
->i_len
);
343 IEEE80211_FREE(p
, M_TEMP
);
351 struct ieee80211req_sta_info
*si
;
356 sta_space(const struct ieee80211_node
*ni
, size_t *ielen
)
358 *ielen
= ni
->ni_ies
.len
;
359 return roundup(sizeof(struct ieee80211req_sta_info
) + *ielen
,
364 get_sta_space(void *arg
, struct ieee80211_node
*ni
)
366 struct stainforeq
*req
= arg
;
369 if (ni
->ni_vap
->iv_opmode
== IEEE80211_M_HOSTAP
&&
370 ni
->ni_associd
== 0) /* only associated stations */
372 req
->space
+= sta_space(ni
, &ielen
);
376 get_sta_info(void *arg
, struct ieee80211_node
*ni
)
378 struct stainforeq
*req
= arg
;
379 struct ieee80211vap
*vap
= ni
->ni_vap
;
380 struct ieee80211req_sta_info
*si
;
384 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
&&
385 ni
->ni_associd
== 0) /* only associated stations */
387 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
) /* XXX bogus entry */
389 len
= sta_space(ni
, &ielen
);
390 if (len
> req
->space
)
394 si
->isi_ie_off
= sizeof(struct ieee80211req_sta_info
);
395 si
->isi_ie_len
= ielen
;
396 si
->isi_freq
= ni
->ni_chan
->ic_freq
;
397 si
->isi_flags
= ni
->ni_chan
->ic_flags
;
398 si
->isi_state
= ni
->ni_flags
;
399 si
->isi_authmode
= ni
->ni_authmode
;
400 vap
->iv_ic
->ic_node_getsignal(ni
, &si
->isi_rssi
, &si
->isi_noise
);
401 vap
->iv_ic
->ic_node_getmimoinfo(ni
, &si
->isi_mimo
);
402 si
->isi_capinfo
= ni
->ni_capinfo
;
403 si
->isi_erp
= ni
->ni_erp
;
404 IEEE80211_ADDR_COPY(si
->isi_macaddr
, ni
->ni_macaddr
);
405 si
->isi_nrates
= ni
->ni_rates
.rs_nrates
;
406 if (si
->isi_nrates
> 15)
408 memcpy(si
->isi_rates
, ni
->ni_rates
.rs_rates
, si
->isi_nrates
);
409 si
->isi_txrate
= ni
->ni_txrate
;
410 if (si
->isi_txrate
& IEEE80211_RATE_MCS
) {
411 const struct ieee80211_mcs_rates
*mcs
=
412 &ieee80211_htrates
[ni
->ni_txrate
&~ IEEE80211_RATE_MCS
];
413 if (IEEE80211_IS_CHAN_HT40(ni
->ni_chan
)) {
414 if (ni
->ni_flags
& IEEE80211_NODE_SGI40
)
415 si
->isi_txmbps
= mcs
->ht40_rate_800ns
;
417 si
->isi_txmbps
= mcs
->ht40_rate_400ns
;
419 if (ni
->ni_flags
& IEEE80211_NODE_SGI20
)
420 si
->isi_txmbps
= mcs
->ht20_rate_800ns
;
422 si
->isi_txmbps
= mcs
->ht20_rate_400ns
;
425 si
->isi_txmbps
= si
->isi_txrate
;
426 si
->isi_associd
= ni
->ni_associd
;
427 si
->isi_txpower
= ni
->ni_txpower
;
428 si
->isi_vlan
= ni
->ni_vlan
;
429 if (ni
->ni_flags
& IEEE80211_NODE_QOS
) {
430 memcpy(si
->isi_txseqs
, ni
->ni_txseqs
, sizeof(ni
->ni_txseqs
));
431 memcpy(si
->isi_rxseqs
, ni
->ni_rxseqs
, sizeof(ni
->ni_rxseqs
));
433 si
->isi_txseqs
[0] = ni
->ni_txseqs
[IEEE80211_NONQOS_TID
];
434 si
->isi_rxseqs
[0] = ni
->ni_rxseqs
[IEEE80211_NONQOS_TID
];
436 /* NB: leave all cases in case we relax ni_associd == 0 check */
437 if (ieee80211_node_is_authorized(ni
))
438 si
->isi_inact
= vap
->iv_inact_run
;
439 else if (ni
->ni_associd
!= 0 ||
440 (vap
->iv_opmode
== IEEE80211_M_WDS
&&
441 (vap
->iv_flags_ext
& IEEE80211_FEXT_WDSLEGACY
)))
442 si
->isi_inact
= vap
->iv_inact_auth
;
444 si
->isi_inact
= vap
->iv_inact_init
;
445 si
->isi_inact
= (si
->isi_inact
- ni
->ni_inact
) * IEEE80211_INACT_WAIT
;
446 si
->isi_localid
= ni
->ni_mllid
;
447 si
->isi_peerid
= ni
->ni_mlpid
;
448 si
->isi_peerstate
= ni
->ni_mlstate
;
451 cp
= ((uint8_t *)si
) + si
->isi_ie_off
;
452 memcpy(cp
, ni
->ni_ies
.data
, ielen
);
455 req
->si
= (struct ieee80211req_sta_info
*)(((uint8_t *)si
) + len
);
460 getstainfo_common(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
,
461 struct ieee80211_node
*ni
, size_t off
)
463 struct ieee80211com
*ic
= vap
->iv_ic
;
464 struct stainforeq req
;
472 ieee80211_iterate_nodes_vap(&ic
->ic_sta
, vap
, get_sta_space
,
475 get_sta_space(&req
, ni
);
476 if (req
.space
> ireq
->i_len
)
477 req
.space
= ireq
->i_len
;
480 /* XXX IEEE80211_M_WAITOK after driver lock released */
481 p
= IEEE80211_MALLOC(space
, M_TEMP
,
482 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
489 ieee80211_iterate_nodes_vap(&ic
->ic_sta
, vap
,
492 get_sta_info(&req
, ni
);
493 ireq
->i_len
= space
- req
.space
;
494 error
= copyout(p
, (uint8_t *) ireq
->i_data
+off
, ireq
->i_len
);
495 IEEE80211_FREE(p
, M_TEMP
);
500 ieee80211_free_node(ni
);
505 ieee80211_ioctl_getstainfo(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
507 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
508 const size_t off
= __offsetof(struct ieee80211req_sta_req
, info
);
509 struct ieee80211_node
*ni
;
512 if (ireq
->i_len
< sizeof(struct ieee80211req_sta_req
))
514 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
517 if (IEEE80211_ADDR_EQ(macaddr
, vap
->iv_ifp
->if_broadcastaddr
)) {
520 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
524 return getstainfo_common(vap
, ireq
, ni
, off
);
528 ieee80211_ioctl_getstatxpow(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
530 struct ieee80211_node
*ni
;
531 struct ieee80211req_sta_txpow txpow
;
534 if (ireq
->i_len
!= sizeof(txpow
))
536 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
539 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, txpow
.it_macaddr
);
542 txpow
.it_txpow
= ni
->ni_txpower
;
543 error
= copyout(&txpow
, ireq
->i_data
, sizeof(txpow
));
544 ieee80211_free_node(ni
);
549 ieee80211_ioctl_getwmeparam(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
551 struct ieee80211com
*ic
= vap
->iv_ic
;
552 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
553 struct wmeParams
*wmep
;
556 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
559 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
560 if (ac
>= WME_NUM_AC
)
562 if (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
)
563 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
565 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
566 switch (ireq
->i_type
) {
567 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
568 ireq
->i_val
= wmep
->wmep_logcwmin
;
570 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
571 ireq
->i_val
= wmep
->wmep_logcwmax
;
573 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
574 ireq
->i_val
= wmep
->wmep_aifsn
;
576 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
577 ireq
->i_val
= wmep
->wmep_txopLimit
;
579 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
580 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
581 ireq
->i_val
= wmep
->wmep_acm
;
583 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
584 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
585 ireq
->i_val
= !wmep
->wmep_noackPolicy
;
592 ieee80211_ioctl_getmaccmd(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
594 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
596 return (acl
== NULL
? EINVAL
: acl
->iac_getioctl(vap
, ireq
));
600 ieee80211_ioctl_getcurchan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
602 struct ieee80211com
*ic
= vap
->iv_ic
;
603 struct ieee80211_channel
*c
;
605 if (ireq
->i_len
!= sizeof(struct ieee80211_channel
))
608 * vap's may have different operating channels when HT is
609 * in use. When in RUN state report the vap-specific channel.
610 * Otherwise return curchan.
612 if (vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
)
613 c
= vap
->iv_bss
->ni_chan
;
616 return copyout(c
, ireq
->i_data
, sizeof(*c
));
620 getappie(const struct ieee80211_appie
*aie
, struct ieee80211req
*ireq
)
624 /* NB: truncate, caller can check length */
625 if (ireq
->i_len
> aie
->ie_len
)
626 ireq
->i_len
= aie
->ie_len
;
627 return copyout(aie
->ie_data
, ireq
->i_data
, ireq
->i_len
);
631 ieee80211_ioctl_getappie(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
635 fc0
= ireq
->i_val
& 0xff;
636 if ((fc0
& IEEE80211_FC0_TYPE_MASK
) != IEEE80211_FC0_TYPE_MGT
)
638 /* NB: could check iv_opmode and reject but hardly worth the effort */
639 switch (fc0
& IEEE80211_FC0_SUBTYPE_MASK
) {
640 case IEEE80211_FC0_SUBTYPE_BEACON
:
641 return getappie(vap
->iv_appie_beacon
, ireq
);
642 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
643 return getappie(vap
->iv_appie_proberesp
, ireq
);
644 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
645 return getappie(vap
->iv_appie_assocresp
, ireq
);
646 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
647 return getappie(vap
->iv_appie_probereq
, ireq
);
648 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
649 return getappie(vap
->iv_appie_assocreq
, ireq
);
650 case IEEE80211_FC0_SUBTYPE_BEACON
|IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
651 return getappie(vap
->iv_appie_wpa
, ireq
);
657 ieee80211_ioctl_getregdomain(struct ieee80211vap
*vap
,
658 const struct ieee80211req
*ireq
)
660 struct ieee80211com
*ic
= vap
->iv_ic
;
662 if (ireq
->i_len
!= sizeof(ic
->ic_regdomain
))
664 return copyout(&ic
->ic_regdomain
, ireq
->i_data
,
665 sizeof(ic
->ic_regdomain
));
669 ieee80211_ioctl_getroam(struct ieee80211vap
*vap
,
670 const struct ieee80211req
*ireq
)
672 size_t len
= ireq
->i_len
;
673 /* NB: accept short requests for backwards compat */
674 if (len
> sizeof(vap
->iv_roamparms
))
675 len
= sizeof(vap
->iv_roamparms
);
676 return copyout(vap
->iv_roamparms
, ireq
->i_data
, len
);
680 ieee80211_ioctl_gettxparams(struct ieee80211vap
*vap
,
681 const struct ieee80211req
*ireq
)
683 size_t len
= ireq
->i_len
;
684 /* NB: accept short requests for backwards compat */
685 if (len
> sizeof(vap
->iv_txparms
))
686 len
= sizeof(vap
->iv_txparms
);
687 return copyout(vap
->iv_txparms
, ireq
->i_data
, len
);
691 ieee80211_ioctl_getdevcaps(struct ieee80211com
*ic
,
692 const struct ieee80211req
*ireq
)
694 struct ieee80211_devcaps_req
*dc
;
695 struct ieee80211req_chaninfo
*ci
;
698 maxchans
= 1 + ((ireq
->i_len
- sizeof(struct ieee80211_devcaps_req
)) /
699 sizeof(struct ieee80211_channel
));
700 /* NB: require 1 so we know ic_nchans is accessible */
703 /* constrain max request size, 2K channels is ~24Kbytes */
706 dc
= (struct ieee80211_devcaps_req
*)
707 IEEE80211_MALLOC(IEEE80211_DEVCAPS_SIZE(maxchans
), M_TEMP
,
708 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
711 dc
->dc_drivercaps
= ic
->ic_caps
;
713 * Announce the set of both hardware and software supported
716 dc
->dc_cryptocaps
= ic
->ic_cryptocaps
| ic
->ic_sw_cryptocaps
;
717 dc
->dc_htcaps
= ic
->ic_htcaps
;
718 dc
->dc_vhtcaps
= ic
->ic_vht_cap
.vht_cap_info
;
719 ci
= &dc
->dc_chaninfo
;
720 ic
->ic_getradiocaps(ic
, maxchans
, &ci
->ic_nchans
, ci
->ic_chans
);
721 KASSERT(ci
->ic_nchans
<= maxchans
,
722 ("nchans %d maxchans %d", ci
->ic_nchans
, maxchans
));
723 ieee80211_sort_channels(ci
->ic_chans
, ci
->ic_nchans
);
724 error
= copyout(dc
, ireq
->i_data
, IEEE80211_DEVCAPS_SPACE(dc
));
725 IEEE80211_FREE(dc
, M_TEMP
);
730 ieee80211_ioctl_getstavlan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
732 struct ieee80211_node
*ni
;
733 struct ieee80211req_sta_vlan vlan
;
736 if (ireq
->i_len
!= sizeof(vlan
))
738 error
= copyin(ireq
->i_data
, &vlan
, sizeof(vlan
));
741 if (!IEEE80211_ADDR_EQ(vlan
.sv_macaddr
, zerobssid
)) {
742 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
747 ni
= ieee80211_ref_node(vap
->iv_bss
);
748 vlan
.sv_vlan
= ni
->ni_vlan
;
749 error
= copyout(&vlan
, ireq
->i_data
, sizeof(vlan
));
750 ieee80211_free_node(ni
);
755 * Dummy ioctl get handler so the linker set is defined.
758 dummy_ioctl_get(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
762 IEEE80211_IOCTL_GET(dummy
, dummy_ioctl_get
);
765 ieee80211_ioctl_getdefault(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
767 ieee80211_ioctl_getfunc
* const *get
;
770 SET_FOREACH(get
, ieee80211_ioctl_getset
) {
771 error
= (*get
)(vap
, ireq
);
779 ieee80211_ioctl_get80211(struct ieee80211vap
*vap
, u_long cmd
,
780 struct ieee80211req
*ireq
)
782 struct ieee80211com
*ic
= vap
->iv_ic
;
784 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
785 char tmpssid
[IEEE80211_NWID_LEN
];
788 switch (ireq
->i_type
) {
789 case IEEE80211_IOC_IC_NAME
:
790 len
= strlen(ic
->ic_name
) + 1;
791 if (len
> ireq
->i_len
)
794 error
= copyout(ic
->ic_name
, ireq
->i_data
, ireq
->i_len
);
796 case IEEE80211_IOC_SSID
:
797 switch (vap
->iv_state
) {
798 case IEEE80211_S_INIT
:
799 case IEEE80211_S_SCAN
:
800 ireq
->i_len
= vap
->iv_des_ssid
[0].len
;
801 memcpy(tmpssid
, vap
->iv_des_ssid
[0].ssid
, ireq
->i_len
);
804 ireq
->i_len
= vap
->iv_bss
->ni_esslen
;
805 memcpy(tmpssid
, vap
->iv_bss
->ni_essid
, ireq
->i_len
);
808 error
= copyout(tmpssid
, ireq
->i_data
, ireq
->i_len
);
810 case IEEE80211_IOC_NUMSSIDS
:
813 case IEEE80211_IOC_WEP
:
814 if ((vap
->iv_flags
& IEEE80211_F_PRIVACY
) == 0)
815 ireq
->i_val
= IEEE80211_WEP_OFF
;
816 else if (vap
->iv_flags
& IEEE80211_F_DROPUNENC
)
817 ireq
->i_val
= IEEE80211_WEP_ON
;
819 ireq
->i_val
= IEEE80211_WEP_MIXED
;
821 case IEEE80211_IOC_WEPKEY
:
822 kid
= (u_int
) ireq
->i_val
;
823 if (kid
>= IEEE80211_WEP_NKID
)
825 len
= (u_int
) vap
->iv_nw_keys
[kid
].wk_keylen
;
826 /* NB: only root can read WEP keys */
827 if (ieee80211_priv_check_vap_getkey(cmd
, vap
, NULL
) == 0) {
828 bcopy(vap
->iv_nw_keys
[kid
].wk_key
, tmpkey
, len
);
833 error
= copyout(tmpkey
, ireq
->i_data
, len
);
835 case IEEE80211_IOC_NUMWEPKEYS
:
836 ireq
->i_val
= IEEE80211_WEP_NKID
;
838 case IEEE80211_IOC_WEPTXKEY
:
839 ireq
->i_val
= vap
->iv_def_txkey
;
841 case IEEE80211_IOC_AUTHMODE
:
842 if (vap
->iv_flags
& IEEE80211_F_WPA
)
843 ireq
->i_val
= IEEE80211_AUTH_WPA
;
845 ireq
->i_val
= vap
->iv_bss
->ni_authmode
;
847 case IEEE80211_IOC_CHANNEL
:
848 ireq
->i_val
= ieee80211_chan2ieee(ic
, ic
->ic_curchan
);
850 case IEEE80211_IOC_POWERSAVE
:
851 if (vap
->iv_flags
& IEEE80211_F_PMGTON
)
852 ireq
->i_val
= IEEE80211_POWERSAVE_ON
;
854 ireq
->i_val
= IEEE80211_POWERSAVE_OFF
;
856 case IEEE80211_IOC_POWERSAVESLEEP
:
857 ireq
->i_val
= ic
->ic_lintval
;
859 case IEEE80211_IOC_RTSTHRESHOLD
:
860 ireq
->i_val
= vap
->iv_rtsthreshold
;
862 case IEEE80211_IOC_PROTMODE
:
863 ireq
->i_val
= vap
->iv_protmode
;
865 case IEEE80211_IOC_TXPOWER
:
867 * Tx power limit is the min of max regulatory
868 * power, any user-set limit, and the max the
871 * TODO: methodize this
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(cmd
, 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
|| vap
->iv_state
== IEEE80211_S_SLEEP
) {
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 case IEEE80211_IOC_WPAIE2
:
938 error
= ieee80211_ioctl_getwpaie(vap
, ireq
, ireq
->i_type
);
940 case IEEE80211_IOC_SCAN_RESULTS
:
941 error
= ieee80211_ioctl_getscanresults(vap
, ireq
);
943 case IEEE80211_IOC_STA_STATS
:
944 error
= ieee80211_ioctl_getstastats(vap
, ireq
);
946 case IEEE80211_IOC_TXPOWMAX
:
947 ireq
->i_val
= vap
->iv_bss
->ni_txpower
;
949 case IEEE80211_IOC_STA_TXPOW
:
950 error
= ieee80211_ioctl_getstatxpow(vap
, ireq
);
952 case IEEE80211_IOC_STA_INFO
:
953 error
= ieee80211_ioctl_getstainfo(vap
, ireq
);
955 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
956 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
957 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
958 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
959 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
960 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only) */
961 error
= ieee80211_ioctl_getwmeparam(vap
, ireq
);
963 case IEEE80211_IOC_DTIM_PERIOD
:
964 ireq
->i_val
= vap
->iv_dtim_period
;
966 case IEEE80211_IOC_BEACON_INTERVAL
:
967 /* NB: get from ic_bss for station mode */
968 ireq
->i_val
= vap
->iv_bss
->ni_intval
;
970 case IEEE80211_IOC_PUREG
:
971 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_PUREG
) != 0;
973 case IEEE80211_IOC_QUIET
:
974 ireq
->i_val
= vap
->iv_quiet
;
976 case IEEE80211_IOC_QUIET_COUNT
:
977 ireq
->i_val
= vap
->iv_quiet_count
;
979 case IEEE80211_IOC_QUIET_PERIOD
:
980 ireq
->i_val
= vap
->iv_quiet_period
;
982 case IEEE80211_IOC_QUIET_DUR
:
983 ireq
->i_val
= vap
->iv_quiet_duration
;
985 case IEEE80211_IOC_QUIET_OFFSET
:
986 ireq
->i_val
= vap
->iv_quiet_offset
;
988 case IEEE80211_IOC_BGSCAN
:
989 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_BGSCAN
) != 0;
991 case IEEE80211_IOC_BGSCAN_IDLE
:
992 ireq
->i_val
= vap
->iv_bgscanidle
*hz
/1000; /* ms */
994 case IEEE80211_IOC_BGSCAN_INTERVAL
:
995 ireq
->i_val
= vap
->iv_bgscanintvl
/hz
; /* seconds */
997 case IEEE80211_IOC_SCANVALID
:
998 ireq
->i_val
= vap
->iv_scanvalid
/hz
; /* seconds */
1000 case IEEE80211_IOC_FRAGTHRESHOLD
:
1001 ireq
->i_val
= vap
->iv_fragthreshold
;
1003 case IEEE80211_IOC_MACCMD
:
1004 error
= ieee80211_ioctl_getmaccmd(vap
, ireq
);
1006 case IEEE80211_IOC_BURST
:
1007 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_BURST
) != 0;
1009 case IEEE80211_IOC_BMISSTHRESHOLD
:
1010 ireq
->i_val
= vap
->iv_bmissthreshold
;
1012 case IEEE80211_IOC_CURCHAN
:
1013 error
= ieee80211_ioctl_getcurchan(vap
, ireq
);
1015 case IEEE80211_IOC_SHORTGI
:
1017 if (vap
->iv_flags_ht
& IEEE80211_FHT_SHORTGI20
)
1018 ireq
->i_val
|= IEEE80211_HTCAP_SHORTGI20
;
1019 if (vap
->iv_flags_ht
& IEEE80211_FHT_SHORTGI40
)
1020 ireq
->i_val
|= IEEE80211_HTCAP_SHORTGI40
;
1022 case IEEE80211_IOC_AMPDU
:
1024 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMPDU_TX
)
1026 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMPDU_RX
)
1029 case IEEE80211_IOC_AMPDU_LIMIT
:
1030 /* XXX TODO: make this a per-node thing; and leave this as global */
1031 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
1032 ireq
->i_val
= vap
->iv_ampdu_rxmax
;
1033 else if (vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
)
1035 * XXX TODO: this isn't completely correct, as we've
1036 * negotiated the higher of the two.
1038 ireq
->i_val
= _IEEE80211_MASKSHIFT( vap
->iv_bss
->ni_htparam
,
1039 IEEE80211_HTCAP_MAXRXAMPDU
);
1041 ireq
->i_val
= vap
->iv_ampdu_limit
;
1043 case IEEE80211_IOC_AMPDU_DENSITY
:
1044 /* XXX TODO: make this a per-node thing; and leave this as global */
1045 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1046 (vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
))
1048 * XXX TODO: this isn't completely correct, as we've
1049 * negotiated the higher of the two.
1051 ireq
->i_val
= _IEEE80211_MASKSHIFT(vap
->iv_bss
->ni_htparam
,
1052 IEEE80211_HTCAP_MPDUDENSITY
);
1054 ireq
->i_val
= vap
->iv_ampdu_density
;
1056 case IEEE80211_IOC_AMSDU
:
1058 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMSDU_TX
)
1060 if (vap
->iv_flags_ht
& IEEE80211_FHT_AMSDU_RX
)
1063 case IEEE80211_IOC_AMSDU_LIMIT
:
1064 ireq
->i_val
= vap
->iv_amsdu_limit
; /* XXX truncation? */
1066 case IEEE80211_IOC_PUREN
:
1067 ireq
->i_val
= (vap
->iv_flags_ht
& IEEE80211_FHT_PUREN
) != 0;
1069 case IEEE80211_IOC_DOTH
:
1070 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_DOTH
) != 0;
1072 case IEEE80211_IOC_REGDOMAIN
:
1073 error
= ieee80211_ioctl_getregdomain(vap
, ireq
);
1075 case IEEE80211_IOC_ROAM
:
1076 error
= ieee80211_ioctl_getroam(vap
, ireq
);
1078 case IEEE80211_IOC_TXPARAMS
:
1079 error
= ieee80211_ioctl_gettxparams(vap
, ireq
);
1081 case IEEE80211_IOC_HTCOMPAT
:
1082 ireq
->i_val
= (vap
->iv_flags_ht
& IEEE80211_FHT_HTCOMPAT
) != 0;
1084 case IEEE80211_IOC_DWDS
:
1085 ireq
->i_val
= (vap
->iv_flags
& IEEE80211_F_DWDS
) != 0;
1087 case IEEE80211_IOC_INACTIVITY
:
1088 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_INACT
) != 0;
1090 case IEEE80211_IOC_APPIE
:
1091 error
= ieee80211_ioctl_getappie(vap
, ireq
);
1093 case IEEE80211_IOC_WPS
:
1094 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_WPS
) != 0;
1096 case IEEE80211_IOC_TSN
:
1097 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_TSN
) != 0;
1099 case IEEE80211_IOC_DFS
:
1100 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_DFS
) != 0;
1102 case IEEE80211_IOC_DOTD
:
1103 ireq
->i_val
= (vap
->iv_flags_ext
& IEEE80211_FEXT_DOTD
) != 0;
1105 case IEEE80211_IOC_DEVCAPS
:
1106 error
= ieee80211_ioctl_getdevcaps(ic
, ireq
);
1108 case IEEE80211_IOC_HTPROTMODE
:
1109 ireq
->i_val
= vap
->iv_htprotmode
;
1111 case IEEE80211_IOC_HTCONF
:
1112 if (vap
->iv_flags_ht
& IEEE80211_FHT_HT
) {
1114 if (vap
->iv_flags_ht
& IEEE80211_FHT_USEHT40
)
1119 case IEEE80211_IOC_STA_VLAN
:
1120 error
= ieee80211_ioctl_getstavlan(vap
, ireq
);
1122 case IEEE80211_IOC_SMPS
:
1123 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1124 (vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
)) {
1125 if (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_MIMO_RTS
)
1126 ireq
->i_val
= IEEE80211_HTCAP_SMPS_DYNAMIC
;
1127 else if (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_MIMO_PS
)
1128 ireq
->i_val
= IEEE80211_HTCAP_SMPS_ENA
;
1130 ireq
->i_val
= IEEE80211_HTCAP_SMPS_OFF
;
1132 ireq
->i_val
= vap
->iv_htcaps
& IEEE80211_HTCAP_SMPS
;
1134 case IEEE80211_IOC_RIFS
:
1135 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1136 (vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
))
1138 (vap
->iv_bss
->ni_flags
& IEEE80211_NODE_RIFS
) != 0;
1141 (vap
->iv_flags_ht
& IEEE80211_FHT_RIFS
) != 0;
1143 case IEEE80211_IOC_STBC
:
1145 if (vap
->iv_flags_ht
& IEEE80211_FHT_STBC_TX
)
1147 if (vap
->iv_flags_ht
& IEEE80211_FHT_STBC_RX
)
1150 case IEEE80211_IOC_LDPC
:
1152 if (vap
->iv_flags_ht
& IEEE80211_FHT_LDPC_TX
)
1154 if (vap
->iv_flags_ht
& IEEE80211_FHT_LDPC_RX
)
1157 case IEEE80211_IOC_UAPSD
:
1159 if (vap
->iv_flags_ext
& IEEE80211_FEXT_UAPSD
)
1162 case IEEE80211_IOC_VHTCONF
:
1163 ireq
->i_val
= vap
->iv_vht_flags
& IEEE80211_FVHT_MASK
;
1166 error
= ieee80211_ioctl_getdefault(vap
, ireq
);
1173 ieee80211_ioctl_setkey(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1175 struct ieee80211req_key ik
;
1176 struct ieee80211_node
*ni
;
1177 struct ieee80211_key
*wk
;
1181 if (ireq
->i_len
!= sizeof(ik
))
1183 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
1186 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1187 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1188 if (ik
.ik_keylen
> sizeof(ik
.ik_keydata
))
1191 if (kid
== IEEE80211_KEYIX_NONE
) {
1192 /* XXX unicast keys currently must be tx/rx */
1193 if (ik
.ik_flags
!= (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
))
1195 if (vap
->iv_opmode
== IEEE80211_M_STA
) {
1196 ni
= ieee80211_ref_node(vap
->iv_bss
);
1197 if (!IEEE80211_ADDR_EQ(ik
.ik_macaddr
, ni
->ni_bssid
)) {
1198 ieee80211_free_node(ni
);
1199 return EADDRNOTAVAIL
;
1202 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
1207 wk
= &ni
->ni_ucastkey
;
1209 if (kid
>= IEEE80211_WEP_NKID
)
1211 wk
= &vap
->iv_nw_keys
[kid
];
1213 * Global slots start off w/o any assigned key index.
1214 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1216 if (wk
->wk_keyix
== IEEE80211_KEYIX_NONE
)
1221 ieee80211_key_update_begin(vap
);
1222 if (ieee80211_crypto_newkey(vap
, ik
.ik_type
, ik
.ik_flags
, wk
)) {
1223 wk
->wk_keylen
= ik
.ik_keylen
;
1224 /* NB: MIC presence is implied by cipher type */
1225 if (wk
->wk_keylen
> IEEE80211_KEYBUF_SIZE
)
1226 wk
->wk_keylen
= IEEE80211_KEYBUF_SIZE
;
1227 for (i
= 0; i
< IEEE80211_TID_SIZE
; i
++)
1228 wk
->wk_keyrsc
[i
] = ik
.ik_keyrsc
;
1229 wk
->wk_keytsc
= 0; /* new key, reset */
1230 memset(wk
->wk_key
, 0, sizeof(wk
->wk_key
));
1231 memcpy(wk
->wk_key
, ik
.ik_keydata
, ik
.ik_keylen
);
1232 IEEE80211_ADDR_COPY(wk
->wk_macaddr
,
1233 ni
!= NULL
? ni
->ni_macaddr
: ik
.ik_macaddr
);
1234 if (!ieee80211_crypto_setkey(vap
, wk
))
1236 else if ((ik
.ik_flags
& IEEE80211_KEY_DEFAULT
))
1238 * Inform the driver that this is the default
1239 * transmit key. Now, ideally we'd just set
1240 * a flag in the key update that would
1241 * say "yes, we're the default key", but
1242 * that currently isn't the way the ioctl ->
1243 * key interface works.
1245 ieee80211_crypto_set_deftxkey(vap
, kid
);
1248 ieee80211_key_update_end(vap
);
1250 ieee80211_free_node(ni
);
1255 ieee80211_ioctl_delkey(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1257 struct ieee80211req_del_key dk
;
1260 if (ireq
->i_len
!= sizeof(dk
))
1262 error
= copyin(ireq
->i_data
, &dk
, sizeof(dk
));
1266 /* XXX uint8_t -> uint16_t */
1267 if (dk
.idk_keyix
== (uint8_t) IEEE80211_KEYIX_NONE
) {
1268 struct ieee80211_node
*ni
;
1270 if (vap
->iv_opmode
== IEEE80211_M_STA
) {
1271 ni
= ieee80211_ref_node(vap
->iv_bss
);
1272 if (!IEEE80211_ADDR_EQ(dk
.idk_macaddr
, ni
->ni_bssid
)) {
1273 ieee80211_free_node(ni
);
1274 return EADDRNOTAVAIL
;
1277 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
1282 /* XXX error return */
1283 ieee80211_node_delucastkey(ni
);
1284 ieee80211_free_node(ni
);
1286 if (kid
>= IEEE80211_WEP_NKID
)
1288 /* XXX error return */
1289 ieee80211_crypto_delkey(vap
, &vap
->iv_nw_keys
[kid
]);
1295 struct ieee80211vap
*vap
;
1301 mlmedebug(struct ieee80211vap
*vap
, const uint8_t mac
[IEEE80211_ADDR_LEN
],
1304 #ifdef IEEE80211_DEBUG
1305 static const struct {
1310 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1311 IEEE80211_MSG_ASSOC
, "assoc" },
1312 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1313 IEEE80211_MSG_ASSOC
, "disassoc" },
1314 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1315 IEEE80211_MSG_AUTH
, "deauth" },
1316 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1317 IEEE80211_MSG_AUTH
, "authorize" },
1318 { IEEE80211_MSG_IOCTL
| IEEE80211_MSG_STATE
|
1319 IEEE80211_MSG_AUTH
, "unauthorize" },
1322 if (op
== IEEE80211_MLME_AUTH
) {
1323 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_IOCTL
|
1324 IEEE80211_MSG_STATE
| IEEE80211_MSG_AUTH
, mac
,
1325 "station authenticate %s via MLME (reason: %d (%s))",
1326 reason
== IEEE80211_STATUS_SUCCESS
? "ACCEPT" : "REJECT",
1327 reason
, ieee80211_reason_to_string(reason
));
1328 } else if (!(IEEE80211_MLME_ASSOC
<= op
&& op
<= IEEE80211_MLME_AUTH
)) {
1329 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_ANY
, mac
,
1330 "unknown MLME request %d (reason: %d (%s))", op
, reason
,
1331 ieee80211_reason_to_string(reason
));
1332 } else if (reason
== IEEE80211_STATUS_SUCCESS
) {
1333 IEEE80211_NOTE_MAC(vap
, ops
[op
].mask
, mac
,
1334 "station %s via MLME", ops
[op
].opstr
);
1336 IEEE80211_NOTE_MAC(vap
, ops
[op
].mask
, mac
,
1337 "station %s via MLME (reason: %d (%s))", ops
[op
].opstr
,
1338 reason
, ieee80211_reason_to_string(reason
));
1340 #endif /* IEEE80211_DEBUG */
1344 domlme(void *arg
, struct ieee80211_node
*ni
)
1346 struct mlmeop
*mop
= arg
;
1347 struct ieee80211vap
*vap
= ni
->ni_vap
;
1349 if (vap
!= mop
->vap
)
1352 * NB: if ni_associd is zero then the node is already cleaned
1353 * up and we don't need to do this (we're safely holding a
1354 * reference but should otherwise not modify it's state).
1356 if (ni
->ni_associd
== 0)
1358 mlmedebug(vap
, ni
->ni_macaddr
, mop
->op
, mop
->reason
);
1359 if (mop
->op
== IEEE80211_MLME_DEAUTH
) {
1360 IEEE80211_SEND_MGMT(ni
, IEEE80211_FC0_SUBTYPE_DEAUTH
,
1363 IEEE80211_SEND_MGMT(ni
, IEEE80211_FC0_SUBTYPE_DISASSOC
,
1366 ieee80211_node_leave(ni
);
1370 setmlme_dropsta(struct ieee80211vap
*vap
,
1371 const uint8_t mac
[IEEE80211_ADDR_LEN
], struct mlmeop
*mlmeop
)
1373 struct ieee80211_node_table
*nt
= &vap
->iv_ic
->ic_sta
;
1374 struct ieee80211_node
*ni
;
1377 /* NB: the broadcast address means do 'em all */
1378 if (!IEEE80211_ADDR_EQ(mac
, vap
->iv_ifp
->if_broadcastaddr
)) {
1379 IEEE80211_NODE_LOCK(nt
);
1380 ni
= ieee80211_find_node_locked(nt
, mac
);
1381 IEEE80211_NODE_UNLOCK(nt
);
1383 * Don't do the node update inside the node
1384 * table lock. This unfortunately causes LORs
1385 * with drivers and their TX paths.
1389 ieee80211_free_node(ni
);
1393 ieee80211_iterate_nodes(nt
, domlme
, mlmeop
);
1399 setmlme_common(struct ieee80211vap
*vap
, int op
,
1400 const uint8_t mac
[IEEE80211_ADDR_LEN
], int reason
)
1402 struct ieee80211com
*ic
= vap
->iv_ic
;
1403 struct ieee80211_node_table
*nt
= &ic
->ic_sta
;
1404 struct ieee80211_node
*ni
;
1405 struct mlmeop mlmeop
;
1410 case IEEE80211_MLME_DISASSOC
:
1411 case IEEE80211_MLME_DEAUTH
:
1412 switch (vap
->iv_opmode
) {
1413 case IEEE80211_M_STA
:
1414 mlmedebug(vap
, vap
->iv_bss
->ni_macaddr
, op
, reason
);
1415 /* XXX not quite right */
1416 ieee80211_new_state(vap
, IEEE80211_S_INIT
, reason
);
1418 case IEEE80211_M_HOSTAP
:
1421 mlmeop
.reason
= reason
;
1422 error
= setmlme_dropsta(vap
, mac
, &mlmeop
);
1424 case IEEE80211_M_WDS
:
1425 /* XXX user app should send raw frame? */
1426 if (op
!= IEEE80211_MLME_DEAUTH
) {
1431 /* XXX accept any address, simplifies user code */
1432 if (!IEEE80211_ADDR_EQ(mac
, vap
->iv_bss
->ni_macaddr
)) {
1437 mlmedebug(vap
, vap
->iv_bss
->ni_macaddr
, op
, reason
);
1438 ni
= ieee80211_ref_node(vap
->iv_bss
);
1439 IEEE80211_SEND_MGMT(ni
,
1440 IEEE80211_FC0_SUBTYPE_DEAUTH
, reason
);
1441 ieee80211_free_node(ni
);
1443 case IEEE80211_M_MBSS
:
1444 IEEE80211_NODE_LOCK(nt
);
1445 ni
= ieee80211_find_node_locked(nt
, mac
);
1447 * Don't do the node update inside the node
1448 * table lock. This unfortunately causes LORs
1449 * with drivers and their TX paths.
1451 IEEE80211_NODE_UNLOCK(nt
);
1453 ieee80211_node_leave(ni
);
1454 ieee80211_free_node(ni
);
1464 case IEEE80211_MLME_AUTHORIZE
:
1465 case IEEE80211_MLME_UNAUTHORIZE
:
1466 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
1467 vap
->iv_opmode
!= IEEE80211_M_WDS
) {
1471 IEEE80211_NODE_LOCK(nt
);
1472 ni
= ieee80211_find_vap_node_locked(nt
, vap
, mac
);
1474 * Don't do the node update inside the node
1475 * table lock. This unfortunately causes LORs
1476 * with drivers and their TX paths.
1478 IEEE80211_NODE_UNLOCK(nt
);
1480 mlmedebug(vap
, mac
, op
, reason
);
1481 if (op
== IEEE80211_MLME_AUTHORIZE
)
1482 ieee80211_node_authorize(ni
);
1484 ieee80211_node_unauthorize(ni
);
1485 ieee80211_free_node(ni
);
1489 case IEEE80211_MLME_AUTH
:
1490 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
) {
1494 IEEE80211_NODE_LOCK(nt
);
1495 ni
= ieee80211_find_vap_node_locked(nt
, vap
, mac
);
1497 * Don't do the node update inside the node
1498 * table lock. This unfortunately causes LORs
1499 * with drivers and their TX paths.
1501 IEEE80211_NODE_UNLOCK(nt
);
1503 mlmedebug(vap
, mac
, op
, reason
);
1504 if (reason
== IEEE80211_STATUS_SUCCESS
) {
1505 IEEE80211_SEND_MGMT(ni
,
1506 IEEE80211_FC0_SUBTYPE_AUTH
, 2);
1508 * For shared key auth, just continue the
1509 * exchange. Otherwise when 802.1x is not in
1510 * use mark the port authorized at this point
1511 * so traffic can flow.
1513 if (ni
->ni_authmode
!= IEEE80211_AUTH_8021X
&&
1514 ni
->ni_challenge
== NULL
)
1515 ieee80211_node_authorize(ni
);
1517 vap
->iv_stats
.is_rx_acl
++;
1518 ieee80211_send_error(ni
, ni
->ni_macaddr
,
1519 IEEE80211_FC0_SUBTYPE_AUTH
, 2|(reason
<<16));
1520 ieee80211_node_leave(ni
);
1522 ieee80211_free_node(ni
);
1536 const uint8_t *essid
;
1537 const struct ieee80211_scan_entry
*se
;
1541 * Match mac address and any ssid.
1544 mlmelookup(void *arg
, const struct ieee80211_scan_entry
*se
)
1546 struct scanlookup
*look
= arg
;
1548 if (!IEEE80211_ADDR_EQ(look
->mac
, se
->se_macaddr
))
1550 if (look
->esslen
!= 0) {
1551 if (se
->se_ssid
[1] != look
->esslen
)
1553 if (memcmp(look
->essid
, se
->se_ssid
+2, look
->esslen
))
1560 setmlme_assoc_sta(struct ieee80211vap
*vap
,
1561 const uint8_t mac
[IEEE80211_ADDR_LEN
], int ssid_len
,
1562 const uint8_t ssid
[IEEE80211_NWID_LEN
])
1564 struct scanlookup lookup
;
1566 KASSERT(vap
->iv_opmode
== IEEE80211_M_STA
,
1567 ("expected opmode STA not %s",
1568 ieee80211_opmode_name
[vap
->iv_opmode
]));
1570 /* NB: this is racey if roaming is !manual */
1573 lookup
.esslen
= ssid_len
;
1574 lookup
.essid
= ssid
;
1575 ieee80211_scan_iterate(vap
, mlmelookup
, &lookup
);
1576 if (lookup
.se
== NULL
)
1578 mlmedebug(vap
, mac
, IEEE80211_MLME_ASSOC
, 0);
1579 if (!ieee80211_sta_join(vap
, lookup
.se
->se_chan
, lookup
.se
))
1580 return EIO
; /* XXX unique but could be better */
1585 setmlme_assoc_adhoc(struct ieee80211vap
*vap
,
1586 const uint8_t mac
[IEEE80211_ADDR_LEN
], int ssid_len
,
1587 const uint8_t ssid
[IEEE80211_NWID_LEN
])
1589 struct ieee80211_scan_req
*sr
;
1592 KASSERT(vap
->iv_opmode
== IEEE80211_M_IBSS
||
1593 vap
->iv_opmode
== IEEE80211_M_AHDEMO
,
1594 ("expected opmode IBSS or AHDEMO not %s",
1595 ieee80211_opmode_name
[vap
->iv_opmode
]));
1597 if (ssid_len
== 0 || ssid_len
> IEEE80211_NWID_LEN
)
1600 sr
= IEEE80211_MALLOC(sizeof(*sr
), M_TEMP
,
1601 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
1605 /* NB: IEEE80211_IOC_SSID call missing for ap_scan=2. */
1606 memset(vap
->iv_des_ssid
[0].ssid
, 0, IEEE80211_NWID_LEN
);
1607 vap
->iv_des_ssid
[0].len
= ssid_len
;
1608 memcpy(vap
->iv_des_ssid
[0].ssid
, ssid
, ssid_len
);
1609 vap
->iv_des_nssid
= 1;
1611 sr
->sr_flags
= IEEE80211_IOC_SCAN_ACTIVE
| IEEE80211_IOC_SCAN_ONCE
;
1612 sr
->sr_duration
= IEEE80211_IOC_SCAN_FOREVER
;
1613 memcpy(sr
->sr_ssid
[0].ssid
, ssid
, ssid_len
);
1614 sr
->sr_ssid
[0].len
= ssid_len
;
1617 error
= ieee80211_scanreq(vap
, sr
);
1619 IEEE80211_FREE(sr
, M_TEMP
);
1624 ieee80211_ioctl_setmlme(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1626 struct ieee80211req_mlme mlme
;
1629 if (ireq
->i_len
!= sizeof(mlme
))
1631 error
= copyin(ireq
->i_data
, &mlme
, sizeof(mlme
));
1634 if (vap
->iv_opmode
== IEEE80211_M_STA
&&
1635 mlme
.im_op
== IEEE80211_MLME_ASSOC
)
1636 return setmlme_assoc_sta(vap
, mlme
.im_macaddr
,
1637 vap
->iv_des_ssid
[0].len
, vap
->iv_des_ssid
[0].ssid
);
1638 else if ((vap
->iv_opmode
== IEEE80211_M_IBSS
||
1639 vap
->iv_opmode
== IEEE80211_M_AHDEMO
) &&
1640 mlme
.im_op
== IEEE80211_MLME_ASSOC
)
1641 return setmlme_assoc_adhoc(vap
, mlme
.im_macaddr
,
1642 mlme
.im_ssid_len
, mlme
.im_ssid
);
1644 return setmlme_common(vap
, mlme
.im_op
,
1645 mlme
.im_macaddr
, mlme
.im_reason
);
1649 ieee80211_ioctl_macmac(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1651 uint8_t mac
[IEEE80211_ADDR_LEN
];
1652 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
1655 if (ireq
->i_len
!= sizeof(mac
))
1657 error
= copyin(ireq
->i_data
, mac
, ireq
->i_len
);
1661 acl
= ieee80211_aclator_get("mac");
1662 if (acl
== NULL
|| !acl
->iac_attach(vap
))
1666 if (ireq
->i_type
== IEEE80211_IOC_ADDMAC
)
1667 acl
->iac_add(vap
, mac
);
1669 acl
->iac_remove(vap
, mac
);
1674 ieee80211_ioctl_setmaccmd(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1676 const struct ieee80211_aclator
*acl
= vap
->iv_acl
;
1678 switch (ireq
->i_val
) {
1679 case IEEE80211_MACCMD_POLICY_OPEN
:
1680 case IEEE80211_MACCMD_POLICY_ALLOW
:
1681 case IEEE80211_MACCMD_POLICY_DENY
:
1682 case IEEE80211_MACCMD_POLICY_RADIUS
:
1684 acl
= ieee80211_aclator_get("mac");
1685 if (acl
== NULL
|| !acl
->iac_attach(vap
))
1689 acl
->iac_setpolicy(vap
, ireq
->i_val
);
1691 case IEEE80211_MACCMD_FLUSH
:
1693 acl
->iac_flush(vap
);
1694 /* NB: silently ignore when not in use */
1696 case IEEE80211_MACCMD_DETACH
:
1699 acl
->iac_detach(vap
);
1706 return acl
->iac_setioctl(vap
, ireq
);
1712 ieee80211_ioctl_setchanlist(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1714 struct ieee80211com
*ic
= vap
->iv_ic
;
1715 uint8_t *chanlist
, *list
;
1716 int i
, nchan
, maxchan
, error
;
1718 if (ireq
->i_len
> sizeof(ic
->ic_chan_active
))
1719 ireq
->i_len
= sizeof(ic
->ic_chan_active
);
1720 list
= IEEE80211_MALLOC(ireq
->i_len
+ IEEE80211_CHAN_BYTES
, M_TEMP
,
1721 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
1724 error
= copyin(ireq
->i_data
, list
, ireq
->i_len
);
1726 IEEE80211_FREE(list
, M_TEMP
);
1730 chanlist
= list
+ ireq
->i_len
; /* NB: zero'd already */
1731 maxchan
= ireq
->i_len
* NBBY
;
1732 for (i
= 0; i
< ic
->ic_nchans
; i
++) {
1733 const struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
1735 * Calculate the intersection of the user list and the
1736 * available channels so users can do things like specify
1737 * 1-255 to get all available channels.
1739 if (c
->ic_ieee
< maxchan
&& isset(list
, c
->ic_ieee
)) {
1740 setbit(chanlist
, c
->ic_ieee
);
1745 IEEE80211_FREE(list
, M_TEMP
);
1748 if (ic
->ic_bsschan
!= IEEE80211_CHAN_ANYC
&& /* XXX */
1749 isclr(chanlist
, ic
->ic_bsschan
->ic_ieee
))
1750 ic
->ic_bsschan
= IEEE80211_CHAN_ANYC
;
1751 memcpy(ic
->ic_chan_active
, chanlist
, IEEE80211_CHAN_BYTES
);
1752 ieee80211_scan_flush(vap
);
1753 IEEE80211_FREE(list
, M_TEMP
);
1758 ieee80211_ioctl_setstastats(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1760 struct ieee80211_node
*ni
;
1761 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
1765 * NB: we could copyin ieee80211req_sta_stats so apps
1766 * could make selective changes but that's overkill;
1767 * just clear all stats for now.
1769 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
1771 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
1774 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, macaddr
);
1777 /* XXX require ni_vap == vap? */
1778 memset(&ni
->ni_stats
, 0, sizeof(ni
->ni_stats
));
1779 ieee80211_free_node(ni
);
1784 ieee80211_ioctl_setstatxpow(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1786 struct ieee80211_node
*ni
;
1787 struct ieee80211req_sta_txpow txpow
;
1790 if (ireq
->i_len
!= sizeof(txpow
))
1792 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1795 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
, txpow
.it_macaddr
);
1798 ni
->ni_txpower
= txpow
.it_txpow
;
1799 ieee80211_free_node(ni
);
1804 ieee80211_ioctl_setwmeparam(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
1806 struct ieee80211com
*ic
= vap
->iv_ic
;
1807 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1808 struct wmeParams
*wmep
, *chanp
;
1809 int isbss
, ac
, aggrmode
;
1811 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1814 isbss
= (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
);
1815 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1816 aggrmode
= (wme
->wme_flags
& WME_F_AGGRMODE
);
1817 if (ac
>= WME_NUM_AC
)
1820 chanp
= &wme
->wme_bssChanParams
.cap_wmeParams
[ac
];
1821 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1823 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[ac
];
1824 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1826 switch (ireq
->i_type
) {
1827 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1828 wmep
->wmep_logcwmin
= ireq
->i_val
;
1829 if (!isbss
|| !aggrmode
)
1830 chanp
->wmep_logcwmin
= ireq
->i_val
;
1832 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1833 wmep
->wmep_logcwmax
= ireq
->i_val
;
1834 if (!isbss
|| !aggrmode
)
1835 chanp
->wmep_logcwmax
= ireq
->i_val
;
1837 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1838 wmep
->wmep_aifsn
= ireq
->i_val
;
1839 if (!isbss
|| !aggrmode
)
1840 chanp
->wmep_aifsn
= ireq
->i_val
;
1842 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1843 wmep
->wmep_txopLimit
= ireq
->i_val
;
1844 if (!isbss
|| !aggrmode
)
1845 chanp
->wmep_txopLimit
= ireq
->i_val
;
1847 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1848 wmep
->wmep_acm
= ireq
->i_val
;
1850 chanp
->wmep_acm
= ireq
->i_val
;
1852 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
1853 wmep
->wmep_noackPolicy
= chanp
->wmep_noackPolicy
=
1857 ieee80211_wme_updateparams(vap
);
1862 find11gchannel(struct ieee80211com
*ic
, int start
, int freq
)
1864 const struct ieee80211_channel
*c
;
1867 for (i
= start
+1; i
< ic
->ic_nchans
; i
++) {
1868 c
= &ic
->ic_channels
[i
];
1869 if (c
->ic_freq
== freq
&& IEEE80211_IS_CHAN_ANYG(c
))
1872 /* NB: should not be needed but in case things are mis-sorted */
1873 for (i
= 0; i
< start
; i
++) {
1874 c
= &ic
->ic_channels
[i
];
1875 if (c
->ic_freq
== freq
&& IEEE80211_IS_CHAN_ANYG(c
))
1881 static struct ieee80211_channel
*
1882 findchannel(struct ieee80211com
*ic
, int ieee
, int mode
)
1884 static const u_int chanflags
[IEEE80211_MODE_MAX
] = {
1885 [IEEE80211_MODE_AUTO
] = 0,
1886 [IEEE80211_MODE_11A
] = IEEE80211_CHAN_A
,
1887 [IEEE80211_MODE_11B
] = IEEE80211_CHAN_B
,
1888 [IEEE80211_MODE_11G
] = IEEE80211_CHAN_G
,
1889 [IEEE80211_MODE_FH
] = IEEE80211_CHAN_FHSS
,
1890 [IEEE80211_MODE_TURBO_A
] = IEEE80211_CHAN_108A
,
1891 [IEEE80211_MODE_TURBO_G
] = IEEE80211_CHAN_108G
,
1892 [IEEE80211_MODE_STURBO_A
] = IEEE80211_CHAN_STURBO
,
1893 [IEEE80211_MODE_HALF
] = IEEE80211_CHAN_HALF
,
1894 [IEEE80211_MODE_QUARTER
] = IEEE80211_CHAN_QUARTER
,
1895 /* NB: handled specially below */
1896 [IEEE80211_MODE_11NA
] = IEEE80211_CHAN_A
,
1897 [IEEE80211_MODE_11NG
] = IEEE80211_CHAN_G
,
1898 [IEEE80211_MODE_VHT_5GHZ
] = IEEE80211_CHAN_A
,
1899 [IEEE80211_MODE_VHT_2GHZ
] = IEEE80211_CHAN_G
,
1904 modeflags
= chanflags
[mode
];
1905 for (i
= 0; i
< ic
->ic_nchans
; i
++) {
1906 struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
1908 if (c
->ic_ieee
!= ieee
)
1910 if (mode
== IEEE80211_MODE_AUTO
) {
1911 /* ignore turbo channels for autoselect */
1912 if (IEEE80211_IS_CHAN_TURBO(c
))
1915 * XXX special-case 11b/g channels so we
1916 * always select the g channel if both
1918 * XXX prefer HT to non-HT?
1920 if (!IEEE80211_IS_CHAN_B(c
) ||
1921 !find11gchannel(ic
, i
, c
->ic_freq
))
1924 /* must check VHT specifically */
1925 if ((mode
== IEEE80211_MODE_VHT_5GHZ
||
1926 mode
== IEEE80211_MODE_VHT_2GHZ
) &&
1927 !IEEE80211_IS_CHAN_VHT(c
))
1931 * Must check HT specially - only match on HT,
1932 * not HT+VHT channels
1934 if ((mode
== IEEE80211_MODE_11NA
||
1935 mode
== IEEE80211_MODE_11NG
) &&
1936 !IEEE80211_IS_CHAN_HT(c
))
1939 if ((mode
== IEEE80211_MODE_11NA
||
1940 mode
== IEEE80211_MODE_11NG
) &&
1941 IEEE80211_IS_CHAN_VHT(c
))
1944 /* Check that the modeflags above match */
1945 if ((c
->ic_flags
& modeflags
) == modeflags
)
1953 * Check the specified against any desired mode (aka netband).
1954 * This is only used (presently) when operating in hostap mode
1955 * to enforce consistency.
1958 check_mode_consistency(const struct ieee80211_channel
*c
, int mode
)
1960 KASSERT(c
!= IEEE80211_CHAN_ANYC
, ("oops, no channel"));
1963 case IEEE80211_MODE_11B
:
1964 return (IEEE80211_IS_CHAN_B(c
));
1965 case IEEE80211_MODE_11G
:
1966 return (IEEE80211_IS_CHAN_ANYG(c
) && !IEEE80211_IS_CHAN_HT(c
));
1967 case IEEE80211_MODE_11A
:
1968 return (IEEE80211_IS_CHAN_A(c
) && !IEEE80211_IS_CHAN_HT(c
));
1969 case IEEE80211_MODE_STURBO_A
:
1970 return (IEEE80211_IS_CHAN_STURBO(c
));
1971 case IEEE80211_MODE_11NA
:
1972 return (IEEE80211_IS_CHAN_HTA(c
));
1973 case IEEE80211_MODE_11NG
:
1974 return (IEEE80211_IS_CHAN_HTG(c
));
1981 * Common code to set the current channel. If the device
1982 * is up and running this may result in an immediate channel
1983 * change or a kick of the state machine.
1986 setcurchan(struct ieee80211vap
*vap
, struct ieee80211_channel
*c
)
1988 struct ieee80211com
*ic
= vap
->iv_ic
;
1991 if (c
!= IEEE80211_CHAN_ANYC
) {
1992 if (IEEE80211_IS_CHAN_RADAR(c
))
1993 return EBUSY
; /* XXX better code? */
1994 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
) {
1995 if (IEEE80211_IS_CHAN_NOHOSTAP(c
))
1997 if (!check_mode_consistency(c
, vap
->iv_des_mode
))
1999 } else if (vap
->iv_opmode
== IEEE80211_M_IBSS
) {
2000 if (IEEE80211_IS_CHAN_NOADHOC(c
))
2003 if ((vap
->iv_state
== IEEE80211_S_RUN
|| vap
->iv_state
== IEEE80211_S_SLEEP
) &&
2004 vap
->iv_bss
->ni_chan
== c
)
2005 return 0; /* NB: nothing to do */
2007 vap
->iv_des_chan
= c
;
2010 if (vap
->iv_opmode
== IEEE80211_M_MONITOR
&&
2011 vap
->iv_des_chan
!= IEEE80211_CHAN_ANYC
) {
2013 * Monitor mode can switch directly.
2015 if (IFNET_IS_UP_RUNNING(vap
->iv_ifp
)) {
2016 /* XXX need state machine for other vap's to follow */
2017 ieee80211_setcurchan(ic
, vap
->iv_des_chan
);
2018 vap
->iv_bss
->ni_chan
= ic
->ic_curchan
;
2020 ic
->ic_curchan
= vap
->iv_des_chan
;
2021 ic
->ic_rt
= ieee80211_get_ratetable(ic
->ic_curchan
);
2025 * Need to go through the state machine in case we
2026 * need to reassociate or the like. The state machine
2027 * will pickup the desired channel and avoid scanning.
2029 if (IS_UP_AUTO(vap
))
2030 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
2031 else if (vap
->iv_des_chan
!= IEEE80211_CHAN_ANYC
) {
2033 * When not up+running and a real channel has
2034 * been specified fix the current channel so
2035 * there is immediate feedback; e.g. via ifconfig.
2037 ic
->ic_curchan
= vap
->iv_des_chan
;
2038 ic
->ic_rt
= ieee80211_get_ratetable(ic
->ic_curchan
);
2045 * Old api for setting the current channel; this is
2046 * deprecated because channel numbers are ambiguous.
2049 ieee80211_ioctl_setchannel(struct ieee80211vap
*vap
,
2050 const struct ieee80211req
*ireq
)
2052 struct ieee80211com
*ic
= vap
->iv_ic
;
2053 struct ieee80211_channel
*c
;
2055 /* XXX 0xffff overflows 16-bit signed */
2056 if (ireq
->i_val
== 0 ||
2057 ireq
->i_val
== (int16_t) IEEE80211_CHAN_ANY
) {
2058 c
= IEEE80211_CHAN_ANYC
;
2060 struct ieee80211_channel
*c2
;
2062 c
= findchannel(ic
, ireq
->i_val
, vap
->iv_des_mode
);
2064 c
= findchannel(ic
, ireq
->i_val
,
2065 IEEE80211_MODE_AUTO
);
2071 * Fine tune channel selection based on desired mode:
2072 * if 11b is requested, find the 11b version of any
2073 * 11g channel returned,
2074 * if static turbo, find the turbo version of any
2075 * 11a channel return,
2076 * if 11na is requested, find the ht version of any
2077 * 11a channel returned,
2078 * if 11ng is requested, find the ht version of any
2079 * 11g channel returned,
2080 * if 11ac is requested, find the 11ac version
2081 * of any 11a/11na channel returned,
2082 * (TBD) 11acg (2GHz VHT)
2083 * otherwise we should be ok with what we've got.
2085 switch (vap
->iv_des_mode
) {
2086 case IEEE80211_MODE_11B
:
2087 if (IEEE80211_IS_CHAN_ANYG(c
)) {
2088 c2
= findchannel(ic
, ireq
->i_val
,
2089 IEEE80211_MODE_11B
);
2090 /* NB: should not happen, =>'s 11g w/o 11b */
2095 case IEEE80211_MODE_TURBO_A
:
2096 if (IEEE80211_IS_CHAN_A(c
)) {
2097 c2
= findchannel(ic
, ireq
->i_val
,
2098 IEEE80211_MODE_TURBO_A
);
2103 case IEEE80211_MODE_11NA
:
2104 if (IEEE80211_IS_CHAN_A(c
)) {
2105 c2
= findchannel(ic
, ireq
->i_val
,
2106 IEEE80211_MODE_11NA
);
2111 case IEEE80211_MODE_11NG
:
2112 if (IEEE80211_IS_CHAN_ANYG(c
)) {
2113 c2
= findchannel(ic
, ireq
->i_val
,
2114 IEEE80211_MODE_11NG
);
2119 case IEEE80211_MODE_VHT_2GHZ
:
2120 printf("%s: TBD\n", __func__
);
2122 case IEEE80211_MODE_VHT_5GHZ
:
2123 if (IEEE80211_IS_CHAN_A(c
)) {
2124 c2
= findchannel(ic
, ireq
->i_val
,
2125 IEEE80211_MODE_VHT_5GHZ
);
2130 default: /* NB: no static turboG */
2134 return setcurchan(vap
, c
);
2138 * New/current api for setting the current channel; a complete
2139 * channel description is provide so there is no ambiguity in
2140 * identifying the channel.
2143 ieee80211_ioctl_setcurchan(struct ieee80211vap
*vap
,
2144 const struct ieee80211req
*ireq
)
2146 struct ieee80211com
*ic
= vap
->iv_ic
;
2147 struct ieee80211_channel chan
, *c
;
2150 if (ireq
->i_len
!= sizeof(chan
))
2152 error
= copyin(ireq
->i_data
, &chan
, sizeof(chan
));
2156 /* XXX 0xffff overflows 16-bit signed */
2157 if (chan
.ic_freq
== 0 || chan
.ic_freq
== IEEE80211_CHAN_ANY
) {
2158 c
= IEEE80211_CHAN_ANYC
;
2160 c
= ieee80211_find_channel(ic
, chan
.ic_freq
, chan
.ic_flags
);
2164 return setcurchan(vap
, c
);
2168 ieee80211_ioctl_setregdomain(struct ieee80211vap
*vap
,
2169 const struct ieee80211req
*ireq
)
2171 struct ieee80211_regdomain_req
*reg
;
2174 nchans
= 1 + ((ireq
->i_len
- sizeof(struct ieee80211_regdomain_req
)) /
2175 sizeof(struct ieee80211_channel
));
2176 if (!(1 <= nchans
&& nchans
<= IEEE80211_CHAN_MAX
)) {
2177 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2178 "%s: bad # chans, i_len %d nchans %d\n", __func__
,
2179 ireq
->i_len
, nchans
);
2182 reg
= (struct ieee80211_regdomain_req
*)
2183 IEEE80211_MALLOC(IEEE80211_REGDOMAIN_SIZE(nchans
), M_TEMP
,
2184 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
2186 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2187 "%s: no memory, nchans %d\n", __func__
, nchans
);
2190 error
= copyin(ireq
->i_data
, reg
, IEEE80211_REGDOMAIN_SIZE(nchans
));
2192 /* NB: validate inline channel count against storage size */
2193 if (reg
->chaninfo
.ic_nchans
!= nchans
) {
2194 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_IOCTL
,
2195 "%s: chan cnt mismatch, %d != %d\n", __func__
,
2196 reg
->chaninfo
.ic_nchans
, nchans
);
2199 error
= ieee80211_setregdomain(vap
, reg
);
2201 IEEE80211_FREE(reg
, M_TEMP
);
2203 return (error
== 0 ? ENETRESET
: error
);
2207 checkrate(const struct ieee80211_rateset
*rs
, int rate
)
2211 if (rate
== IEEE80211_FIXED_RATE_NONE
)
2213 for (i
= 0; i
< rs
->rs_nrates
; i
++)
2214 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
) == rate
)
2220 checkmcs(const struct ieee80211_htrateset
*rs
, int mcs
)
2222 int rate_val
= IEEE80211_RV(mcs
);
2225 if (mcs
== IEEE80211_FIXED_RATE_NONE
)
2227 if ((mcs
& IEEE80211_RATE_MCS
) == 0) /* MCS always have 0x80 set */
2229 for (i
= 0; i
< rs
->rs_nrates
; i
++)
2230 if (IEEE80211_RV(rs
->rs_rates
[i
]) == rate_val
)
2236 ieee80211_ioctl_setroam(struct ieee80211vap
*vap
,
2237 const struct ieee80211req
*ireq
)
2239 struct ieee80211com
*ic
= vap
->iv_ic
;
2240 struct ieee80211_roamparams_req
*parms
;
2241 struct ieee80211_roamparam
*src
, *dst
;
2242 const struct ieee80211_htrateset
*rs_ht
;
2243 const struct ieee80211_rateset
*rs
;
2244 int changed
, error
, mode
, is11n
, nmodes
;
2246 if (ireq
->i_len
!= sizeof(vap
->iv_roamparms
))
2249 parms
= IEEE80211_MALLOC(sizeof(*parms
), M_TEMP
,
2250 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
2254 error
= copyin(ireq
->i_data
, parms
, ireq
->i_len
);
2259 nmodes
= IEEE80211_MODE_MAX
;
2261 /* validate parameters and check if anything changed */
2262 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2263 if (isclr(ic
->ic_modecaps
, mode
))
2265 src
= &parms
->params
[mode
];
2266 dst
= &vap
->iv_roamparms
[mode
];
2267 rs
= &ic
->ic_sup_rates
[mode
]; /* NB: 11n maps to legacy */
2268 rs_ht
= &ic
->ic_sup_htrates
;
2269 is11n
= (mode
== IEEE80211_MODE_11NA
||
2270 mode
== IEEE80211_MODE_11NG
);
2271 /* XXX TODO: 11ac */
2272 if (src
->rate
!= dst
->rate
) {
2273 if (!checkrate(rs
, src
->rate
) &&
2274 (!is11n
|| !checkmcs(rs_ht
, src
->rate
))) {
2280 if (src
->rssi
!= dst
->rssi
)
2285 * Copy new parameters in place and notify the
2286 * driver so it can push state to the device.
2289 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2290 if (isset(ic
->ic_modecaps
, mode
))
2291 vap
->iv_roamparms
[mode
] = parms
->params
[mode
];
2294 if (vap
->iv_roaming
== IEEE80211_ROAMING_DEVICE
)
2298 fail
: IEEE80211_FREE(parms
, M_TEMP
);
2303 ieee80211_ioctl_settxparams(struct ieee80211vap
*vap
,
2304 const struct ieee80211req
*ireq
)
2306 struct ieee80211com
*ic
= vap
->iv_ic
;
2307 struct ieee80211_txparams_req parms
; /* XXX stack use? */
2308 struct ieee80211_txparam
*src
, *dst
;
2309 const struct ieee80211_htrateset
*rs_ht
;
2310 const struct ieee80211_rateset
*rs
;
2311 int error
, mode
, changed
, is11n
, nmodes
;
2313 /* NB: accept short requests for backwards compat */
2314 if (ireq
->i_len
> sizeof(parms
))
2316 error
= copyin(ireq
->i_data
, &parms
, ireq
->i_len
);
2319 nmodes
= ireq
->i_len
/ sizeof(struct ieee80211_txparam
);
2321 /* validate parameters and check if anything changed */
2322 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2323 if (isclr(ic
->ic_modecaps
, mode
))
2325 src
= &parms
.params
[mode
];
2326 dst
= &vap
->iv_txparms
[mode
];
2327 rs
= &ic
->ic_sup_rates
[mode
]; /* NB: 11n maps to legacy */
2328 rs_ht
= &ic
->ic_sup_htrates
;
2329 is11n
= (mode
== IEEE80211_MODE_11NA
||
2330 mode
== IEEE80211_MODE_11NG
);
2331 if (src
->ucastrate
!= dst
->ucastrate
) {
2332 if (!checkrate(rs
, src
->ucastrate
) &&
2333 (!is11n
|| !checkmcs(rs_ht
, src
->ucastrate
)))
2337 if (src
->mcastrate
!= dst
->mcastrate
) {
2338 if (!checkrate(rs
, src
->mcastrate
) &&
2339 (!is11n
|| !checkmcs(rs_ht
, src
->mcastrate
)))
2343 if (src
->mgmtrate
!= dst
->mgmtrate
) {
2344 if (!checkrate(rs
, src
->mgmtrate
) &&
2345 (!is11n
|| !checkmcs(rs_ht
, src
->mgmtrate
)))
2349 if (src
->maxretry
!= dst
->maxretry
) /* NB: no bounds */
2354 * Copy new parameters in place and notify the
2355 * driver so it can push state to the device.
2357 for (mode
= IEEE80211_MODE_11A
; mode
< nmodes
; mode
++) {
2358 if (isset(ic
->ic_modecaps
, mode
))
2359 vap
->iv_txparms
[mode
] = parms
.params
[mode
];
2361 /* XXX could be more intelligent,
2362 e.g. don't reset if setting not being used */
2369 * Application Information Element support.
2372 setappie(struct ieee80211_appie
**aie
, const struct ieee80211req
*ireq
)
2374 struct ieee80211_appie
*app
= *aie
;
2375 struct ieee80211_appie
*napp
;
2378 if (ireq
->i_len
== 0) { /* delete any existing ie */
2380 *aie
= NULL
; /* XXX racey */
2381 IEEE80211_FREE(app
, M_80211_NODE_IE
);
2385 if (!(2 <= ireq
->i_len
&& ireq
->i_len
<= IEEE80211_MAX_APPIE
))
2388 * Allocate a new appie structure and copy in the user data.
2389 * When done swap in the new structure. Note that we do not
2390 * guard against users holding a ref to the old structure;
2391 * this must be handled outside this code.
2395 napp
= (struct ieee80211_appie
*) IEEE80211_MALLOC(
2396 sizeof(struct ieee80211_appie
) + ireq
->i_len
, M_80211_NODE_IE
,
2397 IEEE80211_M_NOWAIT
);
2400 /* XXX holding ic lock */
2401 error
= copyin(ireq
->i_data
, napp
->ie_data
, ireq
->i_len
);
2403 IEEE80211_FREE(napp
, M_80211_NODE_IE
);
2406 napp
->ie_len
= ireq
->i_len
;
2409 IEEE80211_FREE(app
, M_80211_NODE_IE
);
2414 setwparsnie(struct ieee80211vap
*vap
, uint8_t *ie
, int space
)
2416 /* validate data is present as best we can */
2417 if (space
== 0 || 2+ie
[1] > space
)
2419 if (ie
[0] == IEEE80211_ELEMID_VENDOR
)
2420 vap
->iv_wpa_ie
= ie
;
2421 else if (ie
[0] == IEEE80211_ELEMID_RSN
)
2422 vap
->iv_rsn_ie
= ie
;
2426 ieee80211_ioctl_setappie_locked(struct ieee80211vap
*vap
,
2427 const struct ieee80211req
*ireq
, int fc0
)
2431 IEEE80211_LOCK_ASSERT(vap
->iv_ic
);
2433 switch (fc0
& IEEE80211_FC0_SUBTYPE_MASK
) {
2434 case IEEE80211_FC0_SUBTYPE_BEACON
:
2435 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
2436 vap
->iv_opmode
!= IEEE80211_M_IBSS
) {
2440 error
= setappie(&vap
->iv_appie_beacon
, ireq
);
2442 ieee80211_beacon_notify(vap
, IEEE80211_BEACON_APPIE
);
2444 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
2445 error
= setappie(&vap
->iv_appie_proberesp
, ireq
);
2447 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
2448 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
2449 error
= setappie(&vap
->iv_appie_assocresp
, ireq
);
2453 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
2454 error
= setappie(&vap
->iv_appie_probereq
, ireq
);
2456 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
2457 if (vap
->iv_opmode
== IEEE80211_M_STA
)
2458 error
= setappie(&vap
->iv_appie_assocreq
, ireq
);
2462 case (IEEE80211_APPIE_WPA
& IEEE80211_FC0_SUBTYPE_MASK
):
2463 error
= setappie(&vap
->iv_appie_wpa
, ireq
);
2466 * Must split single blob of data into separate
2467 * WPA and RSN ie's because they go in different
2468 * locations in the mgt frames.
2469 * XXX use IEEE80211_IOC_WPA2 so user code does split
2471 vap
->iv_wpa_ie
= NULL
;
2472 vap
->iv_rsn_ie
= NULL
;
2473 if (vap
->iv_appie_wpa
!= NULL
) {
2474 struct ieee80211_appie
*appie
=
2476 uint8_t *data
= appie
->ie_data
;
2478 /* XXX ie length validate is painful, cheat */
2479 setwparsnie(vap
, data
, appie
->ie_len
);
2480 setwparsnie(vap
, data
+ 2 + data
[1],
2481 appie
->ie_len
- (2 + data
[1]));
2483 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
||
2484 vap
->iv_opmode
== IEEE80211_M_IBSS
) {
2486 * Must rebuild beacon frame as the update
2487 * mechanism doesn't handle WPA/RSN ie's.
2488 * Could extend it but it doesn't normally
2489 * change; this is just to deal with hostapd
2490 * plumbing the ie after the interface is up.
2504 ieee80211_ioctl_setappie(struct ieee80211vap
*vap
,
2505 const struct ieee80211req
*ireq
)
2507 struct ieee80211com
*ic
= vap
->iv_ic
;
2511 fc0
= ireq
->i_val
& 0xff;
2512 if ((fc0
& IEEE80211_FC0_TYPE_MASK
) != IEEE80211_FC0_TYPE_MGT
)
2514 /* NB: could check iv_opmode and reject but hardly worth the effort */
2516 error
= ieee80211_ioctl_setappie_locked(vap
, ireq
, fc0
);
2517 IEEE80211_UNLOCK(ic
);
2522 ieee80211_ioctl_chanswitch(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2524 struct ieee80211com
*ic
= vap
->iv_ic
;
2525 struct ieee80211_chanswitch_req csr
;
2526 struct ieee80211_channel
*c
;
2529 if (ireq
->i_len
!= sizeof(csr
))
2531 error
= copyin(ireq
->i_data
, &csr
, sizeof(csr
));
2534 /* XXX adhoc mode not supported */
2535 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
||
2536 (vap
->iv_flags
& IEEE80211_F_DOTH
) == 0)
2538 c
= ieee80211_find_channel(ic
,
2539 csr
.csa_chan
.ic_freq
, csr
.csa_chan
.ic_flags
);
2543 if ((ic
->ic_flags
& IEEE80211_F_CSAPENDING
) == 0)
2544 ieee80211_csa_startswitch(ic
, c
, csr
.csa_mode
, csr
.csa_count
);
2545 else if (csr
.csa_count
== 0)
2546 ieee80211_csa_cancelswitch(ic
);
2549 IEEE80211_UNLOCK(ic
);
2554 ieee80211_scanreq(struct ieee80211vap
*vap
, struct ieee80211_scan_req
*sr
)
2556 #define IEEE80211_IOC_SCAN_FLAGS \
2557 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \
2558 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \
2559 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \
2560 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \
2561 IEEE80211_IOC_SCAN_CHECK)
2562 struct ieee80211com
*ic
= vap
->iv_ic
;
2565 /* convert duration */
2566 if (sr
->sr_duration
== IEEE80211_IOC_SCAN_FOREVER
)
2567 sr
->sr_duration
= IEEE80211_SCAN_FOREVER
;
2569 if (sr
->sr_duration
< IEEE80211_IOC_SCAN_DURATION_MIN
||
2570 sr
->sr_duration
> IEEE80211_IOC_SCAN_DURATION_MAX
)
2572 sr
->sr_duration
= msecs_to_ticks(sr
->sr_duration
);
2574 /* convert min/max channel dwell */
2575 if (sr
->sr_mindwell
!= 0)
2576 sr
->sr_mindwell
= msecs_to_ticks(sr
->sr_mindwell
);
2577 if (sr
->sr_maxdwell
!= 0)
2578 sr
->sr_maxdwell
= msecs_to_ticks(sr
->sr_maxdwell
);
2579 /* NB: silently reduce ssid count to what is supported */
2580 if (sr
->sr_nssid
> IEEE80211_SCAN_MAX_SSID
)
2581 sr
->sr_nssid
= IEEE80211_SCAN_MAX_SSID
;
2582 for (i
= 0; i
< sr
->sr_nssid
; i
++)
2583 if (sr
->sr_ssid
[i
].len
> IEEE80211_NWID_LEN
)
2585 /* cleanse flags just in case, could reject if invalid flags */
2586 sr
->sr_flags
&= IEEE80211_IOC_SCAN_FLAGS
;
2588 * Add an implicit NOPICK if the vap is not marked UP. This
2589 * allows applications to scan without joining a bss (or picking
2590 * a channel and setting up a bss) and without forcing manual
2591 * roaming mode--you just need to mark the parent device UP.
2593 if ((vap
->iv_ifp
->if_flags
& IFF_UP
) == 0)
2594 sr
->sr_flags
|= IEEE80211_IOC_SCAN_NOPICK
;
2596 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
2597 "%s: vap %p iv_state %#x (%s) flags 0x%x%s "
2598 "duration 0x%x mindwell %u maxdwell %u nssid %d\n",
2599 __func__
, vap
, vap
->iv_state
, ieee80211_state_name
[vap
->iv_state
],
2601 (vap
->iv_ifp
->if_flags
& IFF_UP
) == 0 ? " (!IFF_UP)" : "",
2602 sr
->sr_duration
, sr
->sr_mindwell
, sr
->sr_maxdwell
, sr
->sr_nssid
);
2604 * If we are in INIT state then the driver has never had a chance
2605 * to setup hardware state to do a scan; we must use the state
2606 * machine to get us up to the SCAN state but once we reach SCAN
2607 * state we then want to use the supplied params. Stash the
2608 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the
2609 * state machines will recognize this and use the stashed params
2610 * to issue the scan request.
2612 * Otherwise just invoke the scan machinery directly.
2615 if (ic
->ic_nrunning
== 0) {
2616 IEEE80211_UNLOCK(ic
);
2620 if (vap
->iv_state
== IEEE80211_S_INIT
) {
2621 /* NB: clobbers previous settings */
2622 vap
->iv_scanreq_flags
= sr
->sr_flags
;
2623 vap
->iv_scanreq_duration
= sr
->sr_duration
;
2624 vap
->iv_scanreq_nssid
= sr
->sr_nssid
;
2625 for (i
= 0; i
< sr
->sr_nssid
; i
++) {
2626 vap
->iv_scanreq_ssid
[i
].len
= sr
->sr_ssid
[i
].len
;
2627 memcpy(vap
->iv_scanreq_ssid
[i
].ssid
,
2628 sr
->sr_ssid
[i
].ssid
, sr
->sr_ssid
[i
].len
);
2630 vap
->iv_flags_ext
|= IEEE80211_FEXT_SCANREQ
;
2631 IEEE80211_UNLOCK(ic
);
2632 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
2634 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_SCANREQ
;
2635 IEEE80211_UNLOCK(ic
);
2636 if (sr
->sr_flags
& IEEE80211_IOC_SCAN_CHECK
) {
2637 error
= ieee80211_check_scan(vap
, sr
->sr_flags
,
2638 sr
->sr_duration
, sr
->sr_mindwell
, sr
->sr_maxdwell
,
2640 /* NB: cheat, we assume structures are compatible */
2641 (const struct ieee80211_scan_ssid
*) &sr
->sr_ssid
[0]);
2643 error
= ieee80211_start_scan(vap
, sr
->sr_flags
,
2644 sr
->sr_duration
, sr
->sr_mindwell
, sr
->sr_maxdwell
,
2646 /* NB: cheat, we assume structures are compatible */
2647 (const struct ieee80211_scan_ssid
*) &sr
->sr_ssid
[0]);
2653 #undef IEEE80211_IOC_SCAN_FLAGS
2657 ieee80211_ioctl_scanreq(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2659 struct ieee80211_scan_req
*sr
;
2662 if (ireq
->i_len
!= sizeof(*sr
))
2664 sr
= IEEE80211_MALLOC(sizeof(*sr
), M_TEMP
,
2665 IEEE80211_M_NOWAIT
| IEEE80211_M_ZERO
);
2668 error
= copyin(ireq
->i_data
, sr
, sizeof(*sr
));
2671 error
= ieee80211_scanreq(vap
, sr
);
2673 IEEE80211_FREE(sr
, M_TEMP
);
2678 ieee80211_ioctl_setstavlan(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2680 struct ieee80211_node
*ni
;
2681 struct ieee80211req_sta_vlan vlan
;
2684 if (ireq
->i_len
!= sizeof(vlan
))
2686 error
= copyin(ireq
->i_data
, &vlan
, sizeof(vlan
));
2689 if (!IEEE80211_ADDR_EQ(vlan
.sv_macaddr
, zerobssid
)) {
2690 ni
= ieee80211_find_vap_node(&vap
->iv_ic
->ic_sta
, vap
,
2695 ni
= ieee80211_ref_node(vap
->iv_bss
);
2696 ni
->ni_vlan
= vlan
.sv_vlan
;
2697 ieee80211_free_node(ni
);
2702 isvap11g(const struct ieee80211vap
*vap
)
2704 const struct ieee80211_node
*bss
= vap
->iv_bss
;
2705 return bss
->ni_chan
!= IEEE80211_CHAN_ANYC
&&
2706 IEEE80211_IS_CHAN_ANYG(bss
->ni_chan
);
2710 isvapht(const struct ieee80211vap
*vap
)
2712 const struct ieee80211_node
*bss
= vap
->iv_bss
;
2713 return bss
->ni_chan
!= IEEE80211_CHAN_ANYC
&&
2714 IEEE80211_IS_CHAN_HT(bss
->ni_chan
);
2718 * Dummy ioctl set handler so the linker set is defined.
2721 dummy_ioctl_set(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2725 IEEE80211_IOCTL_SET(dummy
, dummy_ioctl_set
);
2728 ieee80211_ioctl_setdefault(struct ieee80211vap
*vap
, struct ieee80211req
*ireq
)
2730 ieee80211_ioctl_setfunc
* const *set
;
2733 SET_FOREACH(set
, ieee80211_ioctl_setset
) {
2734 error
= (*set
)(vap
, ireq
);
2735 if (error
!= ENOSYS
)
2742 ieee80211_ioctl_set80211(struct ieee80211vap
*vap
, u_long cmd
, struct ieee80211req
*ireq
)
2744 struct ieee80211com
*ic
= vap
->iv_ic
;
2746 const struct ieee80211_authenticator
*auth
;
2747 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
2748 char tmpssid
[IEEE80211_NWID_LEN
];
2749 uint8_t tmpbssid
[IEEE80211_ADDR_LEN
];
2750 struct ieee80211_key
*k
;
2755 switch (ireq
->i_type
) {
2756 case IEEE80211_IOC_SSID
:
2757 if (ireq
->i_val
!= 0 ||
2758 ireq
->i_len
> IEEE80211_NWID_LEN
)
2760 error
= copyin(ireq
->i_data
, tmpssid
, ireq
->i_len
);
2763 memset(vap
->iv_des_ssid
[0].ssid
, 0, IEEE80211_NWID_LEN
);
2764 vap
->iv_des_ssid
[0].len
= ireq
->i_len
;
2765 memcpy(vap
->iv_des_ssid
[0].ssid
, tmpssid
, ireq
->i_len
);
2766 vap
->iv_des_nssid
= (ireq
->i_len
> 0);
2769 case IEEE80211_IOC_WEP
:
2770 switch (ireq
->i_val
) {
2771 case IEEE80211_WEP_OFF
:
2772 vap
->iv_flags
&= ~IEEE80211_F_PRIVACY
;
2773 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2775 case IEEE80211_WEP_ON
:
2776 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2777 vap
->iv_flags
|= IEEE80211_F_DROPUNENC
;
2779 case IEEE80211_WEP_MIXED
:
2780 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2781 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2786 case IEEE80211_IOC_WEPKEY
:
2787 kid
= (u_int
) ireq
->i_val
;
2788 if (kid
>= IEEE80211_WEP_NKID
)
2790 k
= &vap
->iv_nw_keys
[kid
];
2791 if (ireq
->i_len
== 0) {
2792 /* zero-len =>'s delete any existing key */
2793 (void) ieee80211_crypto_delkey(vap
, k
);
2796 if (ireq
->i_len
> sizeof(tmpkey
))
2798 memset(tmpkey
, 0, sizeof(tmpkey
));
2799 error
= copyin(ireq
->i_data
, tmpkey
, ireq
->i_len
);
2802 ieee80211_key_update_begin(vap
);
2803 k
->wk_keyix
= kid
; /* NB: force fixed key id */
2804 if (ieee80211_crypto_newkey(vap
, IEEE80211_CIPHER_WEP
,
2805 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, k
)) {
2806 k
->wk_keylen
= ireq
->i_len
;
2807 memcpy(k
->wk_key
, tmpkey
, sizeof(tmpkey
));
2808 IEEE80211_ADDR_COPY(k
->wk_macaddr
, vap
->iv_myaddr
);
2809 if (!ieee80211_crypto_setkey(vap
, k
))
2813 ieee80211_key_update_end(vap
);
2815 case IEEE80211_IOC_WEPTXKEY
:
2816 kid
= (u_int
) ireq
->i_val
;
2817 if (kid
>= IEEE80211_WEP_NKID
&&
2818 (uint16_t) kid
!= IEEE80211_KEYIX_NONE
)
2821 * Firmware devices may need to be told about an explicit
2822 * key index here, versus just inferring it from the
2823 * key set / change. Since we may also need to pause
2824 * things like transmit before the key is updated,
2825 * give the driver a chance to flush things by tying
2826 * into key update begin/end.
2828 ieee80211_key_update_begin(vap
);
2829 ieee80211_crypto_set_deftxkey(vap
, kid
);
2830 ieee80211_key_update_end(vap
);
2832 case IEEE80211_IOC_AUTHMODE
:
2833 switch (ireq
->i_val
) {
2834 case IEEE80211_AUTH_WPA
:
2835 case IEEE80211_AUTH_8021X
: /* 802.1x */
2836 case IEEE80211_AUTH_OPEN
: /* open */
2837 case IEEE80211_AUTH_SHARED
: /* shared-key */
2838 case IEEE80211_AUTH_AUTO
: /* auto */
2839 auth
= ieee80211_authenticator_get(ireq
->i_val
);
2846 switch (ireq
->i_val
) {
2847 case IEEE80211_AUTH_WPA
: /* WPA w/ 802.1x */
2848 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2849 ireq
->i_val
= IEEE80211_AUTH_8021X
;
2851 case IEEE80211_AUTH_OPEN
: /* open */
2852 vap
->iv_flags
&= ~(IEEE80211_F_WPA
|IEEE80211_F_PRIVACY
);
2854 case IEEE80211_AUTH_SHARED
: /* shared-key */
2855 case IEEE80211_AUTH_8021X
: /* 802.1x */
2856 vap
->iv_flags
&= ~IEEE80211_F_WPA
;
2857 /* both require a key so mark the PRIVACY capability */
2858 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2860 case IEEE80211_AUTH_AUTO
: /* auto */
2861 vap
->iv_flags
&= ~IEEE80211_F_WPA
;
2862 /* XXX PRIVACY handling? */
2863 /* XXX what's the right way to do this? */
2866 /* NB: authenticator attach/detach happens on state change */
2867 vap
->iv_bss
->ni_authmode
= ireq
->i_val
;
2868 /* XXX mixed/mode/usage? */
2869 vap
->iv_auth
= auth
;
2872 case IEEE80211_IOC_CHANNEL
:
2873 error
= ieee80211_ioctl_setchannel(vap
, ireq
);
2875 case IEEE80211_IOC_POWERSAVE
:
2876 switch (ireq
->i_val
) {
2877 case IEEE80211_POWERSAVE_OFF
:
2878 if (vap
->iv_flags
& IEEE80211_F_PMGTON
) {
2879 ieee80211_syncflag(vap
, -IEEE80211_F_PMGTON
);
2883 case IEEE80211_POWERSAVE_ON
:
2884 if ((vap
->iv_caps
& IEEE80211_C_PMGT
) == 0)
2886 else if ((vap
->iv_flags
& IEEE80211_F_PMGTON
) == 0) {
2887 ieee80211_syncflag(vap
, IEEE80211_F_PMGTON
);
2896 case IEEE80211_IOC_POWERSAVESLEEP
:
2897 if (ireq
->i_val
< 0)
2899 ic
->ic_lintval
= ireq
->i_val
;
2902 case IEEE80211_IOC_RTSTHRESHOLD
:
2903 if (!(IEEE80211_RTS_MIN
<= ireq
->i_val
&&
2904 ireq
->i_val
<= IEEE80211_RTS_MAX
))
2906 vap
->iv_rtsthreshold
= ireq
->i_val
;
2909 case IEEE80211_IOC_PROTMODE
:
2910 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
2912 vap
->iv_protmode
= (enum ieee80211_protmode
)ireq
->i_val
;
2913 /* NB: if not operating in 11g this can wait */
2914 if (ic
->ic_bsschan
!= IEEE80211_CHAN_ANYC
&&
2915 IEEE80211_IS_CHAN_ANYG(ic
->ic_bsschan
))
2917 /* driver callback for protection mode update */
2918 ieee80211_vap_update_erp_protmode(vap
);
2920 case IEEE80211_IOC_TXPOWER
:
2921 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
2923 if (!(IEEE80211_TXPOWER_MIN
<= ireq
->i_val
&&
2924 ireq
->i_val
<= IEEE80211_TXPOWER_MAX
))
2926 ic
->ic_txpowlimit
= ireq
->i_val
;
2929 case IEEE80211_IOC_ROAMING
:
2930 if (!(IEEE80211_ROAMING_DEVICE
<= ireq
->i_val
&&
2931 ireq
->i_val
<= IEEE80211_ROAMING_MANUAL
))
2933 vap
->iv_roaming
= (enum ieee80211_roamingmode
)ireq
->i_val
;
2936 case IEEE80211_IOC_PRIVACY
:
2938 /* XXX check for key state? */
2939 vap
->iv_flags
|= IEEE80211_F_PRIVACY
;
2941 vap
->iv_flags
&= ~IEEE80211_F_PRIVACY
;
2944 case IEEE80211_IOC_DROPUNENCRYPTED
:
2946 vap
->iv_flags
|= IEEE80211_F_DROPUNENC
;
2948 vap
->iv_flags
&= ~IEEE80211_F_DROPUNENC
;
2951 case IEEE80211_IOC_WPAKEY
:
2952 error
= ieee80211_ioctl_setkey(vap
, ireq
);
2954 case IEEE80211_IOC_DELKEY
:
2955 error
= ieee80211_ioctl_delkey(vap
, ireq
);
2957 case IEEE80211_IOC_MLME
:
2958 error
= ieee80211_ioctl_setmlme(vap
, ireq
);
2960 case IEEE80211_IOC_COUNTERMEASURES
:
2962 if ((vap
->iv_flags
& IEEE80211_F_WPA
) == 0)
2964 vap
->iv_flags
|= IEEE80211_F_COUNTERM
;
2966 vap
->iv_flags
&= ~IEEE80211_F_COUNTERM
;
2969 case IEEE80211_IOC_WPA
:
2970 if (ireq
->i_val
> 3)
2972 /* XXX verify ciphers available */
2973 flags
= vap
->iv_flags
& ~IEEE80211_F_WPA
;
2974 switch (ireq
->i_val
) {
2976 /* wpa_supplicant calls this to clear the WPA config */
2979 if (!(vap
->iv_caps
& IEEE80211_C_WPA1
))
2981 flags
|= IEEE80211_F_WPA1
;
2984 if (!(vap
->iv_caps
& IEEE80211_C_WPA2
))
2986 flags
|= IEEE80211_F_WPA2
;
2989 if ((vap
->iv_caps
& IEEE80211_C_WPA
) != IEEE80211_C_WPA
)
2991 flags
|= IEEE80211_F_WPA1
| IEEE80211_F_WPA2
;
2993 default: /* Can't set any -> error */
2996 vap
->iv_flags
= flags
;
2997 error
= ERESTART
; /* NB: can change beacon frame */
2999 case IEEE80211_IOC_WME
:
3001 if ((vap
->iv_caps
& IEEE80211_C_WME
) == 0)
3003 ieee80211_syncflag(vap
, IEEE80211_F_WME
);
3005 ieee80211_syncflag(vap
, -IEEE80211_F_WME
);
3006 error
= ERESTART
; /* NB: can change beacon frame */
3008 case IEEE80211_IOC_HIDESSID
:
3010 vap
->iv_flags
|= IEEE80211_F_HIDESSID
;
3012 vap
->iv_flags
&= ~IEEE80211_F_HIDESSID
;
3013 error
= ERESTART
; /* XXX ENETRESET? */
3015 case IEEE80211_IOC_APBRIDGE
:
3016 if (ireq
->i_val
== 0)
3017 vap
->iv_flags
|= IEEE80211_F_NOBRIDGE
;
3019 vap
->iv_flags
&= ~IEEE80211_F_NOBRIDGE
;
3021 case IEEE80211_IOC_BSSID
:
3022 if (ireq
->i_len
!= sizeof(tmpbssid
))
3024 error
= copyin(ireq
->i_data
, tmpbssid
, ireq
->i_len
);
3027 IEEE80211_ADDR_COPY(vap
->iv_des_bssid
, tmpbssid
);
3028 if (IEEE80211_ADDR_EQ(vap
->iv_des_bssid
, zerobssid
))
3029 vap
->iv_flags
&= ~IEEE80211_F_DESBSSID
;
3031 vap
->iv_flags
|= IEEE80211_F_DESBSSID
;
3034 case IEEE80211_IOC_CHANLIST
:
3035 error
= ieee80211_ioctl_setchanlist(vap
, ireq
);
3037 #define OLD_IEEE80211_IOC_SCAN_REQ 23
3038 #ifdef OLD_IEEE80211_IOC_SCAN_REQ
3039 case OLD_IEEE80211_IOC_SCAN_REQ
:
3040 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
3041 "%s: active scan request\n", __func__
);
3043 * If we are in INIT state then the driver has never
3044 * had a chance to setup hardware state to do a scan;
3045 * use the state machine to get us up the SCAN state.
3046 * Otherwise just invoke the scan machinery to start
3049 if (vap
->iv_state
== IEEE80211_S_INIT
)
3050 ieee80211_new_state(vap
, IEEE80211_S_SCAN
, 0);
3052 (void) ieee80211_start_scan(vap
,
3053 IEEE80211_SCAN_ACTIVE
|
3054 IEEE80211_SCAN_NOPICK
|
3055 IEEE80211_SCAN_ONCE
,
3056 IEEE80211_SCAN_FOREVER
, 0, 0,
3057 /* XXX use ioctl params */
3058 vap
->iv_des_nssid
, vap
->iv_des_ssid
);
3060 #endif /* OLD_IEEE80211_IOC_SCAN_REQ */
3061 case IEEE80211_IOC_SCAN_REQ
:
3062 error
= ieee80211_ioctl_scanreq(vap
, ireq
);
3064 case IEEE80211_IOC_SCAN_CANCEL
:
3065 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
,
3066 "%s: cancel scan\n", __func__
);
3067 ieee80211_cancel_scan(vap
);
3069 case IEEE80211_IOC_HTCONF
:
3070 if (ireq
->i_val
& 1)
3071 ieee80211_syncflag_ht(vap
, IEEE80211_FHT_HT
);
3073 ieee80211_syncflag_ht(vap
, -IEEE80211_FHT_HT
);
3074 if (ireq
->i_val
& 2)
3075 ieee80211_syncflag_ht(vap
, IEEE80211_FHT_USEHT40
);
3077 ieee80211_syncflag_ht(vap
, -IEEE80211_FHT_USEHT40
);
3080 case IEEE80211_IOC_ADDMAC
:
3081 case IEEE80211_IOC_DELMAC
:
3082 error
= ieee80211_ioctl_macmac(vap
, ireq
);
3084 case IEEE80211_IOC_MACCMD
:
3085 error
= ieee80211_ioctl_setmaccmd(vap
, ireq
);
3087 case IEEE80211_IOC_STA_STATS
:
3088 error
= ieee80211_ioctl_setstastats(vap
, ireq
);
3090 case IEEE80211_IOC_STA_TXPOW
:
3091 error
= ieee80211_ioctl_setstatxpow(vap
, ireq
);
3093 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
3094 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
3095 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
3096 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
3097 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
3098 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only) */
3099 error
= ieee80211_ioctl_setwmeparam(vap
, ireq
);
3101 case IEEE80211_IOC_DTIM_PERIOD
:
3102 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
3103 vap
->iv_opmode
!= IEEE80211_M_MBSS
&&
3104 vap
->iv_opmode
!= IEEE80211_M_IBSS
)
3106 if (IEEE80211_DTIM_MIN
<= ireq
->i_val
&&
3107 ireq
->i_val
<= IEEE80211_DTIM_MAX
) {
3108 vap
->iv_dtim_period
= ireq
->i_val
;
3109 error
= ENETRESET
; /* requires restart */
3113 case IEEE80211_IOC_BEACON_INTERVAL
:
3114 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
3115 vap
->iv_opmode
!= IEEE80211_M_MBSS
&&
3116 vap
->iv_opmode
!= IEEE80211_M_IBSS
)
3118 if (IEEE80211_BINTVAL_MIN
<= ireq
->i_val
&&
3119 ireq
->i_val
<= IEEE80211_BINTVAL_MAX
) {
3120 ic
->ic_bintval
= ireq
->i_val
;
3121 error
= ENETRESET
; /* requires restart */
3125 case IEEE80211_IOC_PUREG
:
3127 vap
->iv_flags
|= IEEE80211_F_PUREG
;
3129 vap
->iv_flags
&= ~IEEE80211_F_PUREG
;
3130 /* NB: reset only if we're operating on an 11g channel */
3134 case IEEE80211_IOC_QUIET
:
3135 vap
->iv_quiet
= ireq
->i_val
;
3137 case IEEE80211_IOC_QUIET_COUNT
:
3138 vap
->iv_quiet_count
=ireq
->i_val
;
3140 case IEEE80211_IOC_QUIET_PERIOD
:
3141 vap
->iv_quiet_period
=ireq
->i_val
;
3143 case IEEE80211_IOC_QUIET_OFFSET
:
3144 vap
->iv_quiet_offset
=ireq
->i_val
;
3146 case IEEE80211_IOC_QUIET_DUR
:
3147 if(ireq
->i_val
< vap
->iv_bss
->ni_intval
)
3148 vap
->iv_quiet_duration
= ireq
->i_val
;
3152 case IEEE80211_IOC_BGSCAN
:
3154 if ((vap
->iv_caps
& IEEE80211_C_BGSCAN
) == 0)
3156 vap
->iv_flags
|= IEEE80211_F_BGSCAN
;
3158 vap
->iv_flags
&= ~IEEE80211_F_BGSCAN
;
3160 case IEEE80211_IOC_BGSCAN_IDLE
:
3161 if (ireq
->i_val
>= IEEE80211_BGSCAN_IDLE_MIN
)
3162 vap
->iv_bgscanidle
= ireq
->i_val
*hz
/1000;
3166 case IEEE80211_IOC_BGSCAN_INTERVAL
:
3167 if (ireq
->i_val
>= IEEE80211_BGSCAN_INTVAL_MIN
)
3168 vap
->iv_bgscanintvl
= ireq
->i_val
*hz
;
3172 case IEEE80211_IOC_SCANVALID
:
3173 if (ireq
->i_val
>= IEEE80211_SCAN_VALID_MIN
)
3174 vap
->iv_scanvalid
= ireq
->i_val
*hz
;
3178 case IEEE80211_IOC_FRAGTHRESHOLD
:
3179 if ((vap
->iv_caps
& IEEE80211_C_TXFRAG
) == 0 &&
3180 ireq
->i_val
!= IEEE80211_FRAG_MAX
)
3182 if (!(IEEE80211_FRAG_MIN
<= ireq
->i_val
&&
3183 ireq
->i_val
<= IEEE80211_FRAG_MAX
))
3185 vap
->iv_fragthreshold
= ireq
->i_val
;
3188 case IEEE80211_IOC_BURST
:
3190 if ((vap
->iv_caps
& IEEE80211_C_BURST
) == 0)
3192 ieee80211_syncflag(vap
, IEEE80211_F_BURST
);
3194 ieee80211_syncflag(vap
, -IEEE80211_F_BURST
);
3197 case IEEE80211_IOC_BMISSTHRESHOLD
:
3198 if (!(IEEE80211_HWBMISS_MIN
<= ireq
->i_val
&&
3199 ireq
->i_val
<= IEEE80211_HWBMISS_MAX
))
3201 vap
->iv_bmissthreshold
= ireq
->i_val
;
3204 case IEEE80211_IOC_CURCHAN
:
3205 error
= ieee80211_ioctl_setcurchan(vap
, ireq
);
3207 case IEEE80211_IOC_SHORTGI
:
3209 #define IEEE80211_HTCAP_SHORTGI \
3210 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
3211 if (((ireq
->i_val
^ vap
->iv_htcaps
) & IEEE80211_HTCAP_SHORTGI
) != 0)
3213 if (ireq
->i_val
& IEEE80211_HTCAP_SHORTGI20
)
3214 vap
->iv_flags_ht
|= IEEE80211_FHT_SHORTGI20
;
3215 if (ireq
->i_val
& IEEE80211_HTCAP_SHORTGI40
)
3216 vap
->iv_flags_ht
|= IEEE80211_FHT_SHORTGI40
;
3217 #undef IEEE80211_HTCAP_SHORTGI
3220 ~(IEEE80211_FHT_SHORTGI20
| IEEE80211_FHT_SHORTGI40
);
3223 case IEEE80211_IOC_AMPDU
:
3224 if (ireq
->i_val
&& (vap
->iv_htcaps
& IEEE80211_HTC_AMPDU
) == 0)
3226 if (ireq
->i_val
& 1)
3227 vap
->iv_flags_ht
|= IEEE80211_FHT_AMPDU_TX
;
3229 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMPDU_TX
;
3230 if (ireq
->i_val
& 2)
3231 vap
->iv_flags_ht
|= IEEE80211_FHT_AMPDU_RX
;
3233 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMPDU_RX
;
3234 /* NB: reset only if we're operating on an 11n channel */
3238 case IEEE80211_IOC_AMPDU_LIMIT
:
3239 /* XXX TODO: figure out ampdu_limit versus ampdu_rxmax */
3240 if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K
<= ireq
->i_val
&&
3241 ireq
->i_val
<= IEEE80211_HTCAP_MAXRXAMPDU_64K
))
3243 if (vap
->iv_opmode
== IEEE80211_M_HOSTAP
)
3244 vap
->iv_ampdu_rxmax
= ireq
->i_val
;
3246 vap
->iv_ampdu_limit
= ireq
->i_val
;
3249 case IEEE80211_IOC_AMPDU_DENSITY
:
3250 if (!(IEEE80211_HTCAP_MPDUDENSITY_NA
<= ireq
->i_val
&&
3251 ireq
->i_val
<= IEEE80211_HTCAP_MPDUDENSITY_16
))
3253 vap
->iv_ampdu_density
= ireq
->i_val
;
3256 case IEEE80211_IOC_AMSDU
:
3257 if (ireq
->i_val
&& (vap
->iv_htcaps
& IEEE80211_HTC_AMSDU
) == 0)
3259 if (ireq
->i_val
& 1)
3260 vap
->iv_flags_ht
|= IEEE80211_FHT_AMSDU_TX
;
3262 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMSDU_TX
;
3263 if (ireq
->i_val
& 2)
3264 vap
->iv_flags_ht
|= IEEE80211_FHT_AMSDU_RX
;
3266 vap
->iv_flags_ht
&= ~IEEE80211_FHT_AMSDU_RX
;
3267 /* NB: reset only if we're operating on an 11n channel */
3271 case IEEE80211_IOC_AMSDU_LIMIT
:
3273 vap
->iv_amsdu_limit
= ireq
->i_val
; /* XXX truncation? */
3275 case IEEE80211_IOC_PUREN
:
3277 if ((vap
->iv_flags_ht
& IEEE80211_FHT_HT
) == 0)
3279 vap
->iv_flags_ht
|= IEEE80211_FHT_PUREN
;
3281 vap
->iv_flags_ht
&= ~IEEE80211_FHT_PUREN
;
3282 /* NB: reset only if we're operating on an 11n channel */
3286 case IEEE80211_IOC_DOTH
:
3289 /* XXX no capability */
3290 if ((vap
->iv_caps
& IEEE80211_C_DOTH
) == 0)
3293 vap
->iv_flags
|= IEEE80211_F_DOTH
;
3295 vap
->iv_flags
&= ~IEEE80211_F_DOTH
;
3298 case IEEE80211_IOC_REGDOMAIN
:
3299 error
= ieee80211_ioctl_setregdomain(vap
, ireq
);
3301 case IEEE80211_IOC_ROAM
:
3302 error
= ieee80211_ioctl_setroam(vap
, ireq
);
3304 case IEEE80211_IOC_TXPARAMS
:
3305 error
= ieee80211_ioctl_settxparams(vap
, ireq
);
3307 case IEEE80211_IOC_HTCOMPAT
:
3309 if ((vap
->iv_flags_ht
& IEEE80211_FHT_HT
) == 0)
3311 vap
->iv_flags_ht
|= IEEE80211_FHT_HTCOMPAT
;
3313 vap
->iv_flags_ht
&= ~IEEE80211_FHT_HTCOMPAT
;
3314 /* NB: reset only if we're operating on an 11n channel */
3318 case IEEE80211_IOC_DWDS
:
3320 /* NB: DWDS only makes sense for WDS-capable devices */
3321 if ((ic
->ic_caps
& IEEE80211_C_WDS
) == 0)
3323 /* NB: DWDS is used only with ap+sta vaps */
3324 if (vap
->iv_opmode
!= IEEE80211_M_HOSTAP
&&
3325 vap
->iv_opmode
!= IEEE80211_M_STA
)
3327 vap
->iv_flags
|= IEEE80211_F_DWDS
;
3328 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3329 vap
->iv_flags_ext
|= IEEE80211_FEXT_4ADDR
;
3331 vap
->iv_flags
&= ~IEEE80211_F_DWDS
;
3332 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3333 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_4ADDR
;
3336 case IEEE80211_IOC_INACTIVITY
:
3338 vap
->iv_flags_ext
|= IEEE80211_FEXT_INACT
;
3340 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_INACT
;
3342 case IEEE80211_IOC_APPIE
:
3343 error
= ieee80211_ioctl_setappie(vap
, ireq
);
3345 case IEEE80211_IOC_WPS
:
3347 if ((vap
->iv_caps
& IEEE80211_C_WPA
) == 0)
3349 vap
->iv_flags_ext
|= IEEE80211_FEXT_WPS
;
3351 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_WPS
;
3353 case IEEE80211_IOC_TSN
:
3355 if ((vap
->iv_caps
& IEEE80211_C_WPA
) == 0)
3357 vap
->iv_flags_ext
|= IEEE80211_FEXT_TSN
;
3359 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_TSN
;
3361 case IEEE80211_IOC_CHANSWITCH
:
3362 error
= ieee80211_ioctl_chanswitch(vap
, ireq
);
3364 case IEEE80211_IOC_DFS
:
3366 if ((vap
->iv_caps
& IEEE80211_C_DFS
) == 0)
3368 /* NB: DFS requires 11h support */
3369 if ((vap
->iv_flags
& IEEE80211_F_DOTH
) == 0)
3371 vap
->iv_flags_ext
|= IEEE80211_FEXT_DFS
;
3373 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_DFS
;
3375 case IEEE80211_IOC_DOTD
:
3377 vap
->iv_flags_ext
|= IEEE80211_FEXT_DOTD
;
3379 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_DOTD
;
3380 if (vap
->iv_opmode
== IEEE80211_M_STA
)
3383 case IEEE80211_IOC_HTPROTMODE
:
3384 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
3386 vap
->iv_htprotmode
= ireq
->i_val
?
3387 IEEE80211_PROT_RTSCTS
: IEEE80211_PROT_NONE
;
3388 /* NB: if not operating in 11n this can wait */
3391 /* Notify driver layer of HT protmode changes */
3392 ieee80211_vap_update_ht_protmode(vap
);
3394 case IEEE80211_IOC_STA_VLAN
:
3395 error
= ieee80211_ioctl_setstavlan(vap
, ireq
);
3397 case IEEE80211_IOC_SMPS
:
3398 if ((ireq
->i_val
&~ IEEE80211_HTCAP_SMPS
) != 0 ||
3399 ireq
->i_val
== 0x0008) /* value of 2 is reserved */
3401 if (ireq
->i_val
!= IEEE80211_HTCAP_SMPS_OFF
&&
3402 (vap
->iv_htcaps
& IEEE80211_HTC_SMPS
) == 0)
3404 vap
->iv_htcaps
= (vap
->iv_htcaps
&~ IEEE80211_HTCAP_SMPS
) |
3406 /* NB: if not operating in 11n this can wait */
3410 case IEEE80211_IOC_RIFS
:
3411 if (ireq
->i_val
!= 0) {
3412 if ((vap
->iv_htcaps
& IEEE80211_HTC_RIFS
) == 0)
3414 vap
->iv_flags_ht
|= IEEE80211_FHT_RIFS
;
3416 vap
->iv_flags_ht
&= ~IEEE80211_FHT_RIFS
;
3417 /* NB: if not operating in 11n this can wait */
3421 case IEEE80211_IOC_STBC
:
3422 /* Check if we can do STBC TX/RX before changing the setting */
3423 if ((ireq
->i_val
& 1) &&
3424 ((vap
->iv_htcaps
& IEEE80211_HTCAP_TXSTBC
) == 0))
3426 if ((ireq
->i_val
& 2) &&
3427 ((vap
->iv_htcaps
& IEEE80211_HTCAP_RXSTBC
) == 0))
3431 if (ireq
->i_val
& 1)
3432 vap
->iv_flags_ht
|= IEEE80211_FHT_STBC_TX
;
3434 vap
->iv_flags_ht
&= ~IEEE80211_FHT_STBC_TX
;
3437 if (ireq
->i_val
& 2)
3438 vap
->iv_flags_ht
|= IEEE80211_FHT_STBC_RX
;
3440 vap
->iv_flags_ht
&= ~IEEE80211_FHT_STBC_RX
;
3442 /* NB: reset only if we're operating on an 11n channel */
3446 case IEEE80211_IOC_LDPC
:
3447 /* Check if we can do LDPC TX/RX before changing the setting */
3448 if ((ireq
->i_val
& 1) &&
3449 (vap
->iv_htcaps
& IEEE80211_HTC_TXLDPC
) == 0)
3451 if ((ireq
->i_val
& 2) &&
3452 (vap
->iv_htcaps
& IEEE80211_HTCAP_LDPC
) == 0)
3456 if (ireq
->i_val
& 1)
3457 vap
->iv_flags_ht
|= IEEE80211_FHT_LDPC_TX
;
3459 vap
->iv_flags_ht
&= ~IEEE80211_FHT_LDPC_TX
;
3462 if (ireq
->i_val
& 2)
3463 vap
->iv_flags_ht
|= IEEE80211_FHT_LDPC_RX
;
3465 vap
->iv_flags_ht
&= ~IEEE80211_FHT_LDPC_RX
;
3467 /* NB: reset only if we're operating on an 11n channel */
3471 case IEEE80211_IOC_UAPSD
:
3472 if ((vap
->iv_caps
& IEEE80211_C_UAPSD
) == 0)
3474 if (ireq
->i_val
== 0)
3475 vap
->iv_flags_ext
&= ~IEEE80211_FEXT_UAPSD
;
3476 else if (ireq
->i_val
== 1)
3477 vap
->iv_flags_ext
|= IEEE80211_FEXT_UAPSD
;
3483 case IEEE80211_IOC_VHTCONF
:
3484 if (ireq
->i_val
& IEEE80211_FVHT_VHT
)
3485 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_VHT
);
3487 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_VHT
);
3489 if (ireq
->i_val
& IEEE80211_FVHT_USEVHT40
)
3490 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_USEVHT40
);
3492 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_USEVHT40
);
3494 if (ireq
->i_val
& IEEE80211_FVHT_USEVHT80
)
3495 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_USEVHT80
);
3497 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_USEVHT80
);
3499 if (ireq
->i_val
& IEEE80211_FVHT_USEVHT160
)
3500 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_USEVHT160
);
3502 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_USEVHT160
);
3504 if (ireq
->i_val
& IEEE80211_FVHT_USEVHT80P80
)
3505 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_USEVHT80P80
);
3507 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_USEVHT80P80
);
3509 /* Check if we can do STBC TX/RX before changing the setting. */
3510 if ((ireq
->i_val
& IEEE80211_FVHT_STBC_TX
) &&
3511 ((vap
->iv_vht_cap
.vht_cap_info
& IEEE80211_VHTCAP_TXSTBC
) == 0))
3513 if ((ireq
->i_val
& IEEE80211_FVHT_STBC_RX
) &&
3514 ((vap
->iv_vht_cap
.vht_cap_info
& IEEE80211_VHTCAP_RXSTBC_MASK
) == 0))
3518 if (ireq
->i_val
& IEEE80211_FVHT_STBC_TX
)
3519 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_STBC_TX
);
3521 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_STBC_TX
);
3524 if (ireq
->i_val
& IEEE80211_FVHT_STBC_RX
)
3525 ieee80211_syncflag_vht(vap
, IEEE80211_FVHT_STBC_RX
);
3527 ieee80211_syncflag_vht(vap
, -IEEE80211_FVHT_STBC_RX
);
3533 error
= ieee80211_ioctl_setdefault(vap
, ireq
);
3537 * The convention is that ENETRESET means an operation
3538 * requires a complete re-initialization of the device (e.g.
3539 * changing something that affects the association state).
3540 * ERESTART means the request may be handled with only a
3541 * reload of the hardware state. We hand ERESTART requests
3542 * to the iv_reset callback so the driver can decide. If
3543 * a device does not fillin iv_reset then it defaults to one
3544 * that returns ENETRESET. Otherwise a driver may return
3545 * ENETRESET (in which case a full reset will be done) or
3546 * 0 to mean there's no need to do anything (e.g. when the
3547 * change has no effect on the driver/device).
3549 if (error
== ERESTART
)
3550 error
= IFNET_IS_UP_RUNNING(vap
->iv_ifp
) ?
3551 vap
->iv_reset(vap
, ireq
->i_type
) : 0;
3552 if (error
== ENETRESET
) {
3553 /* XXX need to re-think AUTO handling */
3554 if (IS_UP_AUTO(vap
))
3555 ieee80211_init(vap
);
3562 ieee80211_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
)
3564 struct ieee80211vap
*vap
= ifp
->if_softc
;
3565 struct ieee80211com
*ic
= vap
->iv_ic
;
3566 int error
= 0, wait
= 0, ic_used
;
3568 struct ifaddr
*ifa
; /* XXX */
3570 ic_used
= (cmd
!= SIOCSIFMTU
&& cmd
!= SIOCG80211STATS
);
3571 if (ic_used
&& (error
= ieee80211_com_vincref(vap
)) != 0)
3577 if ((ifp
->if_flags
^ vap
->iv_ifflags
) & IFF_PROMISC
) {
3579 * Enable promiscuous mode when:
3580 * 1. Interface is not a member of bridge, or
3581 * 2. Requested by user, or
3582 * 3. In monitor (or adhoc-demo) mode.
3584 if (ifp
->if_bridge
== NULL
||
3585 (ifp
->if_flags
& IFF_PPROMISC
) != 0 ||
3586 vap
->iv_opmode
== IEEE80211_M_MONITOR
||
3587 (vap
->iv_opmode
== IEEE80211_M_AHDEMO
&&
3588 (vap
->iv_caps
& IEEE80211_C_TDMA
) == 0)) {
3589 ieee80211_promisc(vap
,
3590 ifp
->if_flags
& IFF_PROMISC
);
3591 vap
->iv_ifflags
^= IFF_PROMISC
;
3594 if ((ifp
->if_flags
^ vap
->iv_ifflags
) & IFF_ALLMULTI
) {
3595 ieee80211_allmulti(vap
, ifp
->if_flags
& IFF_ALLMULTI
);
3596 vap
->iv_ifflags
^= IFF_ALLMULTI
;
3598 if (ifp
->if_flags
& IFF_UP
) {
3600 * Bring ourself up unless we're already operational.
3601 * If we're the first vap and the parent is not up
3602 * then it will automatically be brought up as a
3603 * side-effect of bringing ourself up.
3605 if (vap
->iv_state
== IEEE80211_S_INIT
) {
3606 if (ic
->ic_nrunning
== 0)
3608 ieee80211_start_locked(vap
);
3610 } else if (ifp
->if_drv_flags
& IFF_DRV_RUNNING
) {
3612 * Stop ourself. If we are the last vap to be
3613 * marked down the parent will also be taken down.
3615 if (ic
->ic_nrunning
== 1)
3617 ieee80211_stop_locked(vap
);
3619 IEEE80211_UNLOCK(ic
);
3620 /* Wait for parent ioctl handler if it was queued */
3622 struct epoch_tracker et
;
3624 ieee80211_waitfor_parent(ic
);
3627 * Check if the MAC address was changed
3628 * via SIOCSIFLLADDR ioctl.
3630 * NB: device may be detached during initialization;
3631 * use if_ioctl for existence check.
3633 NET_EPOCH_ENTER(et
);
3634 if (ifp
->if_ioctl
== ieee80211_ioctl
&&
3635 (ifp
->if_flags
& IFF_UP
) == 0 &&
3636 !IEEE80211_ADDR_EQ(vap
->iv_myaddr
, IF_LLADDR(ifp
)))
3637 IEEE80211_ADDR_COPY(vap
->iv_myaddr
,
3644 ieee80211_runtask(ic
, &ic
->ic_mcast_task
);
3648 ifr
= (struct ifreq
*)data
;
3649 error
= ifmedia_ioctl(ifp
, ifr
, &vap
->iv_media
, cmd
);
3652 error
= ieee80211_ioctl_get80211(vap
, cmd
,
3653 (struct ieee80211req
*) data
);
3656 error
= ieee80211_priv_check_vap_manage(cmd
, vap
, ifp
);
3658 error
= ieee80211_ioctl_set80211(vap
, cmd
,
3659 (struct ieee80211req
*) data
);
3661 case SIOCG80211STATS
:
3662 ifr
= (struct ifreq
*)data
;
3663 error
= copyout(&vap
->iv_stats
, ifr_data_get_ptr(ifr
),
3664 sizeof(vap
->iv_stats
));
3667 ifr
= (struct ifreq
*)data
;
3668 if (!(IEEE80211_MTU_MIN
<= ifr
->ifr_mtu
&&
3669 ifr
->ifr_mtu
<= IEEE80211_MTU_MAX
))
3672 ifp
->if_mtu
= ifr
->ifr_mtu
;
3676 * XXX Handle this directly so we can suppress if_init calls.
3677 * XXX This should be done in ether_ioctl but for the moment
3678 * XXX there are too many other parts of the system that
3679 * XXX set IFF_UP and so suppress if_init being called when
3682 ifa
= (struct ifaddr
*) data
;
3683 switch (ifa
->ifa_addr
->sa_family
) {
3686 if ((ifp
->if_flags
& IFF_UP
) == 0) {
3687 ifp
->if_flags
|= IFF_UP
;
3688 ifp
->if_init(ifp
->if_softc
);
3690 arp_ifinit(ifp
, ifa
);
3694 if ((ifp
->if_flags
& IFF_UP
) == 0) {
3695 ifp
->if_flags
|= IFF_UP
;
3696 ifp
->if_init(ifp
->if_softc
);
3702 error
= ieee80211_priv_check_vap_setmac(cmd
, vap
, ifp
);
3708 * Pass unknown ioctls first to the driver, and if it
3709 * returns ENOTTY, then to the generic Ethernet handler.
3711 if (ic
->ic_ioctl
!= NULL
&&
3712 (error
= ic
->ic_ioctl(ic
, cmd
, data
)) != ENOTTY
)
3714 error
= ether_ioctl(ifp
, cmd
, data
);
3719 ieee80211_com_vdecref(vap
);