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"
41 #include <netpacket/packet.h>
42 #endif /* CONFIG_WPS */
44 #ifndef ETH_P_80211_RAW
45 #define ETH_P_80211_RAW 0x0019
48 #include "linux_wext.h"
52 #include "priv_netlink.h"
53 #include "l2_packet/l2_packet.h"
54 #include "common/ieee802_11_defs.h"
56 #include "linux_ioctl.h"
59 struct atheros_driver_data
{
60 struct hostapd_data
*hapd
; /* back pointer */
62 char iface
[IFNAMSIZ
+ 1];
64 struct l2_packet_data
*sock_xmit
; /* raw packet xmit socket */
65 struct l2_packet_data
*sock_recv
; /* raw packet recv socket */
66 int ioctl_sock
; /* socket for ioctl() use */
67 struct netlink_data
*netlink
;
69 u8 acct_mac
[ETH_ALEN
];
70 struct hostap_sta_driver_data acct_data
;
72 struct l2_packet_data
*sock_raw
; /* raw 802.11 management frames */
73 struct wpabuf
*wpa_ie
;
74 struct wpabuf
*wps_beacon_ie
;
75 struct wpabuf
*wps_probe_resp_ie
;
76 u8 own_addr
[ETH_ALEN
];
79 static int atheros_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
81 static int atheros_set_privacy(void *priv
, int enabled
);
83 static const char * athr_get_ioctl_name(int op
)
86 case IEEE80211_IOCTL_SETPARAM
:
88 case IEEE80211_IOCTL_GETPARAM
:
90 case IEEE80211_IOCTL_SETKEY
:
92 case IEEE80211_IOCTL_SETWMMPARAMS
:
93 return "SETWMMPARAMS";
94 case IEEE80211_IOCTL_DELKEY
:
96 case IEEE80211_IOCTL_GETWMMPARAMS
:
97 return "GETWMMPARAMS";
98 case IEEE80211_IOCTL_SETMLME
:
100 case IEEE80211_IOCTL_GETCHANINFO
:
101 return "GETCHANINFO";
102 case IEEE80211_IOCTL_SETOPTIE
:
104 case IEEE80211_IOCTL_GETOPTIE
:
106 case IEEE80211_IOCTL_ADDMAC
:
108 case IEEE80211_IOCTL_DELMAC
:
110 case IEEE80211_IOCTL_GETCHANLIST
:
111 return "GETCHANLIST";
112 case IEEE80211_IOCTL_SETCHANLIST
:
113 return "SETCHANLIST";
114 case IEEE80211_IOCTL_KICKMAC
:
116 case IEEE80211_IOCTL_CHANSWITCH
:
118 case IEEE80211_IOCTL_GETMODE
:
120 case IEEE80211_IOCTL_SETMODE
:
122 case IEEE80211_IOCTL_GET_APPIEBUF
:
123 return "GET_APPIEBUF";
124 case IEEE80211_IOCTL_SET_APPIEBUF
:
125 return "SET_APPIEBUF";
126 case IEEE80211_IOCTL_SET_ACPARAMS
:
127 return "SET_ACPARAMS";
128 case IEEE80211_IOCTL_FILTERFRAME
:
129 return "FILTERFRAME";
130 case IEEE80211_IOCTL_SET_RTPARAMS
:
131 return "SET_RTPARAMS";
132 case IEEE80211_IOCTL_SET_MEDENYENTRY
:
133 return "SET_MEDENYENTRY";
134 case IEEE80211_IOCTL_GET_MACADDR
:
135 return "GET_MACADDR";
136 case IEEE80211_IOCTL_SET_HBRPARAMS
:
137 return "SET_HBRPARAMS";
138 case IEEE80211_IOCTL_SET_RXTIMEOUT
:
139 return "SET_RXTIMEOUT";
140 case IEEE80211_IOCTL_STA_STATS
:
142 case IEEE80211_IOCTL_GETWPAIE
:
150 static const char * athr_get_param_name(int op
)
153 case IEEE80211_IOC_MCASTCIPHER
:
154 return "MCASTCIPHER";
155 case IEEE80211_PARAM_MCASTKEYLEN
:
156 return "MCASTKEYLEN";
157 case IEEE80211_PARAM_UCASTCIPHERS
:
158 return "UCASTCIPHERS";
159 case IEEE80211_PARAM_KEYMGTALGS
:
161 case IEEE80211_PARAM_RSNCAPS
:
163 case IEEE80211_PARAM_WPA
:
165 case IEEE80211_PARAM_AUTHMODE
:
167 case IEEE80211_PARAM_PRIVACY
:
169 case IEEE80211_PARAM_COUNTERMEASURES
:
170 return "COUNTERMEASURES";
178 set80211priv(struct atheros_driver_data
*drv
, int op
, void *data
, int len
)
181 int do_inline
= len
< IFNAMSIZ
;
183 /* Certain ioctls must use the non-inlined method */
184 if (op
== IEEE80211_IOCTL_SET_APPIEBUF
||
185 op
== IEEE80211_IOCTL_FILTERFRAME
)
188 memset(&iwr
, 0, sizeof(iwr
));
189 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
192 * Argument data fits inline; put it there.
194 memcpy(iwr
.u
.name
, data
, len
);
197 * Argument data too big for inline transfer; setup a
198 * parameter block instead; the kernel will transfer
199 * the data for the driver.
201 iwr
.u
.data
.pointer
= data
;
202 iwr
.u
.data
.length
= len
;
205 if (ioctl(drv
->ioctl_sock
, op
, &iwr
) < 0) {
206 wpa_printf(MSG_DEBUG
, "atheros: %s: %s: ioctl op=0x%x "
207 "(%s) len=%d failed: %d (%s)",
208 __func__
, drv
->iface
, op
,
209 athr_get_ioctl_name(op
),
210 len
, errno
, strerror(errno
));
217 set80211param(struct atheros_driver_data
*drv
, int op
, int arg
)
221 memset(&iwr
, 0, sizeof(iwr
));
222 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
224 memcpy(iwr
.u
.name
+sizeof(__u32
), &arg
, sizeof(arg
));
226 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_SETPARAM
, &iwr
) < 0) {
228 "%s: %s: Failed to set parameter (op %d (%s) arg %d): ioctl[IEEE80211_IOCTL_SETPARAM]: %s",
229 __func__
, drv
->iface
, op
, athr_get_param_name(op
),
230 arg
, strerror(errno
));
236 #ifndef CONFIG_NO_STDOUT_DEBUG
238 ether_sprintf(const u8
*addr
)
240 static char buf
[sizeof(MACSTR
)];
243 snprintf(buf
, sizeof(buf
), MACSTR
, MAC2STR(addr
));
245 snprintf(buf
, sizeof(buf
), MACSTR
, 0,0,0,0,0,0);
248 #endif /* CONFIG_NO_STDOUT_DEBUG */
251 * Configure WPA parameters.
254 atheros_configure_wpa(struct atheros_driver_data
*drv
,
255 struct wpa_bss_params
*params
)
259 switch (params
->wpa_group
) {
260 case WPA_CIPHER_CCMP
:
261 v
= IEEE80211_CIPHER_AES_CCM
;
263 #ifdef ATH_GCM_SUPPORT
264 case WPA_CIPHER_CCMP_256
:
265 v
= IEEE80211_CIPHER_AES_CCM_256
;
267 case WPA_CIPHER_GCMP
:
268 v
= IEEE80211_CIPHER_AES_GCM
;
270 case WPA_CIPHER_GCMP_256
:
271 v
= IEEE80211_CIPHER_AES_GCM_256
;
273 #endif /* ATH_GCM_SUPPORT */
274 case WPA_CIPHER_TKIP
:
275 v
= IEEE80211_CIPHER_TKIP
;
277 case WPA_CIPHER_WEP104
:
278 v
= IEEE80211_CIPHER_WEP
;
280 case WPA_CIPHER_WEP40
:
281 v
= IEEE80211_CIPHER_WEP
;
283 case WPA_CIPHER_NONE
:
284 v
= IEEE80211_CIPHER_NONE
;
287 wpa_printf(MSG_ERROR
, "Unknown group key cipher %u",
291 wpa_printf(MSG_DEBUG
, "%s: group key cipher=%d", __func__
, v
);
292 if (set80211param(drv
, IEEE80211_PARAM_MCASTCIPHER
, v
)) {
293 wpa_printf(MSG_INFO
, "Unable to set group key cipher to %u", v
);
296 if (v
== IEEE80211_CIPHER_WEP
) {
297 /* key length is done only for specific ciphers */
298 v
= (params
->wpa_group
== WPA_CIPHER_WEP104
? 13 : 5);
299 if (set80211param(drv
, IEEE80211_PARAM_MCASTKEYLEN
, v
)) {
301 "Unable to set group key length to %u", v
);
307 if (params
->wpa_pairwise
& WPA_CIPHER_CCMP
)
308 v
|= 1<<IEEE80211_CIPHER_AES_CCM
;
309 #ifdef ATH_GCM_SUPPORT
310 if (params
->wpa_pairwise
& WPA_CIPHER_CCMP_256
)
311 v
|= 1<<IEEE80211_CIPHER_AES_CCM_256
;
312 if (params
->wpa_pairwise
& WPA_CIPHER_GCMP
)
313 v
|= 1<<IEEE80211_CIPHER_AES_GCM
;
314 if (params
->wpa_pairwise
& WPA_CIPHER_GCMP_256
)
315 v
|= 1<<IEEE80211_CIPHER_AES_GCM_256
;
316 #endif /* ATH_GCM_SUPPORT */
317 if (params
->wpa_pairwise
& WPA_CIPHER_TKIP
)
318 v
|= 1<<IEEE80211_CIPHER_TKIP
;
319 if (params
->wpa_pairwise
& WPA_CIPHER_NONE
)
320 v
|= 1<<IEEE80211_CIPHER_NONE
;
321 wpa_printf(MSG_DEBUG
, "%s: pairwise key ciphers=0x%x", __func__
, v
);
322 if (set80211param(drv
, IEEE80211_PARAM_UCASTCIPHERS
, v
)) {
324 "Unable to set pairwise key ciphers to 0x%x", v
);
328 wpa_printf(MSG_DEBUG
, "%s: key management algorithms=0x%x",
329 __func__
, params
->wpa_key_mgmt
);
330 if (set80211param(drv
, IEEE80211_PARAM_KEYMGTALGS
,
331 params
->wpa_key_mgmt
)) {
333 "Unable to set key management algorithms to 0x%x",
334 params
->wpa_key_mgmt
);
339 if (params
->rsn_preauth
)
341 #ifdef CONFIG_IEEE80211W
342 if (params
->ieee80211w
!= NO_MGMT_FRAME_PROTECTION
) {
344 if (params
->ieee80211w
== MGMT_FRAME_PROTECTION_REQUIRED
)
347 #endif /* CONFIG_IEEE80211W */
349 wpa_printf(MSG_DEBUG
, "%s: rsn capabilities=0x%x", __func__
, v
);
350 if (set80211param(drv
, IEEE80211_PARAM_RSNCAPS
, v
)) {
351 wpa_printf(MSG_INFO
, "Unable to set RSN capabilities to 0x%x",
356 wpa_printf(MSG_DEBUG
, "%s: enable WPA=0x%x", __func__
, params
->wpa
);
357 if (set80211param(drv
, IEEE80211_PARAM_WPA
, params
->wpa
)) {
358 wpa_printf(MSG_INFO
, "Unable to set WPA to %u", params
->wpa
);
365 atheros_set_ieee8021x(void *priv
, struct wpa_bss_params
*params
)
367 struct atheros_driver_data
*drv
= priv
;
369 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, params
->enabled
);
371 if (!params
->enabled
) {
372 /* XXX restore state */
373 if (set80211param(priv
, IEEE80211_PARAM_AUTHMODE
,
374 IEEE80211_AUTH_AUTO
) < 0)
376 /* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */
377 return atheros_set_privacy(drv
, 0);
379 if (!params
->wpa
&& !params
->ieee802_1x
) {
380 wpa_printf(MSG_WARNING
, "No 802.1X or WPA enabled!");
383 if (params
->wpa
&& atheros_configure_wpa(drv
, params
) != 0) {
384 wpa_printf(MSG_WARNING
, "Error configuring WPA state!");
387 if (set80211param(priv
, IEEE80211_PARAM_AUTHMODE
,
388 (params
->wpa
? IEEE80211_AUTH_WPA
: IEEE80211_AUTH_8021X
))) {
389 wpa_printf(MSG_WARNING
, "Error enabling WPA/802.1X!");
397 atheros_set_privacy(void *priv
, int enabled
)
399 struct atheros_driver_data
*drv
= priv
;
401 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
403 return set80211param(drv
, IEEE80211_PARAM_PRIVACY
, enabled
);
407 atheros_set_sta_authorized(void *priv
, const u8
*addr
, int authorized
)
409 struct atheros_driver_data
*drv
= priv
;
410 struct ieee80211req_mlme mlme
;
413 wpa_printf(MSG_DEBUG
, "%s: addr=%s authorized=%d",
414 __func__
, ether_sprintf(addr
), authorized
);
417 mlme
.im_op
= IEEE80211_MLME_AUTHORIZE
;
419 mlme
.im_op
= IEEE80211_MLME_UNAUTHORIZE
;
421 memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
422 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
424 wpa_printf(MSG_DEBUG
, "%s: Failed to %sauthorize STA " MACSTR
,
425 __func__
, authorized
? "" : "un", MAC2STR(addr
));
432 atheros_sta_set_flags(void *priv
, const u8
*addr
,
433 int total_flags
, int flags_or
, int flags_and
)
435 /* For now, only support setting Authorized flag */
436 if (flags_or
& WPA_STA_AUTHORIZED
)
437 return atheros_set_sta_authorized(priv
, addr
, 1);
438 if (!(flags_and
& WPA_STA_AUTHORIZED
))
439 return atheros_set_sta_authorized(priv
, addr
, 0);
444 atheros_del_key(void *priv
, const u8
*addr
, int key_idx
)
446 struct atheros_driver_data
*drv
= priv
;
447 struct ieee80211req_del_key wk
;
450 wpa_printf(MSG_DEBUG
, "%s: addr=%s key_idx=%d",
451 __func__
, ether_sprintf(addr
), key_idx
);
453 memset(&wk
, 0, sizeof(wk
));
455 memcpy(wk
.idk_macaddr
, addr
, IEEE80211_ADDR_LEN
);
456 wk
.idk_keyix
= (u8
) IEEE80211_KEYIX_NONE
;
458 wk
.idk_keyix
= key_idx
;
461 ret
= set80211priv(drv
, IEEE80211_IOCTL_DELKEY
, &wk
, sizeof(wk
));
463 wpa_printf(MSG_DEBUG
, "%s: Failed to delete key (addr %s"
464 " key_idx %d)", __func__
, ether_sprintf(addr
),
472 atheros_set_key(const char *ifname
, void *priv
, enum wpa_alg alg
,
473 const u8
*addr
, int key_idx
, int set_tx
, const u8
*seq
,
474 size_t seq_len
, const u8
*key
, size_t key_len
)
476 struct atheros_driver_data
*drv
= priv
;
477 struct ieee80211req_key wk
;
481 if (alg
== WPA_ALG_NONE
)
482 return atheros_del_key(drv
, addr
, key_idx
);
484 wpa_printf(MSG_DEBUG
, "%s: alg=%d addr=%s key_idx=%d",
485 __func__
, alg
, ether_sprintf(addr
), key_idx
);
489 cipher
= IEEE80211_CIPHER_WEP
;
492 cipher
= IEEE80211_CIPHER_TKIP
;
495 cipher
= IEEE80211_CIPHER_AES_CCM
;
497 #ifdef ATH_GCM_SUPPORT
498 case WPA_ALG_CCMP_256
:
499 cipher
= IEEE80211_CIPHER_AES_CCM_256
;
502 cipher
= IEEE80211_CIPHER_AES_GCM
;
504 case WPA_ALG_GCMP_256
:
505 cipher
= IEEE80211_CIPHER_AES_GCM_256
;
507 #endif /* ATH_GCM_SUPPORT */
508 #ifdef CONFIG_IEEE80211W
510 cipher
= IEEE80211_CIPHER_AES_CMAC
;
512 #ifdef ATH_GCM_SUPPORT
513 case WPA_ALG_BIP_CMAC_256
:
514 cipher
= IEEE80211_CIPHER_AES_CMAC_256
;
516 case WPA_ALG_BIP_GMAC_128
:
517 cipher
= IEEE80211_CIPHER_AES_GMAC
;
519 case WPA_ALG_BIP_GMAC_256
:
520 cipher
= IEEE80211_CIPHER_AES_GMAC_256
;
522 #endif /* ATH_GCM_SUPPORT */
523 #endif /* CONFIG_IEEE80211W */
525 wpa_printf(MSG_INFO
, "%s: unknown/unsupported algorithm %d",
530 if (key_len
> sizeof(wk
.ik_keydata
)) {
531 wpa_printf(MSG_INFO
, "%s: key length %lu too big", __func__
,
532 (unsigned long) key_len
);
536 memset(&wk
, 0, sizeof(wk
));
538 wk
.ik_flags
= IEEE80211_KEY_RECV
| IEEE80211_KEY_XMIT
;
539 if (addr
== NULL
|| is_broadcast_ether_addr(addr
)) {
540 memset(wk
.ik_macaddr
, 0xff, IEEE80211_ADDR_LEN
);
541 wk
.ik_keyix
= key_idx
;
543 wk
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
545 memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
546 wk
.ik_keyix
= IEEE80211_KEYIX_NONE
;
548 wk
.ik_keylen
= key_len
;
549 memcpy(wk
.ik_keydata
, key
, key_len
);
551 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETKEY
, &wk
, sizeof(wk
));
553 wpa_printf(MSG_DEBUG
, "%s: Failed to set key (addr %s"
554 " key_idx %d alg %d key_len %lu set_tx %d)",
555 __func__
, ether_sprintf(wk
.ik_macaddr
), key_idx
,
556 alg
, (unsigned long) key_len
, set_tx
);
564 atheros_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
, int idx
,
567 struct atheros_driver_data
*drv
= priv
;
568 struct ieee80211req_key wk
;
570 wpa_printf(MSG_DEBUG
, "%s: addr=%s idx=%d",
571 __func__
, ether_sprintf(addr
), idx
);
573 memset(&wk
, 0, sizeof(wk
));
575 memset(wk
.ik_macaddr
, 0xff, IEEE80211_ADDR_LEN
);
577 memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
580 if (set80211priv(drv
, IEEE80211_IOCTL_GETKEY
, &wk
, sizeof(wk
))) {
581 wpa_printf(MSG_DEBUG
, "%s: Failed to get encryption data "
582 "(addr " MACSTR
" key_idx %d)",
583 __func__
, MAC2STR(wk
.ik_macaddr
), idx
);
587 #ifdef WORDS_BIGENDIAN
590 * wk.ik_keytsc is in host byte order (big endian), need to
591 * swap it to match with the byte order used in WPA.
594 #ifndef WPA_KEY_RSC_LEN
595 #define WPA_KEY_RSC_LEN 8
597 u8 tmp
[WPA_KEY_RSC_LEN
];
598 memcpy(tmp
, &wk
.ik_keytsc
, sizeof(wk
.ik_keytsc
));
599 for (i
= 0; i
< WPA_KEY_RSC_LEN
; i
++) {
600 seq
[i
] = tmp
[WPA_KEY_RSC_LEN
- i
- 1];
603 #else /* WORDS_BIGENDIAN */
604 memcpy(seq
, &wk
.ik_keytsc
, sizeof(wk
.ik_keytsc
));
605 #endif /* WORDS_BIGENDIAN */
611 atheros_flush(void *priv
)
613 u8 allsta
[IEEE80211_ADDR_LEN
];
614 memset(allsta
, 0xff, IEEE80211_ADDR_LEN
);
615 return atheros_sta_deauth(priv
, NULL
, allsta
,
616 IEEE80211_REASON_AUTH_LEAVE
);
621 atheros_read_sta_driver_data(void *priv
, struct hostap_sta_driver_data
*data
,
624 struct atheros_driver_data
*drv
= priv
;
625 struct ieee80211req_sta_stats stats
;
627 memset(data
, 0, sizeof(*data
));
630 * Fetch statistics for station from the system.
632 memset(&stats
, 0, sizeof(stats
));
633 memcpy(stats
.is_u
.macaddr
, addr
, IEEE80211_ADDR_LEN
);
634 if (set80211priv(drv
, IEEE80211_IOCTL_STA_STATS
,
635 &stats
, sizeof(stats
))) {
636 wpa_printf(MSG_DEBUG
, "%s: Failed to fetch STA stats (addr "
637 MACSTR
")", __func__
, MAC2STR(addr
));
638 if (memcmp(addr
, drv
->acct_mac
, ETH_ALEN
) == 0) {
639 memcpy(data
, &drv
->acct_data
, sizeof(*data
));
644 "Failed to get station stats information element");
648 data
->rx_packets
= stats
.is_stats
.ns_rx_data
;
649 data
->rx_bytes
= stats
.is_stats
.ns_rx_bytes
;
650 data
->tx_packets
= stats
.is_stats
.ns_tx_data
;
651 data
->tx_bytes
= stats
.is_stats
.ns_tx_bytes
;
657 atheros_sta_clear_stats(void *priv
, const u8
*addr
)
659 struct atheros_driver_data
*drv
= priv
;
660 struct ieee80211req_mlme mlme
;
663 wpa_printf(MSG_DEBUG
, "%s: addr=%s", __func__
, ether_sprintf(addr
));
665 mlme
.im_op
= IEEE80211_MLME_CLEAR_STATS
;
666 memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
667 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
,
670 wpa_printf(MSG_DEBUG
, "%s: Failed to clear STA stats (addr "
671 MACSTR
")", __func__
, MAC2STR(addr
));
679 atheros_set_opt_ie(void *priv
, const u8
*ie
, size_t ie_len
)
681 struct atheros_driver_data
*drv
= priv
;
683 struct ieee80211req_getset_appiebuf
*app_ie
;
685 wpa_printf(MSG_DEBUG
, "%s buflen = %lu", __func__
,
686 (unsigned long) ie_len
);
687 wpa_hexdump(MSG_DEBUG
, "atheros: set_generic_elem", ie
, ie_len
);
689 wpabuf_free(drv
->wpa_ie
);
690 drv
->wpa_ie
= wpabuf_alloc_copy(ie
, ie_len
);
692 app_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
693 os_memcpy(&(app_ie
->app_buf
[0]), ie
, ie_len
);
694 app_ie
->app_buflen
= ie_len
;
696 app_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_BEACON
;
698 /* append WPS IE for Beacon */
699 if (drv
->wps_beacon_ie
!= NULL
) {
700 os_memcpy(&(app_ie
->app_buf
[ie_len
]),
701 wpabuf_head(drv
->wps_beacon_ie
),
702 wpabuf_len(drv
->wps_beacon_ie
));
703 app_ie
->app_buflen
= ie_len
+ wpabuf_len(drv
->wps_beacon_ie
);
705 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF(Beacon)",
706 app_ie
->app_buf
, app_ie
->app_buflen
);
707 set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, app_ie
,
708 sizeof(struct ieee80211req_getset_appiebuf
) +
711 /* append WPS IE for Probe Response */
712 app_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_PROBE_RESP
;
713 if (drv
->wps_probe_resp_ie
!= NULL
) {
714 os_memcpy(&(app_ie
->app_buf
[ie_len
]),
715 wpabuf_head(drv
->wps_probe_resp_ie
),
716 wpabuf_len(drv
->wps_probe_resp_ie
));
717 app_ie
->app_buflen
= ie_len
+
718 wpabuf_len(drv
->wps_probe_resp_ie
);
720 app_ie
->app_buflen
= ie_len
;
721 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF(ProbeResp)",
722 app_ie
->app_buf
, app_ie
->app_buflen
);
723 set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, app_ie
,
724 sizeof(struct ieee80211req_getset_appiebuf
) +
730 atheros_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
733 struct atheros_driver_data
*drv
= priv
;
734 struct ieee80211req_mlme mlme
;
737 wpa_printf(MSG_DEBUG
, "%s: addr=%s reason_code=%d",
738 __func__
, ether_sprintf(addr
), reason_code
);
740 mlme
.im_op
= IEEE80211_MLME_DEAUTH
;
741 mlme
.im_reason
= reason_code
;
742 memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
743 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
745 wpa_printf(MSG_DEBUG
, "%s: Failed to deauth STA (addr " MACSTR
747 __func__
, MAC2STR(addr
), reason_code
);
754 atheros_sta_disassoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
757 struct atheros_driver_data
*drv
= priv
;
758 struct ieee80211req_mlme mlme
;
761 wpa_printf(MSG_DEBUG
, "%s: addr=%s reason_code=%d",
762 __func__
, ether_sprintf(addr
), reason_code
);
764 mlme
.im_op
= IEEE80211_MLME_DISASSOC
;
765 mlme
.im_reason
= reason_code
;
766 memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
767 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
769 wpa_printf(MSG_DEBUG
, "%s: Failed to disassoc STA (addr "
770 MACSTR
" reason %d)",
771 __func__
, MAC2STR(addr
), reason_code
);
777 static int atheros_set_qos_map(void *ctx
, const u8
*qos_map_set
,
780 #ifdef CONFIG_ATHEROS_QOS_MAP
781 struct atheros_driver_data
*drv
= ctx
;
782 struct ieee80211req_athdbg req
;
783 struct ieee80211_qos_map
*qos_map
= &req
.data
.qos_map
;
787 if (qos_map_set_len
< 16 || qos_map_set_len
> 58 ||
788 qos_map_set_len
& 1) {
789 wpa_printf(MSG_ERROR
, "Invalid QoS Map");
792 memset(&req
, 0, sizeof(struct ieee80211req_athdbg
));
793 req
.cmd
= IEEE80211_DBGREQ_SETQOSMAPCONF
;
794 os_memset(&iwr
, 0, sizeof(iwr
));
795 os_strlcpy(iwr
.ifr_name
, drv
->iface
, sizeof(iwr
.ifr_name
));
796 iwr
.u
.data
.pointer
= (void *) &req
;
797 iwr
.u
.data
.length
= sizeof(struct ieee80211req_athdbg
);
801 qos_map
->num_dscp_except
= (qos_map_set_len
- 16) / 2;
802 if (qos_map
->num_dscp_except
) {
803 for (i
= 0; i
< qos_map
->num_dscp_except
; i
++) {
804 qos_map
->dscp_exception
[i
].dscp
= qos_map_set
[i
* 2];
805 qos_map
->dscp_exception
[i
].up
= qos_map_set
[i
* 2 + 1];
809 up_start
= qos_map_set_len
- 16;
810 for (i
= 0; i
< IEEE80211_MAX_QOS_UP_RANGE
; i
++) {
811 qos_map
->up
[i
].low
= qos_map_set
[up_start
+ (i
* 2)];
812 qos_map
->up
[i
].high
= qos_map_set
[up_start
+ (i
* 2) + 1];
815 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_DBGREQ
, &iwr
) < 0) {
816 wpa_printf(MSG_ERROR
,
817 "%s: %s: Failed to set QoS Map: ioctl[IEEE80211_IOCTL_DBGREQ]: %s",
818 __func__
, drv
->iface
, strerror(errno
));
821 #endif /* CONFIG_ATHEROS_QOS_MAP */
826 #if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WNM) || defined(CONFIG_HS20)
827 static void atheros_raw_receive(void *ctx
, const u8
*src_addr
, const u8
*buf
,
830 struct atheros_driver_data
*drv
= ctx
;
831 const struct ieee80211_mgmt
*mgmt
;
832 union wpa_event_data event
;
837 if (len
< IEEE80211_HDRLEN
)
840 mgmt
= (const struct ieee80211_mgmt
*) buf
;
842 fc
= le_to_host16(mgmt
->frame_control
);
844 if (WLAN_FC_GET_TYPE(fc
) != WLAN_FC_TYPE_MGMT
)
847 stype
= WLAN_FC_GET_STYPE(fc
);
849 wpa_printf(MSG_DEBUG
, "%s: subtype 0x%x len %d", __func__
, stype
,
852 if (stype
== WLAN_FC_STYPE_PROBE_REQ
) {
853 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.probe_req
))
856 os_memset(&event
, 0, sizeof(event
));
857 event
.rx_probe_req
.sa
= mgmt
->sa
;
858 event
.rx_probe_req
.da
= mgmt
->da
;
859 event
.rx_probe_req
.bssid
= mgmt
->bssid
;
860 event
.rx_probe_req
.ie
= mgmt
->u
.probe_req
.variable
;
861 event
.rx_probe_req
.ie_len
=
862 len
- (IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.probe_req
));
863 wpa_supplicant_event(drv
->hapd
, EVENT_RX_PROBE_REQ
, &event
);
867 if (os_memcmp(drv
->own_addr
, mgmt
->bssid
, ETH_ALEN
) != 0) {
868 wpa_printf(MSG_DEBUG
, "%s: BSSID does not match - ignore",
874 case WLAN_FC_STYPE_ASSOC_REQ
:
875 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.assoc_req
))
877 ielen
= len
- (IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.assoc_req
));
878 iebuf
= mgmt
->u
.assoc_req
.variable
;
879 drv_event_assoc(drv
->hapd
, mgmt
->sa
, iebuf
, ielen
, 0);
881 case WLAN_FC_STYPE_REASSOC_REQ
:
882 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.reassoc_req
))
884 ielen
= len
- (IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.reassoc_req
));
885 iebuf
= mgmt
->u
.reassoc_req
.variable
;
886 drv_event_assoc(drv
->hapd
, mgmt
->sa
, iebuf
, ielen
, 1);
888 case WLAN_FC_STYPE_ACTION
:
889 os_memset(&event
, 0, sizeof(event
));
890 event
.rx_mgmt
.frame
= buf
;
891 event
.rx_mgmt
.frame_len
= len
;
892 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
, &event
);
894 case WLAN_FC_STYPE_AUTH
:
895 if (len
< IEEE80211_HDRLEN
+ sizeof(mgmt
->u
.auth
))
897 os_memset(&event
, 0, sizeof(event
));
898 os_memcpy(event
.auth
.peer
, mgmt
->sa
, ETH_ALEN
);
899 os_memcpy(event
.auth
.bssid
, mgmt
->bssid
, ETH_ALEN
);
900 event
.auth
.auth_type
= le_to_host16(mgmt
->u
.auth
.auth_alg
);
901 event
.auth
.status_code
=
902 le_to_host16(mgmt
->u
.auth
.status_code
);
903 event
.auth
.auth_transaction
=
904 le_to_host16(mgmt
->u
.auth
.auth_transaction
);
905 event
.auth
.ies
= mgmt
->u
.auth
.variable
;
906 event
.auth
.ies_len
= len
- IEEE80211_HDRLEN
-
907 sizeof(mgmt
->u
.auth
);
908 wpa_supplicant_event(drv
->hapd
, EVENT_AUTH
, &event
);
916 static int atheros_receive_pkt(struct atheros_driver_data
*drv
)
919 struct ieee80211req_set_filter filt
;
921 wpa_printf(MSG_DEBUG
, "%s Enter", __func__
);
922 filt
.app_filterype
= 0;
924 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_PROBE_REQ
;
925 #endif /* CONFIG_WPS */
926 #ifdef CONFIG_IEEE80211R
927 filt
.app_filterype
|= (IEEE80211_FILTER_TYPE_ASSOC_REQ
|
928 IEEE80211_FILTER_TYPE_AUTH
|
929 IEEE80211_FILTER_TYPE_ACTION
);
932 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_ACTION
;
933 #endif /* CONFIG_WNM */
935 filt
.app_filterype
|= IEEE80211_FILTER_TYPE_ACTION
;
936 #endif /* CONFIG_HS20 */
937 if (filt
.app_filterype
) {
938 ret
= set80211priv(drv
, IEEE80211_IOCTL_FILTERFRAME
, &filt
,
939 sizeof(struct ieee80211req_set_filter
));
944 #if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R)
945 drv
->sock_raw
= l2_packet_init(drv
->iface
, NULL
, ETH_P_80211_RAW
,
946 atheros_raw_receive
, drv
, 1);
947 if (drv
->sock_raw
== NULL
)
949 #endif /* CONFIG_WPS || CONFIG_IEEE80211R */
953 static int atheros_reset_appfilter(struct atheros_driver_data
*drv
)
955 struct ieee80211req_set_filter filt
;
956 filt
.app_filterype
= 0;
957 return set80211priv(drv
, IEEE80211_IOCTL_FILTERFRAME
, &filt
,
958 sizeof(struct ieee80211req_set_filter
));
963 atheros_set_wps_ie(void *priv
, const u8
*ie
, size_t len
, u32 frametype
)
965 struct atheros_driver_data
*drv
= priv
;
967 struct ieee80211req_getset_appiebuf
*beac_ie
;
969 wpa_printf(MSG_DEBUG
, "%s buflen = %lu frametype=%u", __func__
,
970 (unsigned long) len
, frametype
);
971 wpa_hexdump(MSG_DEBUG
, "atheros: IE", ie
, len
);
973 beac_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
974 beac_ie
->app_frmtype
= frametype
;
975 beac_ie
->app_buflen
= len
;
976 os_memcpy(&(beac_ie
->app_buf
[0]), ie
, len
);
978 /* append the WPA/RSN IE if it is set already */
979 if (((frametype
== IEEE80211_APPIE_FRAME_BEACON
) ||
980 (frametype
== IEEE80211_APPIE_FRAME_PROBE_RESP
)) &&
981 (drv
->wpa_ie
!= NULL
)) {
982 wpa_hexdump_buf(MSG_DEBUG
, "atheros: Append WPA/RSN IE",
984 os_memcpy(&(beac_ie
->app_buf
[len
]), wpabuf_head(drv
->wpa_ie
),
985 wpabuf_len(drv
->wpa_ie
));
986 beac_ie
->app_buflen
+= wpabuf_len(drv
->wpa_ie
);
989 wpa_hexdump(MSG_DEBUG
, "atheros: SET_APPIEBUF",
990 beac_ie
->app_buf
, beac_ie
->app_buflen
);
991 return set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, beac_ie
,
992 sizeof(struct ieee80211req_getset_appiebuf
) +
993 beac_ie
->app_buflen
);
997 atheros_set_ap_wps_ie(void *priv
, const struct wpabuf
*beacon
,
998 const struct wpabuf
*proberesp
,
999 const struct wpabuf
*assocresp
)
1001 struct atheros_driver_data
*drv
= priv
;
1003 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - beacon", beacon
);
1004 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - proberesp",
1006 wpa_hexdump_buf(MSG_DEBUG
, "atheros: set_ap_wps_ie - assocresp",
1008 wpabuf_free(drv
->wps_beacon_ie
);
1009 drv
->wps_beacon_ie
= beacon
? wpabuf_dup(beacon
) : NULL
;
1010 wpabuf_free(drv
->wps_probe_resp_ie
);
1011 drv
->wps_probe_resp_ie
= proberesp
? wpabuf_dup(proberesp
) : NULL
;
1013 atheros_set_wps_ie(priv
, assocresp
? wpabuf_head(assocresp
) : NULL
,
1014 assocresp
? wpabuf_len(assocresp
) : 0,
1015 IEEE80211_APPIE_FRAME_ASSOC_RESP
);
1016 if (atheros_set_wps_ie(priv
, beacon
? wpabuf_head(beacon
) : NULL
,
1017 beacon
? wpabuf_len(beacon
) : 0,
1018 IEEE80211_APPIE_FRAME_BEACON
))
1020 return atheros_set_wps_ie(priv
,
1021 proberesp
? wpabuf_head(proberesp
) : NULL
,
1022 proberesp
? wpabuf_len(proberesp
): 0,
1023 IEEE80211_APPIE_FRAME_PROBE_RESP
);
1025 #else /* CONFIG_WPS */
1026 #define atheros_set_ap_wps_ie NULL
1027 #endif /* CONFIG_WPS */
1029 #ifdef CONFIG_IEEE80211R
1031 atheros_sta_auth(void *priv
, const u8
*own_addr
, const u8
*addr
, u16 seq
,
1032 u16 status_code
, const u8
*ie
, size_t len
)
1034 struct atheros_driver_data
*drv
= priv
;
1035 struct ieee80211req_mlme mlme
;
1038 wpa_printf(MSG_DEBUG
, "%s: addr=%s status_code=%d",
1039 __func__
, ether_sprintf(addr
), status_code
);
1041 mlme
.im_op
= IEEE80211_MLME_AUTH
;
1042 mlme
.im_reason
= status_code
;
1044 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
1045 mlme
.im_optie_len
= len
;
1047 if (len
< IEEE80211_MAX_OPT_IE
) {
1048 os_memcpy(mlme
.im_optie
, ie
, len
);
1050 wpa_printf(MSG_DEBUG
, "%s: Not enough space to copy "
1051 "opt_ie STA (addr " MACSTR
" reason %d, "
1053 __func__
, MAC2STR(addr
), status_code
,
1058 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
1060 wpa_printf(MSG_DEBUG
, "%s: Failed to auth STA (addr " MACSTR
1062 __func__
, MAC2STR(addr
), status_code
);
1068 atheros_sta_assoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
1069 int reassoc
, u16 status_code
, const u8
*ie
, size_t len
)
1071 struct atheros_driver_data
*drv
= priv
;
1072 struct ieee80211req_mlme mlme
;
1075 wpa_printf(MSG_DEBUG
, "%s: addr=%s status_code=%d reassoc %d",
1076 __func__
, ether_sprintf(addr
), status_code
, reassoc
);
1079 mlme
.im_op
= IEEE80211_MLME_REASSOC
;
1081 mlme
.im_op
= IEEE80211_MLME_ASSOC
;
1082 mlme
.im_reason
= status_code
;
1083 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
1084 mlme
.im_optie_len
= len
;
1086 if (len
< IEEE80211_MAX_OPT_IE
) {
1087 os_memcpy(mlme
.im_optie
, ie
, len
);
1089 wpa_printf(MSG_DEBUG
, "%s: Not enough space to copy "
1090 "opt_ie STA (addr " MACSTR
" reason %d, "
1092 __func__
, MAC2STR(addr
), status_code
,
1097 ret
= set80211priv(drv
, IEEE80211_IOCTL_SETMLME
, &mlme
, sizeof(mlme
));
1099 wpa_printf(MSG_DEBUG
, "%s: Failed to assoc STA (addr " MACSTR
1101 __func__
, MAC2STR(addr
), status_code
);
1105 #endif /* CONFIG_IEEE80211R */
1108 atheros_new_sta(struct atheros_driver_data
*drv
, u8 addr
[IEEE80211_ADDR_LEN
])
1110 struct hostapd_data
*hapd
= drv
->hapd
;
1111 struct ieee80211req_wpaie ie
;
1116 * Fetch negotiated WPA/RSN parameters from the system.
1118 memset(&ie
, 0, sizeof(ie
));
1119 memcpy(ie
.wpa_macaddr
, addr
, IEEE80211_ADDR_LEN
);
1120 if (set80211priv(drv
, IEEE80211_IOCTL_GETWPAIE
, &ie
, sizeof(ie
))) {
1122 * See ATH_WPS_IE comment in the beginning of the file for a
1123 * possible cause for the failure..
1125 wpa_printf(MSG_DEBUG
, "%s: Failed to get WPA/RSN IE: %s",
1126 __func__
, strerror(errno
));
1129 wpa_hexdump(MSG_MSGDUMP
, "atheros req WPA IE",
1130 ie
.wpa_ie
, IEEE80211_MAX_OPT_IE
);
1131 wpa_hexdump(MSG_MSGDUMP
, "atheros req RSN IE",
1132 ie
.rsn_ie
, IEEE80211_MAX_OPT_IE
);
1134 wpa_hexdump(MSG_MSGDUMP
, "atheros req WPS IE",
1135 ie
.wps_ie
, IEEE80211_MAX_OPT_IE
);
1136 #endif /* ATH_WPS_IE */
1138 /* atheros seems to return some random data if WPA/RSN IE is not set.
1139 * Assume the IE was not included if the IE type is unknown. */
1140 if (iebuf
[0] != WLAN_EID_VENDOR_SPECIFIC
)
1142 if (iebuf
[1] == 0 && ie
.rsn_ie
[1] > 0) {
1143 /* atheros-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not
1144 * set. This is needed for WPA2. */
1146 if (iebuf
[0] != WLAN_EID_RSN
)
1153 /* if WPS IE is present, preference is given to WPS */
1155 (ie
.wps_ie
[1] > 0 && (ie
.wps_ie
[0] == WLAN_EID_VENDOR_SPECIFIC
))) {
1157 ielen
= ie
.wps_ie
[1];
1159 #endif /* ATH_WPS_IE */
1167 drv_event_assoc(hapd
, addr
, iebuf
, ielen
, 0);
1169 if (memcmp(addr
, drv
->acct_mac
, ETH_ALEN
) == 0) {
1170 /* Cached accounting data is not valid anymore. */
1171 memset(drv
->acct_mac
, 0, ETH_ALEN
);
1172 memset(&drv
->acct_data
, 0, sizeof(drv
->acct_data
));
1177 atheros_wireless_event_wireless_custom(struct atheros_driver_data
*drv
,
1178 char *custom
, char *end
)
1180 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
1182 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
1185 pos
= strstr(custom
, "addr=");
1187 wpa_printf(MSG_DEBUG
,
1188 "MLME-MICHAELMICFAILURE.indication "
1189 "without sender address ignored");
1193 if (hwaddr_aton(pos
, addr
) == 0) {
1194 union wpa_event_data data
;
1195 os_memset(&data
, 0, sizeof(data
));
1196 data
.michael_mic_failure
.unicast
= 1;
1197 data
.michael_mic_failure
.src
= addr
;
1198 wpa_supplicant_event(drv
->hapd
,
1199 EVENT_MICHAEL_MIC_FAILURE
, &data
);
1201 wpa_printf(MSG_DEBUG
,
1202 "MLME-MICHAELMICFAILURE.indication "
1203 "with invalid MAC address");
1205 } else if (strncmp(custom
, "STA-TRAFFIC-STAT", 16) == 0) {
1209 while ((key
= strchr(key
, '\n')) != NULL
) {
1211 value
= strchr(key
, '=');
1215 val
= strtoul(value
, NULL
, 10);
1216 if (strcmp(key
, "mac") == 0)
1217 hwaddr_aton(value
, drv
->acct_mac
);
1218 else if (strcmp(key
, "rx_packets") == 0)
1219 drv
->acct_data
.rx_packets
= val
;
1220 else if (strcmp(key
, "tx_packets") == 0)
1221 drv
->acct_data
.tx_packets
= val
;
1222 else if (strcmp(key
, "rx_bytes") == 0)
1223 drv
->acct_data
.rx_bytes
= val
;
1224 else if (strcmp(key
, "tx_bytes") == 0)
1225 drv
->acct_data
.tx_bytes
= val
;
1229 } else if (strncmp(custom
, "PUSH-BUTTON.indication", 22) == 0) {
1230 /* Some atheros kernels send push button as a wireless event */
1231 /* PROBLEM! this event is received for ALL BSSs ...
1232 * so all are enabled for WPS... ugh.
1234 wpa_supplicant_event(drv
->hapd
, EVENT_WPS_BUTTON_PUSHED
, NULL
);
1235 #endif /* CONFIG_WPS */
1236 #if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) || defined(CONFIG_HS20)
1237 #define MGMT_FRAM_TAG_SIZE 30 /* hardcoded in driver */
1238 } else if (strncmp(custom
, "Manage.prob_req ", 16) == 0) {
1240 * Atheros driver uses a hack to pass Probe Request frames as a
1241 * binary data in the custom wireless event. The old way (using
1242 * packet sniffing) didn't work when bridging.
1243 * Format: "Manage.prob_req <frame len>" | zero padding | frame
1245 int len
= atoi(custom
+ 16);
1246 if (len
< 0 || custom
+ MGMT_FRAM_TAG_SIZE
+ len
> end
) {
1247 wpa_printf(MSG_DEBUG
, "Invalid Manage.prob_req event "
1251 atheros_raw_receive(drv
, NULL
,
1252 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1253 } else if (strncmp(custom
, "Manage.assoc_req ", 17) == 0) {
1254 /* Format: "Manage.assoc_req <frame len>" | zero padding |
1256 int len
= atoi(custom
+ 17);
1257 if (len
< 0 || custom
+ MGMT_FRAM_TAG_SIZE
+ len
> end
) {
1258 wpa_printf(MSG_DEBUG
, "Invalid Manage.prob_req/"
1259 "assoc_req/auth event length %d", len
);
1262 atheros_raw_receive(drv
, NULL
,
1263 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1264 } else if (strncmp(custom
, "Manage.action ", 14) == 0) {
1265 /* Format: "Manage.assoc_req <frame len>" | zero padding |
1267 int len
= atoi(custom
+ 14);
1268 if (len
< 0 || custom
+ MGMT_FRAM_TAG_SIZE
+ len
> end
) {
1269 wpa_printf(MSG_DEBUG
, "Invalid Manage.prob_req/"
1270 "assoc_req/auth event length %d", len
);
1273 atheros_raw_receive(drv
, NULL
,
1274 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1275 } else if (strncmp(custom
, "Manage.auth ", 12) == 0) {
1276 /* Format: "Manage.auth <frame len>" | zero padding | frame
1278 int len
= atoi(custom
+ 12);
1279 if (len
< 0 || custom
+ MGMT_FRAM_TAG_SIZE
+ len
> end
) {
1280 wpa_printf(MSG_DEBUG
, "Invalid Manage.prob_req/"
1281 "assoc_req/auth event length %d", len
);
1284 atheros_raw_receive(drv
, NULL
,
1285 (u8
*) custom
+ MGMT_FRAM_TAG_SIZE
, len
);
1286 #endif /* CONFIG_WPS or CONFIG_IEEE80211R */
1291 * Handle size of data problem. WEXT only allows data of 256 bytes for custom
1292 * events, and p2p data can be much bigger. So the athr driver sends a small
1293 * event telling me to collect the big data with an ioctl.
1294 * On the first event, send all pending events to supplicant.
1296 static void fetch_pending_big_events(struct atheros_driver_data
*drv
)
1298 union wpa_event_data event
;
1299 const struct ieee80211_mgmt
*mgmt
;
1300 u8 tbuf
[IW_PRIV_SIZE_MASK
]; /* max size is 2047 bytes */
1304 u32 freq
, frame_type
;
1307 os_memset(&iwr
, 0, sizeof(iwr
));
1308 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1310 iwr
.u
.data
.pointer
= (void *) tbuf
;
1311 iwr
.u
.data
.length
= sizeof(tbuf
);
1312 iwr
.u
.data
.flags
= IEEE80211_IOC_P2P_FETCH_FRAME
;
1314 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_P2P_BIG_PARAM
, &iwr
)
1316 if (errno
== ENOSPC
) {
1317 wpa_printf(MSG_DEBUG
, "%s:%d exit",
1318 __func__
, __LINE__
);
1321 wpa_printf(MSG_DEBUG
, "athr: %s: P2P_BIG_PARAM["
1322 "P2P_FETCH_FRAME] failed: %s",
1323 __func__
, strerror(errno
));
1326 data_len
= iwr
.u
.data
.length
;
1327 wpa_hexdump(MSG_DEBUG
, "athr: P2P_FETCH_FRAME data",
1328 (u8
*) tbuf
, data_len
);
1329 if (data_len
< sizeof(freq
) + sizeof(frame_type
) + 24) {
1330 wpa_printf(MSG_DEBUG
, "athr: frame too short");
1333 os_memcpy(&freq
, tbuf
, sizeof(freq
));
1334 os_memcpy(&frame_type
, &tbuf
[sizeof(freq
)],
1335 sizeof(frame_type
));
1336 mgmt
= (void *) &tbuf
[sizeof(freq
) + sizeof(frame_type
)];
1337 data_len
-= sizeof(freq
) + sizeof(frame_type
);
1339 if (frame_type
== IEEE80211_EV_RX_MGMT
) {
1340 fc
= le_to_host16(mgmt
->frame_control
);
1341 stype
= WLAN_FC_GET_STYPE(fc
);
1343 wpa_printf(MSG_DEBUG
, "athr: EV_RX_MGMT stype=%u "
1344 "freq=%u len=%u", stype
, freq
, (int) data_len
);
1346 if (stype
== WLAN_FC_STYPE_ACTION
) {
1347 os_memset(&event
, 0, sizeof(event
));
1348 event
.rx_mgmt
.frame
= (const u8
*) mgmt
;
1349 event
.rx_mgmt
.frame_len
= data_len
;
1350 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
,
1355 wpa_printf(MSG_DEBUG
, "athr: %s unknown type %d",
1356 __func__
, frame_type
);
1363 atheros_wireless_event_atheros_custom(struct atheros_driver_data
*drv
,
1364 int opcode
, char *buf
, int len
)
1367 case IEEE80211_EV_RX_MGMT
:
1368 wpa_printf(MSG_DEBUG
, "WEXT: EV_RX_MGMT");
1369 fetch_pending_big_events(drv
);
1377 atheros_wireless_event_wireless(struct atheros_driver_data
*drv
,
1378 char *data
, int len
)
1380 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
1381 char *pos
, *end
, *custom
, *buf
;
1386 while (pos
+ IW_EV_LCP_LEN
<= end
) {
1387 /* Event data may be unaligned, so make a local, aligned copy
1388 * before processing. */
1389 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
1390 wpa_printf(MSG_MSGDUMP
, "Wireless event: cmd=0x%x len=%d",
1391 iwe
->cmd
, iwe
->len
);
1392 if (iwe
->len
<= IW_EV_LCP_LEN
)
1395 custom
= pos
+ IW_EV_POINT_LEN
;
1396 if (drv
->we_version
> 18 &&
1397 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
1398 iwe
->cmd
== IWEVASSOCREQIE
||
1399 iwe
->cmd
== IWEVCUSTOM
)) {
1400 /* WE-19 removed the pointer from struct iw_point */
1401 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
1402 int dlen
= dpos
- (char *) &iwe_buf
;
1403 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
1404 sizeof(struct iw_event
) - dlen
);
1406 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
1407 custom
+= IW_EV_POINT_OFF
;
1412 drv_event_disassoc(drv
->hapd
,
1413 (u8
*) iwe
->u
.addr
.sa_data
);
1415 case IWEVREGISTERED
:
1416 atheros_new_sta(drv
, (u8
*) iwe
->u
.addr
.sa_data
);
1418 case IWEVASSOCREQIE
:
1419 /* Driver hack.. Use IWEVASSOCREQIE to bypass
1420 * IWEVCUSTOM size limitations. Need to handle this
1421 * just like IWEVCUSTOM.
1424 if (custom
+ iwe
->u
.data
.length
> end
)
1426 buf
= malloc(iwe
->u
.data
.length
+ 1);
1429 memcpy(buf
, custom
, iwe
->u
.data
.length
);
1430 buf
[iwe
->u
.data
.length
] = '\0';
1432 if (iwe
->u
.data
.flags
!= 0) {
1433 atheros_wireless_event_atheros_custom(
1434 drv
, (int) iwe
->u
.data
.flags
,
1437 atheros_wireless_event_wireless_custom(
1438 drv
, buf
, buf
+ iwe
->u
.data
.length
);
1450 atheros_wireless_event_rtm_newlink(void *ctx
,
1451 struct ifinfomsg
*ifi
, u8
*buf
, size_t len
)
1453 struct atheros_driver_data
*drv
= ctx
;
1454 int attrlen
, rta_len
;
1455 struct rtattr
*attr
;
1457 if (ifi
->ifi_index
!= drv
->ifindex
)
1461 attr
= (struct rtattr
*) buf
;
1463 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
1464 while (RTA_OK(attr
, attrlen
)) {
1465 if (attr
->rta_type
== IFLA_WIRELESS
) {
1466 atheros_wireless_event_wireless(
1467 drv
, ((char *) attr
) + rta_len
,
1468 attr
->rta_len
- rta_len
);
1470 attr
= RTA_NEXT(attr
, attrlen
);
1476 atheros_get_we_version(struct atheros_driver_data
*drv
)
1478 struct iw_range
*range
;
1483 drv
->we_version
= 0;
1486 * Use larger buffer than struct iw_range in order to allow the
1487 * structure to grow in the future.
1489 buflen
= sizeof(struct iw_range
) + 500;
1490 range
= os_zalloc(buflen
);
1494 memset(&iwr
, 0, sizeof(iwr
));
1495 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1496 iwr
.u
.data
.pointer
= (caddr_t
) range
;
1497 iwr
.u
.data
.length
= buflen
;
1499 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1500 sizeof(range
->enc_capa
);
1502 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1503 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWRANGE]: %s",
1507 } else if (iwr
.u
.data
.length
>= minlen
&&
1508 range
->we_version_compiled
>= 18) {
1509 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1510 "WE(source)=%d enc_capa=0x%x",
1511 range
->we_version_compiled
,
1512 range
->we_version_source
,
1514 drv
->we_version
= range
->we_version_compiled
;
1523 atheros_wireless_event_init(struct atheros_driver_data
*drv
)
1525 struct netlink_config
*cfg
;
1527 atheros_get_we_version(drv
);
1529 cfg
= os_zalloc(sizeof(*cfg
));
1533 cfg
->newlink_cb
= atheros_wireless_event_rtm_newlink
;
1534 drv
->netlink
= netlink_init(cfg
);
1535 if (drv
->netlink
== NULL
) {
1545 atheros_send_eapol(void *priv
, const u8
*addr
, const u8
*data
, size_t data_len
,
1546 int encrypt
, const u8
*own_addr
, u32 flags
)
1548 struct atheros_driver_data
*drv
= priv
;
1549 unsigned char buf
[3000];
1550 unsigned char *bp
= buf
;
1551 struct l2_ethhdr
*eth
;
1556 * Prepend the Ethernet header. If the caller left us
1557 * space at the front we could just insert it but since
1558 * we don't know we copy to a local buffer. Given the frequency
1559 * and size of frames this probably doesn't matter.
1561 len
= data_len
+ sizeof(struct l2_ethhdr
);
1562 if (len
> sizeof(buf
)) {
1565 wpa_printf(MSG_INFO
,
1566 "EAPOL frame discarded, cannot malloc temp buffer of size %lu!",
1567 (unsigned long) len
);
1571 eth
= (struct l2_ethhdr
*) bp
;
1572 memcpy(eth
->h_dest
, addr
, ETH_ALEN
);
1573 memcpy(eth
->h_source
, own_addr
, ETH_ALEN
);
1574 eth
->h_proto
= host_to_be16(ETH_P_EAPOL
);
1575 memcpy(eth
+1, data
, data_len
);
1577 wpa_hexdump(MSG_MSGDUMP
, "TX EAPOL", bp
, len
);
1579 status
= l2_packet_send(drv
->sock_xmit
, addr
, ETH_P_EAPOL
, bp
, len
);
1587 handle_read(void *ctx
, const u8
*src_addr
, const u8
*buf
, size_t len
)
1589 struct atheros_driver_data
*drv
= ctx
;
1590 drv_event_eapol_rx(drv
->hapd
, src_addr
, buf
+ sizeof(struct l2_ethhdr
),
1591 len
- sizeof(struct l2_ethhdr
));
1595 atheros_init(struct hostapd_data
*hapd
, struct wpa_init_params
*params
)
1597 struct atheros_driver_data
*drv
;
1600 char brname
[IFNAMSIZ
];
1602 drv
= os_zalloc(sizeof(struct atheros_driver_data
));
1604 wpa_printf(MSG_INFO
,
1605 "Could not allocate memory for atheros driver data");
1610 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1611 if (drv
->ioctl_sock
< 0) {
1612 wpa_printf(MSG_ERROR
, "socket[PF_INET,SOCK_DGRAM]: %s",
1616 memcpy(drv
->iface
, params
->ifname
, sizeof(drv
->iface
));
1618 memset(&ifr
, 0, sizeof(ifr
));
1619 os_strlcpy(ifr
.ifr_name
, drv
->iface
, sizeof(ifr
.ifr_name
));
1620 if (ioctl(drv
->ioctl_sock
, SIOCGIFINDEX
, &ifr
) != 0) {
1621 wpa_printf(MSG_ERROR
, "ioctl(SIOCGIFINDEX): %s",
1625 drv
->ifindex
= ifr
.ifr_ifindex
;
1627 drv
->sock_xmit
= l2_packet_init(drv
->iface
, NULL
, ETH_P_EAPOL
,
1628 handle_read
, drv
, 1);
1629 if (drv
->sock_xmit
== NULL
)
1631 if (l2_packet_get_own_addr(drv
->sock_xmit
, params
->own_addr
))
1633 os_memcpy(drv
->own_addr
, params
->own_addr
, ETH_ALEN
);
1634 if (params
->bridge
[0]) {
1635 wpa_printf(MSG_DEBUG
, "Configure bridge %s for EAPOL traffic.",
1637 drv
->sock_recv
= l2_packet_init(params
->bridge
[0], NULL
,
1638 ETH_P_EAPOL
, handle_read
, drv
,
1640 if (drv
->sock_recv
== NULL
)
1642 } else if (linux_br_get(brname
, drv
->iface
) == 0) {
1643 wpa_printf(MSG_DEBUG
, "Interface in bridge %s; configure for "
1644 "EAPOL receive", brname
);
1645 drv
->sock_recv
= l2_packet_init(brname
, NULL
, ETH_P_EAPOL
,
1646 handle_read
, drv
, 1);
1647 if (drv
->sock_recv
== NULL
)
1650 drv
->sock_recv
= drv
->sock_xmit
;
1652 memset(&iwr
, 0, sizeof(iwr
));
1653 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1655 iwr
.u
.mode
= IW_MODE_MASTER
;
1657 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) < 0) {
1658 wpa_printf(MSG_ERROR
,
1659 "Could not set interface to master mode! ioctl[SIOCSIWMODE]: %s",
1664 /* mark down during setup */
1665 linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 0);
1666 atheros_set_privacy(drv
, 0); /* default to no privacy */
1668 if (atheros_receive_pkt(drv
))
1671 if (atheros_wireless_event_init(drv
))
1676 atheros_reset_appfilter(drv
);
1678 l2_packet_deinit(drv
->sock_raw
);
1679 if (drv
->sock_recv
!= NULL
&& drv
->sock_recv
!= drv
->sock_xmit
)
1680 l2_packet_deinit(drv
->sock_recv
);
1681 if (drv
->sock_xmit
!= NULL
)
1682 l2_packet_deinit(drv
->sock_xmit
);
1683 if (drv
->ioctl_sock
>= 0)
1684 close(drv
->ioctl_sock
);
1692 atheros_deinit(void *priv
)
1694 struct atheros_driver_data
*drv
= priv
;
1696 atheros_reset_appfilter(drv
);
1697 netlink_deinit(drv
->netlink
);
1698 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 0);
1699 if (drv
->ioctl_sock
>= 0)
1700 close(drv
->ioctl_sock
);
1701 if (drv
->sock_recv
!= NULL
&& drv
->sock_recv
!= drv
->sock_xmit
)
1702 l2_packet_deinit(drv
->sock_recv
);
1703 if (drv
->sock_xmit
!= NULL
)
1704 l2_packet_deinit(drv
->sock_xmit
);
1706 l2_packet_deinit(drv
->sock_raw
);
1707 wpabuf_free(drv
->wpa_ie
);
1708 wpabuf_free(drv
->wps_beacon_ie
);
1709 wpabuf_free(drv
->wps_probe_resp_ie
);
1714 atheros_set_ssid(void *priv
, const u8
*buf
, int len
)
1716 struct atheros_driver_data
*drv
= priv
;
1719 memset(&iwr
, 0, sizeof(iwr
));
1720 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1721 iwr
.u
.essid
.flags
= 1; /* SSID active */
1722 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
1723 iwr
.u
.essid
.length
= len
+ 1;
1725 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
1726 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWESSID,len=%d]: %s",
1727 len
, strerror(errno
));
1734 atheros_get_ssid(void *priv
, u8
*buf
, int len
)
1736 struct atheros_driver_data
*drv
= priv
;
1740 memset(&iwr
, 0, sizeof(iwr
));
1741 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1742 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
1743 iwr
.u
.essid
.length
= (len
> IW_ESSID_MAX_SIZE
) ?
1744 IW_ESSID_MAX_SIZE
: len
;
1746 if (ioctl(drv
->ioctl_sock
, SIOCGIWESSID
, &iwr
) < 0) {
1747 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWESSID]: %s",
1751 ret
= iwr
.u
.essid
.length
;
1757 atheros_set_countermeasures(void *priv
, int enabled
)
1759 struct atheros_driver_data
*drv
= priv
;
1760 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1761 return set80211param(drv
, IEEE80211_PARAM_COUNTERMEASURES
, enabled
);
1765 atheros_commit(void *priv
)
1767 struct atheros_driver_data
*drv
= priv
;
1768 return linux_set_iface_flags(drv
->ioctl_sock
, drv
->iface
, 1);
1771 static int atheros_set_authmode(void *priv
, int auth_algs
)
1775 if ((auth_algs
& WPA_AUTH_ALG_OPEN
) &&
1776 (auth_algs
& WPA_AUTH_ALG_SHARED
))
1777 authmode
= IEEE80211_AUTH_AUTO
;
1778 else if (auth_algs
& WPA_AUTH_ALG_OPEN
)
1779 authmode
= IEEE80211_AUTH_OPEN
;
1780 else if (auth_algs
& WPA_AUTH_ALG_SHARED
)
1781 authmode
= IEEE80211_AUTH_SHARED
;
1785 return set80211param(priv
, IEEE80211_PARAM_AUTHMODE
, authmode
);
1788 static int atheros_set_ap(void *priv
, struct wpa_driver_ap_params
*params
)
1791 * TODO: Use this to replace set_authmode, set_privacy, set_ieee8021x,
1792 * set_generic_elem, and hapd_set_ssid.
1795 wpa_printf(MSG_DEBUG
, "atheros: set_ap - pairwise_ciphers=0x%x "
1796 "group_cipher=0x%x key_mgmt_suites=0x%x auth_algs=0x%x "
1797 "wpa_version=0x%x privacy=%d interworking=%d",
1798 params
->pairwise_ciphers
, params
->group_cipher
,
1799 params
->key_mgmt_suites
, params
->auth_algs
,
1800 params
->wpa_version
, params
->privacy
, params
->interworking
);
1801 wpa_hexdump_ascii(MSG_DEBUG
, "atheros: SSID",
1802 params
->ssid
, params
->ssid_len
);
1804 wpa_printf(MSG_DEBUG
, "atheros: HESSID " MACSTR
,
1805 MAC2STR(params
->hessid
));
1806 wpa_hexdump_buf(MSG_DEBUG
, "atheros: beacon_ies",
1807 params
->beacon_ies
);
1808 wpa_hexdump_buf(MSG_DEBUG
, "atheros: proberesp_ies",
1809 params
->proberesp_ies
);
1810 wpa_hexdump_buf(MSG_DEBUG
, "atheros: assocresp_ies",
1811 params
->assocresp_ies
);
1813 #if defined(CONFIG_HS20) && defined(IEEE80211_PARAM_OSEN)
1815 struct wpa_bss_params bss_params
;
1817 os_memset(&bss_params
, 0, sizeof(struct wpa_bss_params
));
1818 bss_params
.enabled
= 1;
1820 bss_params
.wpa_pairwise
= WPA_CIPHER_CCMP
;
1821 bss_params
.wpa_group
= WPA_CIPHER_CCMP
;
1822 bss_params
.ieee802_1x
= 1;
1824 if (atheros_set_privacy(priv
, 1) ||
1825 set80211param(priv
, IEEE80211_PARAM_OSEN
, 1))
1828 return atheros_set_ieee8021x(priv
, &bss_params
);
1830 #endif /* CONFIG_HS20 && IEEE80211_PARAM_OSEN */
1836 #ifdef CONFIG_IEEE80211R
1838 static int atheros_send_mgmt(void *priv
, const u8
*frm
, size_t data_len
,
1841 struct atheros_driver_data
*drv
= priv
;
1843 const struct ieee80211_mgmt
*mgmt
;
1844 struct ieee80211req_mgmtbuf
*mgmt_frm
;
1846 mgmt
= (const struct ieee80211_mgmt
*) frm
;
1847 wpa_printf(MSG_DEBUG
, "%s frmlen = %lu " MACSTR
, __func__
,
1848 (unsigned long) data_len
, MAC2STR(mgmt
->da
));
1849 mgmt_frm
= (struct ieee80211req_mgmtbuf
*) buf
;
1850 memcpy(mgmt_frm
->macaddr
, (u8
*)mgmt
->da
, IEEE80211_ADDR_LEN
);
1851 mgmt_frm
->buflen
= data_len
;
1852 if (&mgmt_frm
->buf
[0] + data_len
> buf
+ sizeof(buf
)) {
1853 wpa_printf(MSG_INFO
, "atheros: Too long frame for "
1854 "atheros_send_mgmt (%u)", (unsigned int) data_len
);
1857 os_memcpy(&mgmt_frm
->buf
[0], frm
, data_len
);
1858 return set80211priv(drv
, IEEE80211_IOCTL_SEND_MGMT
, mgmt_frm
,
1859 sizeof(struct ieee80211req_mgmtbuf
) + data_len
);
1863 static int atheros_add_tspec(void *priv
, const u8
*addr
, u8
*tspec_ie
,
1866 struct atheros_driver_data
*drv
= priv
;
1868 struct ieee80211req_res req
;
1869 struct ieee80211req_res_addts
*addts
= &req
.u
.addts
;
1871 wpa_printf(MSG_DEBUG
, "%s", __func__
);
1872 req
.type
= IEEE80211_RESREQ_ADDTS
;
1873 os_memcpy(&req
.macaddr
[0], addr
, IEEE80211_ADDR_LEN
);
1874 os_memcpy(addts
->tspecie
, tspec_ie
, tspec_ielen
);
1875 retv
= set80211priv(drv
, IEEE80211_IOCTL_RES_REQ
, &req
,
1876 sizeof(struct ieee80211req_res
));
1878 wpa_printf(MSG_DEBUG
, "%s IEEE80211_IOCTL_RES_REQ FAILED "
1879 "retv = %d", __func__
, retv
);
1882 os_memcpy(tspec_ie
, addts
->tspecie
, tspec_ielen
);
1883 return addts
->status
;
1887 static int atheros_add_sta_node(void *priv
, const u8
*addr
, u16 auth_alg
)
1889 struct atheros_driver_data
*drv
= priv
;
1890 struct ieee80211req_res req
;
1891 struct ieee80211req_res_addnode
*addnode
= &req
.u
.addnode
;
1893 wpa_printf(MSG_DEBUG
, "%s", __func__
);
1894 req
.type
= IEEE80211_RESREQ_ADDNODE
;
1895 os_memcpy(&req
.macaddr
[0], addr
, IEEE80211_ADDR_LEN
);
1896 addnode
->auth_alg
= auth_alg
;
1897 return set80211priv(drv
, IEEE80211_IOCTL_RES_REQ
, &req
,
1898 sizeof(struct ieee80211req_res
));
1901 #endif /* CONFIG_IEEE80211R */
1904 /* Use only to set a big param, get will not work. */
1906 set80211big(struct atheros_driver_data
*drv
, int op
, const void *data
, int len
)
1910 os_memset(&iwr
, 0, sizeof(iwr
));
1911 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
1913 iwr
.u
.data
.pointer
= (void *) data
;
1914 iwr
.u
.data
.length
= len
;
1915 iwr
.u
.data
.flags
= op
;
1916 wpa_printf(MSG_DEBUG
, "%s: op=0x%x=%d (%s) len=0x%x",
1917 __func__
, op
, op
, athr_get_param_name(op
), len
);
1919 if (ioctl(drv
->ioctl_sock
, IEEE80211_IOCTL_P2P_BIG_PARAM
, &iwr
) < 0) {
1920 wpa_printf(MSG_DEBUG
, "%s: op=0x%x (%s) subop=0x%x=%d "
1921 "value=0x%x,0x%x failed: %d (%s)",
1922 __func__
, op
, athr_get_ioctl_name(op
), iwr
.u
.mode
,
1923 iwr
.u
.mode
, iwr
.u
.data
.length
,
1924 iwr
.u
.data
.flags
, errno
, strerror(errno
));
1931 static int atheros_send_action(void *priv
, unsigned int freq
,
1933 const u8
*dst
, const u8
*src
,
1935 const u8
*data
, size_t data_len
, int no_cck
)
1937 struct atheros_driver_data
*drv
= priv
;
1938 struct ieee80211_p2p_send_action
*act
;
1941 act
= os_zalloc(sizeof(*act
) + data_len
);
1945 os_memcpy(act
->dst_addr
, dst
, ETH_ALEN
);
1946 os_memcpy(act
->src_addr
, src
, ETH_ALEN
);
1947 os_memcpy(act
->bssid
, bssid
, ETH_ALEN
);
1948 os_memcpy(act
+ 1, data
, data_len
);
1949 wpa_printf(MSG_DEBUG
, "%s: freq=%d, wait=%u, dst=" MACSTR
", src="
1950 MACSTR
", bssid=" MACSTR
,
1951 __func__
, act
->freq
, wait
, MAC2STR(act
->dst_addr
),
1952 MAC2STR(act
->src_addr
), MAC2STR(act
->bssid
));
1953 wpa_hexdump(MSG_MSGDUMP
, "athr: act", (u8
*) act
, sizeof(*act
));
1954 wpa_hexdump(MSG_MSGDUMP
, "athr: data", data
, data_len
);
1956 res
= set80211big(drv
, IEEE80211_IOC_P2P_SEND_ACTION
,
1957 act
, sizeof(*act
) + data_len
);
1963 #if defined(CONFIG_WNM) && defined(IEEE80211_APPIE_FRAME_WNM)
1964 static int athr_wnm_tfs(struct atheros_driver_data
*drv
, const u8
* peer
,
1965 u8
*ie
, u16
*len
, enum wnm_oper oper
)
1967 #define IEEE80211_APPIE_MAX 1024 /* max appie buffer size */
1968 u8 buf
[IEEE80211_APPIE_MAX
];
1969 struct ieee80211req_getset_appiebuf
*tfs_ie
;
1972 wpa_printf(MSG_DEBUG
, "atheros: ifname=%s, WNM TFS IE oper=%d " MACSTR
,
1973 drv
->iface
, oper
, MAC2STR(peer
));
1976 case WNM_SLEEP_TFS_REQ_IE_SET
:
1977 if (*len
> IEEE80211_APPIE_MAX
-
1978 sizeof(struct ieee80211req_getset_appiebuf
)) {
1979 wpa_printf(MSG_DEBUG
, "TFS Req IE(s) too large");
1982 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
1983 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
1984 tfs_ie
->app_buflen
= ETH_ALEN
+ 2 + 2 + *len
;
1986 /* Command header for driver */
1987 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
1989 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
1991 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
1994 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2 + 2, ie
, *len
);
1996 if (set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, tfs_ie
,
1997 IEEE80211_APPIE_MAX
)) {
1998 wpa_printf(MSG_DEBUG
, "%s: Failed to set WNM TFS IE: "
1999 "%s", __func__
, strerror(errno
));
2003 case WNM_SLEEP_TFS_RESP_IE_ADD
:
2004 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
2005 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
2006 tfs_ie
->app_buflen
= IEEE80211_APPIE_MAX
-
2007 sizeof(struct ieee80211req_getset_appiebuf
);
2008 /* Command header for driver */
2009 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
2011 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
2013 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
2015 if (set80211priv(drv
, IEEE80211_IOCTL_GET_APPIEBUF
, tfs_ie
,
2016 IEEE80211_APPIE_MAX
)) {
2017 wpa_printf(MSG_DEBUG
, "%s: Failed to get WNM TFS IE: "
2018 "%s", __func__
, strerror(errno
));
2022 *len
= tfs_ie
->app_buflen
;
2023 os_memcpy(ie
, &(tfs_ie
->app_buf
[0]), *len
);
2024 wpa_printf(MSG_DEBUG
, "atheros: %c len=%d", tfs_ie
->app_buf
[0],
2027 case WNM_SLEEP_TFS_RESP_IE_NONE
:
2030 case WNM_SLEEP_TFS_IE_DEL
:
2031 tfs_ie
= (struct ieee80211req_getset_appiebuf
*) buf
;
2032 tfs_ie
->app_frmtype
= IEEE80211_APPIE_FRAME_WNM
;
2033 tfs_ie
->app_buflen
= IEEE80211_APPIE_MAX
-
2034 sizeof(struct ieee80211req_getset_appiebuf
);
2035 /* Command header for driver */
2036 os_memcpy(&(tfs_ie
->app_buf
[0]), peer
, ETH_ALEN
);
2038 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
, &val
, 2);
2040 os_memcpy(&(tfs_ie
->app_buf
[0]) + ETH_ALEN
+ 2, &val
, 2);
2042 if (set80211priv(drv
, IEEE80211_IOCTL_SET_APPIEBUF
, tfs_ie
,
2043 IEEE80211_APPIE_MAX
)) {
2044 wpa_printf(MSG_DEBUG
, "%s: Failed to set WNM TFS IE: "
2045 "%s", __func__
, strerror(errno
));
2050 wpa_printf(MSG_DEBUG
, "Unsupported TFS oper %d", oper
);
2058 static int atheros_wnm_sleep(struct atheros_driver_data
*drv
,
2059 const u8
*peer
, enum wnm_oper oper
)
2066 wpa_printf(MSG_DEBUG
, "atheros: WNM-Sleep Oper %d, " MACSTR
,
2067 oper
, MAC2STR(peer
));
2069 dlen
= ETH_ALEN
+ 2 + 2;
2070 data
= os_malloc(dlen
);
2074 /* Command header for driver */
2076 os_memcpy(pos
, peer
, ETH_ALEN
);
2080 os_memcpy(pos
, &val
, 2);
2084 os_memcpy(pos
, &val
, 2);
2086 ret
= atheros_set_wps_ie(drv
, data
, dlen
, IEEE80211_APPIE_FRAME_WNM
);
2094 static int atheros_wnm_oper(void *priv
, enum wnm_oper oper
, const u8
*peer
,
2095 u8
*buf
, u16
*buf_len
)
2097 struct atheros_driver_data
*drv
= priv
;
2100 case WNM_SLEEP_ENTER_CONFIRM
:
2101 case WNM_SLEEP_ENTER_FAIL
:
2102 case WNM_SLEEP_EXIT_CONFIRM
:
2103 case WNM_SLEEP_EXIT_FAIL
:
2104 return atheros_wnm_sleep(drv
, peer
, oper
);
2105 case WNM_SLEEP_TFS_REQ_IE_SET
:
2106 case WNM_SLEEP_TFS_RESP_IE_ADD
:
2107 case WNM_SLEEP_TFS_RESP_IE_NONE
:
2108 case WNM_SLEEP_TFS_IE_DEL
:
2109 return athr_wnm_tfs(drv
, peer
, buf
, buf_len
, oper
);
2111 wpa_printf(MSG_DEBUG
, "atheros: Unsupported WNM operation %d",
2116 #endif /* CONFIG_WNM && IEEE80211_APPIE_FRAME_WNM */
2119 const struct wpa_driver_ops wpa_driver_atheros_ops
= {
2121 .hapd_init
= atheros_init
,
2122 .hapd_deinit
= atheros_deinit
,
2123 .set_ieee8021x
= atheros_set_ieee8021x
,
2124 .set_privacy
= atheros_set_privacy
,
2125 .set_key
= atheros_set_key
,
2126 .get_seqnum
= atheros_get_seqnum
,
2127 .flush
= atheros_flush
,
2128 .set_generic_elem
= atheros_set_opt_ie
,
2129 .sta_set_flags
= atheros_sta_set_flags
,
2130 .read_sta_data
= atheros_read_sta_driver_data
,
2131 .hapd_send_eapol
= atheros_send_eapol
,
2132 .sta_disassoc
= atheros_sta_disassoc
,
2133 .sta_deauth
= atheros_sta_deauth
,
2134 .hapd_set_ssid
= atheros_set_ssid
,
2135 .hapd_get_ssid
= atheros_get_ssid
,
2136 .set_countermeasures
= atheros_set_countermeasures
,
2137 .sta_clear_stats
= atheros_sta_clear_stats
,
2138 .commit
= atheros_commit
,
2139 .set_ap_wps_ie
= atheros_set_ap_wps_ie
,
2140 .set_authmode
= atheros_set_authmode
,
2141 .set_ap
= atheros_set_ap
,
2142 #ifdef CONFIG_IEEE80211R
2143 .sta_assoc
= atheros_sta_assoc
,
2144 .sta_auth
= atheros_sta_auth
,
2145 .send_mlme
= atheros_send_mgmt
,
2146 .add_tspec
= atheros_add_tspec
,
2147 .add_sta_node
= atheros_add_sta_node
,
2148 #endif /* CONFIG_IEEE80211R */
2149 .send_action
= atheros_send_action
,
2150 #if defined(CONFIG_WNM) && defined(IEEE80211_APPIE_FRAME_WNM)
2151 .wnm_oper
= atheros_wnm_oper
,
2152 #endif /* CONFIG_WNM && IEEE80211_APPIE_FRAME_WNM */
2153 .set_qos_map
= atheros_set_qos_map
,