1 /* $NetBSD: ieee80211_ioctl.c,v 1.53 2009/03/18 17:06:51 cegger Exp $ */
3 * Copyright (c) 2001 Atsushi Onoe
4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.35 2005/08/30 14:27:47 avatar Exp $");
39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.53 2009/03/18 17:06:51 cegger Exp $");
43 * IEEE 802.11 ioctl support (FreeBSD-specific)
47 #include "opt_compat_netbsd.h"
49 #include <sys/endian.h>
50 #include <sys/param.h>
51 #include <sys/kernel.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/systm.h>
56 #include <sys/kauth.h>
59 #include <net/if_arp.h>
60 #include <net/if_media.h>
61 #include <net/if_ether.h>
64 #include <netinet/in.h>
65 #include <netinet/if_inarp.h>
68 #include <net80211/ieee80211_var.h>
69 #include <net80211/ieee80211_ioctl.h>
71 #include <dev/ic/wi_ieee.h>
73 #if defined(COMPAT_09) || defined(COMPAT_10) || defined(COMPAT_11) || \
74 defined(COMPAT_12) || defined(COMPAT_13) || defined(COMPAT_14) || \
75 defined(COMPAT_15) || defined(COMPAT_16) || defined(COMPAT_20) || \
76 defined(COMPAT_30) || defined(COMPAT_40)
77 #include <compat/sys/sockio.h>
82 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
83 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
87 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
88 ((_ic)->ic_ifp->if_flags & IFF_RUNNING))
90 #define IS_UP_AUTO(_ic) \
91 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
95 * Wireless LAN specific configuration interface, which is compatible
99 struct wi_read_ap_args
{
100 int i
; /* result count */
101 struct wi_apinfo
*ap
; /* current entry in result buffer */
102 void * max
; /* result buffer bound */
106 wi_read_ap_result(void *arg
, struct ieee80211_node
*ni
)
108 struct ieee80211com
*ic
= ni
->ni_ic
;
109 struct wi_read_ap_args
*sa
= arg
;
110 struct wi_apinfo
*ap
= sa
->ap
;
111 struct ieee80211_rateset
*rs
;
114 if ((void *)(ap
+ 1) > sa
->max
)
116 memset(ap
, 0, sizeof(struct wi_apinfo
));
117 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
118 IEEE80211_ADDR_COPY(ap
->bssid
, ni
->ni_macaddr
);
119 ap
->namelen
= ic
->ic_des_esslen
;
120 if (ic
->ic_des_esslen
)
121 memcpy(ap
->name
, ic
->ic_des_essid
,
124 IEEE80211_ADDR_COPY(ap
->bssid
, ni
->ni_bssid
);
125 ap
->namelen
= ni
->ni_esslen
;
127 memcpy(ap
->name
, ni
->ni_essid
,
130 ap
->channel
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
131 ap
->signal
= ic
->ic_node_getrssi(ni
);
132 ap
->capinfo
= ni
->ni_capinfo
;
133 ap
->interval
= ni
->ni_intval
;
135 for (j
= 0; j
< rs
->rs_nrates
; j
++) {
136 if (rs
->rs_rates
[j
] & IEEE80211_RATE_BASIC
) {
137 ap
->rate
= (rs
->rs_rates
[j
] &
138 IEEE80211_RATE_VAL
) * 5; /* XXX */
145 struct wi_read_prism2_args
{
146 int i
; /* result count */
147 struct wi_scan_res
*res
;/* current entry in result buffer */
148 void * max
; /* result buffer bound */
153 wi_read_prism2_result(void *arg
, struct ieee80211_node
*ni
)
155 struct ieee80211com
*ic
= ni
->ni_ic
;
156 struct wi_read_prism2_args
*sa
= arg
;
157 struct wi_scan_res
*res
= sa
->res
;
159 if ((void *)(res
+ 1) > sa
->max
)
161 res
->wi_chan
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
163 res
->wi_signal
= ic
->ic_node_getrssi(ni
);
164 IEEE80211_ADDR_COPY(res
->wi_bssid
, ni
->ni_bssid
);
165 res
->wi_interval
= ni
->ni_intval
;
166 res
->wi_capinfo
= ni
->ni_capinfo
;
167 res
->wi_ssid_len
= ni
->ni_esslen
;
168 memcpy(res
->wi_ssid
, ni
->ni_essid
, IEEE80211_NWID_LEN
);
169 /* NB: assumes wi_srates holds <= ni->ni_rates */
170 memcpy(res
->wi_srates
, ni
->ni_rates
.rs_rates
,
171 sizeof(res
->wi_srates
));
172 if (ni
->ni_rates
.rs_nrates
< 10)
173 res
->wi_srates
[ni
->ni_rates
.rs_nrates
] = 0;
174 res
->wi_rate
= ni
->ni_rates
.rs_rates
[ni
->ni_txrate
];
181 struct wi_read_sigcache_args
{
182 int i
; /* result count */
183 struct wi_sigcache
*wsc
;/* current entry in result buffer */
184 void * max
; /* result buffer bound */
188 wi_read_sigcache(void *arg
, struct ieee80211_node
*ni
)
190 struct ieee80211com
*ic
= ni
->ni_ic
;
191 struct wi_read_sigcache_args
*sa
= arg
;
192 struct wi_sigcache
*wsc
= sa
->wsc
;
194 if ((void *)(wsc
+ 1) > sa
->max
)
196 memset(wsc
, 0, sizeof(struct wi_sigcache
));
197 IEEE80211_ADDR_COPY(wsc
->macsrc
, ni
->ni_macaddr
);
198 wsc
->signal
= ic
->ic_node_getrssi(ni
);
206 ieee80211_cfgget(struct ieee80211com
*ic
, u_long cmd
, void *data
)
208 struct ifnet
*ifp
= ic
->ic_ifp
;
210 struct ifreq
*ifr
= (struct ifreq
*)data
;
212 struct wi_ltv_keys
*keys
;
214 wreq
= malloc(sizeof(*wreq
), M_TEMP
, M_WAITOK
);
215 error
= copyin(ifr
->ifr_data
, wreq
, sizeof(*wreq
));
219 switch (wreq
->wi_type
) {
220 case WI_RID_SERIALNO
:
221 case WI_RID_STA_IDENTITY
:
222 /* nothing appropriate */
224 case WI_RID_NODENAME
:
225 strlcpy((char *)&wreq
->wi_val
[1], hostname
,
226 sizeof(wreq
->wi_val
) - sizeof(wreq
->wi_val
[0]));
227 wreq
->wi_val
[0] = htole16(strlen(hostname
));
228 wreq
->wi_len
= (1 + strlen(hostname
) + 1) / 2;
230 case WI_RID_CURRENT_SSID
:
231 if (ic
->ic_state
!= IEEE80211_S_RUN
) {
236 wreq
->wi_val
[0] = htole16(ic
->ic_bss
->ni_esslen
);
237 memcpy(&wreq
->wi_val
[1], ic
->ic_bss
->ni_essid
,
238 ic
->ic_bss
->ni_esslen
);
239 wreq
->wi_len
= (1 + ic
->ic_bss
->ni_esslen
+ 1) / 2;
241 case WI_RID_OWN_SSID
:
242 case WI_RID_DESIRED_SSID
:
243 wreq
->wi_val
[0] = htole16(ic
->ic_des_esslen
);
244 memcpy(&wreq
->wi_val
[1], ic
->ic_des_essid
, ic
->ic_des_esslen
);
245 wreq
->wi_len
= (1 + ic
->ic_des_esslen
+ 1) / 2;
247 case WI_RID_CURRENT_BSSID
:
248 if (ic
->ic_state
== IEEE80211_S_RUN
)
249 IEEE80211_ADDR_COPY(wreq
->wi_val
, ic
->ic_bss
->ni_bssid
);
251 memset(wreq
->wi_val
, 0, IEEE80211_ADDR_LEN
);
252 wreq
->wi_len
= IEEE80211_ADDR_LEN
/ 2;
254 case WI_RID_CHANNEL_LIST
:
255 memset(wreq
->wi_val
, 0, sizeof(wreq
->wi_val
));
257 * Since channel 0 is not available for DS, channel 1
258 * is assigned to LSB on WaveLAN.
260 if (ic
->ic_phytype
== IEEE80211_T_DS
)
264 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++)
265 if (isset(ic
->ic_chan_active
, i
)) {
266 setbit((u_int8_t
*)wreq
->wi_val
, j
);
267 wreq
->wi_len
= j
/ 16 + 1;
270 case WI_RID_OWN_CHNL
:
271 wreq
->wi_val
[0] = htole16(
272 ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
));
275 case WI_RID_CURRENT_CHAN
:
276 wreq
->wi_val
[0] = htole16(
277 ieee80211_chan2ieee(ic
, ic
->ic_curchan
));
280 case WI_RID_COMMS_QUALITY
:
281 wreq
->wi_val
[0] = 0; /* quality */
282 wreq
->wi_val
[1] = htole16(ic
->ic_node_getrssi(ic
->ic_bss
));
283 wreq
->wi_val
[2] = 0; /* noise */
287 wreq
->wi_val
[0] = htole16((ifp
->if_flags
& IFF_PROMISC
) ? 1 : 0);
290 case WI_RID_PORTTYPE
:
291 wreq
->wi_val
[0] = htole16(ic
->ic_opmode
);
294 case WI_RID_MAC_NODE
:
295 IEEE80211_ADDR_COPY(wreq
->wi_val
, ic
->ic_myaddr
);
296 wreq
->wi_len
= IEEE80211_ADDR_LEN
/ 2;
299 if (ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
)
300 wreq
->wi_val
[0] = 0; /* auto */
302 wreq
->wi_val
[0] = htole16(
303 (ic
->ic_sup_rates
[ic
->ic_curmode
].rs_rates
[ic
->ic_fixed_rate
] &
304 IEEE80211_RATE_VAL
) / 2);
307 case WI_RID_CUR_TX_RATE
:
308 wreq
->wi_val
[0] = htole16(
309 (ic
->ic_bss
->ni_rates
.rs_rates
[ic
->ic_bss
->ni_txrate
] &
310 IEEE80211_RATE_VAL
) / 2);
313 case WI_RID_FRAG_THRESH
:
314 wreq
->wi_val
[0] = htole16(ic
->ic_fragthreshold
);
317 case WI_RID_RTS_THRESH
:
318 wreq
->wi_val
[0] = htole16(ic
->ic_rtsthreshold
);
321 case WI_RID_CREATE_IBSS
:
323 htole16((ic
->ic_flags
& IEEE80211_F_IBSSON
) ? 1 : 0);
326 case WI_RID_MICROWAVE_OVEN
:
327 wreq
->wi_val
[0] = 0; /* no ... not supported */
330 case WI_RID_ROAMING_MODE
:
331 wreq
->wi_val
[0] = htole16(ic
->ic_roaming
); /* XXX map */
334 case WI_RID_SYSTEM_SCALE
:
335 wreq
->wi_val
[0] = htole16(1); /* low density ... not supp */
338 case WI_RID_PM_ENABLED
:
340 htole16((ic
->ic_flags
& IEEE80211_F_PMGTON
) ? 1 : 0);
343 case WI_RID_MAX_SLEEP
:
344 wreq
->wi_val
[0] = htole16(ic
->ic_lintval
);
347 case WI_RID_CUR_BEACON_INT
:
348 wreq
->wi_val
[0] = htole16(ic
->ic_bss
->ni_intval
);
351 case WI_RID_WEP_AVAIL
:
352 wreq
->wi_val
[0] = htole16(1); /* always available */
355 case WI_RID_CNFAUTHMODE
:
356 wreq
->wi_val
[0] = htole16(1); /* TODO: open system only */
359 case WI_RID_ENCRYPTION
:
361 htole16((ic
->ic_flags
& IEEE80211_F_PRIVACY
) ? 1 : 0);
364 case WI_RID_TX_CRYPT_KEY
:
365 wreq
->wi_val
[0] = htole16(ic
->ic_def_txkey
);
368 case WI_RID_DEFLT_CRYPT_KEYS
:
369 keys
= (struct wi_ltv_keys
*)wreq
;
370 /* do not show keys to non-root user */
371 error
= kauth_authorize_network(curlwp
->l_cred
,
372 KAUTH_NETWORK_INTERFACE
,
373 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV
, ifp
,
376 memset(keys
, 0, sizeof(*keys
));
380 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
381 keys
->wi_keys
[i
].wi_keylen
=
382 htole16(ic
->ic_nw_keys
[i
].wk_keylen
);
383 memcpy(keys
->wi_keys
[i
].wi_keydat
,
384 ic
->ic_nw_keys
[i
].wk_key
,
385 ic
->ic_nw_keys
[i
].wk_keylen
);
387 wreq
->wi_len
= sizeof(*keys
) / 2;
389 case WI_RID_MAX_DATALEN
:
390 wreq
->wi_val
[0] = htole16(ic
->ic_fragthreshold
);
393 case WI_RID_DBM_ADJUST
:
394 /* not supported, we just pass rssi value from driver. */
396 case WI_RID_IFACE_STATS
:
397 /* XXX: should be implemented in lower drivers */
399 case WI_RID_READ_APS
:
401 * Don't return results until active scan completes.
403 if ((ic
->ic_flags
& (IEEE80211_F_SCAN
|IEEE80211_F_ASCAN
)) == 0) {
404 struct wi_read_ap_args args
;
407 args
.ap
= (void *)((char *)wreq
->wi_val
+ sizeof(i
));
408 args
.max
= (void *)(wreq
+ 1);
409 ieee80211_iterate_nodes(&ic
->ic_scan
,
410 wi_read_ap_result
, &args
);
411 memcpy(wreq
->wi_val
, &args
.i
, sizeof(args
.i
));
412 wreq
->wi_len
= (sizeof(int) +
413 sizeof(struct wi_apinfo
) * args
.i
) / 2;
418 case WI_RID_SCAN_RES
: /* compatibility interface */
419 if ((ic
->ic_flags
& (IEEE80211_F_SCAN
|IEEE80211_F_ASCAN
)) == 0) {
420 struct wi_read_prism2_args args
;
421 struct wi_scan_p2_hdr
*p2
;
423 /* NB: use Prism2 format so we can include rate info */
424 p2
= (struct wi_scan_p2_hdr
*)wreq
->wi_val
;
426 args
.res
= (void *)&p2
[1];
427 args
.max
= (void *)(wreq
+ 1);
428 ieee80211_iterate_nodes(&ic
->ic_scan
,
429 wi_read_prism2_result
, &args
);
431 p2
->wi_reason
= args
.i
;
432 wreq
->wi_len
= (sizeof(*p2
) +
433 sizeof(struct wi_scan_res
) * args
.i
) / 2;
437 case WI_RID_READ_CACHE
: {
438 struct wi_read_sigcache_args args
;
440 args
.wsc
= (struct wi_sigcache
*) wreq
->wi_val
;
441 args
.max
= (void *)(wreq
+ 1);
442 ieee80211_iterate_nodes(&ic
->ic_scan
, wi_read_sigcache
, &args
);
443 wreq
->wi_len
= sizeof(struct wi_sigcache
) * args
.i
/ 2;
453 error
= copyout(wreq
, ifr
->ifr_data
, sizeof(*wreq
));
461 findrate(struct ieee80211com
*ic
, enum ieee80211_phymode mode
, int rate
)
463 #define IEEERATE(_ic,_m,_i) \
464 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
465 int i
, nrates
= ic
->ic_sup_rates
[mode
].rs_nrates
;
466 for (i
= 0; i
< nrates
; i
++)
467 if (IEEERATE(ic
, mode
, i
) == rate
)
474 * Prepare to do a user-initiated scan for AP's. If no
475 * current/default channel is setup or the current channel
476 * is invalid then pick the first available channel from
477 * the active list as the place to start the scan.
480 ieee80211_setupscan(struct ieee80211com
*ic
, const u_int8_t chanlist
[])
484 * XXX don't permit a scan to be started unless we
485 * know the device is ready. For the moment this means
486 * the device is marked up as this is the required to
487 * initialize the hardware. It would be better to permit
488 * scanning prior to being up but that'll require some
489 * changes to the infrastructure.
493 memcpy(ic
->ic_chan_active
, chanlist
, sizeof(ic
->ic_chan_active
));
495 * We force the state to INIT before calling ieee80211_new_state
496 * to get ieee80211_begin_scan called. We really want to scan w/o
497 * altering the current state but that's not possible right now.
499 /* XXX handle proberequest case */
500 ic
->ic_state
= IEEE80211_S_INIT
; /* XXX bypass state machine */
505 ieee80211_cfgset(struct ieee80211com
*ic
, u_long cmd
, void *data
)
507 struct ifnet
*ifp
= ic
->ic_ifp
;
508 int i
, j
, len
, error
, rate
;
509 struct ifreq
*ifr
= (struct ifreq
*)data
;
510 struct wi_ltv_keys
*keys
;
512 u_int8_t chanlist
[IEEE80211_CHAN_BYTES
];
514 wreq
= malloc(sizeof(*wreq
), M_TEMP
, M_WAITOK
);
515 error
= copyin(ifr
->ifr_data
, wreq
, sizeof(*wreq
));
518 len
= wreq
->wi_len
? (wreq
->wi_len
- 1) * 2 : 0;
519 switch (wreq
->wi_type
) {
520 case WI_RID_SERIALNO
:
521 case WI_RID_NODENAME
:
522 case WI_RID_CURRENT_SSID
:
525 case WI_RID_OWN_SSID
:
526 case WI_RID_DESIRED_SSID
:
527 if (le16toh(wreq
->wi_val
[0]) * 2 > len
||
528 le16toh(wreq
->wi_val
[0]) > IEEE80211_NWID_LEN
) {
532 memset(ic
->ic_des_essid
, 0, sizeof(ic
->ic_des_essid
));
533 ic
->ic_des_esslen
= le16toh(wreq
->wi_val
[0]) * 2;
534 memcpy(ic
->ic_des_essid
, &wreq
->wi_val
[1], ic
->ic_des_esslen
);
537 case WI_RID_CURRENT_BSSID
:
540 case WI_RID_OWN_CHNL
:
543 i
= le16toh(wreq
->wi_val
[0]);
545 i
> IEEE80211_CHAN_MAX
||
546 isclr(ic
->ic_chan_active
, i
))
548 ic
->ic_ibss_chan
= &ic
->ic_channels
[i
];
549 if (ic
->ic_opmode
== IEEE80211_M_MONITOR
)
550 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
554 case WI_RID_CURRENT_CHAN
:
555 case WI_RID_COMMS_QUALITY
:
561 if (ifp
->if_flags
& IFF_PROMISC
) {
562 if (wreq
->wi_val
[0] == 0) {
563 ifp
->if_flags
&= ~IFF_PROMISC
;
567 if (wreq
->wi_val
[0] != 0) {
568 ifp
->if_flags
|= IFF_PROMISC
;
573 case WI_RID_PORTTYPE
:
576 switch (le16toh(wreq
->wi_val
[0])) {
577 case IEEE80211_M_STA
:
579 case IEEE80211_M_IBSS
:
580 if (!(ic
->ic_caps
& IEEE80211_C_IBSS
))
583 case IEEE80211_M_AHDEMO
:
584 if (ic
->ic_phytype
!= IEEE80211_T_DS
||
585 !(ic
->ic_caps
& IEEE80211_C_AHDEMO
))
588 case IEEE80211_M_HOSTAP
:
589 if (!(ic
->ic_caps
& IEEE80211_C_HOSTAP
))
595 if (le16toh(wreq
->wi_val
[0]) != ic
->ic_opmode
) {
596 ic
->ic_opmode
= le16toh(wreq
->wi_val
[0]);
597 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
601 case WI_RID_MAC_NODE
:
602 if (len
!= IEEE80211_ADDR_LEN
)
604 IEEE80211_ADDR_COPY(LLADDR(ifp
->if_sadl
), wreq
->wi_val
);
605 /* if_init will copy lladdr into ic_myaddr */
612 if (wreq
->wi_val
[0] == 0) {
614 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
617 rate
= 2 * le16toh(wreq
->wi_val
[0]);
618 if (ic
->ic_curmode
== IEEE80211_MODE_AUTO
) {
620 * In autoselect mode search for the rate. We take
621 * the first instance which may not be right, but we
622 * are limited by the interface. Note that we also
623 * lock the mode to insure the rate is meaningful
626 for (j
= IEEE80211_MODE_11A
;
627 j
< IEEE80211_MODE_MAX
; j
++) {
628 if ((ic
->ic_modecaps
& (1<<j
)) == 0)
630 i
= findrate(ic
, j
, rate
);
638 i
= findrate(ic
, ic
->ic_curmode
, rate
);
644 ic
->ic_fixed_rate
= i
;
645 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
647 case WI_RID_CUR_TX_RATE
:
650 case WI_RID_FRAG_THRESH
:
653 ic
->ic_fragthreshold
= le16toh(wreq
->wi_val
[0]);
656 case WI_RID_RTS_THRESH
:
659 ic
->ic_rtsthreshold
= le16toh(wreq
->wi_val
[0]);
662 case WI_RID_CREATE_IBSS
:
665 if (wreq
->wi_val
[0] != 0) {
666 if ((ic
->ic_caps
& IEEE80211_C_IBSS
) == 0)
668 if ((ic
->ic_flags
& IEEE80211_F_IBSSON
) == 0) {
669 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
670 if (ic
->ic_opmode
== IEEE80211_M_IBSS
&&
671 ic
->ic_state
== IEEE80211_S_SCAN
)
672 error
= IS_UP_AUTO(ic
) ? ENETRESET
: 0;
675 if (ic
->ic_flags
& IEEE80211_F_IBSSON
) {
676 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
677 if (ic
->ic_flags
& IEEE80211_F_SIBSS
) {
678 ic
->ic_flags
&= ~IEEE80211_F_SIBSS
;
679 error
= IS_UP_AUTO(ic
) ? ENETRESET
: 0;
684 case WI_RID_MICROWAVE_OVEN
:
687 if (wreq
->wi_val
[0] != 0)
688 goto invalid
; /* not supported */
690 case WI_RID_ROAMING_MODE
:
693 i
= le16toh(wreq
->wi_val
[0]);
694 if (i
> IEEE80211_ROAMING_MANUAL
)
695 goto invalid
; /* not supported */
698 case WI_RID_SYSTEM_SCALE
:
701 if (le16toh(wreq
->wi_val
[0]) != 1)
702 goto invalid
; /* not supported */
704 case WI_RID_PM_ENABLED
:
707 if (wreq
->wi_val
[0] != 0) {
708 if ((ic
->ic_caps
& IEEE80211_C_PMGT
) == 0)
710 if ((ic
->ic_flags
& IEEE80211_F_PMGTON
) == 0) {
711 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
712 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
715 if (ic
->ic_flags
& IEEE80211_F_PMGTON
) {
716 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
717 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
721 case WI_RID_MAX_SLEEP
:
724 ic
->ic_lintval
= le16toh(wreq
->wi_val
[0]);
725 if (ic
->ic_flags
& IEEE80211_F_PMGTON
)
726 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
728 case WI_RID_CUR_BEACON_INT
:
729 case WI_RID_WEP_AVAIL
:
732 case WI_RID_CNFAUTHMODE
:
735 i
= le16toh(wreq
->wi_val
[0]);
736 if (i
> IEEE80211_AUTH_WPA
)
738 ic
->ic_bss
->ni_authmode
= i
; /* XXX ENETRESET? */
741 case WI_RID_ENCRYPTION
:
744 if (wreq
->wi_val
[0] != 0) {
745 if ((ic
->ic_caps
& IEEE80211_C_WEP
) == 0)
747 if ((ic
->ic_flags
& IEEE80211_F_PRIVACY
) == 0) {
748 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
752 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
753 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
758 case WI_RID_TX_CRYPT_KEY
:
761 i
= le16toh(wreq
->wi_val
[0]);
762 if (i
>= IEEE80211_WEP_NKID
)
764 ic
->ic_def_txkey
= i
;
765 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
767 case WI_RID_DEFLT_CRYPT_KEYS
:
768 if (len
!= sizeof(struct wi_ltv_keys
))
770 keys
= (struct wi_ltv_keys
*)wreq
;
771 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
772 len
= le16toh(keys
->wi_keys
[i
].wi_keylen
);
773 if (len
!= 0 && len
< IEEE80211_WEP_KEYLEN
)
775 if (len
> IEEE80211_KEYBUF_SIZE
)
778 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
779 struct ieee80211_key
*k
= &ic
->ic_nw_keys
[i
];
781 len
= le16toh(keys
->wi_keys
[i
].wi_keylen
);
783 k
->wk_flags
= IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
;
784 memset(k
->wk_key
, 0, sizeof(k
->wk_key
));
785 memcpy(k
->wk_key
, keys
->wi_keys
[i
].wi_keydat
, len
);
787 k
->wk_type
= IEEE80211_CIPHER_WEP
;
792 case WI_RID_MAX_DATALEN
:
795 len
= le16toh(wreq
->wi_val
[0]);
796 if (len
< 350 /* ? */ || len
> IEEE80211_MAX_LEN
)
798 ic
->ic_fragthreshold
= len
;
799 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
801 case WI_RID_IFACE_STATS
:
804 case WI_RID_SCAN_REQ
: /* XXX wicontrol */
805 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
807 error
= ieee80211_setupscan(ic
, ic
->ic_chan_avail
);
809 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
811 case WI_RID_SCAN_APS
:
812 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
814 len
--; /* XXX: tx rate? */
816 case WI_RID_CHANNEL_LIST
:
817 memset(chanlist
, 0, sizeof(chanlist
));
819 * Since channel 0 is not available for DS, channel 1
820 * is assigned to LSB on WaveLAN.
822 if (ic
->ic_phytype
== IEEE80211_T_DS
)
826 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++) {
829 if (isclr((u_int8_t
*)wreq
->wi_val
, j
))
831 if (isclr(ic
->ic_chan_active
, i
)) {
832 if (wreq
->wi_type
!= WI_RID_CHANNEL_LIST
)
834 if (isclr(ic
->ic_chan_avail
, i
)) {
841 error
= ieee80211_setupscan(ic
, chanlist
);
842 if (wreq
->wi_type
== WI_RID_CHANNEL_LIST
) {
843 /* NB: ignore error from ieee80211_setupscan */
845 } else if (error
== 0)
846 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
851 if (error
== ENETRESET
&& !IS_UP_AUTO(ic
))
865 case IEEE80211_C_WEP
: return IEEE80211_CIPHER_WEP
;
866 case IEEE80211_C_AES
: return IEEE80211_CIPHER_AES_OCB
;
867 case IEEE80211_C_AES_CCM
: return IEEE80211_CIPHER_AES_CCM
;
868 case IEEE80211_C_CKIP
: return IEEE80211_CIPHER_CKIP
;
869 case IEEE80211_C_TKIP
: return IEEE80211_CIPHER_TKIP
;
875 ieee80211_ioctl_getkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
877 struct ieee80211_node
*ni
;
878 struct ieee80211req_key ik
;
879 struct ieee80211_key
*wk
;
880 const struct ieee80211_cipher
*cip
;
884 if (ireq
->i_len
!= sizeof(ik
))
886 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
890 if (kid
== IEEE80211_KEYIX_NONE
) {
891 ni
= ieee80211_find_node(&ic
->ic_sta
, ik
.ik_macaddr
);
893 return EINVAL
; /* XXX */
894 wk
= &ni
->ni_ucastkey
;
896 if (kid
>= IEEE80211_WEP_NKID
)
898 wk
= &ic
->ic_nw_keys
[kid
];
899 IEEE80211_ADDR_COPY(&ik
.ik_macaddr
, ic
->ic_bss
->ni_macaddr
);
903 ik
.ik_type
= cip
->ic_cipher
;
904 ik
.ik_keylen
= wk
->wk_keylen
;
905 ik
.ik_flags
= wk
->wk_flags
& (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
);
906 if (wk
->wk_keyix
== ic
->ic_def_txkey
)
907 ik
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
908 if (kauth_authorize_network(curlwp
->l_cred
, KAUTH_NETWORK_INTERFACE
,
909 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV
, ic
->ic_ifp
, NULL
, NULL
) == 0) {
910 /* NB: only root can read key data */
911 ik
.ik_keyrsc
= wk
->wk_keyrsc
;
912 ik
.ik_keytsc
= wk
->wk_keytsc
;
913 memcpy(ik
.ik_keydata
, wk
->wk_key
, wk
->wk_keylen
);
914 if (cip
->ic_cipher
== IEEE80211_CIPHER_TKIP
) {
915 memcpy(ik
.ik_keydata
+wk
->wk_keylen
,
916 wk
->wk_key
+ IEEE80211_KEYBUF_SIZE
,
917 IEEE80211_MICBUF_SIZE
);
918 ik
.ik_keylen
+= IEEE80211_MICBUF_SIZE
;
923 memset(ik
.ik_keydata
, 0, sizeof(ik
.ik_keydata
));
926 ieee80211_free_node(ni
);
927 return copyout(&ik
, ireq
->i_data
, sizeof(ik
));
931 ieee80211_ioctl_getchanlist(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
933 size_t len
= ireq
->i_len
;
935 if (sizeof(ic
->ic_chan_active
) < len
) {
936 len
= sizeof(ic
->ic_chan_active
);
938 return copyout(&ic
->ic_chan_active
, ireq
->i_data
, len
);
942 ieee80211_ioctl_getchaninfo(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
944 struct ieee80211req_chaninfo
*chans
;
948 * Since channel 0 is not available for DS, channel 1
949 * is assigned to LSB on WaveLAN.
951 if (ic
->ic_phytype
== IEEE80211_T_DS
)
956 chans
= malloc(sizeof(*chans
), M_TEMP
, M_WAITOK
|M_ZERO
);
958 for (; i
<= IEEE80211_CHAN_MAX
; i
++)
959 if (isset(ic
->ic_chan_avail
, i
)) {
960 struct ieee80211_channel
*c
= &ic
->ic_channels
[i
];
961 chans
->ic_chans
[chans
->ic_nchans
].ic_freq
= c
->ic_freq
;
962 chans
->ic_chans
[chans
->ic_nchans
].ic_flags
= c
->ic_flags
;
965 space
= __offsetof(struct ieee80211req_chaninfo
,
966 ic_chans
[chans
->ic_nchans
]);
967 if (space
> ireq
->i_len
)
969 error
= copyout(chans
, ireq
->i_data
, space
);
975 ieee80211_ioctl_getwpaie(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
977 struct ieee80211_node
*ni
;
978 struct ieee80211req_wpaie wpaie
;
981 if (ireq
->i_len
< IEEE80211_ADDR_LEN
)
983 error
= copyin(ireq
->i_data
, wpaie
.wpa_macaddr
, IEEE80211_ADDR_LEN
);
986 ni
= ieee80211_find_node(&ic
->ic_sta
, wpaie
.wpa_macaddr
);
988 return EINVAL
; /* XXX */
989 memset(wpaie
.wpa_ie
, 0, sizeof(wpaie
.wpa_ie
));
990 if (ni
->ni_wpa_ie
!= NULL
) {
991 int ielen
= ni
->ni_wpa_ie
[1] + 2;
992 if (ielen
> sizeof(wpaie
.wpa_ie
))
993 ielen
= sizeof(wpaie
.wpa_ie
);
994 memcpy(wpaie
.wpa_ie
, ni
->ni_wpa_ie
, ielen
);
996 ieee80211_free_node(ni
);
997 if (ireq
->i_len
> sizeof(wpaie
))
998 ireq
->i_len
= sizeof(wpaie
);
999 return copyout(&wpaie
, ireq
->i_data
, ireq
->i_len
);
1003 ieee80211_ioctl_getstastats(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1005 struct ieee80211_node
*ni
;
1006 u_int8_t macaddr
[IEEE80211_ADDR_LEN
];
1007 const int off
= __offsetof(struct ieee80211req_sta_stats
, is_stats
);
1010 if (ireq
->i_len
< off
)
1012 error
= copyin(ireq
->i_data
, macaddr
, IEEE80211_ADDR_LEN
);
1015 ni
= ieee80211_find_node(&ic
->ic_sta
, macaddr
);
1017 return EINVAL
; /* XXX */
1018 if (ireq
->i_len
> sizeof(struct ieee80211req_sta_stats
))
1019 ireq
->i_len
= sizeof(struct ieee80211req_sta_stats
);
1020 /* NB: copy out only the statistics */
1021 error
= copyout(&ni
->ni_stats
, (u_int8_t
*) ireq
->i_data
+ off
,
1023 ieee80211_free_node(ni
);
1028 get_scan_result(struct ieee80211req_scan_result
*sr
,
1029 const struct ieee80211_node
*ni
)
1031 struct ieee80211com
*ic
= ni
->ni_ic
;
1034 memset(sr
, 0, sizeof(*sr
));
1035 sr
->isr_ssid_len
= ni
->ni_esslen
;
1036 if (ni
->ni_wpa_ie
!= NULL
)
1037 ielen
+= 2+ni
->ni_wpa_ie
[1];
1038 if (ni
->ni_wme_ie
!= NULL
)
1039 ielen
+= 2+ni
->ni_wme_ie
[1];
1042 * The value sr->isr_ie_len is defined as a uint8_t, so we
1043 * need to be careful to avoid an integer overflow. If the
1044 * value would overflow, we will set isr_ie_len to zero, and
1045 * ieee80211_ioctl_getscanresults (below) will avoid copying
1046 * the (overflowing) data.
1050 sr
->isr_ie_len
= ielen
;
1051 sr
->isr_len
= sizeof(*sr
) + sr
->isr_ssid_len
+ sr
->isr_ie_len
;
1052 sr
->isr_len
= roundup(sr
->isr_len
, sizeof(u_int32_t
));
1053 if (ni
->ni_chan
!= IEEE80211_CHAN_ANYC
) {
1054 sr
->isr_freq
= ni
->ni_chan
->ic_freq
;
1055 sr
->isr_flags
= ni
->ni_chan
->ic_flags
;
1057 sr
->isr_rssi
= ic
->ic_node_getrssi(ni
);
1058 sr
->isr_intval
= ni
->ni_intval
;
1059 sr
->isr_capinfo
= ni
->ni_capinfo
;
1060 sr
->isr_erp
= ni
->ni_erp
;
1061 IEEE80211_ADDR_COPY(sr
->isr_bssid
, ni
->ni_bssid
);
1062 sr
->isr_nrates
= ni
->ni_rates
.rs_nrates
;
1063 if (sr
->isr_nrates
> 15)
1064 sr
->isr_nrates
= 15;
1065 memcpy(sr
->isr_rates
, ni
->ni_rates
.rs_rates
, sr
->isr_nrates
);
1069 ieee80211_ioctl_getscanresults(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1072 struct ieee80211req_scan_result res
;
1073 char data
[sizeof(struct ieee80211req_scan_result
) + IEEE80211_NWID_LEN
+ 256 * 2];
1075 struct ieee80211req_scan_result
*sr
= &u
.res
;
1076 struct ieee80211_node_table
*nt
;
1077 struct ieee80211_node
*ni
;
1082 space
= ireq
->i_len
;
1086 TAILQ_FOREACH(ni
, &nt
->nt_node
, ni_list
) {
1087 /* NB: skip pre-scan node state */
1088 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
)
1090 get_scan_result(sr
, ni
);
1091 if (sr
->isr_len
> sizeof(u
))
1093 if (space
< sr
->isr_len
)
1095 cp
= (u_int8_t
*)(sr
+1);
1096 memcpy(cp
, ni
->ni_essid
, ni
->ni_esslen
);
1097 cp
+= ni
->ni_esslen
;
1098 if (sr
->isr_ie_len
> 0 && ni
->ni_wpa_ie
!= NULL
) {
1099 memcpy(cp
, ni
->ni_wpa_ie
, 2+ni
->ni_wpa_ie
[1]);
1100 cp
+= 2+ni
->ni_wpa_ie
[1];
1102 if (sr
->isr_ie_len
> 0 && ni
->ni_wme_ie
!= NULL
) {
1103 memcpy(cp
, ni
->ni_wme_ie
, 2+ni
->ni_wme_ie
[1]);
1104 cp
+= 2+ni
->ni_wme_ie
[1];
1106 error
= copyout(sr
, p
, sr
->isr_len
);
1110 space
-= sr
->isr_len
;
1112 ireq
->i_len
-= space
;
1117 struct ieee80211com
*ic
;
1118 struct ieee80211req_sta_info
*si
;
1123 sta_space(const struct ieee80211_node
*ni
, size_t *ielen
)
1126 if (ni
->ni_wpa_ie
!= NULL
)
1127 *ielen
+= 2+ni
->ni_wpa_ie
[1];
1128 if (ni
->ni_wme_ie
!= NULL
)
1129 *ielen
+= 2+ni
->ni_wme_ie
[1];
1130 return roundup(sizeof(struct ieee80211req_sta_info
) + *ielen
,
1135 get_sta_space(void *arg
, struct ieee80211_node
*ni
)
1137 struct stainforeq
*req
= arg
;
1138 struct ieee80211com
*ic
= ni
->ni_ic
;
1141 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
1142 ni
->ni_associd
== 0) /* only associated stations */
1144 req
->space
+= sta_space(ni
, &ielen
);
1148 get_sta_info(void *arg
, struct ieee80211_node
*ni
)
1150 struct stainforeq
*req
= arg
;
1151 struct ieee80211com
*ic
= ni
->ni_ic
;
1152 struct ieee80211req_sta_info
*si
;
1156 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
1157 ni
->ni_associd
== 0) /* only associated stations */
1159 if (ni
->ni_chan
== IEEE80211_CHAN_ANYC
) /* XXX bogus entry */
1161 len
= sta_space(ni
, &ielen
);
1162 if (len
> req
->space
)
1166 si
->isi_ie_len
= ielen
;
1167 si
->isi_freq
= ni
->ni_chan
->ic_freq
;
1168 si
->isi_flags
= ni
->ni_chan
->ic_flags
;
1169 si
->isi_state
= ni
->ni_flags
;
1170 si
->isi_authmode
= ni
->ni_authmode
;
1171 si
->isi_rssi
= ic
->ic_node_getrssi(ni
);
1172 si
->isi_capinfo
= ni
->ni_capinfo
;
1173 si
->isi_erp
= ni
->ni_erp
;
1174 IEEE80211_ADDR_COPY(si
->isi_macaddr
, ni
->ni_macaddr
);
1175 si
->isi_nrates
= ni
->ni_rates
.rs_nrates
;
1176 if (si
->isi_nrates
> 15)
1177 si
->isi_nrates
= 15;
1178 memcpy(si
->isi_rates
, ni
->ni_rates
.rs_rates
, si
->isi_nrates
);
1179 si
->isi_txrate
= ni
->ni_txrate
;
1180 si
->isi_associd
= ni
->ni_associd
;
1181 si
->isi_txpower
= ni
->ni_txpower
;
1182 si
->isi_vlan
= ni
->ni_vlan
;
1183 if (ni
->ni_flags
& IEEE80211_NODE_QOS
) {
1184 memcpy(si
->isi_txseqs
, ni
->ni_txseqs
, sizeof(ni
->ni_txseqs
));
1185 memcpy(si
->isi_rxseqs
, ni
->ni_rxseqs
, sizeof(ni
->ni_rxseqs
));
1187 si
->isi_txseqs
[0] = ni
->ni_txseqs
[0];
1188 si
->isi_rxseqs
[0] = ni
->ni_rxseqs
[0];
1190 /* NB: leave all cases in case we relax ni_associd == 0 check */
1191 if (ieee80211_node_is_authorized(ni
))
1192 si
->isi_inact
= ic
->ic_inact_run
;
1193 else if (ni
->ni_associd
!= 0)
1194 si
->isi_inact
= ic
->ic_inact_auth
;
1196 si
->isi_inact
= ic
->ic_inact_init
;
1197 si
->isi_inact
= (si
->isi_inact
- ni
->ni_inact
) * IEEE80211_INACT_WAIT
;
1199 cp
= (u_int8_t
*)(si
+1);
1200 if (ni
->ni_wpa_ie
!= NULL
) {
1201 memcpy(cp
, ni
->ni_wpa_ie
, 2+ni
->ni_wpa_ie
[1]);
1202 cp
+= 2+ni
->ni_wpa_ie
[1];
1204 if (ni
->ni_wme_ie
!= NULL
) {
1205 memcpy(cp
, ni
->ni_wme_ie
, 2+ni
->ni_wme_ie
[1]);
1206 cp
+= 2+ni
->ni_wme_ie
[1];
1209 req
->si
= (struct ieee80211req_sta_info
*)(((u_int8_t
*)si
) + len
);
1214 ieee80211_ioctl_getstainfo(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1216 struct stainforeq req
;
1219 if (ireq
->i_len
< sizeof(struct stainforeq
))
1224 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_space
, &req
);
1225 if (req
.space
> ireq
->i_len
)
1226 req
.space
= ireq
->i_len
;
1227 if (req
.space
> 0) {
1232 /* XXX M_WAITOK after driver lock released */
1233 p
= malloc(space
, M_TEMP
, M_NOWAIT
);
1237 ieee80211_iterate_nodes(&ic
->ic_sta
, get_sta_info
, &req
);
1238 ireq
->i_len
= space
- req
.space
;
1239 error
= copyout(p
, ireq
->i_data
, ireq
->i_len
);
1248 ieee80211_ioctl_getstatxpow(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1250 struct ieee80211_node
*ni
;
1251 struct ieee80211req_sta_txpow txpow
;
1254 if (ireq
->i_len
!= sizeof(txpow
))
1256 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1259 ni
= ieee80211_find_node(&ic
->ic_sta
, txpow
.it_macaddr
);
1261 return EINVAL
; /* XXX */
1262 txpow
.it_txpow
= ni
->ni_txpower
;
1263 error
= copyout(&txpow
, ireq
->i_data
, sizeof(txpow
));
1264 ieee80211_free_node(ni
);
1269 ieee80211_ioctl_getwmeparam(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1271 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1272 struct wmeParams
*wmep
;
1275 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1278 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1279 if (ac
>= WME_NUM_AC
)
1281 if (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
)
1282 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1284 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1285 switch (ireq
->i_type
) {
1286 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1287 ireq
->i_val
= wmep
->wmep_logcwmin
;
1289 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1290 ireq
->i_val
= wmep
->wmep_logcwmax
;
1292 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1293 ireq
->i_val
= wmep
->wmep_aifsn
;
1295 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1296 ireq
->i_val
= wmep
->wmep_txopLimit
;
1298 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1299 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1300 ireq
->i_val
= wmep
->wmep_acm
;
1302 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
1303 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1304 ireq
->i_val
= !wmep
->wmep_noackPolicy
;
1311 ieee80211_ioctl_getmaccmd(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1313 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1315 return (acl
== NULL
? EINVAL
: acl
->iac_getioctl(ic
, ireq
));
1318 #if defined(COMPAT_FREEBSD_NET80211)
1320 ieee80211_ioctl_get80211_fbsd(struct ieee80211com
*ic
, u_long cmd
,
1321 struct ieee80211req
*ireq
)
1324 u_int8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
1325 char tmpssid
[IEEE80211_NWID_LEN
];
1326 struct ifnet
*ifp
= ic
->ic_ifp
;
1330 switch (ireq
->i_type
) {
1331 case IEEE80211_IOC_SSID
:
1332 switch (ic
->ic_state
) {
1333 case IEEE80211_S_INIT
:
1334 case IEEE80211_S_SCAN
:
1335 ireq
->i_len
= ic
->ic_des_esslen
;
1336 memcpy(tmpssid
, ic
->ic_des_essid
, ireq
->i_len
);
1339 ireq
->i_len
= ic
->ic_bss
->ni_esslen
;
1340 memcpy(tmpssid
, ic
->ic_bss
->ni_essid
,
1344 error
= copyout(tmpssid
, ireq
->i_data
, ireq
->i_len
);
1346 case IEEE80211_IOC_NUMSSIDS
:
1349 case IEEE80211_IOC_WEP
:
1350 if ((ic
->ic_flags
& IEEE80211_F_PRIVACY
) == 0)
1351 ireq
->i_val
= IEEE80211_WEP_OFF
;
1352 else if (ic
->ic_flags
& IEEE80211_F_DROPUNENC
)
1353 ireq
->i_val
= IEEE80211_WEP_ON
;
1355 ireq
->i_val
= IEEE80211_WEP_MIXED
;
1357 case IEEE80211_IOC_WEPKEY
:
1358 kid
= (u_int
) ireq
->i_val
;
1359 if (kid
>= IEEE80211_WEP_NKID
)
1361 len
= (u_int
) ic
->ic_nw_keys
[kid
].wk_keylen
;
1362 /* NB: only root can read WEP keys */
1363 if (kauth_authorize_network(curlwp
->l_cred
,
1364 KAUTH_NETWORK_INTERFACE
,
1365 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV
, ifp
, NULL
,
1367 memcpy(tmpkey
, ic
->ic_nw_keys
[kid
].wk_key
, len
);
1369 memset(tmpkey
, 0, len
);
1372 error
= copyout(tmpkey
, ireq
->i_data
, len
);
1374 case IEEE80211_IOC_NUMWEPKEYS
:
1375 ireq
->i_val
= IEEE80211_WEP_NKID
;
1377 case IEEE80211_IOC_WEPTXKEY
:
1378 ireq
->i_val
= ic
->ic_def_txkey
;
1380 case IEEE80211_IOC_CHANNEL
:
1381 ireq
->i_val
= ieee80211_chan2ieee(ic
, ic
->ic_curchan
);
1383 case IEEE80211_IOC_POWERSAVE
:
1384 if (ic
->ic_flags
& IEEE80211_F_PMGTON
)
1385 ireq
->i_val
= IEEE80211_POWERSAVE_ON
;
1387 ireq
->i_val
= IEEE80211_POWERSAVE_OFF
;
1389 case IEEE80211_IOC_POWERSAVESLEEP
:
1390 ireq
->i_val
= ic
->ic_lintval
;
1392 case IEEE80211_IOC_BSSID
:
1393 if (ireq
->i_len
!= IEEE80211_ADDR_LEN
)
1395 error
= copyout(ic
->ic_state
== IEEE80211_S_RUN
?
1396 ic
->ic_bss
->ni_bssid
:
1398 ireq
->i_data
, ireq
->i_len
);
1406 #endif /* COMPAT_FREEBSD_NET80211 */
1409 * When building the kernel with -O2 on the i386 architecture, gcc
1410 * seems to want to inline this function into ieee80211_ioctl()
1411 * (which is the only routine that calls it). When this happens,
1412 * ieee80211_ioctl() ends up consuming an additional 2K of stack
1413 * space. (Exactly why it needs so much is unclear.) The problem
1414 * is that it's possible for ieee80211_ioctl() to invoke other
1415 * routines (including driver init functions) which could then find
1416 * themselves perilously close to exhausting the stack.
1418 * To avoid this, we deliberately prevent gcc from inlining this
1419 * routine. Another way to avoid this is to use less agressive
1420 * optimization when compiling this file (i.e. -O instead of -O2)
1421 * but special-casing the compilation of this one module in the
1422 * build system would be awkward.
1425 __attribute__ ((__noinline__
))
1428 ieee80211_ioctl_get80211(struct ieee80211com
*ic
, u_long cmd
,
1429 struct ieee80211req
*ireq
)
1431 const struct ieee80211_rsnparms
*rsn
= &ic
->ic_bss
->ni_rsn
;
1435 switch (ireq
->i_type
) {
1436 case IEEE80211_IOC_AUTHMODE
:
1437 if (ic
->ic_flags
& IEEE80211_F_WPA
)
1438 ireq
->i_val
= IEEE80211_AUTH_WPA
;
1440 ireq
->i_val
= ic
->ic_bss
->ni_authmode
;
1442 case IEEE80211_IOC_RTSTHRESHOLD
:
1443 ireq
->i_val
= ic
->ic_rtsthreshold
;
1445 case IEEE80211_IOC_PROTMODE
:
1446 ireq
->i_val
= ic
->ic_protmode
;
1448 case IEEE80211_IOC_TXPOWER
:
1449 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
1451 ireq
->i_val
= ic
->ic_txpowlimit
;
1453 case IEEE80211_IOC_MCASTCIPHER
:
1454 ireq
->i_val
= rsn
->rsn_mcastcipher
;
1456 case IEEE80211_IOC_MCASTKEYLEN
:
1457 ireq
->i_val
= rsn
->rsn_mcastkeylen
;
1459 case IEEE80211_IOC_UCASTCIPHERS
:
1461 for (m
= 0x1; m
!= 0; m
<<= 1)
1462 if (rsn
->rsn_ucastcipherset
& m
)
1463 ireq
->i_val
|= 1<<cap2cipher(m
);
1465 case IEEE80211_IOC_UCASTCIPHER
:
1466 ireq
->i_val
= rsn
->rsn_ucastcipher
;
1468 case IEEE80211_IOC_UCASTKEYLEN
:
1469 ireq
->i_val
= rsn
->rsn_ucastkeylen
;
1471 case IEEE80211_IOC_KEYMGTALGS
:
1472 ireq
->i_val
= rsn
->rsn_keymgmtset
;
1474 case IEEE80211_IOC_RSNCAPS
:
1475 ireq
->i_val
= rsn
->rsn_caps
;
1477 case IEEE80211_IOC_WPA
:
1478 switch (ic
->ic_flags
& IEEE80211_F_WPA
) {
1479 case IEEE80211_F_WPA1
:
1482 case IEEE80211_F_WPA2
:
1485 case IEEE80211_F_WPA1
| IEEE80211_F_WPA2
:
1493 case IEEE80211_IOC_CHANLIST
:
1494 error
= ieee80211_ioctl_getchanlist(ic
, ireq
);
1496 case IEEE80211_IOC_ROAMING
:
1497 ireq
->i_val
= ic
->ic_roaming
;
1499 case IEEE80211_IOC_PRIVACY
:
1500 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_PRIVACY
) != 0;
1502 case IEEE80211_IOC_DROPUNENCRYPTED
:
1503 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_DROPUNENC
) != 0;
1505 case IEEE80211_IOC_COUNTERMEASURES
:
1506 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_COUNTERM
) != 0;
1508 case IEEE80211_IOC_DRIVER_CAPS
:
1509 ireq
->i_val
= ic
->ic_caps
>>16;
1510 ireq
->i_len
= ic
->ic_caps
&0xffff;
1512 case IEEE80211_IOC_WME
:
1513 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_WME
) != 0;
1515 case IEEE80211_IOC_HIDESSID
:
1516 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_HIDESSID
) != 0;
1518 case IEEE80211_IOC_APBRIDGE
:
1519 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_NOBRIDGE
) == 0;
1521 case IEEE80211_IOC_OPTIE
:
1522 if (ic
->ic_opt_ie
== NULL
)
1524 /* NB: truncate, caller can check length */
1525 if (ireq
->i_len
> ic
->ic_opt_ie_len
)
1526 ireq
->i_len
= ic
->ic_opt_ie_len
;
1527 error
= copyout(ic
->ic_opt_ie
, ireq
->i_data
, ireq
->i_len
);
1529 case IEEE80211_IOC_WPAKEY
:
1530 error
= ieee80211_ioctl_getkey(ic
, ireq
);
1532 case IEEE80211_IOC_CHANINFO
:
1533 error
= ieee80211_ioctl_getchaninfo(ic
, ireq
);
1535 case IEEE80211_IOC_WPAIE
:
1536 error
= ieee80211_ioctl_getwpaie(ic
, ireq
);
1538 case IEEE80211_IOC_SCAN_RESULTS
:
1539 error
= ieee80211_ioctl_getscanresults(ic
, ireq
);
1541 case IEEE80211_IOC_STA_STATS
:
1542 error
= ieee80211_ioctl_getstastats(ic
, ireq
);
1544 case IEEE80211_IOC_TXPOWMAX
:
1545 ireq
->i_val
= ic
->ic_bss
->ni_txpower
;
1547 case IEEE80211_IOC_STA_TXPOW
:
1548 error
= ieee80211_ioctl_getstatxpow(ic
, ireq
);
1550 case IEEE80211_IOC_STA_INFO
:
1551 error
= ieee80211_ioctl_getstainfo(ic
, ireq
);
1553 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1554 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1555 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1556 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
1557 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
1558 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
1559 error
= ieee80211_ioctl_getwmeparam(ic
, ireq
);
1561 case IEEE80211_IOC_DTIM_PERIOD
:
1562 ireq
->i_val
= ic
->ic_dtim_period
;
1564 case IEEE80211_IOC_BEACON_INTERVAL
:
1565 /* NB: get from ic_bss for station mode */
1566 ireq
->i_val
= ic
->ic_bss
->ni_intval
;
1568 case IEEE80211_IOC_PUREG
:
1569 ireq
->i_val
= (ic
->ic_flags
& IEEE80211_F_PUREG
) != 0;
1571 case IEEE80211_IOC_MCAST_RATE
:
1572 ireq
->i_val
= ic
->ic_mcast_rate
;
1574 case IEEE80211_IOC_FRAGTHRESHOLD
:
1575 ireq
->i_val
= ic
->ic_fragthreshold
;
1577 case IEEE80211_IOC_MACCMD
:
1578 error
= ieee80211_ioctl_getmaccmd(ic
, ireq
);
1581 #if defined(COMPAT_FREEBSD_NET80211)
1582 error
= ieee80211_ioctl_get80211_fbsd(ic
, cmd
, ireq
);
1585 #endif /* COMPAT_FREEBSD_NET80211 */
1592 ieee80211_ioctl_setoptie(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1598 * NB: Doing this for ap operation could be useful (e.g. for
1599 * WPA and/or WME) except that it typically is worthless
1600 * without being able to intervene when processing
1601 * association response frames--so disallow it for now.
1603 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
1605 if (ireq
->i_len
> IEEE80211_MAX_OPT_IE
)
1607 /* NB: data.length is validated by the wireless extensions code */
1608 ie
= malloc(ireq
->i_len
, M_DEVBUF
, M_WAITOK
);
1611 error
= copyin(ireq
->i_data
, ie
, ireq
->i_len
);
1612 /* XXX sanity check data? */
1613 if (ic
->ic_opt_ie
!= NULL
)
1614 free(ic
->ic_opt_ie
, M_DEVBUF
);
1616 ic
->ic_opt_ie_len
= ireq
->i_len
;
1621 ieee80211_ioctl_setkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1623 struct ieee80211req_key ik
;
1624 struct ieee80211_node
*ni
;
1625 struct ieee80211_key
*wk
;
1629 if (ireq
->i_len
!= sizeof(ik
))
1631 error
= copyin(ireq
->i_data
, &ik
, sizeof(ik
));
1634 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1635 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1636 if (ik
.ik_keylen
> sizeof(ik
.ik_keydata
))
1639 if (kid
== IEEE80211_KEYIX_NONE
) {
1640 /* XXX unicast keys currently must be tx/rx */
1641 if (ik
.ik_flags
!= (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
))
1643 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
1644 ni
= ieee80211_ref_node(ic
->ic_bss
);
1645 if (!IEEE80211_ADDR_EQ(ik
.ik_macaddr
, ni
->ni_bssid
)) {
1646 ieee80211_free_node(ni
);
1647 return EADDRNOTAVAIL
;
1650 ni
= ieee80211_find_node(&ic
->ic_sta
, ik
.ik_macaddr
);
1654 wk
= &ni
->ni_ucastkey
;
1656 if (kid
>= IEEE80211_WEP_NKID
)
1658 wk
= &ic
->ic_nw_keys
[kid
];
1662 ieee80211_key_update_begin(ic
);
1663 if (ieee80211_crypto_newkey(ic
, ik
.ik_type
, ik
.ik_flags
, wk
)) {
1664 wk
->wk_keylen
= ik
.ik_keylen
;
1665 /* NB: MIC presence is implied by cipher type */
1666 if (wk
->wk_keylen
> IEEE80211_KEYBUF_SIZE
)
1667 wk
->wk_keylen
= IEEE80211_KEYBUF_SIZE
;
1668 wk
->wk_keyrsc
= ik
.ik_keyrsc
;
1669 wk
->wk_keytsc
= 0; /* new key, reset */
1670 memset(wk
->wk_key
, 0, sizeof(wk
->wk_key
));
1671 memcpy(wk
->wk_key
, ik
.ik_keydata
, ik
.ik_keylen
);
1672 if (!ieee80211_crypto_setkey(ic
, wk
,
1673 ni
!= NULL
? ni
->ni_macaddr
: ik
.ik_macaddr
))
1675 else if ((ik
.ik_flags
& IEEE80211_KEY_DEFAULT
))
1676 ic
->ic_def_txkey
= kid
;
1679 ieee80211_key_update_end(ic
);
1681 ieee80211_free_node(ni
);
1686 ieee80211_ioctl_delkey(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1688 struct ieee80211req_del_key dk
;
1691 if (ireq
->i_len
!= sizeof(dk
))
1693 error
= copyin(ireq
->i_data
, &dk
, sizeof(dk
));
1697 /* XXX u_int8_t -> u_int16_t */
1698 if (dk
.idk_keyix
== (u_int8_t
) IEEE80211_KEYIX_NONE
) {
1699 struct ieee80211_node
*ni
;
1701 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
1702 ni
= ieee80211_ref_node(ic
->ic_bss
);
1703 if (!IEEE80211_ADDR_EQ(dk
.idk_macaddr
, ni
->ni_bssid
)) {
1704 ieee80211_free_node(ni
);
1705 return EADDRNOTAVAIL
;
1708 ni
= ieee80211_find_node(&ic
->ic_sta
, dk
.idk_macaddr
);
1712 /* XXX error return */
1713 ieee80211_node_delucastkey(ni
);
1714 ieee80211_free_node(ni
);
1716 if (kid
>= IEEE80211_WEP_NKID
)
1718 /* XXX error return */
1719 ieee80211_crypto_delkey(ic
, &ic
->ic_nw_keys
[kid
]);
1724 #ifndef IEEE80211_NO_HOSTAP
1726 domlme(void *arg
, struct ieee80211_node
*ni
)
1728 struct ieee80211com
*ic
= ni
->ni_ic
;
1729 struct ieee80211req_mlme
*mlme
= arg
;
1731 if (ni
->ni_associd
!= 0) {
1732 IEEE80211_SEND_MGMT(ic
, ni
,
1733 mlme
->im_op
== IEEE80211_MLME_DEAUTH
?
1734 IEEE80211_FC0_SUBTYPE_DEAUTH
:
1735 IEEE80211_FC0_SUBTYPE_DISASSOC
,
1738 ieee80211_node_leave(ic
, ni
);
1740 #endif /* !IEEE80211_NO_HOSTAP */
1743 ieee80211_ioctl_setmlme(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1745 struct ieee80211req_mlme mlme
;
1746 struct ieee80211_node
*ni
;
1749 if (ireq
->i_len
!= sizeof(mlme
))
1751 error
= copyin(ireq
->i_data
, &mlme
, sizeof(mlme
));
1754 switch (mlme
.im_op
) {
1755 case IEEE80211_MLME_ASSOC
:
1756 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
1758 /* XXX must be in S_SCAN state? */
1760 if (mlme
.im_ssid_len
!= 0) {
1762 * Desired ssid specified; must match both bssid and
1763 * ssid to distinguish ap advertising multiple ssid's.
1765 ni
= ieee80211_find_node_with_ssid(&ic
->ic_scan
,
1767 mlme
.im_ssid_len
, mlme
.im_ssid
);
1770 * Normal case; just match bssid.
1772 ni
= ieee80211_find_node(&ic
->ic_scan
, mlme
.im_macaddr
);
1776 if (!ieee80211_sta_join(ic
, ni
)) {
1777 ieee80211_free_node(ni
);
1781 case IEEE80211_MLME_DISASSOC
:
1782 case IEEE80211_MLME_DEAUTH
:
1783 switch (ic
->ic_opmode
) {
1784 case IEEE80211_M_STA
:
1785 /* XXX not quite right */
1786 ieee80211_new_state(ic
, IEEE80211_S_INIT
,
1789 case IEEE80211_M_HOSTAP
:
1790 #ifndef IEEE80211_NO_HOSTAP
1791 /* NB: the broadcast address means do 'em all */
1792 if (!IEEE80211_ADDR_EQ(mlme
.im_macaddr
, ic
->ic_ifp
->if_broadcastaddr
)) {
1793 if ((ni
= ieee80211_find_node(&ic
->ic_sta
,
1794 mlme
.im_macaddr
)) == NULL
)
1797 ieee80211_free_node(ni
);
1799 ieee80211_iterate_nodes(&ic
->ic_sta
,
1802 #endif /* !IEEE80211_NO_HOSTAP */
1808 case IEEE80211_MLME_AUTHORIZE
:
1809 case IEEE80211_MLME_UNAUTHORIZE
:
1810 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
1812 ni
= ieee80211_find_node(&ic
->ic_sta
, mlme
.im_macaddr
);
1815 if (mlme
.im_op
== IEEE80211_MLME_AUTHORIZE
)
1816 ieee80211_node_authorize(ni
);
1818 ieee80211_node_unauthorize(ni
);
1819 ieee80211_free_node(ni
);
1828 ieee80211_ioctl_macmac(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1830 u_int8_t mac
[IEEE80211_ADDR_LEN
];
1831 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1834 if (ireq
->i_len
!= sizeof(mac
))
1836 error
= copyin(ireq
->i_data
, mac
, ireq
->i_len
);
1840 acl
= ieee80211_aclator_get("mac");
1841 if (acl
== NULL
|| !acl
->iac_attach(ic
))
1845 if (ireq
->i_type
== IEEE80211_IOC_ADDMAC
)
1846 acl
->iac_add(ic
, mac
);
1848 acl
->iac_remove(ic
, mac
);
1853 ieee80211_ioctl_setmaccmd(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1855 const struct ieee80211_aclator
*acl
= ic
->ic_acl
;
1857 switch (ireq
->i_val
) {
1858 case IEEE80211_MACCMD_POLICY_OPEN
:
1859 case IEEE80211_MACCMD_POLICY_ALLOW
:
1860 case IEEE80211_MACCMD_POLICY_DENY
:
1862 acl
= ieee80211_aclator_get("mac");
1863 if (acl
== NULL
|| !acl
->iac_attach(ic
))
1867 acl
->iac_setpolicy(ic
, ireq
->i_val
);
1869 case IEEE80211_MACCMD_FLUSH
:
1872 /* NB: silently ignore when not in use */
1874 case IEEE80211_MACCMD_DETACH
:
1877 acl
->iac_detach(ic
);
1884 return acl
->iac_setioctl(ic
, ireq
);
1890 ieee80211_ioctl_setchanlist(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1892 struct ieee80211req_chanlist list
;
1893 u_int8_t chanlist
[IEEE80211_CHAN_BYTES
];
1896 if (ireq
->i_len
!= sizeof(list
))
1898 error
= copyin(ireq
->i_data
, &list
, sizeof(list
));
1901 memset(chanlist
, 0, sizeof(chanlist
));
1903 * Since channel 0 is not available for DS, channel 1
1904 * is assigned to LSB on WaveLAN.
1906 if (ic
->ic_phytype
== IEEE80211_T_DS
)
1910 for (j
= 0; i
<= IEEE80211_CHAN_MAX
; i
++, j
++) {
1912 * NB: silently discard unavailable channels so users
1913 * can specify 1-255 to get all available channels.
1915 if (isset(list
.ic_channels
, j
) && isset(ic
->ic_chan_avail
, i
))
1916 setbit(chanlist
, i
);
1918 if (ic
->ic_ibss_chan
== NULL
||
1919 isclr(chanlist
, ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
))) {
1920 for (i
= 0; i
<= IEEE80211_CHAN_MAX
; i
++)
1921 if (isset(chanlist
, i
)) {
1922 ic
->ic_ibss_chan
= &ic
->ic_channels
[i
];
1925 return EINVAL
; /* no active channels */
1929 memcpy(ic
->ic_chan_active
, chanlist
, sizeof(ic
->ic_chan_active
));
1930 return IS_UP_AUTO(ic
) ? ENETRESET
: 0;
1934 ieee80211_ioctl_setstatxpow(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1936 struct ieee80211_node
*ni
;
1937 struct ieee80211req_sta_txpow txpow
;
1940 if (ireq
->i_len
!= sizeof(txpow
))
1942 error
= copyin(ireq
->i_data
, &txpow
, sizeof(txpow
));
1945 ni
= ieee80211_find_node(&ic
->ic_sta
, txpow
.it_macaddr
);
1947 return EINVAL
; /* XXX */
1948 ni
->ni_txpower
= txpow
.it_txpow
;
1949 ieee80211_free_node(ni
);
1954 ieee80211_ioctl_setwmeparam(struct ieee80211com
*ic
, struct ieee80211req
*ireq
)
1956 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
1957 struct wmeParams
*wmep
, *chanp
;
1960 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
1963 isbss
= (ireq
->i_len
& IEEE80211_WMEPARAM_BSS
);
1964 ac
= (ireq
->i_len
& IEEE80211_WMEPARAM_VAL
);
1965 if (ac
>= WME_NUM_AC
)
1968 chanp
= &wme
->wme_bssChanParams
.cap_wmeParams
[ac
];
1969 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[ac
];
1971 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[ac
];
1972 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[ac
];
1974 switch (ireq
->i_type
) {
1975 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
1977 wmep
->wmep_logcwmin
= ireq
->i_val
;
1978 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1979 chanp
->wmep_logcwmin
= ireq
->i_val
;
1981 wmep
->wmep_logcwmin
= chanp
->wmep_logcwmin
=
1985 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
1987 wmep
->wmep_logcwmax
= ireq
->i_val
;
1988 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1989 chanp
->wmep_logcwmax
= ireq
->i_val
;
1991 wmep
->wmep_logcwmax
= chanp
->wmep_logcwmax
=
1995 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
1997 wmep
->wmep_aifsn
= ireq
->i_val
;
1998 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
1999 chanp
->wmep_aifsn
= ireq
->i_val
;
2001 wmep
->wmep_aifsn
= chanp
->wmep_aifsn
= ireq
->i_val
;
2004 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
2006 wmep
->wmep_txopLimit
= ireq
->i_val
;
2007 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2008 chanp
->wmep_txopLimit
= ireq
->i_val
;
2010 wmep
->wmep_txopLimit
= chanp
->wmep_txopLimit
=
2014 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
2015 wmep
->wmep_acm
= ireq
->i_val
;
2016 if ((wme
->wme_flags
& WME_F_AGGRMODE
) == 0)
2017 chanp
->wmep_acm
= ireq
->i_val
;
2019 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (!bss only)*/
2020 wmep
->wmep_noackPolicy
= chanp
->wmep_noackPolicy
=
2024 ieee80211_wme_updateparams(ic
);
2029 cipher2cap(int cipher
)
2032 case IEEE80211_CIPHER_WEP
: return IEEE80211_C_WEP
;
2033 case IEEE80211_CIPHER_AES_OCB
: return IEEE80211_C_AES
;
2034 case IEEE80211_CIPHER_AES_CCM
: return IEEE80211_C_AES_CCM
;
2035 case IEEE80211_CIPHER_CKIP
: return IEEE80211_C_CKIP
;
2036 case IEEE80211_CIPHER_TKIP
: return IEEE80211_C_TKIP
;
2042 ieee80211_ioctl_set80211(struct ieee80211com
*ic
, u_long cmd
,
2043 struct ieee80211req
*ireq
)
2045 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211)
2046 static const u_int8_t zerobssid
[IEEE80211_ADDR_LEN
];
2047 u_int8_t tmpkey
[IEEE80211_KEYBUF_SIZE
];
2048 char tmpssid
[IEEE80211_NWID_LEN
];
2049 u_int8_t tmpbssid
[IEEE80211_ADDR_LEN
];
2050 struct ieee80211_key
*k
;
2052 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */
2053 struct ieee80211_rsnparms
*rsn
= &ic
->ic_bss
->ni_rsn
;
2055 const struct ieee80211_authenticator
*auth
;
2059 switch (ireq
->i_type
) {
2060 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211)
2061 case IEEE80211_IOC_SSID
:
2062 if (ireq
->i_val
!= 0 ||
2063 ireq
->i_len
> IEEE80211_NWID_LEN
)
2065 error
= copyin(ireq
->i_data
, tmpssid
, ireq
->i_len
);
2068 memset(ic
->ic_des_essid
, 0, IEEE80211_NWID_LEN
);
2069 ic
->ic_des_esslen
= ireq
->i_len
;
2070 memcpy(ic
->ic_des_essid
, tmpssid
, ireq
->i_len
);
2073 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */
2074 case IEEE80211_IOC_WEP
:
2075 switch (ireq
->i_val
) {
2076 case IEEE80211_WEP_OFF
:
2077 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
2078 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2080 case IEEE80211_WEP_ON
:
2081 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2082 ic
->ic_flags
|= IEEE80211_F_DROPUNENC
;
2084 case IEEE80211_WEP_MIXED
:
2085 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2086 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2091 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211)
2092 case IEEE80211_IOC_WEPKEY
:
2093 kid
= (u_int
) ireq
->i_val
;
2094 if (kid
>= IEEE80211_WEP_NKID
)
2096 k
= &ic
->ic_nw_keys
[kid
];
2097 if (ireq
->i_len
== 0) {
2098 /* zero-len =>'s delete any existing key */
2099 (void) ieee80211_crypto_delkey(ic
, k
);
2102 if (ireq
->i_len
> sizeof(tmpkey
))
2104 memset(tmpkey
, 0, sizeof(tmpkey
));
2105 error
= copyin(ireq
->i_data
, tmpkey
, ireq
->i_len
);
2108 ieee80211_key_update_begin(ic
);
2109 k
->wk_keyix
= kid
; /* NB: force fixed key id */
2110 if (ieee80211_crypto_newkey(ic
, IEEE80211_CIPHER_WEP
,
2111 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, k
)) {
2112 k
->wk_keylen
= ireq
->i_len
;
2113 memcpy(k
->wk_key
, tmpkey
, sizeof(tmpkey
));
2114 if (!ieee80211_crypto_setkey(ic
, k
, ic
->ic_myaddr
))
2118 ieee80211_key_update_end(ic
);
2119 if (!error
) /* NB: for compatibility */
2122 case IEEE80211_IOC_WEPTXKEY
:
2123 kid
= (u_int
) ireq
->i_val
;
2124 if (kid
>= IEEE80211_WEP_NKID
&&
2125 (u_int16_t
) kid
!= IEEE80211_KEYIX_NONE
)
2127 ic
->ic_def_txkey
= kid
;
2128 error
= ENETRESET
; /* push to hardware */
2130 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */
2131 case IEEE80211_IOC_AUTHMODE
:
2132 switch (ireq
->i_val
) {
2133 case IEEE80211_AUTH_WPA
:
2134 case IEEE80211_AUTH_8021X
: /* 802.1x */
2135 case IEEE80211_AUTH_OPEN
: /* open */
2136 case IEEE80211_AUTH_SHARED
: /* shared-key */
2137 case IEEE80211_AUTH_AUTO
: /* auto */
2138 auth
= ieee80211_authenticator_get(ireq
->i_val
);
2145 switch (ireq
->i_val
) {
2146 case IEEE80211_AUTH_WPA
: /* WPA w/ 802.1x */
2147 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2148 ireq
->i_val
= IEEE80211_AUTH_8021X
;
2150 case IEEE80211_AUTH_OPEN
: /* open */
2151 ic
->ic_flags
&= ~(IEEE80211_F_WPA
|IEEE80211_F_PRIVACY
);
2153 case IEEE80211_AUTH_SHARED
: /* shared-key */
2154 case IEEE80211_AUTH_8021X
: /* 802.1x */
2155 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2156 /* both require a key so mark the PRIVACY capability */
2157 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2159 case IEEE80211_AUTH_AUTO
: /* auto */
2160 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2161 /* XXX PRIVACY handling? */
2162 /* XXX what's the right way to do this? */
2165 /* NB: authenticator attach/detach happens on state change */
2166 ic
->ic_bss
->ni_authmode
= ireq
->i_val
;
2167 /* XXX mixed/mode/usage? */
2171 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211)
2172 case IEEE80211_IOC_CHANNEL
:
2173 /* XXX 0xffff overflows 16-bit signed */
2174 if (ireq
->i_val
== 0 ||
2175 ireq
->i_val
== (int16_t) IEEE80211_CHAN_ANY
)
2176 ic
->ic_des_chan
= IEEE80211_CHAN_ANYC
;
2177 else if ((u_int
) ireq
->i_val
> IEEE80211_CHAN_MAX
||
2178 isclr(ic
->ic_chan_active
, ireq
->i_val
)) {
2181 ic
->ic_ibss_chan
= ic
->ic_des_chan
=
2182 &ic
->ic_channels
[ireq
->i_val
];
2183 switch (ic
->ic_state
) {
2184 case IEEE80211_S_INIT
:
2185 case IEEE80211_S_SCAN
:
2190 * If the desired channel has changed (to something
2191 * other than any) and we're not already scanning,
2192 * then kick the state machine.
2194 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
&&
2195 ic
->ic_bss
->ni_chan
!= ic
->ic_des_chan
&&
2196 (ic
->ic_flags
& IEEE80211_F_SCAN
) == 0)
2200 if (error
== ENETRESET
&&
2201 ic
->ic_opmode
== IEEE80211_M_MONITOR
) {
2204 * Monitor mode can switch directly.
2206 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)
2207 ic
->ic_curchan
= ic
->ic_des_chan
;
2208 error
= ic
->ic_reset(ic
->ic_ifp
);
2213 case IEEE80211_IOC_POWERSAVE
:
2214 switch (ireq
->i_val
) {
2215 case IEEE80211_POWERSAVE_OFF
:
2216 if (ic
->ic_flags
& IEEE80211_F_PMGTON
) {
2217 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
2221 case IEEE80211_POWERSAVE_ON
:
2222 if ((ic
->ic_caps
& IEEE80211_C_PMGT
) == 0)
2224 else if ((ic
->ic_flags
& IEEE80211_F_PMGTON
) == 0) {
2225 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
2234 case IEEE80211_IOC_POWERSAVESLEEP
:
2235 if (ireq
->i_val
< 0)
2237 ic
->ic_lintval
= ireq
->i_val
;
2238 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2240 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */
2241 case IEEE80211_IOC_RTSTHRESHOLD
:
2242 if (!(IEEE80211_RTS_MIN
<= ireq
->i_val
&&
2243 ireq
->i_val
<= IEEE80211_RTS_MAX
))
2245 ic
->ic_rtsthreshold
= ireq
->i_val
;
2246 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2248 case IEEE80211_IOC_PROTMODE
:
2249 if (ireq
->i_val
> IEEE80211_PROT_RTSCTS
)
2251 ic
->ic_protmode
= ireq
->i_val
;
2252 /* NB: if not operating in 11g this can wait */
2253 if (ic
->ic_curmode
== IEEE80211_MODE_11G
)
2254 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2256 case IEEE80211_IOC_TXPOWER
:
2257 if ((ic
->ic_caps
& IEEE80211_C_TXPMGT
) == 0)
2259 if (!(IEEE80211_TXPOWER_MIN
< ireq
->i_val
&&
2260 ireq
->i_val
< IEEE80211_TXPOWER_MAX
))
2262 ic
->ic_txpowlimit
= ireq
->i_val
;
2263 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2265 case IEEE80211_IOC_ROAMING
:
2266 if (!(IEEE80211_ROAMING_DEVICE
<= ireq
->i_val
&&
2267 ireq
->i_val
<= IEEE80211_ROAMING_MANUAL
))
2269 ic
->ic_roaming
= ireq
->i_val
;
2272 case IEEE80211_IOC_PRIVACY
:
2274 /* XXX check for key state? */
2275 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2277 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
2279 case IEEE80211_IOC_DROPUNENCRYPTED
:
2281 ic
->ic_flags
|= IEEE80211_F_DROPUNENC
;
2283 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2285 case IEEE80211_IOC_WPAKEY
:
2286 error
= ieee80211_ioctl_setkey(ic
, ireq
);
2288 case IEEE80211_IOC_DELKEY
:
2289 error
= ieee80211_ioctl_delkey(ic
, ireq
);
2291 case IEEE80211_IOC_MLME
:
2292 error
= ieee80211_ioctl_setmlme(ic
, ireq
);
2294 case IEEE80211_IOC_OPTIE
:
2295 error
= ieee80211_ioctl_setoptie(ic
, ireq
);
2297 case IEEE80211_IOC_COUNTERMEASURES
:
2299 if ((ic
->ic_flags
& IEEE80211_F_WPA
) == 0)
2301 ic
->ic_flags
|= IEEE80211_F_COUNTERM
;
2303 ic
->ic_flags
&= ~IEEE80211_F_COUNTERM
;
2305 case IEEE80211_IOC_WPA
:
2306 if (ireq
->i_val
> 3)
2308 /* XXX verify ciphers available */
2309 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2310 switch (ireq
->i_val
) {
2312 ic
->ic_flags
|= IEEE80211_F_WPA1
;
2315 ic
->ic_flags
|= IEEE80211_F_WPA2
;
2318 ic
->ic_flags
|= IEEE80211_F_WPA1
| IEEE80211_F_WPA2
;
2321 error
= ENETRESET
; /* XXX? */
2323 case IEEE80211_IOC_WME
:
2325 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
2327 ic
->ic_flags
|= IEEE80211_F_WME
;
2329 ic
->ic_flags
&= ~IEEE80211_F_WME
;
2330 error
= ENETRESET
; /* XXX maybe not for station? */
2332 case IEEE80211_IOC_HIDESSID
:
2334 ic
->ic_flags
|= IEEE80211_F_HIDESSID
;
2336 ic
->ic_flags
&= ~IEEE80211_F_HIDESSID
;
2339 case IEEE80211_IOC_APBRIDGE
:
2340 if (ireq
->i_val
== 0)
2341 ic
->ic_flags
|= IEEE80211_F_NOBRIDGE
;
2343 ic
->ic_flags
&= ~IEEE80211_F_NOBRIDGE
;
2345 case IEEE80211_IOC_MCASTCIPHER
:
2346 if ((ic
->ic_caps
& cipher2cap(ireq
->i_val
)) == 0 &&
2347 !ieee80211_crypto_available(ireq
->i_val
))
2349 rsn
->rsn_mcastcipher
= ireq
->i_val
;
2350 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2352 case IEEE80211_IOC_MCASTKEYLEN
:
2353 if (!(0 < ireq
->i_val
&& ireq
->i_val
< IEEE80211_KEYBUF_SIZE
))
2355 /* XXX no way to verify driver capability */
2356 rsn
->rsn_mcastkeylen
= ireq
->i_val
;
2357 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2359 case IEEE80211_IOC_UCASTCIPHERS
:
2361 * Convert user-specified cipher set to the set
2362 * we can support (via hardware or software).
2363 * NB: this logic intentionally ignores unknown and
2364 * unsupported ciphers so folks can specify 0xff or
2365 * similar and get all available ciphers.
2368 for (j
= 1; j
< 32; j
++) /* NB: skip WEP */
2369 if ((ireq
->i_val
& (1<<j
)) &&
2370 ((ic
->ic_caps
& cipher2cap(j
)) ||
2371 ieee80211_crypto_available(j
)))
2373 if (caps
== 0) /* nothing available */
2375 /* XXX verify ciphers ok for unicast use? */
2376 /* XXX disallow if running as it'll have no effect */
2377 rsn
->rsn_ucastcipherset
= caps
;
2378 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2380 case IEEE80211_IOC_UCASTCIPHER
:
2381 if ((rsn
->rsn_ucastcipherset
& cipher2cap(ireq
->i_val
)) == 0)
2383 rsn
->rsn_ucastcipher
= ireq
->i_val
;
2385 case IEEE80211_IOC_UCASTKEYLEN
:
2386 if (!(0 < ireq
->i_val
&& ireq
->i_val
< IEEE80211_KEYBUF_SIZE
))
2388 /* XXX no way to verify driver capability */
2389 rsn
->rsn_ucastkeylen
= ireq
->i_val
;
2391 case IEEE80211_IOC_DRIVER_CAPS
:
2392 /* NB: for testing */
2393 ic
->ic_caps
= (((u_int16_t
) ireq
->i_val
) << 16) |
2394 ((u_int16_t
) ireq
->i_len
);
2396 case IEEE80211_IOC_KEYMGTALGS
:
2398 rsn
->rsn_keymgmtset
= ireq
->i_val
;
2399 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2401 case IEEE80211_IOC_RSNCAPS
:
2403 rsn
->rsn_caps
= ireq
->i_val
;
2404 error
= (ic
->ic_flags
& IEEE80211_F_WPA
) ? ENETRESET
: 0;
2406 #if defined(__FreeBSD__) || defined(COMPAT_FREEBSD_NET80211)
2407 case IEEE80211_IOC_BSSID
:
2408 /* NB: should only be set when in STA mode */
2409 if (ic
->ic_opmode
!= IEEE80211_M_STA
)
2411 if (ireq
->i_len
!= sizeof(tmpbssid
))
2413 error
= copyin(ireq
->i_data
, tmpbssid
, ireq
->i_len
);
2416 IEEE80211_ADDR_COPY(ic
->ic_des_bssid
, tmpbssid
);
2417 if (IEEE80211_ADDR_EQ(ic
->ic_des_bssid
, zerobssid
))
2418 ic
->ic_flags
&= ~IEEE80211_F_DESBSSID
;
2420 ic
->ic_flags
|= IEEE80211_F_DESBSSID
;
2423 #endif /* __FreeBSD__ || COMPAT_FREEBSD_NET80211 */
2424 case IEEE80211_IOC_CHANLIST
:
2425 error
= ieee80211_ioctl_setchanlist(ic
, ireq
);
2427 case IEEE80211_IOC_SCAN_REQ
:
2428 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) /* XXX ignore */
2430 error
= ieee80211_setupscan(ic
, ic
->ic_chan_avail
);
2431 if (error
== 0) /* XXX background scan */
2432 error
= ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
2434 case IEEE80211_IOC_ADDMAC
:
2435 case IEEE80211_IOC_DELMAC
:
2436 error
= ieee80211_ioctl_macmac(ic
, ireq
);
2438 case IEEE80211_IOC_MACCMD
:
2439 error
= ieee80211_ioctl_setmaccmd(ic
, ireq
);
2441 case IEEE80211_IOC_STA_TXPOW
:
2442 error
= ieee80211_ioctl_setstatxpow(ic
, ireq
);
2444 case IEEE80211_IOC_WME_CWMIN
: /* WME: CWmin */
2445 case IEEE80211_IOC_WME_CWMAX
: /* WME: CWmax */
2446 case IEEE80211_IOC_WME_AIFS
: /* WME: AIFS */
2447 case IEEE80211_IOC_WME_TXOPLIMIT
: /* WME: txops limit */
2448 case IEEE80211_IOC_WME_ACM
: /* WME: ACM (bss only) */
2449 case IEEE80211_IOC_WME_ACKPOLICY
: /* WME: ACK policy (bss only) */
2450 error
= ieee80211_ioctl_setwmeparam(ic
, ireq
);
2452 case IEEE80211_IOC_DTIM_PERIOD
:
2453 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
2454 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
2456 if (IEEE80211_DTIM_MIN
<= ireq
->i_val
&&
2457 ireq
->i_val
<= IEEE80211_DTIM_MAX
) {
2458 ic
->ic_dtim_period
= ireq
->i_val
;
2459 error
= ENETRESET
; /* requires restart */
2463 case IEEE80211_IOC_BEACON_INTERVAL
:
2464 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
2465 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
2467 if (IEEE80211_BINTVAL_MIN
<= ireq
->i_val
&&
2468 ireq
->i_val
<= IEEE80211_BINTVAL_MAX
) {
2469 ic
->ic_bintval
= ireq
->i_val
;
2470 error
= ENETRESET
; /* requires restart */
2474 case IEEE80211_IOC_PUREG
:
2476 ic
->ic_flags
|= IEEE80211_F_PUREG
;
2478 ic
->ic_flags
&= ~IEEE80211_F_PUREG
;
2479 /* NB: reset only if we're operating on an 11g channel */
2480 if (ic
->ic_curmode
== IEEE80211_MODE_11G
)
2483 case IEEE80211_IOC_MCAST_RATE
:
2484 ic
->ic_mcast_rate
= ireq
->i_val
& IEEE80211_RATE_VAL
;
2486 case IEEE80211_IOC_FRAGTHRESHOLD
:
2487 if ((ic
->ic_caps
& IEEE80211_C_TXFRAG
) == 0 &&
2488 ireq
->i_val
!= IEEE80211_FRAG_MAX
)
2490 if (!(IEEE80211_FRAG_MIN
<= ireq
->i_val
&&
2491 ireq
->i_val
<= IEEE80211_FRAG_MAX
))
2493 ic
->ic_fragthreshold
= ireq
->i_val
;
2494 error
= IS_UP(ic
) ? ic
->ic_reset(ic
->ic_ifp
) : 0;
2500 if (error
== ENETRESET
&& !IS_UP_AUTO(ic
))
2507 ieee80211_ioctl(struct ieee80211com
*ic
, u_long cmd
, void *data
)
2509 struct ifnet
*ifp
= ic
->ic_ifp
;
2512 struct ifaddr
*ifa
; /* XXX */
2517 error
= ifmedia_ioctl(ifp
, (struct ifreq
*) data
,
2518 &ic
->ic_media
, cmd
);
2521 error
= ieee80211_ioctl_get80211(ic
, cmd
,
2522 (struct ieee80211req
*) data
);
2525 error
= suser(curthread
);
2527 error
= ieee80211_ioctl_set80211(ic
, cmd
,
2528 (struct ieee80211req
*) data
);
2530 case SIOCGIFGENERIC
:
2531 error
= ieee80211_cfgget(ic
, cmd
, data
);
2533 case SIOCSIFGENERIC
:
2534 error
= suser(curthread
);
2537 error
= ieee80211_cfgset(ic
, cmd
, data
);
2539 case SIOCG80211STATS
:
2540 ifr
= (struct ifreq
*)data
;
2541 copyout(&ic
->ic_stats
, ifr
->ifr_data
, sizeof (ic
->ic_stats
));
2544 ifr
= (struct ifreq
*)data
;
2545 if (!(IEEE80211_MTU_MIN
<= ifr
->ifr_mtu
&&
2546 ifr
->ifr_mtu
<= IEEE80211_MTU_MAX
))
2549 ifp
->if_mtu
= ifr
->ifr_mtu
;
2552 error
= ether_ioctl(ifp
, cmd
, data
);
2557 #endif /* __FreeBSD__ */
2561 ieee80211_get_ostats(struct ieee80211_ostats
*ostats
,
2562 struct ieee80211_stats
*stats
)
2564 #define COPYSTATS1(__ostats, __nstats, __dstmemb, __srcmemb, __lastmemb)\
2565 (void)memcpy(&(__ostats)->__dstmemb, &(__nstats)->__srcmemb, \
2566 offsetof(struct ieee80211_stats, __lastmemb) - \
2567 offsetof(struct ieee80211_stats, __srcmemb))
2568 #define COPYSTATS(__ostats, __nstats, __dstmemb, __lastmemb) \
2569 COPYSTATS1(__ostats, __nstats, __dstmemb, __dstmemb, __lastmemb)
2571 COPYSTATS(ostats
, stats
, is_rx_badversion
, is_rx_unencrypted
);
2572 COPYSTATS(ostats
, stats
, is_rx_wepfail
, is_rx_beacon
);
2573 COPYSTATS(ostats
, stats
, is_rx_rstoobig
, is_rx_auth_countermeasures
);
2574 COPYSTATS(ostats
, stats
, is_rx_assoc_bss
, is_rx_assoc_badwpaie
);
2575 COPYSTATS(ostats
, stats
, is_rx_deauth
, is_rx_unauth
);
2576 COPYSTATS1(ostats
, stats
, is_tx_nombuf
, is_tx_nobuf
, is_tx_badcipher
);
2577 COPYSTATS(ostats
, stats
, is_scan_active
, is_crypto_tkip
);
2579 #endif /* COMPAT_20 */
2583 ieee80211_ioctl(struct ieee80211com
*ic
, u_long cmd
, void *data
)
2585 struct ifnet
*ifp
= ic
->ic_ifp
;
2586 struct ifreq
*ifr
= (struct ifreq
*)data
;
2587 int i
, error
= 0, kid
, klen
, s
;
2588 struct ieee80211_key
*k
;
2589 struct ieee80211_nwid nwid
;
2590 struct ieee80211_nwkey
*nwkey
;
2591 struct ieee80211_power
*power
;
2592 struct ieee80211_bssid
*bssid
;
2593 struct ieee80211chanreq
*chanreq
;
2594 struct ieee80211_channel
*chan
;
2597 struct ieee80211_ostats ostats
;
2598 #endif /* COMPAT_20 */
2599 static const u_int8_t zerobssid
[IEEE80211_ADDR_LEN
];
2600 u_int8_t tmpkey
[IEEE80211_WEP_NKID
][IEEE80211_KEYBUF_SIZE
];
2603 #ifdef OSIOCSIFMEDIA
2608 error
= ifmedia_ioctl(ifp
, ifr
, &ic
->ic_media
, cmd
);
2611 error
= ieee80211_ioctl_get80211(ic
, cmd
,
2612 (struct ieee80211req
*) data
);
2615 if ((error
= kauth_authorize_network(curlwp
->l_cred
,
2616 KAUTH_NETWORK_INTERFACE
,
2617 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
2620 error
= ieee80211_ioctl_set80211(ic
, cmd
,
2621 (struct ieee80211req
*) data
);
2623 case SIOCS80211NWID
:
2624 if ((error
= copyin(ifr
->ifr_data
, &nwid
, sizeof(nwid
))) != 0)
2626 if (nwid
.i_len
> IEEE80211_NWID_LEN
) {
2630 memset(ic
->ic_des_essid
, 0, IEEE80211_NWID_LEN
);
2631 ic
->ic_des_esslen
= nwid
.i_len
;
2632 memcpy(ic
->ic_des_essid
, nwid
.i_nwid
, nwid
.i_len
);
2635 case SIOCG80211NWID
:
2636 memset(&nwid
, 0, sizeof(nwid
));
2637 switch (ic
->ic_state
) {
2638 case IEEE80211_S_INIT
:
2639 case IEEE80211_S_SCAN
:
2640 nwid
.i_len
= ic
->ic_des_esslen
;
2641 memcpy(nwid
.i_nwid
, ic
->ic_des_essid
, nwid
.i_len
);
2644 nwid
.i_len
= ic
->ic_bss
->ni_esslen
;
2645 memcpy(nwid
.i_nwid
, ic
->ic_bss
->ni_essid
, nwid
.i_len
);
2648 error
= copyout(&nwid
, ifr
->ifr_data
, sizeof(nwid
));
2650 case SIOCS80211NWKEY
:
2651 nwkey
= (struct ieee80211_nwkey
*)data
;
2652 /* transmit key index out of range? */
2653 kid
= nwkey
->i_defkid
- 1;
2654 if (kid
< 0 || kid
>= IEEE80211_WEP_NKID
) {
2658 /* no such transmit key is set? */
2659 if (nwkey
->i_key
[kid
].i_keylen
== 0 ||
2660 (nwkey
->i_key
[kid
].i_keylen
== -1 &&
2661 ic
->ic_nw_keys
[kid
].wk_keylen
== 0)) {
2662 if (nwkey
->i_wepon
!= IEEE80211_NWKEY_OPEN
) {
2667 /* check key lengths */
2668 for (kid
= 0; kid
< IEEE80211_WEP_NKID
; kid
++) {
2669 klen
= nwkey
->i_key
[kid
].i_keylen
;
2671 klen
< IEEE80211_WEP_KEYLEN
) ||
2672 klen
> sizeof(ic
->ic_nw_keys
[kid
].wk_key
)) {
2682 (void)memset(tmpkey
, 0, sizeof(tmpkey
));
2683 for (kid
= 0; kid
< IEEE80211_WEP_NKID
; kid
++) {
2684 klen
= nwkey
->i_key
[kid
].i_keylen
;
2687 if ((error
= copyin(nwkey
->i_key
[kid
].i_keydat
,
2688 tmpkey
[kid
], klen
)) != 0)
2696 ieee80211_key_update_begin(ic
);
2697 for (kid
= 0; kid
< IEEE80211_WEP_NKID
; kid
++) {
2698 klen
= nwkey
->i_key
[kid
].i_keylen
;
2701 k
= &ic
->ic_nw_keys
[kid
];
2703 if (!ieee80211_crypto_newkey(ic
, IEEE80211_CIPHER_WEP
,
2704 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, k
)) {
2708 k
->wk_keylen
= nwkey
->i_key
[kid
].i_keylen
;
2709 (void)memcpy(k
->wk_key
, tmpkey
[kid
],
2710 sizeof(tmpkey
[kid
]));
2711 if (!ieee80211_crypto_setkey(ic
, k
, ic
->ic_myaddr
))
2714 ieee80211_key_update_end(ic
);
2720 for (kid
= 0; kid
< IEEE80211_WEP_NKID
; kid
++) {
2721 klen
= nwkey
->i_key
[kid
].i_keylen
;
2722 k
= &ic
->ic_nw_keys
[kid
];
2724 (void)ieee80211_crypto_delkey(ic
, k
);
2727 /* set transmit key */
2728 kid
= nwkey
->i_defkid
- 1;
2729 if (ic
->ic_def_txkey
!= kid
) {
2730 ic
->ic_def_txkey
= kid
;
2733 oflags
= ic
->ic_flags
;
2734 if (nwkey
->i_wepon
== IEEE80211_NWKEY_OPEN
) {
2735 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
2736 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2738 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
2739 ic
->ic_flags
|= IEEE80211_F_DROPUNENC
;
2741 if (oflags
!= ic
->ic_flags
)
2744 case SIOCG80211NWKEY
:
2745 nwkey
= (struct ieee80211_nwkey
*)data
;
2746 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
2747 nwkey
->i_wepon
= IEEE80211_NWKEY_WEP
;
2749 nwkey
->i_wepon
= IEEE80211_NWKEY_OPEN
;
2750 nwkey
->i_defkid
= ic
->ic_def_txkey
+ 1;
2751 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2752 if (nwkey
->i_key
[i
].i_keydat
== NULL
)
2754 /* do not show any keys to non-root user */
2755 if ((error
= kauth_authorize_network(curlwp
->l_cred
,
2756 KAUTH_NETWORK_INTERFACE
,
2757 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV
, ifp
,
2758 (void *)cmd
, NULL
)) != 0)
2760 nwkey
->i_key
[i
].i_keylen
= ic
->ic_nw_keys
[i
].wk_keylen
;
2761 if ((error
= copyout(ic
->ic_nw_keys
[i
].wk_key
,
2762 nwkey
->i_key
[i
].i_keydat
,
2763 ic
->ic_nw_keys
[i
].wk_keylen
)) != 0)
2767 case SIOCS80211POWER
:
2768 power
= (struct ieee80211_power
*)data
;
2769 ic
->ic_lintval
= power
->i_maxsleep
;
2770 if (power
->i_enabled
!= 0) {
2771 if ((ic
->ic_caps
& IEEE80211_C_PMGT
) == 0)
2773 else if ((ic
->ic_flags
& IEEE80211_F_PMGTON
) == 0) {
2774 ic
->ic_flags
|= IEEE80211_F_PMGTON
;
2778 if (ic
->ic_flags
& IEEE80211_F_PMGTON
) {
2779 ic
->ic_flags
&= ~IEEE80211_F_PMGTON
;
2784 case SIOCG80211POWER
:
2785 power
= (struct ieee80211_power
*)data
;
2786 power
->i_enabled
= (ic
->ic_flags
& IEEE80211_F_PMGTON
) ? 1 : 0;
2787 power
->i_maxsleep
= ic
->ic_lintval
;
2789 case SIOCS80211BSSID
:
2790 bssid
= (struct ieee80211_bssid
*)data
;
2791 IEEE80211_ADDR_COPY(ic
->ic_des_bssid
, bssid
->i_bssid
);
2792 if (IEEE80211_ADDR_EQ(ic
->ic_des_bssid
, zerobssid
))
2793 ic
->ic_flags
&= ~IEEE80211_F_DESBSSID
;
2795 ic
->ic_flags
|= IEEE80211_F_DESBSSID
;
2798 case SIOCG80211BSSID
:
2799 bssid
= (struct ieee80211_bssid
*)data
;
2800 switch (ic
->ic_state
) {
2801 case IEEE80211_S_INIT
:
2802 case IEEE80211_S_SCAN
:
2803 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
2804 IEEE80211_ADDR_COPY(bssid
->i_bssid
,
2806 else if (ic
->ic_flags
& IEEE80211_F_DESBSSID
)
2807 IEEE80211_ADDR_COPY(bssid
->i_bssid
,
2810 memset(bssid
->i_bssid
, 0, IEEE80211_ADDR_LEN
);
2813 IEEE80211_ADDR_COPY(bssid
->i_bssid
,
2814 ic
->ic_bss
->ni_bssid
);
2818 case SIOCS80211CHANNEL
:
2819 chanreq
= (struct ieee80211chanreq
*)data
;
2820 if (chanreq
->i_channel
== IEEE80211_CHAN_ANY
)
2821 ic
->ic_des_chan
= IEEE80211_CHAN_ANYC
;
2822 else if (chanreq
->i_channel
> IEEE80211_CHAN_MAX
||
2823 isclr(ic
->ic_chan_active
, chanreq
->i_channel
)) {
2827 ic
->ic_ibss_chan
= ic
->ic_des_chan
=
2828 &ic
->ic_channels
[chanreq
->i_channel
];
2829 switch (ic
->ic_state
) {
2830 case IEEE80211_S_INIT
:
2831 case IEEE80211_S_SCAN
:
2835 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
2836 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
&&
2837 ic
->ic_bss
->ni_chan
!= ic
->ic_des_chan
)
2840 if (ic
->ic_bss
->ni_chan
!= ic
->ic_ibss_chan
)
2846 case SIOCG80211CHANNEL
:
2847 chanreq
= (struct ieee80211chanreq
*)data
;
2848 switch (ic
->ic_state
) {
2849 case IEEE80211_S_INIT
:
2850 case IEEE80211_S_SCAN
:
2851 if (ic
->ic_opmode
== IEEE80211_M_STA
)
2852 chan
= ic
->ic_des_chan
;
2854 chan
= ic
->ic_ibss_chan
;
2857 chan
= ic
->ic_curchan
;
2860 chanreq
->i_channel
= ieee80211_chan2ieee(ic
, chan
);
2862 case SIOCGIFGENERIC
:
2863 error
= ieee80211_cfgget(ic
, cmd
, data
);
2865 case SIOCSIFGENERIC
:
2866 error
= kauth_authorize_network(curlwp
->l_cred
,
2867 KAUTH_NETWORK_INTERFACE
,
2868 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
2872 error
= ieee80211_cfgset(ic
, cmd
, data
);
2875 case OSIOCG80211STATS
:
2876 case OSIOCG80211ZSTATS
:
2877 ifr
= (struct ifreq
*)data
;
2879 ieee80211_get_ostats(&ostats
, &ic
->ic_stats
);
2880 error
= copyout(&ostats
, ifr
->ifr_data
, sizeof(ostats
));
2881 if (error
== 0 && cmd
== OSIOCG80211ZSTATS
)
2882 (void)memset(&ic
->ic_stats
, 0, sizeof(ic
->ic_stats
));
2885 #endif /* COMPAT_20 */
2886 case SIOCG80211ZSTATS
:
2887 case SIOCG80211STATS
:
2888 ifr
= (struct ifreq
*)data
;
2890 error
= copyout(&ic
->ic_stats
, ifr
->ifr_buf
,
2891 MIN(sizeof(ic
->ic_stats
), ifr
->ifr_buflen
));
2892 if (error
== 0 && cmd
== SIOCG80211ZSTATS
)
2893 (void)memset(&ic
->ic_stats
, 0, sizeof(ic
->ic_stats
));
2897 ifr
= (struct ifreq
*)data
;
2898 if (!(IEEE80211_MTU_MIN
<= ifr
->ifr_mtu
&&
2899 ifr
->ifr_mtu
<= IEEE80211_MTU_MAX
))
2901 else if ((error
= ifioctl_common(ifp
, cmd
, data
)) == ENETRESET
)
2905 error
= ether_ioctl(ifp
, cmd
, data
);
2910 #endif /* __NetBSD__ */