2 * hostapd / Driver interaction with Atheros driver
3 * Copyright (c) 2004, Sam Leffler <sam@errno.com>
4 * Copyright (c) 2004, Video54 Technologies
5 * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
6 * Copyright (c) 2009, Atheros Communications
8 * This software may be distributed under the terms of the BSD license.
9 * See README for more details.
14 #include <sys/ioctl.h>
18 #include "common/ieee802_11_defs.h"
19 #include "l2_packet/l2_packet.h"
24 #ifdef WORDS_BIGENDIAN
25 #define _BYTE_ORDER _BIG_ENDIAN
27 #define _BYTE_ORDER _LITTLE_ENDIAN
29 #endif /* _BYTE_ORDER */
32 * Note, the ATH_WPS_IE setting must match with the driver build.. If the
33 * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail.
37 #include "ieee80211_external.h"
39 /* Avoid conflicting definition from the driver header files with
40 * common/wpa_common.h */
45 #include <netpacket/packet.h>
46 #endif /* CONFIG_WPS */
48 #ifndef ETH_P_80211_RAW
49 #define ETH_P_80211_RAW 0x0019
52 #include "linux_wext.h"
56 #include "priv_netlink.h"
57 #include "l2_packet/l2_packet.h"
58 #include "common/ieee802_11_defs.h"
60 #include "linux_ioctl.h"
62 #if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R) || defined(CONFIG_HS20) || defined(CONFIG_WNM) || defined(CONFIG_WPS) || defined(CONFIG_FILS)
63 #define ATHEROS_USE_RAW_RECEIVE
67 struct atheros_driver_data
{
68 struct hostapd_data
*hapd
; /* back pointer */
70 char iface
[IFNAMSIZ
+ 1];
72 struct l2_packet_data
*sock_xmit
; /* raw packet xmit socket */
73 struct l2_packet_data
*sock_recv
; /* raw packet recv socket */
74 int ioctl_sock
; /* socket for ioctl() use */
75 struct netlink_data
*netlink
;
77 int fils_en
; /* FILS enable/disable in driver */
78 u8 acct_mac
[ETH_ALEN
];
79 struct hostap_sta_driver_data acct_data
;
81 struct l2_packet_data
*sock_raw
; /* raw 802.11 management frames */
82 struct wpabuf
*wpa_ie
;
83 struct wpabuf
*wps_beacon_ie
;
84 struct wpabuf
*wps_probe_resp_ie
;
85 u8 own_addr
[ETH_ALEN
];
88 static int atheros_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
90 static int atheros_set_privacy(void *priv
, int enabled
);
92 static const char * athr_get_ioctl_name(int op
)
95 case IEEE80211_IOCTL_SETPARAM
:
97 case IEEE80211_IOCTL_GETPARAM
:
99 case IEEE80211_IOCTL_SETKEY
:
101 case IEEE80211_IOCTL_SETWMMPARAMS
:
102 return "SETWMMPARAMS";
103 case IEEE80211_IOCTL_DELKEY
:
105 case IEEE80211_IOCTL_GETWMMPARAMS
:
106 return "GETWMMPARAMS";
107 case IEEE80211_IOCTL_SETMLME
:
109 case IEEE80211_IOCTL_GETCHANINFO
:
110 return "GETCHANINFO";
111 case IEEE80211_IOCTL_SETOPTIE
:
113 case IEEE80211_IOCTL_GETOPTIE
:
115 case IEEE80211_IOCTL_ADDMAC
:
117 case IEEE80211_IOCTL_DELMAC
:
119 case IEEE80211_IOCTL_GETCHANLIST
:
120 return "GETCHANLIST";
121 case IEEE80211_IOCTL_SETCHANLIST
:
122 return "SETCHANLIST";
123 case IEEE80211_IOCTL_KICKMAC
:
125 case IEEE80211_IOCTL_CHANSWITCH
:
127 case IEEE80211_IOCTL_GETMODE
:
129 case IEEE80211_IOCTL_SETMODE
:
131 case IEEE80211_IOCTL_GET_APPIEBUF
:
132 return "GET_APPIEBUF";
133 case IEEE80211_IOCTL_SET_APPIEBUF
:
134 return "SET_APPIEBUF";
135 case IEEE80211_IOCTL_SET_ACPARAMS
:
136 return "SET_ACPARAMS";
137 case IEEE80211_IOCTL_FILTERFRAME
:
138 return "FILTERFRAME";
139 case IEEE80211_IOCTL_SET_RTPARAMS
:
140 return "SET_RTPARAMS";
141 case IEEE80211_IOCTL_SET_MEDENYENTRY
:
142 return "SET_MEDENYENTRY";
143 case IEEE80211_IOCTL_GET_MACADDR
:
144 return "GET_MACADDR";
145 case IEEE80211_IOCTL_SET_HBRPARAMS
:
146 return "SET_HBRPARAMS";
147 case IEEE80211_IOCTL_SET_RXTIMEOUT
:
148 return "SET_RXTIMEOUT";
149 case IEEE80211_IOCTL_STA_STATS
:
151 case IEEE80211_IOCTL_GETWPAIE
:
159 static const char * athr_get_param_name(int op
)
162 case IEEE80211_IOC_MCASTCIPHER
:
163 return "MCASTCIPHER";
164 case IEEE80211_PARAM_MCASTKEYLEN
:
165 return "MCASTKEYLEN";
166 case IEEE80211_PARAM_UCASTCIPHERS
:
167 return "UCASTCIPHERS";
168 case IEEE80211_PARAM_KEYMGTALGS
:
170 case IEEE80211_PARAM_RSNCAPS
:
172 case IEEE80211_PARAM_WPA
:
174 case IEEE80211_PARAM_AUTHMODE
:
176 case IEEE80211_PARAM_PRIVACY
:
178 case IEEE80211_PARAM_COUNTERMEASURES
:
179 return "COUNTERMEASURES";
188 get80211param(struct atheros_driver_data
*drv
, int op
, int *data
)
192 os_memset(&iwr
, 0, sizeof(iwr
));
193 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
196 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_GETPARAM
, &iwr
) < 0)
202 #endif /* CONFIG_FILS */
206 set80211priv(struct atheros_driver_data
*drv
, int op
, void *data
, int len
)
209 int do_inline
= len
< IFNAMSIZ
;
211 /* Certain ioctls must use the non-inlined method */
212 if (op
== IEEE80211_IOCTL_SET_APPIEBUF
||
213 op
== IEEE80211_IOCTL_FILTERFRAME
)
216 os_memset(&iwr
, 0, sizeof(iwr
));
217 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
220 * Argument data fits inline; put it there.
222 os_memcpy(iwr
.u
.name
, data
, len
);
225 * Argument data too big for inline transfer; setup a
226 * parameter block instead; the kernel will transfer
227 * the data for the driver.
229 iwr
.u
.data
.pointer
= data
;
230 iwr
.u
.data
.length
= len
;
233 if (ioctl(drv
->ioctl_sock
, op
, &iwr
) < 0) {
234 wpa_printf(MSG_DEBUG
, "atheros: %s: %s: ioctl op=0x%x "
235 "(%s) len=%d failed: %d (%s)",
236 __func__
, drv
->iface
, op
,
237 athr_get_ioctl_name(op
),
238 len
, errno
, strerror(errno
));
245 set80211param(struct atheros_driver_data
*drv
, int op
, int arg
)
249 os_memset(&iwr
, 0, sizeof(iwr
));
250 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
252 os_memcpy(iwr
.u
.name
+ sizeof(__u32
), &arg
, sizeof(arg
));
254 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_SETPARAM
, &iwr
) < 0) {
256 "%s: %s: Failed to set parameter (op %d (%s) arg %d): ioctl[IEEE80211_IOCTL_SETPARAM]: %s",
257 __func__
, drv
->iface
, op
, athr_get_param_name(op
),
258 arg
, strerror(errno
));
264 #ifndef CONFIG_NO_STDOUT_DEBUG
266 ether_sprintf(const u8
*addr
)
268 static char buf
[sizeof(MACSTR
)];
271 os_snprintf(buf
, sizeof(buf
), MACSTR
, MAC2STR(addr
));
273 os_snprintf(buf
, sizeof(buf
), MACSTR
, 0, 0, 0, 0, 0, 0);
276 #endif /* CONFIG_NO_STDOUT_DEBUG */
279 * Configure WPA parameters.
282 atheros_configure_wpa(struct atheros_driver_data
*drv
,
283 struct wpa_bss_params
*params
)
287 switch (params
->wpa_group
) {
288 case WPA_CIPHER_CCMP
:
289 v
= IEEE80211_CIPHER_AES_CCM
;
291 #ifdef ATH_GCM_SUPPORT
292 case WPA_CIPHER_CCMP_256
:
293 v
= IEEE80211_CIPHER_AES_CCM_256
;
295 case WPA_CIPHER_GCMP
:
296 v
= IEEE80211_CIPHER_AES_GCM
;
298 case WPA_CIPHER_GCMP_256
:
299 v
= IEEE80211_CIPHER_AES_GCM_256
;
301 #endif /* ATH_GCM_SUPPORT */
302 case WPA_CIPHER_TKIP
:
303 v
= IEEE80211_CIPHER_TKIP
;
305 case WPA_CIPHER_WEP104
:
306 v
= IEEE80211_CIPHER_WEP
;
308 case WPA_CIPHER_WEP40
:
309 v
= IEEE80211_CIPHER_WEP
;
311 case WPA_CIPHER_NONE
:
312 v
= IEEE80211_CIPHER_NONE
;
315 wpa_printf(MSG_ERROR
, "Unknown group key cipher %u",
319 wpa_printf(MSG_DEBUG
, "%s: group key cipher=%d", __func__
, v
);
320 if (set80211param(drv
, IEEE80211_PARAM_MCASTCIPHER
, v
)) {
321 wpa_printf(MSG_INFO
, "Unable to set group key cipher to %u", v
);
324 if (v
== IEEE80211_CIPHER_WEP
) {
325 /* key length is done only for specific ciphers */
326 v
= (params
->wpa_group
== WPA_CIPHER_WEP104
? 13 : 5);
327 if (set80211param(drv
, IEEE80211_PARAM_MCASTKEYLEN
, v
)) {
329 "Unable to set group key length to %u", v
);
335 if (params
->wpa_pairwise
& WPA_CIPHER_CCMP
)
336 v
|= 1<<IEEE80211_CIPHER_AES_CCM
;
337 #ifdef ATH_GCM_SUPPORT
338 if (params
->wpa_pairwise
& WPA_CIPHER_CCMP_256
)
339 v
|= 1<<IEEE80211_CIPHER_AES_CCM_256
;
340 if (params
->wpa_pairwise
& WPA_CIPHER_GCMP
)
341 v
|= 1<<IEEE80211_CIPHER_AES_GCM
;
342 if (params
->wpa_pairwise
& WPA_CIPHER_GCMP_256
)
343 v
|= 1<<IEEE80211_CIPHER_AES_GCM_256
;
344 #endif /* ATH_GCM_SUPPORT */
345 if (params
->wpa_pairwise
& WPA_CIPHER_TKIP
)
346 v
|= 1<<IEEE80211_CIPHER_TKIP
;
347 if (params
->wpa_pairwise
& WPA_CIPHER_NONE
)
348 v
|= 1<<IEEE80211_CIPHER_NONE
;
349 wpa_printf(MSG_DEBUG
, "%s: pairwise key ciphers=0x%x", __func__
, v
);
350 if (set80211param(drv
, IEEE80211_PARAM_UCASTCIPHERS
, v
)) {
352 "Unable to set pairwise key ciphers to 0x%x", v
);
356 wpa_printf(MSG_DEBUG
, "%s: key management algorithms=0x%x",
357 __func__
, params
->wpa_key_mgmt
);
358 if (set80211param(drv
, IEEE80211_PARAM_KEYMGTALGS
,
359 params
->wpa_key_mgmt
)) {
361 "Unable to set key management algorithms to 0x%x",
362 params
->wpa_key_mgmt
);
367 if (params
->rsn_preauth
)
369 #ifdef CONFIG_IEEE80211W
370 if (params
->ieee80211w
!= NO_MGMT_FRAME_PROTECTION
) {
372 if (params
->ieee80211w
== MGMT_FRAME_PROTECTION_REQUIRED
)
375 #endif /* CONFIG_IEEE80211W */
377 wpa_printf(MSG_DEBUG
, "%s: rsn capabilities=0x%x", __func__
, v
);
378 if (set80211param(drv
, IEEE80211_PARAM_RSNCAPS
, v
)) {
379 wpa_printf(MSG_INFO
, "Unable to set RSN capabilities to 0x%x",
384 wpa_printf(MSG_DEBUG
, "%s: enable WPA=0x%x", __func__
, params
->wpa
);
385 if (set80211param(drv
, IEEE80211_PARAM_WPA
, params
->wpa
)) {
386 wpa_printf(MSG_INFO
, "Unable to set WPA to %u", params
->wpa
);
393 atheros_set_ieee8021x(void *priv
, struct wpa_bss_params
*params
)
395 struct atheros_driver_data
*drv
= priv
;
397 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, params
->enabled
);
399 if (!params
->enabled
) {
400 /* XXX restore state */
401 if (set80211param(priv
, IEEE80211_PARAM_AUTHMODE
,
402 IEEE80211_AUTH_AUTO
) < 0)
404 /* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */
405 return atheros_set_privacy(drv
, 0);
407 if (!params
->wpa
&& !params
->ieee802_1x
) {
408 wpa_printf(MSG_WARNING
, "No 802.1X or WPA enabled!");
411 if (params
->wpa
&& atheros_configure_wpa(drv
, params
) != 0) {
412 wpa_printf(MSG_WARNING
, "Error configuring WPA state!");
415 if (set80211param(priv
, IEEE80211_PARAM_AUTHMODE
,
416 (params
->wpa
? IEEE80211_AUTH_WPA
: IEEE80211_AUTH_8021X
))) {
417 wpa_printf(MSG_WARNING
, "Error enabling WPA/802.1X!");
425 atheros_set_privacy(void *priv
, int enabled
)
427 struct atheros_driver_data
*drv
= priv
;
429 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
431 return set80211param(drv
, IEEE80211_PARAM_PRIVACY
, enabled
);
435 atheros_set_sta_authorized(void *priv
, const u8
*addr
, int authorized
)
437 struct atheros_driver_data
*drv
= priv
;
438 struct ieee80211req_mlme mlme
;
441 wpa_printf(MSG_DEBUG
, "%s: addr=%s authorized=%d",
442 __func__
, ether_sprintf(addr
), authorized
);
445 mlme
.im_op
= IEEE80211_MLME_AUTHORIZE
;
447 mlme
.im_op
= IEEE80211_MLME_UNAUTHORIZE
;
449 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
450 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
452 wpa_printf(MSG_DEBUG
, "%s: Failed to %sauthorize STA " MACSTR
,
453 __func__
, authorized
? "" : "un", MAC2STR(addr
));
460 atheros_sta_set_flags(void *priv
, const u8
*addr
,
461 unsigned int total_flags
, unsigned int flags_or
,
462 unsigned int flags_and
)
464 /* For now, only support setting Authorized flag */
465 if (flags_or
& WPA_STA_AUTHORIZED
)
466 return atheros_set_sta_authorized(priv
, addr
, 1);
467 if (!(flags_and
& WPA_STA_AUTHORIZED
))
468 return atheros_set_sta_authorized(priv
, addr
, 0);
473 atheros_del_key(void *priv
, const u8
*addr
, int key_idx
)
475 struct atheros_driver_data
*drv
= priv
;
476 struct ieee80211req_del_key wk
;
479 wpa_printf(MSG_DEBUG
, "%s: addr=%s key_idx=%d",
480 __func__
, ether_sprintf(addr
), key_idx
);
482 os_memset(&wk
, 0, sizeof(wk
));
484 os_memcpy(wk
.idk_macaddr
, addr
, IEEE80211_ADDR_LEN
);
485 wk
.idk_keyix
= (u8
) IEEE80211_KEYIX_NONE
;
487 wk
.idk_keyix
= key_idx
;
490 ret
= set80211priv(drv
, IEEE80211_IOCTL_DELKEY
, &wk
, sizeof(wk
));
492 wpa_printf(MSG_DEBUG
, "%s: Failed to delete key (addr %s"
493 " key_idx %d)", __func__
, ether_sprintf(addr
),
501 atheros_set_key(const char *ifname
, void *priv
, enum wpa_alg alg
,
502 const u8
*addr
, int key_idx
, int set_tx
, const u8
*seq
,
503 size_t seq_len
, const u8
*key
, size_t key_len
)
505 struct atheros_driver_data
*drv
= priv
;
506 struct ieee80211req_key wk
;
510 if (alg
== WPA_ALG_NONE
)
511 return atheros_del_key(drv
, addr
, key_idx
);
513 wpa_printf(MSG_DEBUG
, "%s: alg=%d addr=%s key_idx=%d",
514 __func__
, alg
, ether_sprintf(addr
), key_idx
);
518 cipher
= IEEE80211_CIPHER_WEP
;
521 cipher
= IEEE80211_CIPHER_TKIP
;
524 cipher
= IEEE80211_CIPHER_AES_CCM
;
526 #ifdef ATH_GCM_SUPPORT
527 case WPA_ALG_CCMP_256
:
528 cipher
= IEEE80211_CIPHER_AES_CCM_256
;
531 cipher
= IEEE80211_CIPHER_AES_GCM
;
533 case WPA_ALG_GCMP_256
:
534 cipher
= IEEE80211_CIPHER_AES_GCM_256
;
536 #endif /* ATH_GCM_SUPPORT */
537 #ifdef CONFIG_IEEE80211W
539 cipher
= IEEE80211_CIPHER_AES_CMAC
;
541 #ifdef ATH_GCM_SUPPORT
542 case WPA_ALG_BIP_CMAC_256
:
543 cipher
= IEEE80211_CIPHER_AES_CMAC_256
;
545 case WPA_ALG_BIP_GMAC_128
:
546 cipher
= IEEE80211_CIPHER_AES_GMAC
;
548 case WPA_ALG_BIP_GMAC_256
:
549 cipher
= IEEE80211_CIPHER_AES_GMAC_256
;
551 #endif /* ATH_GCM_SUPPORT */
552 #endif /* CONFIG_IEEE80211W */
554 wpa_printf(MSG_INFO
, "%s: unknown/unsupported algorithm %d",
559 if (key_len
> sizeof(wk
.ik_keydata
)) {
560 wpa_printf(MSG_INFO
, "%s: key length %lu too big", __func__
,
561 (unsigned long) key_len
);
565 os_memset(&wk
, 0, sizeof(wk
));
567 wk
.ik_flags
= IEEE80211_KEY_RECV
| IEEE80211_KEY_XMIT
;
568 if (addr
== NULL
|| is_broadcast_ether_addr(addr
)) {
569 os_memset(wk
.ik_macaddr
, 0xff, IEEE80211_ADDR_LEN
);
570 wk
.ik_keyix
= key_idx
;
572 wk
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
574 os_memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
575 wk
.ik_keyix
= IEEE80211_KEYIX_NONE
;
577 wk
.ik_keylen
= key_len
;
578 os_memcpy(wk
.ik_keydata
, key
, key_len
);
580 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETKEY
, &wk
, sizeof(wk
));
582 wpa_printf(MSG_DEBUG
, "%s: Failed to set key (addr %s"
583 " key_idx %d alg %d key_len %lu set_tx %d)",
584 __func__
, ether_sprintf(wk
.ik_macaddr
), key_idx
,
585 alg
, (unsigned long) key_len
, set_tx
);
593 atheros_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
, int idx
,
596 struct atheros_driver_data
*drv
= priv
;
597 struct ieee80211req_key wk
;
599 wpa_printf(MSG_DEBUG
, "%s: addr=%s idx=%d",
600 __func__
, ether_sprintf(addr
), idx
);
602 os_memset(&wk
, 0, sizeof(wk
));
604 os_memset(wk
.ik_macaddr
, 0xff, IEEE80211_ADDR_LEN
);
606 os_memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
609 if (set80211priv(drv
, IEEE80211_IOCTL_GETKEY
, &wk
, sizeof(wk
))) {
610 wpa_printf(MSG_DEBUG
, "%s: Failed to get encryption data "
611 "(addr " MACSTR
" key_idx %d)",
612 __func__
, MAC2STR(wk
.ik_macaddr
), idx
);
616 #ifdef WORDS_BIGENDIAN
619 * wk.ik_keytsc is in host byte order (big endian), need to
620 * swap it to match with the byte order used in WPA.
623 #ifndef WPA_KEY_RSC_LEN
624 #define WPA_KEY_RSC_LEN 8
626 u8 tmp
[WPA_KEY_RSC_LEN
];
627 os_memcpy(tmp
, &wk
.ik_keytsc
, sizeof(wk
.ik_keytsc
));
628 for (i
= 0; i
< WPA_KEY_RSC_LEN
; i
++) {
629 seq
[i
] = tmp
[WPA_KEY_RSC_LEN
- i
- 1];
632 #else /* WORDS_BIGENDIAN */
633 os_memcpy(seq
, &wk
.ik_keytsc
, sizeof(wk
.ik_keytsc
));
634 #endif /* WORDS_BIGENDIAN */
640 atheros_flush(void *priv
)
642 u8 allsta
[IEEE80211_ADDR_LEN
];
643 os_memset(allsta
, 0xff, IEEE80211_ADDR_LEN
);
644 return atheros_sta_deauth(priv
, NULL
, allsta
,
645 IEEE80211_REASON_AUTH_LEAVE
);
650 atheros_read_sta_driver_data(void *priv
, struct hostap_sta_driver_data
*data
,
653 struct atheros_driver_data
*drv
= priv
;
654 struct ieee80211req_sta_stats stats
;
656 os_memset(data
, 0, sizeof(*data
));
659 * Fetch statistics for station from the system.
661 os_memset(&stats
, 0, sizeof(stats
));
662 os_memcpy(stats
.is_u
.macaddr
, addr
, IEEE80211_ADDR_LEN
);
663 if (set80211priv(drv
, IEEE80211_IOCTL_STA_STATS
,
664 &stats
, sizeof(stats
))) {
665 wpa_printf(MSG_DEBUG
, "%s: Failed to fetch STA stats (addr "
666 MACSTR
")", __func__
, MAC2STR(addr
));
667 if (os_memcmp(addr
, drv
->acct_mac
, ETH_ALEN
) == 0) {
668 os_memcpy(data
, &drv
->acct_data
, sizeof(*data
));
673 "Failed to get station stats information element");
677 data
->rx_packets
= stats
.is_stats
.ns_rx_data
;
678 data
->rx_bytes
= stats
.is_stats
.ns_rx_bytes
;
679 data
->tx_packets
= stats
.is_stats
.ns_tx_data
;
680 data
->tx_bytes
= stats
.is_stats
.ns_tx_bytes
;
686 atheros_sta_clear_stats(void *priv
, const u8
*addr
)
688 struct atheros_driver_data
*drv
= priv
;
689 struct ieee80211req_mlme mlme
;
692 wpa_printf(MSG_DEBUG
, "%s: addr=%s", __func__
, ether_sprintf(addr
));
694 mlme
.im_op
= IEEE80211_MLME_CLEAR_STATS
;
695 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
696 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
,
699 wpa_printf(MSG_DEBUG
, "%s: Failed to clear STA stats (addr "
700 MACSTR
")", __func__
, MAC2STR(addr
));
708 atheros_set_opt_ie(void *priv
, const u8
*ie
, size_t ie_len
)
710 struct atheros_driver_data
*drv
= priv
;
712 struct ieee80211req_getset_appiebuf
*app_ie
;
714 wpa_printf(MSG_DEBUG
, "%s buflen = %lu", __func__
,
715 (unsigned long) ie_len
);
716 wpa_hexdump(MSG_DEBUG
, "atheros: set_generic_elem", ie
, ie_len
);
718 wpabuf_free(drv
->wpa_ie
);
720 drv
->wpa_ie
= wpabuf_alloc_copy(ie
, ie_len
);
724 app_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
726 os_memcpy(&(app_ie
->app_buf
[0]), ie
, ie_len
);
727 app_ie
->app_buflen
= ie_len
;
729 app_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_BEACON
;
731 /* append WPS IE for Beacon */
732 if (drv
->wps_beacon_ie
!= NULL
) {
733 os_memcpy(&(app_ie
->app_buf
[ie_len
]),
734 wpabuf_head(drv
->wps_beacon_ie
),
735 wpabuf_len(drv
->wps_beacon_ie
));
736 app_ie
->app_buflen
= ie_len
+ wpabuf_len(drv
->wps_beacon_ie
);
738 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF(Beacon)",
739 app_ie
->app_buf
, app_ie
->app_buflen
);
740 set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, app_ie
,
741 sizeof(struct ieee80211req_getset_appiebuf
) +
744 /* append WPS IE for Probe Response */
745 app_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_PROBE_RESP
;
746 if (drv
->wps_probe_resp_ie
!= NULL
) {
747 os_memcpy(&(app_ie
->app_buf
[ie_len
]),
748 wpabuf_head(drv
->wps_probe_resp_ie
),
749 wpabuf_len(drv
->wps_probe_resp_ie
));
750 app_ie
->app_buflen
= ie_len
+
751 wpabuf_len(drv
->wps_probe_resp_ie
);
753 app_ie
->app_buflen
= ie_len
;
754 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF(ProbeResp)",
755 app_ie
->app_buf
, app_ie
->app_buflen
);
756 set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, app_ie
,
757 sizeof(struct ieee80211req_getset_appiebuf
) +
763 atheros_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
766 struct atheros_driver_data
*drv
= priv
;
767 struct ieee80211req_mlme mlme
;
770 wpa_printf(MSG_DEBUG
, "%s: addr=%s reason_code=%d",
771 __func__
, ether_sprintf(addr
), reason_code
);
773 mlme
.im_op
= IEEE80211_MLME_DEAUTH
;
774 mlme
.im_reason
= reason_code
;
775 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
776 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
778 wpa_printf(MSG_DEBUG
, "%s: Failed to deauth STA (addr " MACSTR
780 __func__
, MAC2STR(addr
), reason_code
);
787 atheros_sta_disassoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
790 struct atheros_driver_data
*drv
= priv
;
791 struct ieee80211req_mlme mlme
;
794 wpa_printf(MSG_DEBUG
, "%s: addr=%s reason_code=%d",
795 __func__
, ether_sprintf(addr
), reason_code
);
797 mlme
.im_op
= IEEE80211_MLME_DISASSOC
;
798 mlme
.im_reason
= reason_code
;
799 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
800 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
802 wpa_printf(MSG_DEBUG
, "%s: Failed to disassoc STA (addr "
803 MACSTR
" reason %d)",
804 __func__
, MAC2STR(addr
), reason_code
);
810 static int atheros_set_qos_map(void *ctx
, const u8
*qos_map_set
,
813 #ifdef CONFIG_ATHEROS_QOS_MAP
814 struct atheros_driver_data
*drv
= ctx
;
815 struct ieee80211req_athdbg req
;
816 struct ieee80211_qos_map
*qos_map
= &req
.data
.qos_map
;
820 if (qos_map_set_len
< 16 || qos_map_set_len
> 58 ||
821 qos_map_set_len
& 1) {
822 wpa_printf(MSG_ERROR
, "Invalid QoS Map");
825 os_memset(&req
, 0, sizeof(struct ieee80211req_athdbg
));
826 req
.cmd
= IEEE80211_DBGREQ_SETQOSMAPCONF
;
827 os_memset(&iwr
, 0, sizeof(iwr
));
828 os_strlcpy(iwr
.ifr_name
, drv
->iface
, sizeof(iwr
.ifr_name
));
829 iwr
.u
.data
.pointer
= (void *) &req
;
830 iwr
.u
.data
.length
= sizeof(struct ieee80211req_athdbg
);
834 qos_map
->num_dscp_except
= (qos_map_set_len
- 16) / 2;
835 if (qos_map
->num_dscp_except
) {
836 for (i
= 0; i
< qos_map
->num_dscp_except
; i
++) {
837 qos_map
->dscp_exception
[i
].dscp
= qos_map_set
[i
* 2];
838 qos_map
->dscp_exception
[i
].up
= qos_map_set
[i
* 2 + 1];
842 up_start
= qos_map_set_len
- 16;
843 for (i
= 0; i
< IEEE80211_MAX_QOS_UP_RANGE
; i
++) {
844 qos_map
->up
[i
].low
= qos_map_set
[up_start
+ (i
* 2)];
845 qos_map
->up
[i
].high
= qos_map_set
[up_start
+ (i
* 2) + 1];
848 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_DBGREQ
, &iwr
) < 0) {
849 wpa_printf(MSG_ERROR
,
850 "%s: %s: Failed to set QoS Map: ioctl[IEEE80211_IOCTL_DBGREQ]: %s",
851 __func__
, drv
->iface
, strerror(errno
));
854 #endif /* CONFIG_ATHEROS_QOS_MAP */
859 #ifdef ATHEROS_USE_RAW_RECEIVE
860 static void atheros_raw_receive(void *ctx
, const u8
*src_addr
, const u8
*buf
,
863 struct atheros_driver_data
*drv
= ctx
;
864 const struct ieee80211_mgmt
*mgmt
;
865 union wpa_event_data event
;
870 if (len
< IEEE80211_HDRLEN
)
873 mgmt
= (const struct ieee80211_mgmt
*) buf
;
875 fc
= le_to_host16(mgmt
->frame_control
);
877 if (WLAN_FC_GET_TYPE(fc
) != WLAN_FC_TYPE_MGMT
)
880 stype
= WLAN_FC_GET_STYPE(fc
);
882 wpa_printf(MSG_DEBUG
, "%s: subtype 0x%x len %d", __func__
, stype
,
885 if (stype
== WLAN_FC_STYPE_PROBE_REQ
) {
886 if (len
< IEEE80211_HDRLEN
)
889 os_memset(&event
, 0, sizeof(event
));
890 event
.rx_probe_req
.sa
= mgmt
->sa
;
891 event
.rx_probe_req
.da
= mgmt
->da
;
892 event
.rx_probe_req
.bssid
= mgmt
->bssid
;
893 event
.rx_probe_req
.ie
= buf
+ IEEE80211_HDRLEN
;
894 event
.rx_probe_req
.ie_len
= len
- IEEE80211_HDRLEN
;
895 wpa_supplicant_event(drv
->hapd
, EVENT_RX_PROBE_REQ
, &event
);
899 if (stype
== WLAN_FC_STYPE_ACTION
&&
900 (os_memcmp(drv
->own_addr
, mgmt
->bssid
, ETH_ALEN
) == 0 ||
901 is_broadcast_ether_addr(mgmt
->bssid
))) {
902 os_memset(&event
, 0, sizeof(event
));
903 event
.rx_mgmt
.frame
= buf
;
904 event
.rx_mgmt
.frame_len
= len
;
905 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
, &event
);
909 if (os_memcmp(drv
->own_addr
, mgmt
->bssid
, ETH_ALEN
) != 0) {
910 wpa_printf(MSG_DEBUG
, "%s: BSSID does not match - ignore",
916 case WLAN_FC_STYPE_ASSOC_REQ
:
917 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.assoc_req
))
919 ielen
= len
- (IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.assoc_req
));
920 iebuf
= mgmt
->u
.assoc_req
.variable
;
921 drv_event_assoc(drv
->hapd
, mgmt
->sa
, iebuf
, ielen
, 0);
923 case WLAN_FC_STYPE_REASSOC_REQ
:
924 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.reassoc_req
))
926 ielen
= len
- (IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.reassoc_req
));
927 iebuf
= mgmt
->u
.reassoc_req
.variable
;
928 drv_event_assoc(drv
->hapd
, mgmt
->sa
, iebuf
, ielen
, 1);
930 case WLAN_FC_STYPE_AUTH
:
931 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.auth
))
933 os_memset(&event
, 0, sizeof(event
));
934 if (le_to_host16(mgmt
->u
.auth
.auth_alg
) == WLAN_AUTH_SAE
) {
935 event
.rx_mgmt
.frame
= buf
;
936 event
.rx_mgmt
.frame_len
= len
;
937 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
, &event
);
940 os_memcpy(event
.auth
.peer
, mgmt
->sa
, ETH_ALEN
);
941 os_memcpy(event
.auth
.bssid
, mgmt
->bssid
, ETH_ALEN
);
942 event
.auth
.auth_type
= le_to_host16(mgmt
->u
.auth
.auth_alg
);
943 event
.auth
.status_code
=
944 le_to_host16(mgmt
->u
.auth
.status_code
);
945 event
.auth
.auth_transaction
=
946 le_to_host16(mgmt
->u
.auth
.auth_transaction
);
947 event
.auth
.ies
= mgmt
->u
.auth
.variable
;
948 event
.auth
.ies_len
= len
- IEEE80211_HDRLEN
-
949 sizeof(mgmt
->u
.auth
);
950 wpa_supplicant_event(drv
->hapd
, EVENT_AUTH
, &event
);
956 #endif /* ATHEROS_USE_RAW_RECEIVE */
958 static int atheros_receive_pkt(struct atheros_driver_data
*drv
)
961 struct ieee80211req_set_filter filt
;
963 wpa_printf(MSG_DEBUG
, "%s Enter", __func__
);
964 filt
.app_filterype
= 0;
966 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_PROBE_REQ
;
967 #endif /* CONFIG_WPS */
968 #if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
969 filt
.app_filterype
|= (IEEE80211_FILTER_TYPE_ASSOC_REQ
|
970 IEEE80211_FILTER_TYPE_AUTH
|
971 IEEE80211_FILTER_TYPE_ACTION
);
972 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W || CONFIG_FILS */
974 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_ACTION
;
975 #endif /* CONFIG_WNM */
977 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_ACTION
;
978 #endif /* CONFIG_HS20 */
979 if (filt
.app_filterype
) {
980 ret
= set80211priv(drv
, IEEE80211_IOCTL_FILTERFRAME
, &filt
,
981 sizeof(struct ieee80211req_set_filter
));
986 #if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
987 drv
->sock_raw
= l2_packet_init(drv
->iface
, NULL
, ETH_P_80211_RAW
,
988 atheros_raw_receive
, drv
, 1);
989 if (drv
->sock_raw
== NULL
)
991 #endif /* CONFIG_WPS || CONFIG_IEEE80211R || CONFIG_FILS */
995 static int atheros_reset_appfilter(struct atheros_driver_data
*drv
)
997 struct ieee80211req_set_filter filt
;
998 filt
.app_filterype
= 0;
999 return set80211priv(drv
, IEEE80211_IOCTL_FILTERFRAME
, &filt
,
1000 sizeof(struct ieee80211req_set_filter
));
1005 atheros_set_wps_ie(void *priv
, const u8
*ie
, size_t len
, u32 frametype
)
1007 struct atheros_driver_data
*drv
= priv
;
1009 struct ieee80211req_getset_appiebuf
*beac_ie
;
1011 wpa_printf(MSG_DEBUG
, "%s buflen = %lu frametype=%u", __func__
,
1012 (unsigned long) len
, frametype
);
1013 wpa_hexdump(MSG_DEBUG
, "atheros: IE", ie
, len
);
1015 beac_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
1016 beac_ie
->app_frmtype
= frametype
;
1017 beac_ie
->app_buflen
= len
;
1019 os_memcpy(&(beac_ie
->app_buf
[0]), ie
, len
);
1021 /* append the WPA/RSN IE if it is set already */
1022 if (((frametype
== IEEE80211_APPIE_FRAME_BEACON
) ||
1023 (frametype
== IEEE80211_APPIE_FRAME_PROBE_RESP
)) &&
1024 (drv
->wpa_ie
!= NULL
)) {
1025 wpa_hexdump_buf(MSG_DEBUG
, "atheros: Append WPA/RSN IE",
1027 os_memcpy(&(beac_ie
->app_buf
[len
]), wpabuf_head(drv
->wpa_ie
),
1028 wpabuf_len(drv
->wpa_ie
));
1029 beac_ie
->app_buflen
+= wpabuf_len(drv
->wpa_ie
);
1032 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF",
1033 beac_ie
->app_buf
, beac_ie
->app_buflen
);
1034 return set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, beac_ie
,
1035 sizeof(struct ieee80211req_getset_appiebuf
) +
1036 beac_ie
->app_buflen
);
1040 atheros_set_ap_wps_ie(void *priv
, const struct wpabuf
*beacon
,
1041 const struct wpabuf
*proberesp
,
1042 const struct wpabuf
*assocresp
)
1044 struct atheros_driver_data
*drv
= priv
;
1046 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - beacon", beacon
);
1047 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - proberesp",
1049 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - assocresp",
1051 wpabuf_free(drv
->wps_beacon_ie
);
1052 drv
->wps_beacon_ie
= beacon
? wpabuf_dup(beacon
) : NULL
;
1053 wpabuf_free(drv
->wps_probe_resp_ie
);
1054 drv
->wps_probe_resp_ie
= proberesp
? wpabuf_dup(proberesp
) : NULL
;
1056 atheros_set_wps_ie(priv
, assocresp
? wpabuf_head(assocresp
) : NULL
,
1057 assocresp
? wpabuf_len(assocresp
) : 0,
1058 IEEE80211_APPIE_FRAME_ASSOC_RESP
);
1059 if (atheros_set_wps_ie(priv
, beacon
? wpabuf_head(beacon
) : NULL
,
1060 beacon
? wpabuf_len(beacon
) : 0,
1061 IEEE80211_APPIE_FRAME_BEACON
))
1063 return atheros_set_wps_ie(priv
,
1064 proberesp
? wpabuf_head(proberesp
) : NULL
,
1065 proberesp
? wpabuf_len(proberesp
): 0,
1066 IEEE80211_APPIE_FRAME_PROBE_RESP
);
1068 #else /* CONFIG_WPS */
1069 #define atheros_set_ap_wps_ie NULL
1070 #endif /* CONFIG_WPS */
1072 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1074 atheros_sta_auth(void *priv
, struct wpa_driver_sta_auth_params
*params
)
1076 struct atheros_driver_data
*drv
= priv
;
1077 struct ieee80211req_mlme mlme
;
1080 wpa_printf(MSG_DEBUG
, "%s: addr=%s status_code=%d",
1081 __func__
, ether_sprintf(params
->addr
), params
->status
);
1084 /* Copy FILS AAD parameters if the driver supports FILS */
1085 if (params
->fils_auth
&& drv
->fils_en
) {
1086 wpa_printf(MSG_DEBUG
, "%s: im_op IEEE80211_MLME_AUTH_FILS",
1088 os_memcpy(mlme
.fils_aad
.ANonce
, params
->fils_anonce
,
1089 IEEE80211_FILS_NONCE_LEN
);
1090 os_memcpy(mlme
.fils_aad
.SNonce
, params
->fils_snonce
,
1091 IEEE80211_FILS_NONCE_LEN
);
1092 os_memcpy(mlme
.fils_aad
.kek
, params
->fils_kek
,
1093 IEEE80211_MAX_WPA_KEK_LEN
);
1094 mlme
.fils_aad
.kek_len
= params
->fils_kek_len
;
1095 mlme
.im_op
= IEEE80211_MLME_AUTH_FILS
;
1096 wpa_hexdump(MSG_DEBUG
, "FILS: ANonce",
1097 mlme
.fils_aad
.ANonce
, FILS_NONCE_LEN
);
1098 wpa_hexdump(MSG_DEBUG
, "FILS: SNonce",
1099 mlme
.fils_aad
.SNonce
, FILS_NONCE_LEN
);
1100 wpa_hexdump_key(MSG_DEBUG
, "FILS: KEK",
1101 mlme
.fils_aad
.kek
, mlme
.fils_aad
.kek_len
);
1103 mlme
.im_op
= IEEE80211_MLME_AUTH
;
1105 #else /* CONFIG_FILS */
1106 mlme
.im_op
= IEEE80211_MLME_AUTH
;
1107 #endif /* CONFIG_FILS */
1109 mlme
.im_reason
= params
->status
;
1110 mlme
.im_seq
= params
->seq
;
1111 os_memcpy(mlme
.im_macaddr
, params
->addr
, IEEE80211_ADDR_LEN
);
1112 mlme
.im_optie_len
= params
->len
;
1114 if (params
->len
< IEEE80211_MAX_OPT_IE
) {
1115 os_memcpy(mlme
.im_optie
, params
->ie
, params
->len
);
1117 wpa_printf(MSG_DEBUG
, "%s: Not enough space to copy "
1118 "opt_ie STA (addr " MACSTR
" reason %d, "
1120 __func__
, MAC2STR(params
->addr
),
1121 params
->status
, (int) params
->len
);
1125 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
1127 wpa_printf(MSG_DEBUG
, "%s: Failed to auth STA (addr " MACSTR
1129 __func__
, MAC2STR(params
->addr
), params
->status
);
1135 atheros_sta_assoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
1136 int reassoc
, u16 status_code
, const u8
*ie
, size_t len
)
1138 struct atheros_driver_data
*drv
= priv
;
1139 struct ieee80211req_mlme mlme
;
1142 wpa_printf(MSG_DEBUG
, "%s: addr=%s status_code=%d reassoc %d",
1143 __func__
, ether_sprintf(addr
), status_code
, reassoc
);
1146 mlme
.im_op
= IEEE80211_MLME_REASSOC
;
1148 mlme
.im_op
= IEEE80211_MLME_ASSOC
;
1149 mlme
.im_reason
= status_code
;
1150 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
1151 mlme
.im_optie_len
= len
;
1153 if (len
< IEEE80211_MAX_OPT_IE
) {
1154 os_memcpy(mlme
.im_optie
, ie
, len
);
1156 wpa_printf(MSG_DEBUG
, "%s: Not enough space to copy "
1157 "opt_ie STA (addr " MACSTR
" reason %d, "
1159 __func__
, MAC2STR(addr
), status_code
,
1164 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
1166 wpa_printf(MSG_DEBUG
, "%s: Failed to assoc STA (addr " MACSTR
1168 __func__
, MAC2STR(addr
), status_code
);
1172 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W || CONFIG_FILS */
1175 atheros_new_sta(struct atheros_driver_data
*drv
, u8 addr
[IEEE80211_ADDR_LEN
])
1177 struct hostapd_data
*hapd
= drv
->hapd
;
1178 struct ieee80211req_wpaie ie
;
1183 * Fetch negotiated WPA/RSN parameters from the system.
1185 os_memset(&ie
, 0, sizeof(ie
));
1186 os_memcpy(ie
.wpa_macaddr
, addr
, IEEE80211_ADDR_LEN
);
1187 if (set80211priv(drv
, IEEE80211_IOCTL_GETWPAIE
, &ie
, sizeof(ie
))) {
1189 * See ATH_WPS_IE comment in the beginning of the file for a
1190 * possible cause for the failure..
1192 wpa_printf(MSG_DEBUG
, "%s: Failed to get WPA/RSN IE: %s",
1193 __func__
, strerror(errno
));
1196 wpa_hexdump(MSG_MSGDUMP
, "atheros req WPA IE",
1197 ie
.wpa_ie
, IEEE80211_MAX_OPT_IE
);
1198 wpa_hexdump(MSG_MSGDUMP
, "atheros req RSN IE",
1199 ie
.rsn_ie
, IEEE80211_MAX_OPT_IE
);
1201 wpa_hexdump(MSG_MSGDUMP
, "atheros req WPS IE",
1202 ie
.wps_ie
, IEEE80211_MAX_OPT_IE
);
1203 #endif /* ATH_WPS_IE */
1205 /* atheros seems to return some random data if WPA/RSN IE is not set.
1206 * Assume the IE was not included if the IE type is unknown. */
1207 if (iebuf
[0] != WLAN_EID_VENDOR_SPECIFIC
)
1209 if (iebuf
[1] == 0 && ie
.rsn_ie
[1] > 0) {
1210 /* atheros-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not
1211 * set. This is needed for WPA2. */
1213 if (iebuf
[0] != WLAN_EID_RSN
)
1220 /* if WPS IE is present, preference is given to WPS */
1221 if (ie
.wps_ie
[0] == WLAN_EID_VENDOR_SPECIFIC
&& ie
.wps_ie
[1] > 0) {
1223 ielen
= ie
.wps_ie
[1];
1225 #endif /* ATH_WPS_IE */
1233 drv_event_assoc(hapd
, addr
, iebuf
, ielen
, 0);
1235 if (os_memcmp(addr
, drv
->acct_mac
, ETH_ALEN
) == 0) {
1236 /* Cached accounting data is not valid anymore. */
1237 os_memset(drv
->acct_mac
, 0, ETH_ALEN
);
1238 os_memset(&drv
->acct_data
, 0, sizeof(drv
->acct_data
));
1243 atheros_wireless_event_wireless_custom(struct atheros_driver_data
*drv
,
1244 char *custom
, char *end
)
1246 #define MGMT_FRAM_TAG_SIZE 30 /* hardcoded in driver */
1247 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
1249 if (os_strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
1252 pos
= os_strstr(custom
, "addr=");
1254 wpa_printf(MSG_DEBUG
,
1255 "MLME-MICHAELMICFAILURE.indication "
1256 "without sender address ignored");
1260 if (hwaddr_aton(pos
, addr
) == 0) {
1261 union wpa_event_data data
;
1262 os_memset(&data
, 0, sizeof(data
));
1263 data
.michael_mic_failure
.unicast
= 1;
1264 data
.michael_mic_failure
.src
= addr
;
1265 wpa_supplicant_event(drv
->hapd
,
1266 EVENT_MICHAEL_MIC_FAILURE
, &data
);
1268 wpa_printf(MSG_DEBUG
,
1269 "MLME-MICHAELMICFAILURE.indication "
1270 "with invalid MAC address");
1272 } else if (strncmp(custom
, "STA-TRAFFIC-STAT", 16) == 0) {
1276 while ((key
= os_strchr(key
, '\n')) != NULL
) {
1278 value
= os_strchr(key
, '=');
1282 val
= strtoul(value
, NULL
, 10);
1283 if (os_strcmp(key
, "mac") == 0)
1284 hwaddr_aton(value
, drv
->acct_mac
);
1285 else if (os_strcmp(key
, "rx_packets") == 0)
1286 drv
->acct_data
.rx_packets
= val
;
1287 else if (os_strcmp(key
, "tx_packets") == 0)
1288 drv
->acct_data
.tx_packets
= val
;
1289 else if (os_strcmp(key
, "rx_bytes") == 0)
1290 drv
->acct_data
.rx_bytes
= val
;
1291 else if (os_strcmp(key
, "tx_bytes") == 0)
1292 drv
->acct_data
.tx_bytes
= val
;
1296 } else if (os_strncmp(custom
, "PUSH-BUTTON.indication", 22) == 0) {
1297 /* Some atheros kernels send push button as a wireless event */
1298 /* PROBLEM! this event is received for ALL BSSs ...
1299 * so all are enabled for WPS... ugh.
1301 wpa_supplicant_event(drv
->hapd
, EVENT_WPS_BUTTON_PUSHED
, NULL
);
1302 } else if (os_strncmp(custom
, "Manage.prob_req ", 16) == 0) {
1304 * Atheros driver uses a hack to pass Probe Request frames as a
1305 * binary data in the custom wireless event. The old way (using
1306 * packet sniffing) didn't work when bridging.
1307 * Format: "Manage.prob_req <frame len>" | zero padding | frame
1309 int len
= atoi(custom
+ 16);
1310 if (len
< 0 || MGMT_FRAM_TAG_SIZE
+ len
> end
- custom
) {
1311 wpa_printf(MSG_DEBUG
, "Invalid Manage.prob_req event "
1315 atheros_raw_receive(drv
, NULL
,
1316 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1317 #endif /* CONFIG_WPS */
1318 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1319 } else if (os_strncmp(custom
, "Manage.assoc_req ", 17) == 0) {
1320 /* Format: "Manage.assoc_req <frame len>" | zero padding |
1322 int len
= atoi(custom
+ 17);
1323 if (len
< 0 || MGMT_FRAM_TAG_SIZE
+ len
> end
- custom
) {
1324 wpa_printf(MSG_DEBUG
,
1325 "Invalid Manage.assoc_req event length %d",
1329 atheros_raw_receive(drv
, NULL
,
1330 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1331 } else if (os_strncmp(custom
, "Manage.auth ", 12) == 0) {
1332 /* Format: "Manage.auth <frame len>" | zero padding | frame */
1333 int len
= atoi(custom
+ 12);
1335 MGMT_FRAM_TAG_SIZE
+ len
> end
- custom
) {
1336 wpa_printf(MSG_DEBUG
,
1337 "Invalid Manage.auth event length %d", len
);
1340 atheros_raw_receive(drv
, NULL
,
1341 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1342 #endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R || CONFIG_FILS */
1343 #ifdef ATHEROS_USE_RAW_RECEIVE
1344 } else if (os_strncmp(custom
, "Manage.action ", 14) == 0) {
1345 /* Format: "Manage.assoc_req <frame len>" | zero padding | frame
1347 int len
= atoi(custom
+ 14);
1348 if (len
< 0 || MGMT_FRAM_TAG_SIZE
+ len
> end
- custom
) {
1349 wpa_printf(MSG_DEBUG
,
1350 "Invalid Manage.action event length %d",
1354 atheros_raw_receive(drv
, NULL
,
1355 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1356 #endif /* ATHEROS_USE_RAW_RECEIVE */
1361 static void send_action_cb_event(struct atheros_driver_data
*drv
,
1362 char *data
, size_t data_len
)
1364 union wpa_event_data event
;
1365 struct ieee80211_send_action_cb
*sa
;
1366 const struct ieee80211_hdr
*hdr
;
1369 if (data_len
< sizeof(*sa
) + 24) {
1370 wpa_printf(MSG_DEBUG
,
1371 "athr: Too short event message (data_len=%d sizeof(*sa)=%d)",
1372 (int) data_len
, (int) sizeof(*sa
));
1373 wpa_hexdump(MSG_DEBUG
, "athr: Short event message",
1378 sa
= (struct ieee80211_send_action_cb
*) data
;
1380 hdr
= (const struct ieee80211_hdr
*) (sa
+ 1);
1381 fc
= le_to_host16(hdr
->frame_control
);
1383 os_memset(&event
, 0, sizeof(event
));
1384 event
.tx_status
.type
= WLAN_FC_GET_TYPE(fc
);
1385 event
.tx_status
.stype
= WLAN_FC_GET_STYPE(fc
);
1386 event
.tx_status
.dst
= sa
->dst_addr
;
1387 event
.tx_status
.data
= (const u8
*) hdr
;
1388 event
.tx_status
.data_len
= data_len
- sizeof(*sa
);
1389 event
.tx_status
.ack
= sa
->ack
;
1390 wpa_supplicant_event(drv
->hapd
, EVENT_TX_STATUS
, &event
);
1395 * Handle size of data problem. WEXT only allows data of 256 bytes for custom
1396 * events, and p2p data can be much bigger. So the athr driver sends a small
1397 * event telling me to collect the big data with an ioctl.
1398 * On the first event, send all pending events to supplicant.
1400 static void fetch_pending_big_events(struct atheros_driver_data
*drv
)
1402 union wpa_event_data event
;
1403 const struct ieee80211_mgmt
*mgmt
;
1404 u8 tbuf
[IW_PRIV_SIZE_MASK
]; /* max size is 2047 bytes */
1408 u32 freq
, frame_type
;
1411 os_memset(&iwr
, 0, sizeof(iwr
));
1412 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1414 iwr
.u
.data
.pointer
= (void *) tbuf
;
1415 iwr
.u
.data
.length
= sizeof(tbuf
);
1416 iwr
.u
.data
.flags
= IEEE80211_IOC_P2P_FETCH_FRAME
;
1418 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_P2P_BIG_PARAM
, &iwr
)
1420 if (errno
== ENOSPC
) {
1421 wpa_printf(MSG_DEBUG
, "%s:%d exit",
1422 __func__
, __LINE__
);
1425 wpa_printf(MSG_DEBUG
, "athr: %s: P2P_BIG_PARAM["
1426 "P2P_FETCH_FRAME] failed: %s",
1427 __func__
, strerror(errno
));
1430 data_len
= iwr
.u
.data
.length
;
1431 wpa_hexdump(MSG_DEBUG
, "athr: P2P_FETCH_FRAME data",
1432 (u8
*) tbuf
, data_len
);
1433 if (data_len
< sizeof(freq
) + sizeof(frame_type
) + 24) {
1434 wpa_printf(MSG_DEBUG
, "athr: frame too short");
1437 os_memcpy(&freq
, tbuf
, sizeof(freq
));
1438 os_memcpy(&frame_type
, &tbuf
[sizeof(freq
)],
1439 sizeof(frame_type
));
1440 mgmt
= (void *) &tbuf
[sizeof(freq
) + sizeof(frame_type
)];
1441 data_len
-= sizeof(freq
) + sizeof(frame_type
);
1443 if (frame_type
== IEEE80211_EV_RX_MGMT
) {
1444 fc
= le_to_host16(mgmt
->frame_control
);
1445 stype
= WLAN_FC_GET_STYPE(fc
);
1447 wpa_printf(MSG_DEBUG
, "athr: EV_RX_MGMT stype=%u "
1448 "freq=%u len=%u", stype
, freq
, (int) data_len
);
1450 if (stype
== WLAN_FC_STYPE_ACTION
) {
1451 os_memset(&event
, 0, sizeof(event
));
1452 event
.rx_mgmt
.frame
= (const u8
*) mgmt
;
1453 event
.rx_mgmt
.frame_len
= data_len
;
1454 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
,
1458 } else if (frame_type
== IEEE80211_EV_P2P_SEND_ACTION_CB
) {
1459 wpa_printf(MSG_DEBUG
,
1460 "%s: ACTION_CB frame_type=%u len=%zu",
1461 __func__
, frame_type
, data_len
);
1462 send_action_cb_event(drv
, (void *) mgmt
, data_len
);
1464 wpa_printf(MSG_DEBUG
, "athr: %s unknown type %d",
1465 __func__
, frame_type
);
1472 atheros_wireless_event_atheros_custom(struct atheros_driver_data
*drv
,
1473 int opcode
, char *buf
, int len
)
1476 case IEEE80211_EV_P2P_SEND_ACTION_CB
:
1477 wpa_printf(MSG_DEBUG
, "WEXT: EV_P2P_SEND_ACTION_CB");
1478 fetch_pending_big_events(drv
);
1480 case IEEE80211_EV_RX_MGMT
:
1481 wpa_printf(MSG_DEBUG
, "WEXT: EV_RX_MGMT");
1482 fetch_pending_big_events(drv
);
1490 atheros_wireless_event_wireless(struct atheros_driver_data
*drv
,
1491 char *data
, unsigned int len
)
1493 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
1494 char *pos
, *end
, *custom
, *buf
;
1499 while ((size_t) (end
- pos
) >= IW_EV_LCP_LEN
) {
1500 /* Event data may be unaligned, so make a local, aligned copy
1501 * before processing. */
1502 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
1503 wpa_printf(MSG_MSGDUMP
, "Wireless event: cmd=0x%x len=%d",
1504 iwe
->cmd
, iwe
->len
);
1505 if (iwe
->len
<= IW_EV_LCP_LEN
|| iwe
->len
> end
- pos
)
1508 custom
= pos
+ IW_EV_POINT_LEN
;
1509 if (drv
->we_version
> 18 &&
1510 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
1511 iwe
->cmd
== IWEVASSOCREQIE
||
1512 iwe
->cmd
== IWEVCUSTOM
)) {
1513 /* WE-19 removed the pointer from struct iw_point */
1514 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
1515 int dlen
= dpos
- (char *) &iwe_buf
;
1516 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
1517 sizeof(struct iw_event
) - dlen
);
1519 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
1520 custom
+= IW_EV_POINT_OFF
;
1525 drv_event_disassoc(drv
->hapd
,
1526 (u8
*) iwe
->u
.addr
.sa_data
);
1528 case IWEVREGISTERED
:
1529 atheros_new_sta(drv
, (u8
*) iwe
->u
.addr
.sa_data
);
1531 case IWEVASSOCREQIE
:
1532 /* Driver hack.. Use IWEVASSOCREQIE to bypass
1533 * IWEVCUSTOM size limitations. Need to handle this
1534 * just like IWEVCUSTOM.
1537 if (iwe
->u
.data
.length
> end
- custom
)
1539 buf
= os_malloc(iwe
->u
.data
.length
+ 1);
1542 os_memcpy(buf
, custom
, iwe
->u
.data
.length
);
1543 buf
[iwe
->u
.data
.length
] = '\0';
1545 if (iwe
->u
.data
.flags
!= 0) {
1546 atheros_wireless_event_atheros_custom(
1547 drv
, (int) iwe
->u
.data
.flags
,
1550 atheros_wireless_event_wireless_custom(
1551 drv
, buf
, buf
+ iwe
->u
.data
.length
);
1563 atheros_wireless_event_rtm_newlink(void *ctx
,
1564 struct ifinfomsg
*ifi
, u8
*buf
, size_t len
)
1566 struct atheros_driver_data
*drv
= ctx
;
1567 int attrlen
, rta_len
;
1568 struct rtattr
*attr
;
1570 if (ifi
->ifi_index
!= drv
->ifindex
)
1574 attr
= (struct rtattr
*) buf
;
1576 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
1577 while (RTA_OK(attr
, attrlen
)) {
1578 if (attr
->rta_type
== IFLA_WIRELESS
) {
1579 atheros_wireless_event_wireless(
1580 drv
, ((char *) attr
) + rta_len
,
1581 attr
->rta_len
- rta_len
);
1583 attr
= RTA_NEXT(attr
, attrlen
);
1589 atheros_get_we_version(struct atheros_driver_data
*drv
)
1591 struct iw_range
*range
;
1596 drv
->we_version
= 0;
1599 * Use larger buffer than struct iw_range in order to allow the
1600 * structure to grow in the future.
1602 buflen
= sizeof(struct iw_range
) + 500;
1603 range
= os_zalloc(buflen
);
1607 os_memset(&iwr
, 0, sizeof(iwr
));
1608 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1609 iwr
.u
.data
.pointer
= (caddr_t
) range
;
1610 iwr
.u
.data
.length
= buflen
;
1612 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1613 sizeof(range
->enc_capa
);
1615 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1616 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWRANGE]: %s",
1620 } else if (iwr
.u
.data
.length
>= minlen
&&
1621 range
->we_version_compiled
>= 18) {
1622 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1623 "WE(source)=%d enc_capa=0x%x",
1624 range
->we_version_compiled
,
1625 range
->we_version_source
,
1627 drv
->we_version
= range
->we_version_compiled
;
1636 atheros_wireless_event_init(struct atheros_driver_data
*drv
)
1638 struct netlink_config
*cfg
;
1640 atheros_get_we_version(drv
);
1642 cfg
= os_zalloc(sizeof(*cfg
));
1646 cfg
->newlink_cb
= atheros_wireless_event_rtm_newlink
;
1647 drv
->netlink
= netlink_init(cfg
);
1648 if (drv
->netlink
== NULL
) {
1658 atheros_send_eapol(void *priv
, const u8
*addr
, const u8
*data
, size_t data_len
,
1659 int encrypt
, const u8
*own_addr
, u32 flags
)
1661 struct atheros_driver_data
*drv
= priv
;
1662 unsigned char buf
[3000];
1663 unsigned char *bp
= buf
;
1664 struct l2_ethhdr
*eth
;
1669 * Prepend the Ethernet header. If the caller left us
1670 * space at the front we could just insert it but since
1671 * we don't know we copy to a local buffer. Given the frequency
1672 * and size of frames this probably doesn't matter.
1674 len
= data_len
+ sizeof(struct l2_ethhdr
);
1675 if (len
> sizeof(buf
)) {
1676 bp
= os_malloc(len
);
1678 wpa_printf(MSG_INFO
,
1679 "EAPOL frame discarded, cannot malloc temp buffer of size %lu!",
1680 (unsigned long) len
);
1684 eth
= (struct l2_ethhdr
*) bp
;
1685 os_memcpy(eth
->h_dest
, addr
, ETH_ALEN
);
1686 os_memcpy(eth
->h_source
, own_addr
, ETH_ALEN
);
1687 eth
->h_proto
= host_to_be16(ETH_P_EAPOL
);
1688 os_memcpy(eth
+ 1, data
, data_len
);
1690 wpa_hexdump(MSG_MSGDUMP
, "TX EAPOL", bp
, len
);
1692 status
= l2_packet_send(drv
->sock_xmit
, addr
, ETH_P_EAPOL
, bp
, len
);
1700 handle_read(void *ctx
, const u8
*src_addr
, const u8
*buf
, size_t len
)
1702 struct atheros_driver_data
*drv
= ctx
;
1703 drv_event_eapol_rx(drv
->hapd
, src_addr
, buf
+ sizeof(struct l2_ethhdr
),
1704 len
- sizeof(struct l2_ethhdr
));
1708 static void atheros_read_fils_cap(struct atheros_driver_data
*drv
)
1713 /* TODO: Would be better to have #ifdef on the IEEE80211_PARAM_* value
1714 * to automatically check this against the driver header files. */
1715 if (get80211param(drv
, IEEE80211_PARAM_ENABLE_FILS
, &fils
) < 0) {
1716 wpa_printf(MSG_DEBUG
,
1717 "%s: Failed to get FILS capability from driver",
1719 /* Assume driver does not support FILS */
1722 #endif /* CONFIG_FILS */
1723 drv
->fils_en
= fils
;
1724 wpa_printf(MSG_DEBUG
, "atheros: fils_en=%d", drv
->fils_en
);
1729 atheros_init(struct hostapd_data
*hapd
, struct wpa_init_params
*params
)
1731 struct atheros_driver_data
*drv
;
1734 char brname
[IFNAMSIZ
];
1736 drv
= os_zalloc(sizeof(struct atheros_driver_data
));
1738 wpa_printf(MSG_INFO
,
1739 "Could not allocate memory for atheros driver data");
1744 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1745 if (drv
->ioctl_sock
< 0) {
1746 wpa_printf(MSG_ERROR
, "socket[PF_INET,SOCK_DGRAM]: %s",
1750 os_memcpy(drv
->iface
, params
->ifname
, sizeof(drv
->iface
));
1752 os_memset(&ifr
, 0, sizeof(ifr
));
1753 os_strlcpy(ifr
.ifr_name
, drv
->iface
, sizeof(ifr
.ifr_name
));
1754 if (ioctl(drv
->ioctl_sock
, SIOCGIFINDEX
, &ifr
) != 0) {
1755 wpa_printf(MSG_ERROR
, "ioctl(SIOCGIFINDEX): %s",
1759 drv
->ifindex
= ifr
.ifr_ifindex
;
1761 drv
->sock_xmit
= l2_packet_init(drv
->iface
, NULL
, ETH_P_EAPOL
,
1762 handle_read
, drv
, 1);
1763 if (drv
->sock_xmit
== NULL
)
1765 if (l2_packet_get_own_addr(drv
->sock_xmit
, params
->own_addr
))
1767 os_memcpy(drv
->own_addr
, params
->own_addr
, ETH_ALEN
);
1768 if (params
->bridge
[0]) {
1769 wpa_printf(MSG_DEBUG
, "Configure bridge %s for EAPOL traffic.",
1771 drv
->sock_recv
= l2_packet_init(params
->bridge
[0], NULL
,
1772 ETH_P_EAPOL
, handle_read
, drv
,
1774 if (drv
->sock_recv
== NULL
)
1776 } else if (linux_br_get(brname
, drv
->iface
) == 0) {
1777 wpa_printf(MSG_DEBUG
, "Interface in bridge %s; configure for "
1778 "EAPOL receive", brname
);
1779 drv
->sock_recv
= l2_packet_init(brname
, NULL
, ETH_P_EAPOL
,
1780 handle_read
, drv
, 1);
1781 if (drv
->sock_recv
== NULL
)
1784 drv
->sock_recv
= drv
->sock_xmit
;
1786 os_memset(&iwr
, 0, sizeof(iwr
));
1787 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1789 iwr
.u
.mode
= IW_MODE_MASTER
;
1791 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) < 0) {
1792 wpa_printf(MSG_ERROR
,
1793 "Could not set interface to master mode! ioctl[SIOCSIWMODE]: %s",
1798 /* mark down during setup */
1799 linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 0);
1800 atheros_set_privacy(drv
, 0); /* default to no privacy */
1802 if (atheros_receive_pkt(drv
))
1805 if (atheros_wireless_event_init(drv
))
1808 /* Read FILS capability from the driver */
1809 atheros_read_fils_cap(drv
);
1813 atheros_reset_appfilter(drv
);
1815 l2_packet_deinit(drv
->sock_raw
);
1816 if (drv
->sock_recv
!= NULL
&& drv
->sock_recv
!= drv
->sock_xmit
)
1817 l2_packet_deinit(drv
->sock_recv
);
1818 if (drv
->sock_xmit
!= NULL
)
1819 l2_packet_deinit(drv
->sock_xmit
);
1820 if (drv
->ioctl_sock
>= 0)
1821 close(drv
->ioctl_sock
);
1828 atheros_deinit(void *priv
)
1830 struct atheros_driver_data
*drv
= priv
;
1832 atheros_reset_appfilter(drv
);
1834 if (drv
->wpa_ie
|| drv
->wps_beacon_ie
|| drv
->wps_probe_resp_ie
) {
1835 atheros_set_opt_ie(priv
, NULL
, 0);
1836 wpabuf_free(drv
->wpa_ie
);
1837 wpabuf_free(drv
->wps_beacon_ie
);
1838 wpabuf_free(drv
->wps_probe_resp_ie
);
1840 netlink_deinit(drv
->netlink
);
1841 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 0);
1842 if (drv
->ioctl_sock
>= 0)
1843 close(drv
->ioctl_sock
);
1844 if (drv
->sock_recv
!= NULL
&& drv
->sock_recv
!= drv
->sock_xmit
)
1845 l2_packet_deinit(drv
->sock_recv
);
1846 if (drv
->sock_xmit
!= NULL
)
1847 l2_packet_deinit(drv
->sock_xmit
);
1849 l2_packet_deinit(drv
->sock_raw
);
1854 atheros_set_ssid(void *priv
, const u8
*buf
, int len
)
1856 struct atheros_driver_data
*drv
= priv
;
1859 os_memset(&iwr
, 0, sizeof(iwr
));
1860 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1861 iwr
.u
.essid
.flags
= 1; /* SSID active */
1862 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
1863 iwr
.u
.essid
.length
= len
;
1865 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
1866 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWESSID,len=%d]: %s",
1867 len
, strerror(errno
));
1874 atheros_get_ssid(void *priv
, u8
*buf
, int len
)
1876 struct atheros_driver_data
*drv
= priv
;
1880 os_memset(&iwr
, 0, sizeof(iwr
));
1881 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1882 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
1883 iwr
.u
.essid
.length
= (len
> IW_ESSID_MAX_SIZE
) ?
1884 IW_ESSID_MAX_SIZE
: len
;
1886 if (ioctl(drv
->ioctl_sock
, SIOCGIWESSID
, &iwr
) < 0) {
1887 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWESSID]: %s",
1891 ret
= iwr
.u
.essid
.length
;
1897 atheros_set_countermeasures(void *priv
, int enabled
)
1899 struct atheros_driver_data
*drv
= priv
;
1900 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1901 return set80211param(drv
, IEEE80211_PARAM_COUNTERMEASURES
, enabled
);
1905 atheros_commit(void *priv
)
1907 struct atheros_driver_data
*drv
= priv
;
1908 return linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 1);
1911 static int atheros_set_authmode(void *priv
, int auth_algs
)
1915 if ((auth_algs
& WPA_AUTH_ALG_OPEN
) &&
1916 (auth_algs
& WPA_AUTH_ALG_SHARED
))
1917 authmode
= IEEE80211_AUTH_AUTO
;
1918 else if (auth_algs
& WPA_AUTH_ALG_OPEN
)
1919 authmode
= IEEE80211_AUTH_OPEN
;
1920 else if (auth_algs
& WPA_AUTH_ALG_SHARED
)
1921 authmode
= IEEE80211_AUTH_SHARED
;
1925 return set80211param(priv
, IEEE80211_PARAM_AUTHMODE
, authmode
);
1928 static int atheros_set_ap(void *priv
, struct wpa_driver_ap_params
*params
)
1931 * TODO: Use this to replace set_authmode, set_privacy, set_ieee8021x,
1932 * set_generic_elem, and hapd_set_ssid.
1935 wpa_printf(MSG_DEBUG
, "atheros: set_ap - pairwise_ciphers=0x%x "
1936 "group_cipher=0x%x key_mgmt_suites=0x%x auth_algs=0x%x "
1937 "wpa_version=0x%x privacy=%d interworking=%d",
1938 params
->pairwise_ciphers
, params
->group_cipher
,
1939 params
->key_mgmt_suites
, params
->auth_algs
,
1940 params
->wpa_version
, params
->privacy
, params
->interworking
);
1941 wpa_hexdump_ascii(MSG_DEBUG
, "atheros: SSID",
1942 params
->ssid
, params
->ssid_len
);
1944 wpa_printf(MSG_DEBUG
, "atheros: HESSID " MACSTR
,
1945 MAC2STR(params
->hessid
));
1946 wpa_hexdump_buf(MSG_DEBUG
, "atheros: beacon_ies",
1947 params
->beacon_ies
);
1948 wpa_hexdump_buf(MSG_DEBUG
, "atheros: proberesp_ies",
1949 params
->proberesp_ies
);
1950 wpa_hexdump_buf(MSG_DEBUG
, "atheros: assocresp_ies",
1951 params
->assocresp_ies
);
1953 #if defined(CONFIG_HS20) && (defined(IEEE80211_PARAM_OSEN) || defined(CONFIG_ATHEROS_OSEN))
1955 struct wpa_bss_params bss_params
;
1957 os_memset(&bss_params
, 0, sizeof(struct wpa_bss_params
));
1958 bss_params
.enabled
= 1;
1960 bss_params
.wpa_pairwise
= WPA_CIPHER_CCMP
;
1961 bss_params
.wpa_group
= WPA_CIPHER_CCMP
;
1962 bss_params
.ieee802_1x
= 1;
1964 if (atheros_set_privacy(priv
, 1) ||
1965 set80211param(priv
, IEEE80211_PARAM_OSEN
, 1))
1968 return atheros_set_ieee8021x(priv
, &bss_params
);
1970 #endif /* CONFIG_HS20 && IEEE80211_PARAM_OSEN */
1976 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1978 static int atheros_send_mgmt(void *priv
, const u8
*frm
, size_t data_len
,
1979 int noack
, unsigned int freq
,
1980 const u16
*csa_offs
, size_t csa_offs_len
)
1982 struct atheros_driver_data
*drv
= priv
;
1984 const struct ieee80211_mgmt
*mgmt
;
1985 struct ieee80211req_mgmtbuf
*mgmt_frm
;
1987 mgmt
= (const struct ieee80211_mgmt
*) frm
;
1988 wpa_printf(MSG_DEBUG
, "%s frmlen = %lu " MACSTR
, __func__
,
1989 (unsigned long) data_len
, MAC2STR(mgmt
->da
));
1990 mgmt_frm
= (struct ieee80211req_mgmtbuf
*) buf
;
1991 os_memcpy(mgmt_frm
->macaddr
, (u8
*)mgmt
->da
, IEEE80211_ADDR_LEN
);
1992 mgmt_frm
->buflen
= data_len
;
1993 if (&mgmt_frm
->buf
[0] + data_len
> buf
+ sizeof(buf
)) {
1994 wpa_printf(MSG_INFO
, "atheros: Too long frame for "
1995 "atheros_send_mgmt (%u)", (unsigned int) data_len
);
1998 os_memcpy(&mgmt_frm
->buf
[0], frm
, data_len
);
1999 return set80211priv(drv
, IEEE80211_IOCTL_SEND_MGMT
, mgmt_frm
,
2000 sizeof(struct ieee80211req_mgmtbuf
) + data_len
);
2002 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W || CONFIG_FILS */
2005 #ifdef CONFIG_IEEE80211R
2007 static int atheros_add_tspec(void *priv
, const u8
*addr
, u8
*tspec_ie
,
2010 struct atheros_driver_data
*drv
= priv
;
2012 struct ieee80211req_res req
;
2013 struct ieee80211req_res_addts
*addts
= &req
.u
.addts
;
2015 wpa_printf(MSG_DEBUG
, "%s", __func__
);
2016 req
.type
= IEEE80211_RESREQ_ADDTS
;
2017 os_memcpy(&req
.macaddr
[0], addr
, IEEE80211_ADDR_LEN
);
2018 os_memcpy(addts
->tspecie
, tspec_ie
, tspec_ielen
);
2019 retv
= set80211priv(drv
, IEEE80211_IOCTL_RES_REQ
, &req
,
2020 sizeof(struct ieee80211req_res
));
2022 wpa_printf(MSG_DEBUG
, "%s IEEE80211_IOCTL_RES_REQ FAILED "
2023 "retv = %d", __func__
, retv
);
2026 os_memcpy(tspec_ie
, addts
->tspecie
, tspec_ielen
);
2027 return addts
->status
;
2031 static int atheros_add_sta_node(void *priv
, const u8
*addr
, u16 auth_alg
)
2033 struct atheros_driver_data
*drv
= priv
;
2034 struct ieee80211req_res req
;
2035 struct ieee80211req_res_addnode
*addnode
= &req
.u
.addnode
;
2037 wpa_printf(MSG_DEBUG
, "%s", __func__
);
2038 req
.type
= IEEE80211_RESREQ_ADDNODE
;
2039 os_memcpy(&req
.macaddr
[0], addr
, IEEE80211_ADDR_LEN
);
2040 addnode
->auth_alg
= auth_alg
;
2041 return set80211priv(drv
, IEEE80211_IOCTL_RES_REQ
, &req
,
2042 sizeof(struct ieee80211req_res
));
2045 #endif /* CONFIG_IEEE80211R */
2048 /* Use only to set a big param, get will not work. */
2050 set80211big(struct atheros_driver_data
*drv
, int op
, const void *data
, int len
)
2054 os_memset(&iwr
, 0, sizeof(iwr
));
2055 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
2057 iwr
.u
.data
.pointer
= (void *) data
;
2058 iwr
.u
.data
.length
= len
;
2059 iwr
.u
.data
.flags
= op
;
2060 wpa_printf(MSG_DEBUG
, "%s: op=0x%x=%d (%s) len=0x%x",
2061 __func__
, op
, op
, athr_get_param_name(op
), len
);
2063 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_P2P_BIG_PARAM
, &iwr
) < 0) {
2064 wpa_printf(MSG_DEBUG
, "%s: op=0x%x (%s) subop=0x%x=%d "
2065 "value=0x%x,0x%x failed: %d (%s)",
2066 __func__
, op
, athr_get_ioctl_name(op
), iwr
.u
.mode
,
2067 iwr
.u
.mode
, iwr
.u
.data
.length
,
2068 iwr
.u
.data
.flags
, errno
, strerror(errno
));
2075 static int atheros_send_action(void *priv
, unsigned int freq
,
2077 const u8
*dst
, const u8
*src
,
2079 const u8
*data
, size_t data_len
, int no_cck
)
2081 struct atheros_driver_data
*drv
= priv
;
2082 struct ieee80211_p2p_send_action
*act
;
2085 act
= os_zalloc(sizeof(*act
) + data_len
);
2089 os_memcpy(act
->dst_addr
, dst
, ETH_ALEN
);
2090 os_memcpy(act
->src_addr
, src
, ETH_ALEN
);
2091 os_memcpy(act
->bssid
, bssid
, ETH_ALEN
);
2092 os_memcpy(act
+ 1, data
, data_len
);
2093 wpa_printf(MSG_DEBUG
, "%s: freq=%d, wait=%u, dst=" MACSTR
", src="
2094 MACSTR
", bssid=" MACSTR
,
2095 __func__
, act
->freq
, wait
, MAC2STR(act
->dst_addr
),
2096 MAC2STR(act
->src_addr
), MAC2STR(act
->bssid
));
2097 wpa_hexdump(MSG_MSGDUMP
, "athr: act", (u8
*) act
, sizeof(*act
));
2098 wpa_hexdump(MSG_MSGDUMP
, "athr: data", data
, data_len
);
2100 res
= set80211big(drv
, IEEE80211_IOC_P2P_SEND_ACTION
,
2101 act
, sizeof(*act
) + data_len
);
2107 #if defined(CONFIG_WNM) && defined(IEEE80211_APPIE_FRAME_WNM)
2108 static int athr_wnm_tfs(struct atheros_driver_data
*drv
, const u8
* peer
,
2109 u8
*ie
, u16
*len
, enum wnm_oper oper
)
2111 #define IEEE80211_APPIE_MAX 1024 /* max appie buffer size */
2112 u8 buf
[IEEE80211_APPIE_MAX
];
2113 struct ieee80211req_getset_appiebuf
*tfs_ie
;
2116 wpa_printf(MSG_DEBUG
, "atheros: ifname=%s, WNM TFS IE oper=%d " MACSTR
,
2117 drv
->iface
, oper
, MAC2STR(peer
));
2120 case WNM_SLEEP_TFS_REQ_IE_SET
:
2121 if (*len
> IEEE80211_APPIE_MAX
-
2122 sizeof(struct ieee80211req_getset_appiebuf
)) {
2123 wpa_printf(MSG_DEBUG
, "TFS Req IE(s) too large");
2126 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
2127 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
2128 tfs_ie
->app_buflen
= ETH_ALEN
+ 2 + 2 + *len
;
2130 /* Command header for driver */
2131 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
2133 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
2135 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
2138 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2 + 2, ie
, *len
);
2140 if (set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, tfs_ie
,
2141 IEEE80211_APPIE_MAX
)) {
2142 wpa_printf(MSG_DEBUG
, "%s: Failed to set WNM TFS IE: "
2143 "%s", __func__
, strerror(errno
));
2147 case WNM_SLEEP_TFS_RESP_IE_ADD
:
2148 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
2149 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
2150 tfs_ie
->app_buflen
= IEEE80211_APPIE_MAX
-
2151 sizeof(struct ieee80211req_getset_appiebuf
);
2152 /* Command header for driver */
2153 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
2155 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
2157 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
2159 if (set80211priv(drv
, IEEE80211_IOCTL_GET_APPIEBUF
, tfs_ie
,
2160 IEEE80211_APPIE_MAX
)) {
2161 wpa_printf(MSG_DEBUG
, "%s: Failed to get WNM TFS IE: "
2162 "%s", __func__
, strerror(errno
));
2166 *len
= tfs_ie
->app_buflen
;
2167 os_memcpy(ie
, &(tfs_ie
->app_buf
[0]), *len
);
2168 wpa_printf(MSG_DEBUG
, "atheros: %c len=%d", tfs_ie
->app_buf
[0],
2171 case WNM_SLEEP_TFS_RESP_IE_NONE
:
2174 case WNM_SLEEP_TFS_IE_DEL
:
2175 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
2176 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
2177 tfs_ie
->app_buflen
= IEEE80211_APPIE_MAX
-
2178 sizeof(struct ieee80211req_getset_appiebuf
);
2179 /* Command header for driver */
2180 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
2182 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
2184 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
2186 if (set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, tfs_ie
,
2187 IEEE80211_APPIE_MAX
)) {
2188 wpa_printf(MSG_DEBUG
, "%s: Failed to set WNM TFS IE: "
2189 "%s", __func__
, strerror(errno
));
2194 wpa_printf(MSG_DEBUG
, "Unsupported TFS oper %d", oper
);
2202 static int atheros_wnm_sleep(struct atheros_driver_data
*drv
,
2203 const u8
*peer
, enum wnm_oper oper
)
2210 wpa_printf(MSG_DEBUG
, "atheros: WNM-Sleep Oper %d, " MACSTR
,
2211 oper
, MAC2STR(peer
));
2213 dlen
= ETH_ALEN
+ 2 + 2;
2214 data
= os_malloc(dlen
);
2218 /* Command header for driver */
2220 os_memcpy(pos
, peer
, ETH_ALEN
);
2224 os_memcpy(pos
, &val
, 2);
2228 os_memcpy(pos
, &val
, 2);
2230 ret
= atheros_set_wps_ie(drv
, data
, dlen
, IEEE80211_APPIE_FRAME_WNM
);
2238 static int atheros_wnm_oper(void *priv
, enum wnm_oper oper
, const u8
*peer
,
2239 u8
*buf
, u16
*buf_len
)
2241 struct atheros_driver_data
*drv
= priv
;
2244 case WNM_SLEEP_ENTER_CONFIRM
:
2245 case WNM_SLEEP_ENTER_FAIL
:
2246 case WNM_SLEEP_EXIT_CONFIRM
:
2247 case WNM_SLEEP_EXIT_FAIL
:
2248 return atheros_wnm_sleep(drv
, peer
, oper
);
2249 case WNM_SLEEP_TFS_REQ_IE_SET
:
2250 case WNM_SLEEP_TFS_RESP_IE_ADD
:
2251 case WNM_SLEEP_TFS_RESP_IE_NONE
:
2252 case WNM_SLEEP_TFS_IE_DEL
:
2253 return athr_wnm_tfs(drv
, peer
, buf
, buf_len
, oper
);
2255 wpa_printf(MSG_DEBUG
, "atheros: Unsupported WNM operation %d",
2260 #endif /* CONFIG_WNM && IEEE80211_APPIE_FRAME_WNM */
2263 const struct wpa_driver_ops wpa_driver_atheros_ops
= {
2265 .hapd_init
= atheros_init
,
2266 .hapd_deinit
= atheros_deinit
,
2267 .set_ieee8021x
= atheros_set_ieee8021x
,
2268 .set_privacy
= atheros_set_privacy
,
2269 .set_key
= atheros_set_key
,
2270 .get_seqnum
= atheros_get_seqnum
,
2271 .flush
= atheros_flush
,
2272 .set_generic_elem
= atheros_set_opt_ie
,
2273 .sta_set_flags
= atheros_sta_set_flags
,
2274 .read_sta_data
= atheros_read_sta_driver_data
,
2275 .hapd_send_eapol
= atheros_send_eapol
,
2276 .sta_disassoc
= atheros_sta_disassoc
,
2277 .sta_deauth
= atheros_sta_deauth
,
2278 .hapd_set_ssid
= atheros_set_ssid
,
2279 .hapd_get_ssid
= atheros_get_ssid
,
2280 .set_countermeasures
= atheros_set_countermeasures
,
2281 .sta_clear_stats
= atheros_sta_clear_stats
,
2282 .commit
= atheros_commit
,
2283 .set_ap_wps_ie
= atheros_set_ap_wps_ie
,
2284 .set_authmode
= atheros_set_authmode
,
2285 .set_ap
= atheros_set_ap
,
2286 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
2287 .sta_assoc
= atheros_sta_assoc
,
2288 .sta_auth
= atheros_sta_auth
,
2289 .send_mlme
= atheros_send_mgmt
,
2290 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W || CONFIG_FILS */
2291 #ifdef CONFIG_IEEE80211R
2292 .add_tspec
= atheros_add_tspec
,
2293 .add_sta_node
= atheros_add_sta_node
,
2294 #endif /* CONFIG_IEEE80211R */
2295 .send_action
= atheros_send_action
,
2296 #if defined(CONFIG_WNM) && defined(IEEE80211_APPIE_FRAME_WNM)
2297 .wnm_oper
= atheros_wnm_oper
,
2298 #endif /* CONFIG_WNM && IEEE80211_APPIE_FRAME_WNM */
2299 .set_qos_map
= atheros_set_qos_map
,