nl80211: Send EAPOL frames as QoS data frames for QoS aware clients

This should fix EAPOL reauthentication and rekeying timeout issues
with Intel clients when using WMM (e.g., with IEEE 802.11n). These
stations do not seem to be able to handle EAPOL data frames as
non-QoS Data frames after the initial setup.

This adds STA flags to hapd_send_eapol() driver op to allow
driver_nl80211.c to mark the EAPOL frames as QoS Data frame
when injecting it through the monitor interface.
This commit is contained in:
Felix Fietkau 2011-04-02 22:03:05 +03:00 committed by Jouni Malinen
parent 439efd1eac
commit 4378fc14eb
13 changed files with 27 additions and 24 deletions

View file

@ -26,7 +26,7 @@
#include "ap_drv_ops.h"
static int hostapd_sta_flags_to_drv(int flags)
u32 hostapd_sta_flags_to_drv(u32 flags)
{
int res = 0;
if (flags & WLAN_STA_AUTHORIZED)

View file

@ -20,6 +20,7 @@ struct wpa_bss_params;
struct wpa_driver_scan_params;
struct ieee80211_ht_capabilities;
u32 hostapd_sta_flags_to_drv(u32 flags);
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
@ -135,13 +136,14 @@ static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
const u8 *addr, const u8 *data,
size_t data_len, int encrypt)
size_t data_len, int encrypt,
u32 flags)
{
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
return 0;
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
data_len, encrypt,
hapd->own_addr);
hapd->own_addr, flags);
}
static inline int hostapd_drv_read_sta_data(

View file

@ -73,7 +73,7 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
rsn_preauth_send(hapd, sta, buf, len);
} else {
hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len,
encrypt);
encrypt, sta->flags);
}
os_free(buf);

View file

@ -243,8 +243,15 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
int encrypt)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
u32 flags = 0;
sta = ap_get_sta(hapd, addr);
if (sta)
flags = hostapd_sta_flags_to_drv(sta->flags);
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
encrypt);
encrypt, flags);
}

View file

@ -1406,12 +1406,13 @@ struct wpa_driver_ops {
* @data_len: Length of the EAPOL packet in octets
* @encrypt: Whether the frame should be encrypted
* @own_addr: Source MAC address
* @flags: WPA_STA_* flags for the destination station
*
* Returns: 0 on success, -1 on failure
*/
int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt,
const u8 *own_addr);
const u8 *own_addr, u32 flags);
/**
* sta_deauth - Deauthenticate a station (AP only)

View file

@ -1132,7 +1132,7 @@ atheros_wireless_event_init(struct atheros_driver_data *drv)
static int
atheros_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
int encrypt, const u8 *own_addr, u32 flags)
{
struct atheros_driver_data *drv = priv;
unsigned char buf[3000];

View file

@ -516,7 +516,7 @@ no_ie:
static int
bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
int encrypt, const u8 *own_addr, u32 flags)
{
struct bsd_driver_data *drv = priv;

View file

@ -289,7 +289,8 @@ static int hostap_send_mlme(void *priv, const u8 *msg, size_t len)
static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt, const u8 *own_addr)
size_t data_len, int encrypt, const u8 *own_addr,
u32 flags)
{
struct hostap_driver_data *drv = priv;
struct ieee80211_hdr *hdr;

View file

@ -1067,7 +1067,7 @@ madwifi_wireless_event_init(struct madwifi_driver_data *drv)
static int
madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
int encrypt, const u8 *own_addr, u32 flags)
{
struct madwifi_driver_data *drv = priv;
unsigned char buf[3000];

View file

@ -4240,7 +4240,7 @@ static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
static int wpa_driver_nl80211_hapd_send_eapol(
void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt, const u8 *own_addr)
size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
@ -4248,11 +4248,7 @@ static int wpa_driver_nl80211_hapd_send_eapol(
size_t len;
u8 *pos;
int res;
#if 0 /* FIX */
int qos = sta->flags & WPA_STA_WMM;
#else
int qos = 0;
#endif
int qos = flags & WPA_STA_WMM;
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
data_len;
@ -4268,26 +4264,22 @@ static int wpa_driver_nl80211_hapd_send_eapol(
hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
if (encrypt)
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
#if 0 /* To be enabled if qos determination is added above */
if (qos) {
hdr->frame_control |=
host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
}
#endif
memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
pos = (u8 *) (hdr + 1);
#if 0 /* To be enabled if qos determination is added above */
if (qos) {
/* add an empty QoS header if needed */
pos[0] = 0;
pos[1] = 0;
pos += 2;
}
#endif
memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
pos += sizeof(rfc1042_header);

View file

@ -175,7 +175,7 @@ test_driver_get_cli(struct wpa_driver_test_data *drv, struct sockaddr_un *from,
static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt,
const u8 *own_addr)
const u8 *own_addr, u32 flags)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;

View file

@ -314,7 +314,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
static int wired_send_eapol(void *priv, const u8 *addr,
const u8 *data, size_t data_len, int encrypt,
const u8 *own_addr)
const u8 *own_addr, u32 flags)
{
struct wpa_driver_wired_data *drv = priv;
struct ieee8023_hdr *hdr;

View file

@ -351,12 +351,12 @@ static inline int wpa_drv_sta_remove(struct wpa_supplicant *wpa_s,
static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
const u8 *addr, const u8 *data,
size_t data_len, int encrypt,
const u8 *own_addr)
const u8 *own_addr, u32 flags)
{
if (wpa_s->driver->hapd_send_eapol)
return wpa_s->driver->hapd_send_eapol(wpa_s->drv_priv, addr,
data, data_len, encrypt,
own_addr);
own_addr, flags);
return -1;
}