IEEE 802.11w: Use comeback duration to delay association
authorJouni Malinen <j@w1.fi>
Mon, 1 Sep 2008 08:48:43 +0000 (11:48 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 1 Sep 2008 08:49:51 +0000 (11:49 +0300)
wpa_supplicant/mlme.c

index 61fec6c..092ad41 100644 (file)
@@ -129,6 +129,8 @@ struct ieee802_11_elems {
        u8 mdie_len;
        u8 *ftie;
        u8 ftie_len;
+       u8 *assoc_comeback;
+       u8 assoc_comeback_len;
 };
 
 typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@@ -231,6 +233,10 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
                        elems->ftie = pos;
                        elems->ftie_len = elen;
                        break;
+               case WLAN_EID_ASSOC_COMEBACK_TIME:
+                       elems->assoc_comeback = pos;
+                       elems->assoc_comeback_len = elen;
+                       break;
                default:
 #if 0
                        wpa_printf(MSG_MSGDUMP "MLME: IEEE 802.11 element "
@@ -1231,12 +1237,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                   reassoc ? "Rea" : "A", MAC2STR(mgmt->sa),
                   capab_info, status_code, aid);
 
-       if (status_code != WLAN_STATUS_SUCCESS) {
-               wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)",
-                          status_code);
-               return;
-       }
-
        pos = mgmt->u.assoc_resp.variable;
        if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
            == ParseFailed) {
@@ -1244,6 +1244,28 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                return;
        }
 
+       if (status_code != WLAN_STATUS_SUCCESS) {
+               wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)",
+                          status_code);
+#ifdef CONFIG_IEEE80211W
+               if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
+                   elems.assoc_comeback && elems.assoc_comeback_len == 4) {
+                       u32 tu, ms;
+                       tu = WPA_GET_LE32(elems.assoc_comeback);
+                       ms = tu * 1024 / 1000;
+                       wpa_printf(MSG_DEBUG, "MLME: AP rejected association "
+                                  "temporarily; comeback duration %u TU "
+                                  "(%u ms)", tu, ms);
+                       if (ms > IEEE80211_ASSOC_TIMEOUT) {
+                               wpa_printf(MSG_DEBUG, "MLME: Update timer "
+                                          "based on comeback duration");
+                               ieee80211_reschedule_timer(wpa_s, ms);
+                       }
+               }
+#endif /* CONFIG_IEEE80211W */
+               return;
+       }
+
        if (elems.supp_rates == NULL) {
                wpa_printf(MSG_DEBUG, "MLME: no SuppRates element in "
                           "AssocResp");