]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Send EAPOL frames as QoS data frames for QoS aware clients
authorFelix Fietkau <nbd@openwrt.org>
Sat, 2 Apr 2011 19:03:05 +0000 (22:03 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 2 Apr 2011 19:03:05 +0000 (22:03 +0300)
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.

13 files changed:
src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/ieee802_1x.c
src/ap/wpa_auth_glue.c
src/drivers/driver.h
src/drivers/driver_atheros.c
src/drivers/driver_bsd.c
src/drivers/driver_hostap.c
src/drivers/driver_madwifi.c
src/drivers/driver_nl80211.c
src/drivers/driver_test.c
src/drivers/driver_wired.c
wpa_supplicant/driver_i.h

index 5017cbf2eae7f099364866d0a7752402ecdf0ff7..2ff3a68094c350f20638ad76edec1e7acb4670e4 100644 (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)
index 3af9ecaa69fd2576cea39c85f2fcdac3dfa30199..36bb826db13e65cdcac87a6807a8ff174071808b 100644 (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(
index 676a3e15c744c4cc7510c93c0b885b06a83e85d2..28e08b9ae0c997764f9c74fe5399fd4ee43ad96c 100644 (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);
index f7999b9f02ecab310f8db66e03492de268510b3d..b35b7ba5eef6ab332e203b037cc8cef086af0a43 100644 (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);
 }
 
 
index 2836224a3561ba7e56c6fef468ca826a3c84c132..8e19da14a637c0e3f849f8552fc440ff71af3c4f 100644 (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)
index 56eac5bb76c21655e015c04f3b284e3033c012e3..8f24798a30285780eb81521e2350cf9e5f3123ac 100644 (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];
index b91f5111d9e08d962fcebe3311e53de297e67c94..5348d0974645be0ea91e6eb2274af6dd4d77e9a1 100644 (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;
 
index 4fe6178309f8eba89fc4741a374d5e74c079aa68..e855c1bf633ca56e246313c357f5cd4eb1e9cdad 100644 (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;
index b485d38c2f53919632ae98e087ad8526f5860af9..630fbf4c53bcadfa17795d2eaf4ff2902a3b66ce 100644 (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];
index 59d44a1da10aad4393ff62d51148132c2c4c72bb..87fb4e28c3571a1b18c48253be96787c32d6f175 100644 (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);
index 2aecef53f7cf1545f720cadbb20ef1ac9feff4c0..9e502e4fcfd9f7ef05f18d66d8af0a8b6c63438a 100644 (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;
index de038e28f3991755a5d60dc5472bd470d6e051d7..618db2648f99c986fdde68ad57f907898d53c2d1 100644 (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;
index 693491b97ace47ee11acbbbf9fda020389077c85..0d436dd1f189beef8c4953171688f9ae7c9c12c0 100644 (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;
 }