2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2 as published by the Free
19 * Software Foundation.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.25.2.15 2006/09/02 17:09:26 sam Exp $
33 * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_ioctl.c,v 1.13 2008/01/19 07:34:13 sephe Exp $
37 * IEEE 802.11 ioctl support (DragonFlyBSD-specific)
43 #include <sys/endian.h>
44 #include <sys/param.h>
45 #include <sys/kernel.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/systm.h>
53 #include <net/if_arp.h>
54 #include <net/if_dl.h>
55 #include <net/if_media.h>
56 #include <net/ethernet.h>
59 #include <netinet/in.h>
60 #include <netinet/if_ether.h>
64 #include <netproto/ipx/ipx.h>
65 #include <netproto/ipx/ipx_if.h>
68 #include <netproto/802_11/ieee80211_var.h>
69 #include <netproto/802_11/ieee80211_ioctl.h>
71 #include <netproto/802_11/if_wavelan_ieee.h>
74 (((_ic)->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) == \
75 (IFF_UP | IFF_RUNNING))
77 #define IS_UP_AUTO(_ic) \
78 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
82 * Wireless LAN specific configuration interface, which is compatible
86 struct wi_read_ap_args
{
87 int i
; /* result count */
88 struct wi_apinfo
*ap
; /* current entry in result buffer */
89 caddr_t max
; /* result buffer bound */
93 wi_read_ap_result(void *arg
, struct ieee80211_node
*ni
)
95 struct ieee80211com
*ic
= ni
->ni_ic
;
96 struct wi_read_ap_args
*sa
= arg
;
97 struct wi_apinfo
*ap
= sa
->ap
;
98 struct ieee80211_rateset
*rs
;
101 if ((caddr_t
)(ap
+ 1) > sa
->max
)
103 memset(ap
, 0, sizeof(struct wi_apinfo
));
104 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
105 IEEE80211_ADDR_COPY(ap
->bssid
, ni
->ni_macaddr
);
106 ap
->namelen
= ic
->ic_des_esslen
;
107 if (ic
->ic_des_esslen
)
108 memcpy(ap
->name
, ic
->ic_des_essid
,
111 IEEE80211_ADDR_COPY(ap
->bssid
, ni
->ni_bssid
);
112 ap
->namelen
= ni
->ni_esslen
;
114 memcpy(ap
->name
, ni
->ni_essid
,
117 ap
->channel
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
118 ap
->signal
= ic
->ic_node_getrssi(ni
);
119 ap
->capinfo
= ni
->ni_capinfo
;
120 ap
->interval
= ni
->ni_intval
;
122 for (j
= 0; j
< rs
->rs_nrates
; j
++) {
123 if (rs
->rs_rates
[j
] & IEEE80211_RATE_BASIC
) {
124 ap
->rate
= (rs
->rs_rates
[j
] &
125 IEEE80211_RATE_VAL
) * 5; /* XXX */
132 struct wi_read_prism2_args
{
133 int i
; /* result count */
134 struct wi_scan_res
*res
;/* current entry in result buffer */
135 caddr_t max
; /* result buffer bound */
139 wi_read_prism2_result(void *arg
, struct ieee80211_node
*ni
)
141 struct ieee80211com
*ic
= ni
->ni_ic
;
142 struct wi_read_prism2_args
*sa
= arg
;
143 struct wi_scan_res
*res
= sa
->res
;
145 if ((caddr_t
)(res
+ 1) > sa
->max
)
147 res
->wi_chan
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
149 res
->wi_signal
= ic
->ic_node_getrssi(ni
);
150 IEEE80211_ADDR_COPY(res
->wi_bssid
, ni
->ni_bssid
);
151 res
->wi_interval
= ni
->ni_intval
;
152 res
->wi_capinfo
= ni
->ni_capinfo
;
153 res
->wi_ssid_len
= ni
->ni_esslen
;
154 memcpy(res
->wi_ssid
, ni
->ni_essid
, IEEE80211_NWID_LEN
);
155 /* NB: assumes wi_srates holds <= ni->ni_rates */
156 memcpy(res
->wi_srates
, ni
->ni_rates
.rs_rates
,
157 sizeof(res
->wi_srates
));
158 if (ni
->ni_rates
.rs_nrates
< 10)
159 res
->wi_srates
[ni
->ni_rates
.rs_nrates
] = 0;
160 res
->wi_rate
= ni
->ni_rates
.rs_rates
[ni
->ni_txrate
];
167 struct wi_read_sigcache_args
{
168 int i
; /* result count */
169 struct wi_sigcache
*wsc
;/* current entry in result buffer */
170 caddr_t max
; /* result buffer bound */
174 wi_read_sigcache(void *arg
, struct ieee80211_node
*ni
)
176 struct ieee80211com
*ic
= ni
->ni_ic
;
177 struct wi_read_sigcache_args
*sa
= arg
;
178 struct wi_sigcache
*wsc
= sa
->wsc
;
180 if ((caddr_t
)(wsc
+ 1) > sa
->max
)
182 memset(wsc
, 0, sizeof(struct wi_sigcache
));
183 IEEE80211_ADDR_COPY(wsc
->macsrc
, ni
->ni_macaddr
);
184 wsc
->signal
= ic
->ic_node_getrssi(ni
);
191 ieee80211_cfgget(struct ieee80211com
*ic
, u_long cmd
, caddr_t data
,
194 struct ifnet
*ifp
= ic
->ic_ifp
;
196 struct ifreq
*ifr
= (struct ifreq
*)data
;
198 struct wi_ltv_keys
*keys
;
200 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
204 switch (wreq
.wi_type
) {
205 case WI_RID_SERIALNO
:
206 /* nothing appropriate */
208 case WI_RID_NODENAME
:
209 strcpy((char *)&wreq
.wi_val
[1], hostname
);
210 wreq
.wi_val
[0] = htole16(strlen(hostname
));
211 wreq
.wi_len
= (1 + strlen(hostname
) + 1) / 2;
213 case WI_RID_CURRENT_SSID
:
214 if (ic
->ic_state
!= IEEE80211_S_RUN
) {
219 wreq
.wi_val
[0] = htole16(ic
->ic_bss
->ni_esslen
);
220 memcpy(&wreq
.wi_val
[1], ic
->ic_bss
->ni_essid
,
221 ic
->ic_bss
->ni_esslen
);
222 wreq
.wi_len
= (1 + ic
->ic_bss
->ni_esslen
+ 1) / 2;
224 case WI_RID_OWN_SSID
:
225 case WI_RID_DESIRED_SSID
:
226 wreq
.wi_val
[0] = htole16(ic
->ic_des_esslen
);
227 memcpy(&wreq
.wi_val
[1], ic
->ic_des_essid
, ic
->ic_des_esslen
);
228 wreq
.wi_len
= (1 + ic
->ic_des_esslen
+ 1) / 2;
230 case WI_RID_CURRENT_BSSID
:
231 if (ic
->ic_state
== IEEE80211_S_RUN
)
232 IEEE80211_ADDR_COPY(wreq
.wi_val
, ic
->ic_bss
->ni_bssid
);
234 memset(wreq
.wi_val
, 0, IEEE80211_ADDR_LEN
);
235 wreq
.wi_len
= IEEE80211_ADDR_LEN
/ 2;
237 case WI_RID_CHANNEL_LIST
:
238 memset(wreq
.wi_val
, 0, sizeof(wreq
.wi_val
));
240 * Since channel 0 is not available for DS, channel 1
241 * is assigned to LSB on WaveLAN.
243 if (ic
->ic_phytype
== IEEE80211_T_DS
)
247 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++)
248 if (isset(ic
->ic_chan_active
, i
)) {
249 setbit((uint8_t *)wreq
.wi_val
, j
);
250 wreq
.wi_len
= j
/ 16 + 1;
253 case WI_RID_OWN_CHNL
:
254 wreq
.wi_val
[0] = htole16(
255 ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
));
258 case WI_RID_CURRENT_CHAN
:
259 wreq
.wi_val
[0] = htole16(
260 ieee80211_chan2ieee(ic
, ic
->ic_curchan
));
263 case WI_RID_COMMS_QUALITY
:
264 wreq
.wi_val
[0] = 0; /* quality */
265 wreq
.wi_val
[1] = htole16(ic
->ic_node_getrssi(ic
->ic_bss
));
266 wreq
.wi_val
[2] = 0; /* noise */
270 wreq
.wi_val
[0] = htole16((ifp
->if_flags
& IFF_PROMISC
) ? 1 : 0);
273 case WI_RID_PORTTYPE
:
274 wreq
.wi_val
[0] = htole16(ic
->ic_opmode
);
277 case WI_RID_MAC_NODE
:
278 IEEE80211_ADDR_COPY(wreq
.wi_val
, ic
->ic_myaddr
);
279 wreq
.wi_len
= IEEE80211_ADDR_LEN
/ 2;
282 if (ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
)
283 wreq
.wi_val
[0] = 0; /* auto */
285 wreq
.wi_val
[0] = htole16(
286 (ic
->ic_sup_rates
[ic
->ic_curmode
].rs_rates
[ic
->ic_fixed_rate
] &
287 IEEE80211_RATE_VAL
) / 2);
290 case WI_RID_CUR_TX_RATE
:
291 wreq
.wi_val
[0] = htole16(
292 (ic
->ic_bss
->ni_rates
.rs_rates
[ic
->ic_bss
->ni_txrate
] &
293 IEEE80211_RATE_VAL
) / 2);
296 case WI_RID_RTS_THRESH
:
297 wreq
.wi_val
[0] = htole16(ic
->ic_rtsthreshold
);
300 case WI_RID_CREATE_IBSS
:
302 htole16((ic
->ic_flags
& IEEE80211_F_IBSSON
) ? 1 : 0);
305 case WI_RID_MICROWAVE_OVEN
:
306 wreq
.wi_val
[0] = 0; /* no ... not supported */
309 case WI_RID_ROAMING_MODE
:
310 wreq
.wi_val
[0] = htole16(ic
->ic_roaming
); /* XXX map */
313 case WI_RID_SYSTEM_SCALE
:
314 wreq
.wi_val
[0] = htole16(1); /* low density ... not supp */
317 case WI_RID_PM_ENABLED
:
319 htole16((ic
->ic_flags
& IEEE80211_F_PMGTON
) ? 1 : 0);
322 case WI_RID_MAX_SLEEP
:
323 wreq
.wi_val
[0] = htole16(ic
->ic_lintval
);
326 case WI_RID_CUR_BEACON_INT
:
327 wreq
.wi_val
[0] = htole16(ic
->ic_bss
->ni_intval
);
330 case WI_RID_WEP_AVAIL
:
331 wreq
.wi_val
[0] = htole16(1); /* always available */
334 case WI_RID_CNFAUTHMODE
:
335 wreq
.wi_val
[0] = htole16(1); /* TODO: open system only */
338 case WI_RID_ENCRYPTION
:
340 htole16((ic
->ic_flags
& IEEE80211_F_PRIVACY
) ? 1 : 0);
343 case WI_RID_TX_CRYPT_KEY
:
344 wreq
.wi_val
[0] = htole16(ic
->ic_def_txkey
);
347 case WI_RID_DEFLT_CRYPT_KEYS
:
348 keys
= (struct wi_ltv_keys
*)&wreq
;
349 /* do not show keys to non-root user */
350 error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
);
352 memset(keys
, 0, sizeof(*keys
));
356 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
357 keys
->wi_keys
[i
].wi_keylen
=
358 htole16(ic
->ic_nw_keys
[i
].wk_keylen
);
359 memcpy(keys
->wi_keys
[i
].wi_keydat
,
360 ic
->ic_nw_keys
[i
].wk_key
,
361 ic
->ic_nw_keys
[i
].wk_keylen
);
363 wreq
.wi_len
= sizeof(*keys
) / 2;
365 case WI_RID_MAX_DATALEN
:
366 wreq
.wi_val
[0] = htole16(ic
->ic_fragthreshold
);
369 case WI_RID_IFACE_STATS
:
370 /* XXX: should be implemented in lower drivers */
372 case WI_RID_READ_APS
:
374 * Don't return results until active scan completes.
376 if ((ic
->ic_flags
& (IEEE80211_F_SCAN
|IEEE80211_F_ASCAN
)) == 0) {
377 struct wi_read_ap_args args
;
380 args
.ap
= (void *)((char *)wreq
.wi_val
+ sizeof(i
));
381 args
.max
= (void *)(&wreq
+ 1);
382 ieee80211_iterate_nodes(&ic
->ic_scan
,
383 wi_read_ap_result
, &args
);
384 memcpy(wreq
.wi_val
, &args
.i
, sizeof(args
.i
));
385 wreq
.wi_len
= (sizeof(int) +
386 sizeof(struct wi_apinfo
) * args
.i
) / 2;
391 /* NB: we lie so WI_RID_SCAN_RES can include rates */
393 wreq
.wi_len
= sizeof(uint16_t) / 2;
395 case WI_RID_SCAN_RES
: /* compatibility interface */
396 if ((ic
->ic_flags
& (IEEE80211_F_SCAN
|IEEE80211_F_ASCAN
)) == 0) {
397 struct wi_read_prism2_args args
;
398 struct wi_scan_p2_hdr
*p2
;
400 /* NB: use Prism2 format so we can include rate info */
401 p2
= (struct wi_scan_p2_hdr
*)wreq
.wi_val
;
403 args
.res
= (void *)&p2
[1];
404 args
.max
= (void *)(&wreq
+ 1);
405 ieee80211_iterate_nodes(&ic
->ic_scan
,
406 wi_read_prism2_result
, &args
);
408 p2
->wi_reason
= args
.i
;
409 wreq
.wi_len
= (sizeof(*p2
) +
410 sizeof(struct wi_scan_res
) * args
.i
) / 2;
414 case WI_RID_READ_CACHE
: {
415 struct wi_read_sigcache_args args
;
417 args
.wsc
= (struct wi_sigcache
*) wreq
.wi_val
;
418 args
.max
= (void *)(&wreq
+ 1);
419 ieee80211_iterate_nodes(&ic
->ic_scan
, wi_read_sigcache
, &args
);
420 wreq
.wi_len
= sizeof(struct wi_sigcache
) * args
.i
/ 2;
429 error
= copyout(&wreq
, ifr
->ifr_data
, sizeof(wreq
));
435 findrate(struct ieee80211com
*ic
, enum ieee80211_phymode mode
, int rate
)
437 #define IEEERATE(_ic,_m,_i) \
438 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
439 int i
, nrates
= ic
->ic_sup_rates
[mode
].rs_nrates
;
440 for (i
= 0; i
< nrates
; i
++)
441 if (IEEERATE(ic
, mode
, i
) == rate
)
448 * Prepare to do a user-initiated scan for AP's. If no
449 * current/default channel is setup or the current channel
450 * is invalid then pick the first available channel from
451 * the active list as the place to start the scan.
454 ieee80211_setupscan(struct ieee80211com
*ic
, const uint8_t chanlist
[])
458 * XXX don't permit a scan to be started unless we
459 * know the device is ready. For the moment this means
460 * the device is marked up as this is the required to
461 * initialize the hardware. It would be better to permit
462 * scanning prior to being up but that'll require some
463 * changes to the infrastructure.
467 memcpy(ic
->ic_chan_active
, chanlist
, sizeof(ic
->ic_chan_active
));
469 * We force the state to INIT before calling ieee80211_new_state
470 * to get ieee80211_begin_scan called. We really want to scan w/o
471 * altering the current state but that's not possible right now.
473 /* XXX handle proberequest case */
474 ic
->ic_state
= IEEE80211_S_INIT
; /* XXX bypass state machine */
479 ieee80211_cfgset(struct ieee80211com
*ic
, u_long cmd
, caddr_t data
)
481 struct ifnet
*ifp
= ic
->ic_ifp
;
482 int i
, j
, len
, error
, rate
;
483 struct ifreq
*ifr
= (struct ifreq
*)data
;
484 struct wi_ltv_keys
*keys
;
486 u_char chanlist
[roundup(IEEE80211_CHAN_MAX
, NBBY
)];
488 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
491 len
= wreq
.wi_len
? (wreq
.wi_len
- 1) * 2 : 0;
492 switch (wreq
.wi_type
) {
493 case WI_RID_SERIALNO
:
494 case WI_RID_NODENAME
:
496 case WI_RID_CURRENT_SSID
:
498 case WI_RID_OWN_SSID
:
499 case WI_RID_DESIRED_SSID
:
500 if (le16toh(wreq
.wi_val
[0]) * 2 > len
||
501 le16toh(wreq
.wi_val
[0]) > IEEE80211_NWID_LEN
) {
505 memset(ic
->ic_des_essid
, 0, sizeof(ic
->ic_des_essid
));
506 ic
->ic_des_esslen
= le16toh(wreq
.wi_val
[0]) * 2;
507 memcpy(ic
->ic_des_essid
, &wreq
.wi_val
[1], ic
->ic_des_esslen
);
510 case WI_RID_CURRENT_BSSID
:
512 case WI_RID_OWN_CHNL
:
515 i
= le16toh(wreq
.wi_val
[0]);
517 i
> IEEE80211_CHAN_MAX
||
518 isclr(ic
->ic_chan_active
, i
))
520 ic
->ic_ibss_chan
= &ic
->ic_channels
[i
];
521 if (ic
->ic_opmode
== IEEE80211_M_MONITOR
)
522 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
526 case WI_RID_CURRENT_CHAN
:
528 case WI_RID_COMMS_QUALITY
:
533 if (ifp
->if_flags
& IFF_PROMISC
) {
534 if (wreq
.wi_val
[0] == 0) {
535 ifp
->if_flags
&= ~IFF_PROMISC
;
539 if (wreq
.wi_val
[0] != 0) {
540 ifp
->if_flags
|= IFF_PROMISC
;
545 case WI_RID_PORTTYPE
:
548 switch (le16toh(wreq
.wi_val
[0])) {
549 case IEEE80211_M_STA
:
551 case IEEE80211_M_IBSS
:
552 if (!(ic
->ic_caps
& IEEE80211_C_IBSS
))
555 case IEEE80211_M_AHDEMO
:
556 if (ic
->ic_phytype
!= IEEE80211_T_DS
||
557 !(ic
->ic_caps
& IEEE80211_C_AHDEMO
))
560 case IEEE80211_M_HOSTAP
:
561 if (!(ic
->ic_caps
& IEEE80211_C_HOSTAP
))
567 if (le16toh(wreq
.wi_val
[0]) != ic
->ic_opmode
) {
568 ic
->ic_opmode
= le16toh(wreq
.wi_val
[0]);
569 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
573 case WI_RID_MAC_NODE
:
574 if (len
!= IEEE80211_ADDR_LEN
)
576 IEEE80211_ADDR_COPY(LLADDR(ifp
->if_sadl
), wreq
.wi_val
);
577 /* if_init will copy lladdr into ic_myaddr */
584 if (wreq
.wi_val
[0] == 0) {
586 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
589 rate
= 2 * le16toh(wreq
.wi_val
[0]);
590 if (ic
->ic_curmode
== IEEE80211_MODE_AUTO
) {
592 * In autoselect mode search for the rate. We take
593 * the first instance which may not be right, but we
594 * are limited by the interface. Note that we also
595 * lock the mode to insure the rate is meaningful
598 for (j
= IEEE80211_MODE_11A
;
599 j
< IEEE80211_MODE_MAX
; j
++) {
600 if ((ic
->ic_modecaps
& (1<<j
)) == 0)
602 i
= findrate(ic
, j
, rate
);
610 i
= findrate(ic
, ic
->ic_curmode
, rate
);
616 ic
->ic_fixed_rate
= i
;
617 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
619 case WI_RID_CUR_TX_RATE
:
621 case WI_RID_RTS_THRESH
:
624 if (le16toh(wreq
.wi_val
[0]) != IEEE80211_MAX_LEN
)
625 return EINVAL
; /* TODO: RTS */
627 case WI_RID_CREATE_IBSS
:
630 if (wreq
.wi_val
[0] != 0) {
631 if ((ic
->ic_caps
& IEEE80211_C_IBSS
) == 0)
633 if ((ic
->ic_flags
& IEEE80211_F_IBSSON
) == 0) {
634 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
635 if (ic
->ic_opmode
== IEEE80211_M_IBSS
&&
636 ic
->ic_state
== IEEE80211_S_SCAN
)
637 error
= IS_UP_AUTO(ic
) ? ENETRESET
: 0;
640 if (ic
->ic_flags
& IEEE80211_F_IBSSON
) {
641 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
642 if (ic
->ic_flags
& IEEE80211_F_SIBSS
) {
643 ic
->ic_flags
&= ~IEEE80211_F_SIBSS
;
644 error
= IS_UP_AUTO(ic
) ? ENETRESET
: 0;
649 case WI_RID_MICROWAVE_OVEN
:
652 if (wreq
.wi_val
[0] != 0)
653 return EINVAL
; /* not supported */
655 case WI_RID_ROAMING_MODE
:
658 i
= le16toh(wreq
.wi_val
[0]);
659 if (i
> IEEE80211_ROAMING_MANUAL
)
660 return EINVAL
; /* not supported */
663 case WI_RID_SYSTEM_SCALE
:
666 if (le16toh(wreq
.wi_val
[0]) != 1)
667 return EINVAL
; /* not supported */
669 case WI_RID_PM_ENABLED
:
672 if (wreq
.wi_val
[0] != 0) {
673 if ((ic
->ic_caps
& IEEE80211_C_PMGT
) == 0)
675 if ((ic
->ic_flags
& IEEE80211_F_PMGTON
) == 0) {
676 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
677 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
680 if (ic
->ic_flags
& IEEE80211_F_PMGTON
) {
681 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
682 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
686 case WI_RID_MAX_SLEEP
:
689 ic
->ic_lintval
= le16toh(wreq
.wi_val
[0]);
690 if (ic
->ic_flags
& IEEE80211_F_PMGTON
)
691 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
693 case WI_RID_CUR_BEACON_INT
:
695 case WI_RID_WEP_AVAIL
:
697 case WI_RID_CNFAUTHMODE
:
700 i
= le16toh(wreq
.wi_val
[0]);
701 if (i
> IEEE80211_AUTH_WPA
)
703 ic
->ic_bss
->ni_authmode
= i
; /* XXX ENETRESET? */
706 case WI_RID_ENCRYPTION
:
709 if (wreq
.wi_val
[0] != 0) {
710 if ((ic
->ic_caps
& IEEE80211_C_WEP
) == 0)
712 if ((ic
->ic_flags
& IEEE80211_F_PRIVACY
) == 0) {
713 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
717 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
718 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
723 case WI_RID_TX_CRYPT_KEY
:
726 i
= le16toh(wreq
.wi_val
[0]);
727 if (i
>= IEEE80211_WEP_NKID
)
729 ic
->ic_def_txkey
= i
;
730 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
732 case WI_RID_DEFLT_CRYPT_KEYS
:
733 if (len
!= sizeof(struct wi_ltv_keys
))
735 keys
= (struct wi_ltv_keys
*)&wreq
;
736 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
737 len
= le16toh(keys
->wi_keys
[i
].wi_keylen
);
738 if (len
!= 0 && len
< IEEE80211_WEP_KEYLEN
)
740 if (len
> IEEE80211_KEYBUF_SIZE
)
743 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
744 struct ieee80211_key
*k
= &ic
->ic_nw_keys
[i
];
746 len
= le16toh(keys
->wi_keys
[i
].wi_keylen
);
748 k
->wk_flags
= IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
;
749 memset(k
->wk_key
, 0, sizeof(k
->wk_key
));
750 memcpy(k
->wk_key
, keys
->wi_keys
[i
].wi_keydat
, len
);
752 k
->wk_type
= IEEE80211_CIPHER_WEP
;
757 case WI_RID_MAX_DATALEN
:
760 len
= le16toh(wreq
.wi_val
[0]);
761 if (len
< 350 /* ? */ || len
> IEEE80211_MAX_LEN
)
763 ic
->ic_fragthreshold
= len
;
764 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
766 case WI_RID_IFACE_STATS
:
769 case WI_RID_SCAN_REQ
: /* XXX wicontrol */
770 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
772 error
= ieee80211_setupscan(ic
, ic
->ic_chan_avail
);
774 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
776 case WI_RID_SCAN_APS
:
777 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
779 len
--; /* XXX: tx rate? */
781 case WI_RID_CHANNEL_LIST
:
782 memset(chanlist
, 0, sizeof(chanlist
));
784 * Since channel 0 is not available for DS, channel 1
785 * is assigned to LSB on WaveLAN.
787 if (ic
->ic_phytype
== IEEE80211_T_DS
)
791 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++) {
794 if (isclr((uint8_t *)wreq
.wi_val
, j
))
796 if (isclr(ic
->ic_chan_active
, i
)) {
797 if (wreq
.wi_type
!= WI_RID_CHANNEL_LIST
)
799 if (isclr(ic
->ic_chan_avail
, i
))
804 error
= ieee80211_setupscan(ic
, chanlist
);
805 if (wreq
.wi_type
== WI_RID_CHANNEL_LIST
) {
806 /* NB: ignore error from ieee80211_setupscan */
808 } else if (error
== 0)
809 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
815 if (error
== ENETRESET
&& !IS_UP_AUTO(ic
))
824 case IEEE80211_C_WEP
: return IEEE80211_CIPHER_WEP
;
825 case IEEE80211_C_AES
: return IEEE80211_CIPHER_AES_OCB
;
826 case IEEE80211_C_AES_CCM
: return IEEE80211_CIPHER_AES_CCM
;
827 case IEEE80211_C_CKIP
: return IEEE80211_CIPHER_CKIP
;
828 case IEEE80211_C_TKIP
: return IEEE80211_CIPHER_TKIP
;
834 ieee80211_ioctl_getkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
,
837 struct ieee80211_node
*ni
;
838 struct ieee80211req_key ik
;
839 struct ieee80211_key
*wk
;
840 const struct ieee80211_cipher
*cip
;
844 if (ireq
->i_len
!= sizeof(ik
))
846 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
850 if (kid
== IEEE80211_KEYIX_NONE
) {
851 ni
= ieee80211_find_node(&ic
->ic_sta
, ik
.ik_macaddr
);
853 return EINVAL
; /* XXX */
854 wk
= &ni
->ni_ucastkey
;
856 if (kid
>= IEEE80211_WEP_NKID
)
858 wk
= &ic
->ic_nw_keys
[kid
];
859 IEEE80211_ADDR_COPY(&ik
.ik_macaddr
, ic
->ic_bss
->ni_macaddr
);
863 ik
.ik_type
= cip
->ic_cipher
;
864 ik
.ik_keylen
= wk
->wk_keylen
;
865 ik
.ik_flags
= wk
->wk_flags
& (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
);
866 if (wk
->wk_keyix
== ic
->ic_def_txkey
)
867 ik
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
868 if (priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
) == 0) {
869 /* NB: only root can read key data */
870 ik
.ik_keyrsc
= wk
->wk_keyrsc
;
871 ik
.ik_keytsc
= wk
->wk_keytsc
;
872 memcpy(ik
.ik_keydata
, wk
->wk_key
, wk
->wk_keylen
);
873 if (cip
->ic_cipher
== IEEE80211_CIPHER_TKIP
) {
874 memcpy(ik
.ik_keydata
+wk
->wk_keylen
,
875 wk
->wk_key
+ IEEE80211_KEYBUF_SIZE
,
876 IEEE80211_MICBUF_SIZE
);
877 ik
.ik_keylen
+= IEEE80211_MICBUF_SIZE
;
882 memset(ik
.ik_keydata
, 0, sizeof(ik
.ik_keydata
));
885 ieee80211_free_node(ni
);
886 return copyout(&ik
, ireq
->i_data
, sizeof(ik
));
890 ieee80211_ioctl_getchanlist(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
893 if (sizeof(ic
->ic_chan_active
) < ireq
->i_len
)
894 ireq
->i_len
= sizeof(ic
->ic_chan_active
);
895 return copyout(&ic
->ic_chan_active
, ireq
->i_data
, ireq
->i_len
);
899 ieee80211_ioctl_getchaninfo(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
901 struct ieee80211req_chaninfo chans
; /* XXX off stack? */
905 * Since channel 0 is not available for DS, channel 1
906 * is assigned to LSB on WaveLAN.
908 if (ic
->ic_phytype
== IEEE80211_T_DS
)
912 memset(&chans
, 0, sizeof(chans
));
913 for (; i
<= IEEE80211_CHAN_MAX
; i
++)
914 if (isset(ic
->ic_chan_avail
, i
)) {
915 struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
916 chans
.ic_chans
[chans
.ic_nchans
].ic_freq
= c
->ic_freq
;
917 chans
.ic_chans
[chans
.ic_nchans
].ic_flags
= c
->ic_flags
;
920 space
= __offsetof(struct ieee80211req_chaninfo
,
921 ic_chans
[chans
.ic_nchans
]);
922 if (space
> ireq
->i_len
)
924 return copyout(&chans
, ireq
->i_data
, space
);
928 ieee80211_ioctl_getwpaie(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
930 struct ieee80211_node
*ni
;
931 struct ieee80211req_wpaie wpaie
;
934 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
936 error
= copyin(ireq
->i_data
, wpaie
.wpa_macaddr
, IEEE80211_ADDR_LEN
);
939 ni
= ieee80211_find_node(&ic
->ic_sta
, wpaie
.wpa_macaddr
);
941 return EINVAL
; /* XXX */
942 memset(wpaie
.wpa_ie
, 0, sizeof(wpaie
.wpa_ie
));
943 if (ni
->ni_wpa_ie
!= NULL
) {
944 int ielen
= ni
->ni_wpa_ie
[1] + 2;
945 if (ielen
> sizeof(wpaie
.wpa_ie
))
946 ielen
= sizeof(wpaie
.wpa_ie
);
947 memcpy(wpaie
.wpa_ie
, ni
->ni_wpa_ie
, ielen
);
949 ieee80211_free_node(ni
);
950 if (ireq
->i_len
> sizeof(wpaie
))
951 ireq
->i_len
= sizeof(wpaie
);
952 return copyout(&wpaie
, ireq
->i_data
, ireq
->i_len
);
956 ieee80211_ioctl_getstastats(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
958 struct ieee80211_node
*ni
;
959 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
960 const int off
= __offsetof(struct ieee80211req_sta_stats
, is_stats
);
963 if (ireq
->i_len
< off
)
965 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
968 ni
= ieee80211_find_node(&ic
->ic_sta
, macaddr
);
970 /* XXX special-case sta-mode until bss is node in ic_sta */
971 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
973 ni
= ieee80211_ref_node(ic
->ic_bss
);
975 if (ireq
->i_len
> sizeof(struct ieee80211req_sta_stats
))
976 ireq
->i_len
= sizeof(struct ieee80211req_sta_stats
);
977 /* NB: copy out only the statistics */
978 error
= copyout(&ni
->ni_stats
, (uint8_t *) ireq
->i_data
+ off
,
980 ieee80211_free_node(ni
);
985 get_scan_result(struct ieee80211req_scan_result
*sr
,
986 const struct ieee80211_node
*ni
)
988 struct ieee80211com
*ic
= ni
->ni_ic
;
991 memset(sr
, 0, sizeof(*sr
));
992 sr
->isr_ssid_len
= ni
->ni_esslen
;
993 if (ni
->ni_wpa_ie
!= NULL
)
994 ielen
+= 2+ni
->ni_wpa_ie
[1];
995 if (ni
->ni_wme_ie
!= NULL
)
996 ielen
+= 2+ni
->ni_wme_ie
[1];
999 * The value sr->isr_ie_len is defined as a uint8_t, so we
1000 * need to be careful to avoid an integer overflow. If the
1001 * value would overflow, we will set isr_ie_len to zero, and
1002 * ieee80211_ioctl_getscanresults (below) will avoid copying
1003 * the (overflowing) data.
1007 sr
->isr_ie_len
= ielen
;
1008 sr
->isr_len
= sizeof(*sr
) + sr
->isr_ssid_len
+ sr
->isr_ie_len
;
1009 sr
->isr_len
= roundup(sr
->isr_len
, sizeof(uint32_t));
1010 if (ni
->ni_chan
!= IEEE80211_CHAN_ANYC
) {
1011 sr
->isr_freq
= ni
->ni_chan
->ic_freq
;
1012 sr
->isr_flags
= ni
->ni_chan
->ic_flags
;
1014 sr
->isr_rssi
= ic
->ic_node_getrssi(ni
);
1015 sr
->isr_intval
= ni
->ni_intval
;
1016 sr
->isr_capinfo
= ni
->ni_capinfo
; /* deprecated */
1017 sr
->isr_capinfo2
= ni
->ni_capinfo
;
1018 sr
->isr_erp
= ni
->ni_erp
;
1019 IEEE80211_ADDR_COPY(sr
->isr_bssid
, ni
->ni_bssid
);
1020 sr
->isr_nrates
= ni
->ni_rates
.rs_nrates
;
1021 if (sr
->isr_nrates
> 15)
1022 sr
->isr_nrates
= 15;
1023 memcpy(sr
->isr_rates
, ni
->ni_rates
.rs_rates
, sr
->isr_nrates
);
1027 ieee80211_ioctl_getscanresults(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1030 struct ieee80211req_scan_result res
;
1031 char data
[512]; /* XXX shrink? */
1033 struct ieee80211req_scan_result
*sr
= &u
.res
;
1034 struct ieee80211_node_table
*nt
;
1035 struct ieee80211_node
*ni
;
1040 space
= ireq
->i_len
;
1044 TAILQ_FOREACH(ni
, &nt
->nt_node
, ni_list
) {
1045 /* NB: skip pre-scan node state */
1046 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
)
1048 get_scan_result(sr
, ni
);
1049 if (sr
->isr_len
> sizeof(u
))
1051 if (space
< sr
->isr_len
)
1053 cp
= (uint8_t *)(sr
+1);
1054 memcpy(cp
, ni
->ni_essid
, ni
->ni_esslen
);
1055 cp
+= ni
->ni_esslen
;
1056 if (sr
->isr_ie_len
> 0 && ni
->ni_wpa_ie
!= NULL
) {
1057 memcpy(cp
, ni
->ni_wpa_ie
, 2+ni
->ni_wpa_ie
[1]);
1058 cp
+= 2+ni
->ni_wpa_ie
[1];
1060 if (sr
->isr_ie_len
> 0 && ni
->ni_wme_ie
!= NULL
) {
1061 memcpy(cp
, ni
->ni_wme_ie
, 2+ni
->ni_wme_ie
[1]);
1062 cp
+= 2+ni
->ni_wme_ie
[1];
1064 error
= copyout(sr
, p
, sr
->isr_len
);
1068 space
-= sr
->isr_len
;
1070 ireq
->i_len
-= space
;
1075 struct ieee80211com
*ic
;
1076 struct ieee80211req_sta_info
*si
;
1081 sta_space(const struct ieee80211_node
*ni
, size_t *ielen
)
1084 if (ni
->ni_wpa_ie
!= NULL
)
1085 *ielen
+= 2+ni
->ni_wpa_ie
[1];
1086 if (ni
->ni_wme_ie
!= NULL
)
1087 *ielen
+= 2+ni
->ni_wme_ie
[1];
1088 return roundup(sizeof(struct ieee80211req_sta_info
) + *ielen
,
1093 get_sta_space(void *arg
, struct ieee80211_node
*ni
)
1095 struct stainforeq
*req
= arg
;
1096 struct ieee80211com
*ic
= ni
->ni_ic
;
1099 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
1100 ni
->ni_associd
== 0) /* only associated stations */
1102 req
->space
+= sta_space(ni
, &ielen
);
1106 get_sta_info(void *arg
, struct ieee80211_node
*ni
)
1108 struct stainforeq
*req
= arg
;
1109 struct ieee80211com
*ic
= ni
->ni_ic
;
1110 struct ieee80211req_sta_info
*si
;
1114 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
1115 ni
->ni_associd
== 0) /* only associated stations */
1117 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
) /* XXX bogus entry */
1119 len
= sta_space(ni
, &ielen
);
1120 if (len
> req
->space
)
1124 si
->isi_ie_len
= ielen
;
1125 si
->isi_freq
= ni
->ni_chan
->ic_freq
;
1126 si
->isi_flags
= ni
->ni_chan
->ic_flags
;
1127 si
->isi_state
= ni
->ni_flags
;
1128 si
->isi_authmode
= ni
->ni_authmode
;
1129 si
->isi_rssi
= ic
->ic_node_getrssi(ni
);
1130 si
->isi_noise
= 0; /* XXX */
1131 si
->isi_capinfo
= ni
->ni_capinfo
; /* deprecated */
1132 si
->isi_capinfo2
= ni
->ni_capinfo
;
1133 si
->isi_erp
= ni
->ni_erp
;
1134 IEEE80211_ADDR_COPY(si
->isi_macaddr
, ni
->ni_macaddr
);
1135 si
->isi_nrates
= ni
->ni_rates
.rs_nrates
;
1136 if (si
->isi_nrates
> 15)
1137 si
->isi_nrates
= 15;
1138 memcpy(si
->isi_rates
, ni
->ni_rates
.rs_rates
, si
->isi_nrates
);
1139 si
->isi_txrate
= ni
->ni_txrate
;
1140 si
->isi_associd
= ni
->ni_associd
;
1141 si
->isi_txpower
= ni
->ni_txpower
;
1142 si
->isi_vlan
= ni
->ni_vlan
;
1143 if (ni
->ni_flags
& IEEE80211_NODE_QOS
) {
1144 memcpy(si
->isi_txseqs
, ni
->ni_txseqs
, sizeof(ni
->ni_txseqs
));
1145 memcpy(si
->isi_rxseqs
, ni
->ni_rxseqs
, sizeof(ni
->ni_rxseqs
));
1147 si
->isi_txseqs
[0] = ni
->ni_txseqs
[0];
1148 si
->isi_rxseqs
[0] = ni
->ni_rxseqs
[0];
1150 /* NB: leave all cases in case we relax ni_associd == 0 check */
1151 if (ieee80211_node_is_authorized(ni
))
1152 si
->isi_inact
= ic
->ic_inact_run
;
1153 else if (ni
->ni_associd
!= 0)
1154 si
->isi_inact
= ic
->ic_inact_auth
;
1156 si
->isi_inact
= ic
->ic_inact_init
;
1157 si
->isi_inact
= (si
->isi_inact
- ni
->ni_inact
) * IEEE80211_INACT_WAIT
;
1159 cp
= (uint8_t *)(si
+1);
1160 if (ni
->ni_wpa_ie
!= NULL
) {
1161 memcpy(cp
, ni
->ni_wpa_ie
, 2+ni
->ni_wpa_ie
[1]);
1162 cp
+= 2+ni
->ni_wpa_ie
[1];
1164 if (ni
->ni_wme_ie
!= NULL
) {
1165 memcpy(cp
, ni
->ni_wme_ie
, 2+ni
->ni_wme_ie
[1]);
1166 cp
+= 2+ni
->ni_wme_ie
[1];
1169 req
->si
= (struct ieee80211req_sta_info
*)(((uint8_t *)si
) + len
);
1174 ieee80211_ioctl_getstainfo(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1176 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
1177 const int off
= __offsetof(struct ieee80211req_sta_req
, info
);
1178 struct ieee80211_node
*ni
;
1179 struct stainforeq req
;
1182 if (ireq
->i_len
< sizeof(struct ieee80211req_sta_req
))
1184 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
1187 if (IEEE80211_ADDR_EQ(macaddr
, ic
->ic_ifp
->if_broadcastaddr
)) {
1190 ni
= ieee80211_find_node(&ic
->ic_sta
, macaddr
);
1192 /* XXX special-case sta-mode until bss is in ic_sta */
1193 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
1194 return EINVAL
; /* XXX */
1195 ni
= ieee80211_ref_node(ic
->ic_bss
);
1201 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_space
, &req
);
1203 get_sta_space(&req
, ni
);
1204 if (req
.space
> ireq
->i_len
)
1205 req
.space
= ireq
->i_len
;
1206 if (req
.space
> 0) {
1211 /* XXX M_WAITOK after driver lock released */
1212 p
= kmalloc(space
, M_TEMP
, M_NOWAIT
);
1219 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_info
, &req
);
1221 get_sta_info(&req
, ni
);
1222 ireq
->i_len
= space
- req
.space
;
1223 error
= copyout(p
, (uint8_t *)ireq
->i_data
+ off
, ireq
->i_len
);
1230 ieee80211_free_node(ni
);
1235 ieee80211_ioctl_getstatxpow(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1237 struct ieee80211_node
*ni
;
1238 struct ieee80211req_sta_txpow txpow
;
1241 if (ireq
->i_len
!= sizeof(txpow
))
1243 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1246 ni
= ieee80211_find_node(&ic
->ic_sta
, txpow
.it_macaddr
);
1248 return EINVAL
; /* XXX */
1249 txpow
.it_txpow
= ni
->ni_txpower
;
1250 error
= copyout(&txpow
, ireq
->i_data
, sizeof(txpow
));
1251 ieee80211_free_node(ni
);
1256 ieee80211_ioctl_getwmeparam(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1258 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1259 struct wmeParams
*wmep
;
1262 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1265 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1266 if (ac
>= WME_NUM_AC
)
1268 if (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
)
1269 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1271 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1272 switch (ireq
->i_type
) {
1273 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1274 ireq
->i_val
= wmep
->wmep_logcwmin
;
1276 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1277 ireq
->i_val
= wmep
->wmep_logcwmax
;
1279 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1280 ireq
->i_val
= wmep
->wmep_aifsn
;
1282 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1283 ireq
->i_val
= wmep
->wmep_txopLimit
;
1285 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1286 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1287 ireq
->i_val
= wmep
->wmep_acm
;
1289 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
1290 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1291 ireq
->i_val
= !wmep
->wmep_noackPolicy
;
1298 ieee80211_ioctl_getmaccmd(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1300 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1302 return (acl
== NULL
? EINVAL
: acl
->iac_getioctl(ic
, ireq
));
1306 * When building the kernel with -O2 on the i386 architecture, gcc
1307 * seems to want to inline this function into ieee80211_ioctl()
1308 * (which is the only routine that calls it). When this happens,
1309 * ieee80211_ioctl() ends up consuming an additional 2K of stack
1310 * space. (Exactly why it needs so much is unclear.) The problem
1311 * is that it's possible for ieee80211_ioctl() to invoke other
1312 * routines (including driver init functions) which could then find
1313 * themselves perilously close to exhausting the stack.
1315 * To avoid this, we deliberately prevent gcc from inlining this
1316 * routine. Another way to avoid this is to use less agressive
1317 * optimization when compiling this file (i.e. -O instead of -O2)
1318 * but special-casing the compilation of this one module in the
1319 * build system would be awkward.
1322 __attribute__ ((noinline
))
1325 ieee80211_ioctl_get80211(struct ieee80211com
*ic
, u_long cmd
,
1326 struct ieee80211req
*ireq
, struct ucred
*cr
)
1328 const struct ieee80211_rsnparms
*rsn
= &ic
->ic_bss
->ni_rsn
;
1331 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
1332 char tmpssid
[IEEE80211_NWID_LEN
];
1334 switch (ireq
->i_type
) {
1335 case IEEE80211_IOC_SSID
:
1336 switch (ic
->ic_state
) {
1337 case IEEE80211_S_INIT
:
1338 case IEEE80211_S_SCAN
:
1339 ireq
->i_len
= ic
->ic_des_esslen
;
1340 memcpy(tmpssid
, ic
->ic_des_essid
, ireq
->i_len
);
1343 ireq
->i_len
= ic
->ic_bss
->ni_esslen
;
1344 memcpy(tmpssid
, ic
->ic_bss
->ni_essid
,
1348 error
= copyout(tmpssid
, ireq
->i_data
, ireq
->i_len
);
1350 case IEEE80211_IOC_NUMSSIDS
:
1353 case IEEE80211_IOC_WEP
:
1354 if ((ic
->ic_flags
& IEEE80211_F_PRIVACY
) == 0)
1355 ireq
->i_val
= IEEE80211_WEP_OFF
;
1356 else if (ic
->ic_flags
& IEEE80211_F_DROPUNENC
)
1357 ireq
->i_val
= IEEE80211_WEP_ON
;
1359 ireq
->i_val
= IEEE80211_WEP_MIXED
;
1361 case IEEE80211_IOC_WEPKEY
:
1362 kid
= (u_int
) ireq
->i_val
;
1363 if (kid
>= IEEE80211_WEP_NKID
)
1365 len
= (u_int
) ic
->ic_nw_keys
[kid
].wk_keylen
;
1366 /* NB: only root can read WEP keys */
1367 if (priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
) == 0) {
1368 bcopy(ic
->ic_nw_keys
[kid
].wk_key
, tmpkey
, len
);
1373 error
= copyout(tmpkey
, ireq
->i_data
, len
);
1375 case IEEE80211_IOC_NUMWEPKEYS
:
1376 ireq
->i_val
= IEEE80211_WEP_NKID
;
1378 case IEEE80211_IOC_WEPTXKEY
:
1379 ireq
->i_val
= ic
->ic_def_txkey
;
1381 case IEEE80211_IOC_AUTHMODE
:
1382 if (ic
->ic_flags
& IEEE80211_F_WPA
)
1383 ireq
->i_val
= IEEE80211_AUTH_WPA
;
1385 ireq
->i_val
= ic
->ic_bss
->ni_authmode
;
1387 case IEEE80211_IOC_CHANNEL
:
1388 ireq
->i_val
= ieee80211_chan2ieee(ic
, ic
->ic_curchan
);
1390 case IEEE80211_IOC_POWERSAVE
:
1391 if (ic
->ic_flags
& IEEE80211_F_PMGTON
)
1392 ireq
->i_val
= IEEE80211_POWERSAVE_ON
;
1394 ireq
->i_val
= IEEE80211_POWERSAVE_OFF
;
1396 case IEEE80211_IOC_POWERSAVESLEEP
:
1397 ireq
->i_val
= ic
->ic_lintval
;
1399 case IEEE80211_IOC_RTSTHRESHOLD
:
1400 ireq
->i_val
= ic
->ic_rtsthreshold
;
1402 case IEEE80211_IOC_PROTMODE
:
1403 ireq
->i_val
= ic
->ic_protmode
;
1405 case IEEE80211_IOC_TXPOWER
:
1406 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
1408 ireq
->i_val
= ic
->ic_txpowlimit
;
1410 case IEEE80211_IOC_MCASTCIPHER
:
1411 ireq
->i_val
= rsn
->rsn_mcastcipher
;
1413 case IEEE80211_IOC_MCASTKEYLEN
:
1414 ireq
->i_val
= rsn
->rsn_mcastkeylen
;
1416 case IEEE80211_IOC_UCASTCIPHERS
:
1418 for (m
= 0x1; m
!= 0; m
<<= 1)
1419 if (rsn
->rsn_ucastcipherset
& m
)
1420 ireq
->i_val
|= 1<<cap2cipher(m
);
1422 case IEEE80211_IOC_UCASTCIPHER
:
1423 ireq
->i_val
= rsn
->rsn_ucastcipher
;
1425 case IEEE80211_IOC_UCASTKEYLEN
:
1426 ireq
->i_val
= rsn
->rsn_ucastkeylen
;
1428 case IEEE80211_IOC_KEYMGTALGS
:
1429 ireq
->i_val
= rsn
->rsn_keymgmtset
;
1431 case IEEE80211_IOC_RSNCAPS
:
1432 ireq
->i_val
= rsn
->rsn_caps
;
1434 case IEEE80211_IOC_WPA
:
1435 switch (ic
->ic_flags
& IEEE80211_F_WPA
) {
1436 case IEEE80211_F_WPA1
:
1439 case IEEE80211_F_WPA2
:
1442 case IEEE80211_F_WPA1
| IEEE80211_F_WPA2
:
1450 case IEEE80211_IOC_CHANLIST
:
1451 error
= ieee80211_ioctl_getchanlist(ic
, ireq
);
1453 case IEEE80211_IOC_ROAMING
:
1454 ireq
->i_val
= ic
->ic_roaming
;
1456 case IEEE80211_IOC_PRIVACY
:
1457 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_PRIVACY
) != 0;
1459 case IEEE80211_IOC_DROPUNENCRYPTED
:
1460 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_DROPUNENC
) != 0;
1462 case IEEE80211_IOC_COUNTERMEASURES
:
1463 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_COUNTERM
) != 0;
1465 case IEEE80211_IOC_DRIVER_CAPS
:
1466 if (ireq
->i_len
>= sizeof(ic
->ic_caps_ext
)) {
1467 error
= copyout(&ic
->ic_caps_ext
, ireq
->i_data
,
1468 sizeof(ic
->ic_caps_ext
));
1471 ireq
->i_val
= ic
->ic_caps
>> 16;
1472 ireq
->i_len
= ic
->ic_caps
& 0xffff;
1475 case IEEE80211_IOC_WME
:
1476 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_WME
) != 0;
1478 case IEEE80211_IOC_HIDESSID
:
1479 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_HIDESSID
) != 0;
1481 case IEEE80211_IOC_APBRIDGE
:
1482 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_NOBRIDGE
) == 0;
1484 case IEEE80211_IOC_OPTIE
:
1485 if (ic
->ic_opt_ie
== NULL
)
1487 /* NB: truncate, caller can check length */
1488 if (ireq
->i_len
> ic
->ic_opt_ie_len
)
1489 ireq
->i_len
= ic
->ic_opt_ie_len
;
1490 error
= copyout(ic
->ic_opt_ie
, ireq
->i_data
, ireq
->i_len
);
1492 case IEEE80211_IOC_WPAKEY
:
1493 error
= ieee80211_ioctl_getkey(ic
, ireq
, cr
);
1495 case IEEE80211_IOC_CHANINFO
:
1496 error
= ieee80211_ioctl_getchaninfo(ic
, ireq
);
1498 case IEEE80211_IOC_BSSID
:
1499 if (ireq
->i_len
!= IEEE80211_ADDR_LEN
)
1501 error
= copyout(ic
->ic_state
== IEEE80211_S_RUN
?
1502 ic
->ic_bss
->ni_bssid
:
1504 ireq
->i_data
, ireq
->i_len
);
1506 case IEEE80211_IOC_WPAIE
:
1507 error
= ieee80211_ioctl_getwpaie(ic
, ireq
);
1509 case IEEE80211_IOC_SCAN_RESULTS
:
1510 error
= ieee80211_ioctl_getscanresults(ic
, ireq
);
1512 case IEEE80211_IOC_STA_STATS
:
1513 error
= ieee80211_ioctl_getstastats(ic
, ireq
);
1515 case IEEE80211_IOC_TXPOWMAX
:
1516 ireq
->i_val
= ic
->ic_bss
->ni_txpower
;
1518 case IEEE80211_IOC_STA_TXPOW
:
1519 error
= ieee80211_ioctl_getstatxpow(ic
, ireq
);
1521 case IEEE80211_IOC_STA_INFO
:
1522 error
= ieee80211_ioctl_getstainfo(ic
, ireq
);
1524 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1525 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1526 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1527 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1528 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1529 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
1530 error
= ieee80211_ioctl_getwmeparam(ic
, ireq
);
1532 case IEEE80211_IOC_DTIM_PERIOD
:
1533 ireq
->i_val
= ic
->ic_dtim_period
;
1535 case IEEE80211_IOC_BEACON_INTERVAL
:
1536 /* NB: get from ic_bss for station mode */
1537 ireq
->i_val
= ic
->ic_bss
->ni_intval
;
1539 case IEEE80211_IOC_PUREG
:
1540 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_PUREG
) != 0;
1542 case IEEE80211_IOC_MCAST_RATE
:
1543 ireq
->i_val
= ic
->ic_mcast_rate
;
1545 case IEEE80211_IOC_FRAGTHRESHOLD
:
1546 ireq
->i_val
= ic
->ic_fragthreshold
;
1548 case IEEE80211_IOC_MACCMD
:
1549 error
= ieee80211_ioctl_getmaccmd(ic
, ireq
);
1551 case IEEE80211_IOC_BURST
:
1552 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_BURST
) != 0;
1554 case IEEE80211_IOC_RATECTL
:
1555 ireq
->i_val
= ic
->ic_ratectl
.rc_st_ratectl
;
1557 case IEEE80211_IOC_BMISSTHRESHOLD
:
1558 ireq
->i_val
= ic
->ic_bmissthreshold
;
1568 ieee80211_ioctl_setoptie(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1574 * NB: Doing this for ap operation could be useful (e.g. for
1575 * WPA and/or WME) except that it typically is worthless
1576 * without being able to intervene when processing
1577 * association response frames--so disallow it for now.
1579 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
1581 if (ireq
->i_len
> IEEE80211_MAX_OPT_IE
)
1583 if (ireq
->i_len
> 0) {
1584 ie
= kmalloc(ireq
->i_len
, M_DEVBUF
, M_NOWAIT
);
1587 error
= copyin(ireq
->i_data
, ie
, ireq
->i_len
);
1589 kfree(ie
, M_DEVBUF
);
1596 /* XXX sanity check data? */
1597 oie
= ic
->ic_opt_ie
;
1599 ic
->ic_opt_ie_len
= ireq
->i_len
;
1601 kfree(oie
, M_DEVBUF
);
1606 ieee80211_ioctl_setkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1608 struct ieee80211req_key ik
;
1609 struct ieee80211_node
*ni
;
1610 struct ieee80211_key
*wk
;
1614 if (ireq
->i_len
!= sizeof(ik
))
1616 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
1619 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1620 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1621 if (ik
.ik_keylen
> sizeof(ik
.ik_keydata
))
1624 if (kid
== IEEE80211_KEYIX_NONE
) {
1625 /* XXX unicast keys currently must be tx/rx */
1626 if (ik
.ik_flags
!= (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
))
1628 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
1629 ni
= ieee80211_ref_node(ic
->ic_bss
);
1630 if (!IEEE80211_ADDR_EQ(ik
.ik_macaddr
, ni
->ni_bssid
)) {
1631 ieee80211_free_node(ni
);
1632 return EADDRNOTAVAIL
;
1635 ni
= ieee80211_find_node(&ic
->ic_sta
, ik
.ik_macaddr
);
1639 wk
= &ni
->ni_ucastkey
;
1641 if (kid
>= IEEE80211_WEP_NKID
)
1643 wk
= &ic
->ic_nw_keys
[kid
];
1645 * Global slots start off w/o any assigned key index.
1646 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1648 if (wk
->wk_keyix
== IEEE80211_KEYIX_NONE
)
1653 ieee80211_key_update_begin(ic
);
1654 if (ieee80211_crypto_newkey(ic
, ik
.ik_type
, ik
.ik_flags
, wk
)) {
1655 wk
->wk_keylen
= ik
.ik_keylen
;
1656 /* NB: MIC presence is implied by cipher type */
1657 if (wk
->wk_keylen
> IEEE80211_KEYBUF_SIZE
)
1658 wk
->wk_keylen
= IEEE80211_KEYBUF_SIZE
;
1659 wk
->wk_keyrsc
= ik
.ik_keyrsc
;
1660 wk
->wk_keytsc
= 0; /* new key, reset */
1661 memset(wk
->wk_key
, 0, sizeof(wk
->wk_key
));
1662 memcpy(wk
->wk_key
, ik
.ik_keydata
, ik
.ik_keylen
);
1663 if (!ieee80211_crypto_setkey(ic
, wk
,
1664 ni
!= NULL
? ni
->ni_macaddr
: ik
.ik_macaddr
))
1666 else if ((ik
.ik_flags
& IEEE80211_KEY_DEFAULT
))
1667 ic
->ic_def_txkey
= kid
;
1670 ieee80211_key_update_end(ic
);
1672 ieee80211_free_node(ni
);
1677 ieee80211_ioctl_delkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1679 struct ieee80211req_del_key dk
;
1682 if (ireq
->i_len
!= sizeof(dk
))
1684 error
= copyin(ireq
->i_data
, &dk
, sizeof(dk
));
1688 /* XXX uint8_t -> uint16_t */
1689 if (dk
.idk_keyix
== (uint8_t)IEEE80211_KEYIX_NONE
) {
1690 struct ieee80211_node
*ni
;
1692 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
1693 ni
= ieee80211_ref_node(ic
->ic_bss
);
1694 if (!IEEE80211_ADDR_EQ(dk
.idk_macaddr
, ni
->ni_bssid
)) {
1695 ieee80211_free_node(ni
);
1696 return EADDRNOTAVAIL
;
1699 ni
= ieee80211_find_node(&ic
->ic_sta
, dk
.idk_macaddr
);
1703 /* XXX error return */
1704 ieee80211_node_delucastkey(ni
);
1705 ieee80211_free_node(ni
);
1707 if (kid
>= IEEE80211_WEP_NKID
)
1709 /* XXX error return */
1710 ieee80211_crypto_delkey(ic
, &ic
->ic_nw_keys
[kid
]);
1716 domlme(void *arg
, struct ieee80211_node
*ni
)
1718 struct ieee80211com
*ic
= ni
->ni_ic
;
1719 struct ieee80211req_mlme
*mlme
= arg
;
1721 if (ni
->ni_associd
!= 0) {
1722 IEEE80211_SEND_MGMT(ic
, ni
,
1723 mlme
->im_op
== IEEE80211_MLME_DEAUTH
?
1724 IEEE80211_FC0_SUBTYPE_DEAUTH
:
1725 IEEE80211_FC0_SUBTYPE_DISASSOC
,
1728 ieee80211_node_leave(ic
, ni
);
1732 ieee80211_ioctl_setmlme(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1734 struct ieee80211req_mlme mlme
;
1735 struct ieee80211_node
*ni
;
1738 if (ireq
->i_len
!= sizeof(mlme
))
1740 error
= copyin(ireq
->i_data
, &mlme
, sizeof(mlme
));
1743 switch (mlme
.im_op
) {
1744 case IEEE80211_MLME_ASSOC
:
1745 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
1747 /* XXX must be in S_SCAN state? */
1749 if (mlme
.im_ssid_len
!= 0) {
1751 * Desired ssid specified; must match both bssid and
1752 * ssid to distinguish ap advertising multiple ssid's.
1754 ni
= ieee80211_find_node_with_ssid(&ic
->ic_scan
,
1756 mlme
.im_ssid_len
, mlme
.im_ssid
);
1759 * Normal case; just match bssid.
1761 ni
= ieee80211_find_node(&ic
->ic_scan
, mlme
.im_macaddr
);
1765 if (!ieee80211_sta_join(ic
, ni
)) {
1766 ieee80211_free_node(ni
);
1770 case IEEE80211_MLME_DISASSOC
:
1771 case IEEE80211_MLME_DEAUTH
:
1772 switch (ic
->ic_opmode
) {
1773 case IEEE80211_M_STA
:
1774 /* XXX not quite right */
1775 ieee80211_new_state(ic
, IEEE80211_S_INIT
,
1778 case IEEE80211_M_HOSTAP
:
1779 /* NB: the broadcast address means do 'em all */
1780 if (!IEEE80211_ADDR_EQ(mlme
.im_macaddr
, ic
->ic_ifp
->if_broadcastaddr
)) {
1781 if ((ni
= ieee80211_find_node(&ic
->ic_sta
,
1782 mlme
.im_macaddr
)) == NULL
)
1785 ieee80211_free_node(ni
);
1787 ieee80211_iterate_nodes(&ic
->ic_sta
,
1795 case IEEE80211_MLME_AUTHORIZE
:
1796 case IEEE80211_MLME_UNAUTHORIZE
:
1797 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
1799 ni
= ieee80211_find_node(&ic
->ic_sta
, mlme
.im_macaddr
);
1802 if (mlme
.im_op
== IEEE80211_MLME_AUTHORIZE
)
1803 ieee80211_node_authorize(ni
);
1805 ieee80211_node_unauthorize(ni
);
1806 ieee80211_free_node(ni
);
1815 ieee80211_ioctl_macmac(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1817 uint8_t mac
[IEEE80211_ADDR_LEN
];
1818 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1821 if (ireq
->i_len
!= sizeof(mac
))
1823 error
= copyin(ireq
->i_data
, mac
, ireq
->i_len
);
1827 acl
= ieee80211_aclator_get("mac");
1828 if (acl
== NULL
|| !acl
->iac_attach(ic
))
1832 if (ireq
->i_type
== IEEE80211_IOC_ADDMAC
)
1833 acl
->iac_add(ic
, mac
);
1835 acl
->iac_remove(ic
, mac
);
1840 ieee80211_ioctl_setmaccmd(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1842 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1844 switch (ireq
->i_val
) {
1845 case IEEE80211_MACCMD_POLICY_OPEN
:
1846 case IEEE80211_MACCMD_POLICY_ALLOW
:
1847 case IEEE80211_MACCMD_POLICY_DENY
:
1849 acl
= ieee80211_aclator_get("mac");
1850 if (acl
== NULL
|| !acl
->iac_attach(ic
))
1854 acl
->iac_setpolicy(ic
, ireq
->i_val
);
1856 case IEEE80211_MACCMD_FLUSH
:
1859 /* NB: silently ignore when not in use */
1861 case IEEE80211_MACCMD_DETACH
:
1864 acl
->iac_detach(ic
);
1871 return acl
->iac_setioctl(ic
, ireq
);
1877 ieee80211_ioctl_setchanlist(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1879 struct ieee80211req_chanlist list
;
1880 u_char chanlist
[IEEE80211_CHAN_BYTES
];
1883 if (ireq
->i_len
!= sizeof(list
))
1885 error
= copyin(ireq
->i_data
, &list
, sizeof(list
));
1888 memset(chanlist
, 0, sizeof(chanlist
));
1890 * Since channel 0 is not available for DS, channel 1
1891 * is assigned to LSB on WaveLAN.
1893 if (ic
->ic_phytype
== IEEE80211_T_DS
)
1897 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++) {
1899 * NB: silently discard unavailable channels so users
1900 * can specify 1-255 to get all available channels.
1902 if (isset(list
.ic_channels
, j
) && isset(ic
->ic_chan_avail
, i
))
1903 setbit(chanlist
, i
);
1905 if (ic
->ic_ibss_chan
== NULL
||
1906 isclr(chanlist
, ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
))) {
1907 for (i
= 0; i
<= IEEE80211_CHAN_MAX
; i
++)
1908 if (isset(chanlist
, i
)) {
1909 ic
->ic_ibss_chan
= &ic
->ic_channels
[i
];
1912 return EINVAL
; /* no active channels */
1916 memcpy(ic
->ic_chan_active
, chanlist
, sizeof(ic
->ic_chan_active
));
1917 return IS_UP_AUTO(ic
) ? ENETRESET
: 0;
1921 ieee80211_ioctl_setstastats(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1923 struct ieee80211_node
*ni
;
1924 uint8_t macaddr
[IEEE80211_ADDR_LEN
];
1928 * NB: we could copyin ieee80211req_sta_stats so apps
1929 * could make selective changes but that's overkill;
1930 * just clear all stats for now.
1932 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
1934 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
1937 ni
= ieee80211_find_node(&ic
->ic_sta
, macaddr
);
1939 return EINVAL
; /* XXX */
1940 memset(&ni
->ni_stats
, 0, sizeof(ni
->ni_stats
));
1941 ieee80211_free_node(ni
);
1946 ieee80211_ioctl_setstatxpow(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1948 struct ieee80211_node
*ni
;
1949 struct ieee80211req_sta_txpow txpow
;
1952 if (ireq
->i_len
!= sizeof(txpow
))
1954 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1957 ni
= ieee80211_find_node(&ic
->ic_sta
, txpow
.it_macaddr
);
1959 return EINVAL
; /* XXX */
1960 ni
->ni_txpower
= txpow
.it_txpow
;
1961 ieee80211_free_node(ni
);
1966 ieee80211_ioctl_setwmeparam(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1968 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1969 struct wmeParams
*wmep
, *chanp
;
1972 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1975 isbss
= (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
);
1976 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1977 if (ac
>= WME_NUM_AC
)
1980 chanp
= &wme
->wme_bssChanParams
.cap_wmeParams
[ac
];
1981 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1983 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[ac
];
1984 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1986 switch (ireq
->i_type
) {
1987 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1989 wmep
->wmep_logcwmin
= ireq
->i_val
;
1990 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1991 chanp
->wmep_logcwmin
= ireq
->i_val
;
1993 wmep
->wmep_logcwmin
= chanp
->wmep_logcwmin
=
1997 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1999 wmep
->wmep_logcwmax
= ireq
->i_val
;
2000 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2001 chanp
->wmep_logcwmax
= ireq
->i_val
;
2003 wmep
->wmep_logcwmax
= chanp
->wmep_logcwmax
=
2007 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
2009 wmep
->wmep_aifsn
= ireq
->i_val
;
2010 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2011 chanp
->wmep_aifsn
= ireq
->i_val
;
2013 wmep
->wmep_aifsn
= chanp
->wmep_aifsn
= ireq
->i_val
;
2016 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
2018 wmep
->wmep_txopLimit
= ireq
->i_val
;
2019 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2020 chanp
->wmep_txopLimit
= ireq
->i_val
;
2022 wmep
->wmep_txopLimit
= chanp
->wmep_txopLimit
=
2026 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
2027 wmep
->wmep_acm
= ireq
->i_val
;
2028 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2029 chanp
->wmep_acm
= ireq
->i_val
;
2031 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
2032 wmep
->wmep_noackPolicy
= chanp
->wmep_noackPolicy
=
2036 ieee80211_wme_updateparams(ic
);
2041 cipher2cap(int cipher
)
2044 case IEEE80211_CIPHER_WEP
: return IEEE80211_C_WEP
;
2045 case IEEE80211_CIPHER_AES_OCB
: return IEEE80211_C_AES
;
2046 case IEEE80211_CIPHER_AES_CCM
: return IEEE80211_C_AES_CCM
;
2047 case IEEE80211_CIPHER_CKIP
: return IEEE80211_C_CKIP
;
2048 case IEEE80211_CIPHER_TKIP
: return IEEE80211_C_TKIP
;
2054 ieee80211_ioctl_set80211(struct ieee80211com
*ic
, u_long cmd
, struct ieee80211req
*ireq
)
2056 static const uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
2057 struct ieee80211_rsnparms
*rsn
= &ic
->ic_bss
->ni_rsn
;
2059 const struct ieee80211_authenticator
*auth
;
2060 uint8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
2061 char tmpssid
[IEEE80211_NWID_LEN
];
2062 uint8_t tmpbssid
[IEEE80211_ADDR_LEN
];
2063 struct ieee80211_key
*k
;
2068 switch (ireq
->i_type
) {
2069 case IEEE80211_IOC_SSID
:
2070 if (ireq
->i_val
!= 0 ||
2071 ireq
->i_len
> IEEE80211_NWID_LEN
)
2073 error
= copyin(ireq
->i_data
, tmpssid
, ireq
->i_len
);
2076 memset(ic
->ic_des_essid
, 0, IEEE80211_NWID_LEN
);
2077 ic
->ic_des_esslen
= ireq
->i_len
;
2078 memcpy(ic
->ic_des_essid
, tmpssid
, ireq
->i_len
);
2081 case IEEE80211_IOC_WEP
:
2082 switch (ireq
->i_val
) {
2083 case IEEE80211_WEP_OFF
:
2084 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
2085 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2087 case IEEE80211_WEP_ON
:
2088 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2089 ic
->ic_flags
|= IEEE80211_F_DROPUNENC
;
2091 case IEEE80211_WEP_MIXED
:
2092 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2093 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2098 case IEEE80211_IOC_WEPKEY
:
2099 kid
= (u_int
)ireq
->i_val
;
2100 if (kid
>= IEEE80211_WEP_NKID
)
2102 k
= &ic
->ic_nw_keys
[kid
];
2103 if (ireq
->i_len
== 0) {
2104 /* zero-len =>'s delete any existing key */
2105 ieee80211_crypto_delkey(ic
, k
);
2108 if (ireq
->i_len
> sizeof(tmpkey
))
2110 memset(tmpkey
, 0, sizeof(tmpkey
));
2111 error
= copyin(ireq
->i_data
, tmpkey
, ireq
->i_len
);
2114 ieee80211_key_update_begin(ic
);
2115 k
->wk_keyix
= kid
; /* NB: force fixed key id */
2116 if (ieee80211_crypto_newkey(ic
, IEEE80211_CIPHER_WEP
,
2117 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, k
)) {
2118 k
->wk_keylen
= ireq
->i_len
;
2119 memcpy(k
->wk_key
, tmpkey
, sizeof(tmpkey
));
2120 if (!ieee80211_crypto_setkey(ic
, k
, ic
->ic_myaddr
))
2124 ieee80211_key_update_end(ic
);
2125 if (!error
) /* NB: for compatibility */
2128 case IEEE80211_IOC_WEPTXKEY
:
2129 kid
= (u_int
) ireq
->i_val
;
2130 if (kid
>= IEEE80211_WEP_NKID
&&
2131 (uint16_t) kid
!= IEEE80211_KEYIX_NONE
)
2133 ic
->ic_def_txkey
= kid
;
2134 error
= ENETRESET
; /* push to hardware */
2136 case IEEE80211_IOC_AUTHMODE
:
2137 switch (ireq
->i_val
) {
2138 case IEEE80211_AUTH_WPA
:
2139 case IEEE80211_AUTH_8021X
: /* 802.1x */
2140 case IEEE80211_AUTH_OPEN
: /* open */
2141 case IEEE80211_AUTH_SHARED
: /* shared-key */
2142 case IEEE80211_AUTH_AUTO
: /* auto */
2143 auth
= ieee80211_authenticator_get(ireq
->i_val
);
2150 switch (ireq
->i_val
) {
2151 case IEEE80211_AUTH_WPA
: /* WPA w/ 802.1x */
2152 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2153 ireq
->i_val
= IEEE80211_AUTH_8021X
;
2155 case IEEE80211_AUTH_OPEN
: /* open */
2156 ic
->ic_flags
&= ~(IEEE80211_F_WPA
|IEEE80211_F_PRIVACY
);
2158 case IEEE80211_AUTH_SHARED
: /* shared-key */
2159 case IEEE80211_AUTH_8021X
: /* 802.1x */
2160 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2161 /* both require a key so mark the PRIVACY capability */
2162 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2164 case IEEE80211_AUTH_AUTO
: /* auto */
2165 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2166 /* XXX PRIVACY handling? */
2167 /* XXX what's the right way to do this? */
2170 /* NB: authenticator attach/detach happens on state change */
2171 ic
->ic_bss
->ni_authmode
= ireq
->i_val
;
2172 /* XXX mixed/mode/usage? */
2176 case IEEE80211_IOC_CHANNEL
:
2177 /* XXX 0xffff overflows 16-bit signed */
2178 if (ireq
->i_val
== 0 ||
2179 ireq
->i_val
== (int16_t) IEEE80211_CHAN_ANY
)
2180 ic
->ic_des_chan
= IEEE80211_CHAN_ANYC
;
2181 else if ((u_int
) ireq
->i_val
> IEEE80211_CHAN_MAX
||
2182 isclr(ic
->ic_chan_active
, ireq
->i_val
)) {
2185 ic
->ic_ibss_chan
= ic
->ic_des_chan
=
2186 &ic
->ic_channels
[ireq
->i_val
];
2187 switch (ic
->ic_state
) {
2188 case IEEE80211_S_INIT
:
2189 case IEEE80211_S_SCAN
:
2194 * If the desired channel has changed (to something
2195 * other than any) and we're not already scanning,
2196 * then kick the state machine.
2198 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
&&
2199 ic
->ic_bss
->ni_chan
!= ic
->ic_des_chan
&&
2200 (ic
->ic_flags
& IEEE80211_F_SCAN
) == 0)
2204 if (error
== ENETRESET
&&
2205 ic
->ic_opmode
== IEEE80211_M_MONITOR
) {
2208 * Monitor mode can switch directly.
2210 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)
2211 ic
->ic_curchan
= ic
->ic_des_chan
;
2212 error
= ic
->ic_reset(ic
->ic_ifp
);
2217 case IEEE80211_IOC_POWERSAVE
:
2218 switch (ireq
->i_val
) {
2219 case IEEE80211_POWERSAVE_OFF
:
2220 if (ic
->ic_flags
& IEEE80211_F_PMGTON
) {
2221 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
2225 case IEEE80211_POWERSAVE_ON
:
2226 if ((ic
->ic_caps
& IEEE80211_C_PMGT
) == 0)
2228 else if ((ic
->ic_flags
& IEEE80211_F_PMGTON
) == 0) {
2229 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
2237 if (error
== ENETRESET
) {
2239 * Switching in+out of power save mode
2240 * should not require a state change.
2242 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2245 case IEEE80211_IOC_POWERSAVESLEEP
:
2246 if (ireq
->i_val
< 0)
2248 ic
->ic_lintval
= ireq
->i_val
;
2249 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2251 case IEEE80211_IOC_RTSTHRESHOLD
:
2252 if (!(IEEE80211_RTS_MIN
<= ireq
->i_val
&&
2253 ireq
->i_val
<= IEEE80211_RTS_MAX
))
2255 ic
->ic_rtsthreshold
= ireq
->i_val
;
2256 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2258 case IEEE80211_IOC_PROTMODE
:
2259 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
2261 ic
->ic_protmode
= ireq
->i_val
;
2262 /* NB: if not operating in 11g this can wait */
2263 if (ic
->ic_curmode
== IEEE80211_MODE_11G
)
2264 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2266 case IEEE80211_IOC_TXPOWER
:
2267 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
2269 if (!(IEEE80211_TXPOWER_MIN
< ireq
->i_val
&&
2270 ireq
->i_val
< IEEE80211_TXPOWER_MAX
))
2272 ic
->ic_txpowlimit
= ireq
->i_val
;
2273 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2275 case IEEE80211_IOC_ROAMING
:
2276 if (!(IEEE80211_ROAMING_DEVICE
<= ireq
->i_val
&&
2277 ireq
->i_val
<= IEEE80211_ROAMING_MANUAL
))
2279 ic
->ic_roaming
= ireq
->i_val
;
2282 case IEEE80211_IOC_PRIVACY
:
2284 /* XXX check for key state? */
2285 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2287 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
2289 case IEEE80211_IOC_DROPUNENCRYPTED
:
2291 ic
->ic_flags
|= IEEE80211_F_DROPUNENC
;
2293 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2295 case IEEE80211_IOC_WPAKEY
:
2296 error
= ieee80211_ioctl_setkey(ic
, ireq
);
2298 case IEEE80211_IOC_DELKEY
:
2299 error
= ieee80211_ioctl_delkey(ic
, ireq
);
2301 case IEEE80211_IOC_MLME
:
2302 error
= ieee80211_ioctl_setmlme(ic
, ireq
);
2304 case IEEE80211_IOC_OPTIE
:
2305 error
= ieee80211_ioctl_setoptie(ic
, ireq
);
2307 case IEEE80211_IOC_COUNTERMEASURES
:
2309 if ((ic
->ic_flags
& IEEE80211_F_WPA
) == 0)
2311 ic
->ic_flags
|= IEEE80211_F_COUNTERM
;
2313 ic
->ic_flags
&= ~IEEE80211_F_COUNTERM
;
2315 case IEEE80211_IOC_WPA
:
2316 if (ireq
->i_val
> 3)
2318 /* XXX verify ciphers available */
2319 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2320 switch (ireq
->i_val
) {
2322 ic
->ic_flags
|= IEEE80211_F_WPA1
;
2325 ic
->ic_flags
|= IEEE80211_F_WPA2
;
2328 ic
->ic_flags
|= IEEE80211_F_WPA1
| IEEE80211_F_WPA2
;
2331 error
= ENETRESET
; /* XXX? */
2333 case IEEE80211_IOC_WME
:
2335 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
2337 ic
->ic_flags
|= IEEE80211_F_WME
;
2339 ic
->ic_flags
&= ~IEEE80211_F_WME
;
2340 error
= ENETRESET
; /* XXX maybe not for station? */
2342 case IEEE80211_IOC_HIDESSID
:
2344 ic
->ic_flags
|= IEEE80211_F_HIDESSID
;
2346 ic
->ic_flags
&= ~IEEE80211_F_HIDESSID
;
2349 case IEEE80211_IOC_APBRIDGE
:
2350 if (ireq
->i_val
== 0)
2351 ic
->ic_flags
|= IEEE80211_F_NOBRIDGE
;
2353 ic
->ic_flags
&= ~IEEE80211_F_NOBRIDGE
;
2355 case IEEE80211_IOC_MCASTCIPHER
:
2356 if ((ic
->ic_caps
& cipher2cap(ireq
->i_val
)) == 0 &&
2357 !ieee80211_crypto_available(ireq
->i_val
))
2359 rsn
->rsn_mcastcipher
= ireq
->i_val
;
2360 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2362 case IEEE80211_IOC_MCASTKEYLEN
:
2363 if (!(0 < ireq
->i_val
&& ireq
->i_val
< IEEE80211_KEYBUF_SIZE
))
2365 /* XXX no way to verify driver capability */
2366 rsn
->rsn_mcastkeylen
= ireq
->i_val
;
2367 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2369 case IEEE80211_IOC_UCASTCIPHERS
:
2371 * Convert user-specified cipher set to the set
2372 * we can support (via hardware or software).
2373 * NB: this logic intentionally ignores unknown and
2374 * unsupported ciphers so folks can specify 0xff or
2375 * similar and get all available ciphers.
2378 for (j
= 1; j
< 32; j
++) /* NB: skip WEP */
2379 if ((ireq
->i_val
& (1<<j
)) &&
2380 ((ic
->ic_caps
& cipher2cap(j
)) ||
2381 ieee80211_crypto_available(j
)))
2383 if (caps
== 0) /* nothing available */
2385 /* XXX verify ciphers ok for unicast use? */
2386 /* XXX disallow if running as it'll have no effect */
2387 rsn
->rsn_ucastcipherset
= caps
;
2388 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2390 case IEEE80211_IOC_UCASTCIPHER
:
2391 if ((rsn
->rsn_ucastcipherset
& cipher2cap(ireq
->i_val
)) == 0)
2393 rsn
->rsn_ucastcipher
= ireq
->i_val
;
2395 case IEEE80211_IOC_UCASTKEYLEN
:
2396 if (!(0 < ireq
->i_val
&& ireq
->i_val
< IEEE80211_KEYBUF_SIZE
))
2398 /* XXX no way to verify driver capability */
2399 rsn
->rsn_ucastkeylen
= ireq
->i_val
;
2401 case IEEE80211_IOC_DRIVER_CAPS
:
2402 /* NB: for testing */
2403 ic
->ic_caps
= (((uint16_t)ireq
->i_val
) << 16) |
2404 ((uint16_t)ireq
->i_len
);
2406 case IEEE80211_IOC_KEYMGTALGS
:
2408 rsn
->rsn_keymgmtset
= ireq
->i_val
;
2409 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2411 case IEEE80211_IOC_RSNCAPS
:
2413 rsn
->rsn_caps
= ireq
->i_val
;
2414 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2416 case IEEE80211_IOC_BSSID
:
2417 if (ireq
->i_len
!= sizeof(tmpbssid
))
2419 error
= copyin(ireq
->i_data
, tmpbssid
, ireq
->i_len
);
2422 IEEE80211_ADDR_COPY(ic
->ic_des_bssid
, tmpbssid
);
2423 if (IEEE80211_ADDR_EQ(ic
->ic_des_bssid
, zerobssid
))
2424 ic
->ic_flags
&= ~IEEE80211_F_DESBSSID
;
2426 ic
->ic_flags
|= IEEE80211_F_DESBSSID
;
2429 case IEEE80211_IOC_CHANLIST
:
2430 error
= ieee80211_ioctl_setchanlist(ic
, ireq
);
2432 case IEEE80211_IOC_SCAN_REQ
:
2433 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) /* XXX ignore */
2435 error
= ieee80211_setupscan(ic
, ic
->ic_chan_avail
);
2436 if (error
== 0) /* XXX background scan */
2437 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
2439 case IEEE80211_IOC_ADDMAC
:
2440 case IEEE80211_IOC_DELMAC
:
2441 error
= ieee80211_ioctl_macmac(ic
, ireq
);
2443 case IEEE80211_IOC_MACCMD
:
2444 error
= ieee80211_ioctl_setmaccmd(ic
, ireq
);
2446 case IEEE80211_IOC_STA_STATS
:
2447 error
= ieee80211_ioctl_setstastats(ic
, ireq
);
2449 case IEEE80211_IOC_STA_TXPOW
:
2450 error
= ieee80211_ioctl_setstatxpow(ic
, ireq
);
2452 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
2453 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
2454 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
2455 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
2456 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
2457 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
2458 error
= ieee80211_ioctl_setwmeparam(ic
, ireq
);
2460 case IEEE80211_IOC_DTIM_PERIOD
:
2461 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
2462 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
2464 if (IEEE80211_DTIM_MIN
<= ireq
->i_val
&&
2465 ireq
->i_val
<= IEEE80211_DTIM_MAX
) {
2466 ic
->ic_dtim_period
= ireq
->i_val
;
2467 error
= ENETRESET
; /* requires restart */
2471 case IEEE80211_IOC_BEACON_INTERVAL
:
2472 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
2473 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
2475 if (IEEE80211_BINTVAL_MIN
<= ireq
->i_val
&&
2476 ireq
->i_val
<= IEEE80211_BINTVAL_MAX
) {
2477 ic
->ic_bintval
= ireq
->i_val
;
2478 error
= ENETRESET
; /* requires restart */
2482 case IEEE80211_IOC_PUREG
:
2484 ic
->ic_flags
|= IEEE80211_F_PUREG
;
2486 ic
->ic_flags
&= ~IEEE80211_F_PUREG
;
2489 * NB: reset only if we're operating on an 11g channel
2490 * and we act as AP or we are a member of an IBSS.
2492 if ((ic
->ic_curmode
== IEEE80211_MODE_11G
||
2493 ic
->ic_curmode
== IEEE80211_MODE_TURBO_G
) &&
2494 (ic
->ic_opmode
== IEEE80211_M_HOSTAP
||
2495 ic
->ic_opmode
== IEEE80211_M_IBSS
))
2498 case IEEE80211_IOC_MCAST_RATE
:
2499 ic
->ic_mcast_rate
= ireq
->i_val
& IEEE80211_RATE_VAL
;
2501 case IEEE80211_IOC_FRAGTHRESHOLD
:
2502 if ((ic
->ic_caps
& IEEE80211_C_TXFRAG
) == 0 &&
2503 ireq
->i_val
!= IEEE80211_FRAG_MAX
)
2505 if (!(IEEE80211_FRAG_MIN
<= ireq
->i_val
&&
2506 ireq
->i_val
<= IEEE80211_FRAG_MAX
))
2508 ic
->ic_fragthreshold
= ireq
->i_val
;
2509 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2511 case IEEE80211_IOC_BURST
:
2513 if ((ic
->ic_caps
& IEEE80211_C_BURST
) == 0)
2515 ic
->ic_flags
|= IEEE80211_F_BURST
;
2517 ic
->ic_flags
&= ~IEEE80211_F_BURST
;
2518 error
= ENETRESET
; /* XXX maybe not for station? */
2520 case IEEE80211_IOC_RATECTL
:
2521 if (ireq
->i_val
< 0 || ireq
->i_val
>= IEEE80211_RATECTL_MAX
||
2522 ireq
->i_val
== IEEE80211_RATECTL_NONE
) {
2527 error
= ieee80211_ratectl_change(ic
, ireq
->i_val
);
2529 case IEEE80211_IOC_BMISSTHRESHOLD
:
2530 if (!(IEEE80211_HWBMISS_MIN
<= ireq
->i_val
&&
2531 ireq
->i_val
<= IEEE80211_HWBMISS_MAX
))
2533 ic
->ic_bmissthreshold
= ireq
->i_val
;
2534 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2540 if (error
== ENETRESET
&& !IS_UP_AUTO(ic
))
2546 ieee80211_ioctl(struct ieee80211com
*ic
, u_long cmd
, caddr_t data
,
2549 struct ifnet
*ifp
= ic
->ic_ifp
;
2556 error
= ifmedia_ioctl(ifp
, (struct ifreq
*) data
,
2557 &ic
->ic_media
, cmd
);
2560 error
= ieee80211_ioctl_get80211(ic
, cmd
,
2561 (struct ieee80211req
*) data
, cr
);
2564 error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
);
2566 error
= ieee80211_ioctl_set80211(ic
, cmd
,
2567 (struct ieee80211req
*) data
);
2569 case SIOCGIFGENERIC
:
2570 error
= ieee80211_cfgget(ic
, cmd
, data
, cr
);
2572 case SIOCSIFGENERIC
:
2573 error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
);
2576 error
= ieee80211_cfgset(ic
, cmd
, data
);
2578 case SIOCG80211STATS
:
2579 ifr
= (struct ifreq
*)data
;
2580 copyout(&ic
->ic_stats
, ifr
->ifr_data
, sizeof (ic
->ic_stats
));
2583 ifr
= (struct ifreq
*)data
;
2584 if (!(IEEE80211_MTU_MIN
<= ifr
->ifr_mtu
&&
2585 ifr
->ifr_mtu
<= IEEE80211_MTU_MAX
))
2588 ifp
->if_mtu
= ifr
->ifr_mtu
;
2591 error
= ether_ioctl(ifp
, cmd
, data
);