]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Only advertise MSCS and SCS in Association Request if supported by AP
authorSebastian Priebe <sebastian.priebe@konplan.com>
Wed, 26 Apr 2023 13:22:02 +0000 (13:22 +0000)
committerJouni Malinen <j@w1.fi>
Fri, 3 Nov 2023 11:10:01 +0000 (13:10 +0200)
Since wpa_supplicant version 2.10 the extended capabilities MSCS and SCS
are advertised in the (Re)Association Request frames.

This causes the association request to be rejected by several access
points. Issue was observed with:
- D-Link DIR600
- TP-Link AC1900
- Synology MR2200ac

To avoid this issue the extended capabilities MSCS and SCS shall only be
added if the bss also supports them. While this may not follow the exact
behavior described in IEEE 802.11, this is a reasonable compromise to
avoid interoperability issues since these capabilities cannot be used
with an AP that does not support them anyway.

Note: The Extended Capabilities element is only included in the
Association Request frames if the AP also sent its extended capabilities
(see wpas_populate_assoc_ies()) as a workaround for misbehaving APs.
This workaround exists since version 2.1.

Signed-off-by: Sebastian Priebe <sebastian.priebe@konplan.com>
wpa_supplicant/scan.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index ef5e3e6967f5b866730ceccf4426de5db7b4e5e9..5c5c399e9ce4f6893dfd5c857e6be8839639e29b 100644 (file)
@@ -621,7 +621,7 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
        wpa_drv_get_ext_capa(wpa_s, type);
 
        ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
-                                            sizeof(ext_capab));
+                                            sizeof(ext_capab), NULL);
        if (ext_capab_len > 0 &&
            wpabuf_resize(&default_ies, ext_capab_len) == 0)
                wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
@@ -743,7 +743,7 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
                wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
 
        ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
-                                            sizeof(ext_capab));
+                                            sizeof(ext_capab), NULL);
        if (ext_capab_len > 0 &&
            wpabuf_resize(&extra_ie, ext_capab_len) == 0)
                wpabuf_put_data(extra_ie, ext_capab, ext_capab_len);
index 578e1828c4b9bfd34760ccd7f64f6126c9bf50ed..233adce5bd918a8c23fab1b126117c4dd051d165 100644 (file)
@@ -930,7 +930,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
                wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
 
        ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
-                                            sizeof(ext_capab));
+                                            sizeof(ext_capab), bss);
        if (ext_capab_len > 0) {
                u8 *pos = wpa_s->sme.assoc_req_ie;
                if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
index f288f3fa1b4c7c775b52b4101f7e308bb17ded46..f1dc006515fdbe7c957af1bd27b237fd0a12af9f 100644 (file)
@@ -2077,7 +2077,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 }
 
 
-static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
+static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx,
+                               struct wpa_bss *bss)
 {
        bool scs = true, mscs = true;
 
@@ -2128,6 +2129,13 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
                if (wpa_s->disable_scs_support)
                        scs = false;
 #endif /* CONFIG_TESTING_OPTIONS */
+               if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_SCS)) {
+                       /* Drop own SCS capability indication since the AP does
+                        * not support it. This is needed to avoid
+                        * interoperability issues with APs that get confused
+                        * with Extended Capabilities element. */
+                       scs = false;
+               }
                if (scs)
                        *pos |= 0x40; /* Bit 54 - SCS */
                break;
@@ -2150,6 +2158,13 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
                if (wpa_s->disable_mscs_support)
                        mscs = false;
 #endif /* CONFIG_TESTING_OPTIONS */
+               if (bss && !wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) {
+                       /* Drop own MSCS capability indication since the AP does
+                        * not support it. This is needed to avoid
+                        * interoperability issues with APs that get confused
+                        * with Extended Capabilities element. */
+                       mscs = false;
+               }
                if (mscs)
                        *pos |= 0x20; /* Bit 85 - Mirrored SCS */
                break;
@@ -2157,7 +2172,8 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
 }
 
 
-int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf,
+                         size_t buflen, struct wpa_bss *bss)
 {
        u8 *pos = buf;
        u8 len = 11, i;
@@ -2173,7 +2189,7 @@ int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
        *pos++ = WLAN_EID_EXT_CAPAB;
        *pos++ = len;
        for (i = 0; i < len; i++, pos++) {
-               wpas_ext_capab_byte(wpa_s, pos, i);
+               wpas_ext_capab_byte(wpa_s, pos, i, bss);
 
                if (i < wpa_s->extended_capa_len) {
                        *pos &= ~wpa_s->extended_capa_mask[i];
@@ -3495,7 +3511,7 @@ static u8 * wpas_populate_assoc_ies(
                u8 ext_capab[18];
                int ext_capab_len;
                ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
-                                                    sizeof(ext_capab));
+                                                    sizeof(ext_capab), bss);
                if (ext_capab_len > 0 &&
                    wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
                        u8 *pos = wpa_ie;
index 8787ba61f5238ae03e4d526acb65d63358ff249a..d3bd5e19616b5d165a00d70d341ab07061e64d75 100644 (file)
@@ -1696,7 +1696,8 @@ int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
                    size_t ssid_len);
 void wpas_request_connection(struct wpa_supplicant *wpa_s);
 void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
-int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen,
+                        struct wpa_bss *bss);
 int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
                            enum wpas_mac_addr_style style,
                            struct wpa_ssid *ssid);