]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
mesh: Delay Authentication frame process with no_auto_peer
authorJouni Malinen <j@w1.fi>
Tue, 23 Dec 2014 11:44:38 +0000 (13:44 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 23 Dec 2014 11:44:38 +0000 (13:44 +0200)
There is a possible race condition between receiving the
NEW_PEER_CANDIDATE event and the Authentication frame from the peer.
Previously, if the Authentication frame RX event was indicated first,
that frame got dropped silently. Now, this frame is still dropped, but a
copy of it is stored and the frame gets processed on the following
NEW_PEER_CANDIDATE event if that is received for the same peer within
two seconds.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/ap/hostapd.c
src/ap/hostapd.h
src/ap/ieee802_11.c
wpa_supplicant/mesh_mpm.c

index 5161333d8949fbde0c84d6ce16d329373b60b537..bd3248000c6403c8e5aacb0ad6ea86cc734beb60 100644 (file)
@@ -325,6 +325,11 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
        bin_clear_free(hapd->tmp_eap_user.password,
                       hapd->tmp_eap_user.password_len);
 #endif /* CONFIG_SQLITE */
+
+#ifdef CONFIG_MESH
+       wpabuf_free(hapd->mesh_pending_auth);
+       hapd->mesh_pending_auth = NULL;
+#endif /* CONFIG_MESH */
 }
 
 
index 4a50a008db60ebf2586612c32b29ffa4e6c1e638..8e2c70eca31eef3827eb71ae71faea7eb60b998e 100644 (file)
@@ -251,6 +251,8 @@ struct hostapd_data {
        int num_plinks;
        int max_plinks;
        void (*mesh_sta_free_cb)(struct sta_info *sta);
+       struct wpabuf *mesh_pending_auth;
+       struct os_reltime mesh_pending_auth_time;
 #endif /* CONFIG_MESH */
 
 #ifdef CONFIG_SQLITE
index 09c398ab168bf992848c018d3a9a487239388fe2..97f98f28e0b86aa7655a926b6b646a5ef3f6e6d6 100644 (file)
@@ -889,6 +889,16 @@ static void handle_auth(struct hostapd_data *hapd,
                if (hapd->conf->mesh & MESH_ENABLED) {
                        /* if the mesh peer is not available, we don't do auth.
                         */
+                       wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
+                                  " not yet known - drop Authentiation frame",
+                                  MAC2STR(mgmt->sa));
+                       /*
+                        * Save a copy of the frame so that it can be processed
+                        * if a new peer entry is added shortly after this.
+                        */
+                       wpabuf_free(hapd->mesh_pending_auth);
+                       hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
+                       os_get_reltime(&hapd->mesh_pending_auth_time);
                        return;
                }
 #endif /* CONFIG_MESH */
index ff909faacb0becbb7841f9fb70b2b35ddda2f069..e7c53eacebfc781d5471b64e522b9704a2f58175 100644 (file)
@@ -583,6 +583,29 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
        if (ssid && ssid->no_auto_peer) {
                wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
                        MACSTR " because of no_auto_peer", MAC2STR(addr));
+               if (data->mesh_pending_auth) {
+                       struct os_reltime age;
+                       const struct ieee80211_mgmt *mgmt;
+                       struct hostapd_frame_info fi;
+
+                       mgmt = wpabuf_head(data->mesh_pending_auth);
+                       os_reltime_age(&data->mesh_pending_auth_time, &age);
+                       if (age.sec < 2 &&
+                           os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
+                               wpa_printf(MSG_DEBUG,
+                                          "mesh: Process pending Authentication frame from %u.%06u seconds ago",
+                                          (unsigned int) age.sec,
+                                          (unsigned int) age.usec);
+                               os_memset(&fi, 0, sizeof(fi));
+                               ieee802_11_mgmt(
+                                       data,
+                                       wpabuf_head(data->mesh_pending_auth),
+                                       wpabuf_len(data->mesh_pending_auth),
+                                       &fi);
+                       }
+                       wpabuf_free(data->mesh_pending_auth);
+                       data->mesh_pending_auth = NULL;
+               }
                return;
        }