mesh: Delay Authentication frame process with no_auto_peer
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>
This commit is contained in:
parent
e0cfd223c0
commit
3a322496f9
4 changed files with 40 additions and 0 deletions
|
@ -325,6 +325,11 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||||
bin_clear_free(hapd->tmp_eap_user.password,
|
bin_clear_free(hapd->tmp_eap_user.password,
|
||||||
hapd->tmp_eap_user.password_len);
|
hapd->tmp_eap_user.password_len);
|
||||||
#endif /* CONFIG_SQLITE */
|
#endif /* CONFIG_SQLITE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MESH
|
||||||
|
wpabuf_free(hapd->mesh_pending_auth);
|
||||||
|
hapd->mesh_pending_auth = NULL;
|
||||||
|
#endif /* CONFIG_MESH */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,8 @@ struct hostapd_data {
|
||||||
int num_plinks;
|
int num_plinks;
|
||||||
int max_plinks;
|
int max_plinks;
|
||||||
void (*mesh_sta_free_cb)(struct sta_info *sta);
|
void (*mesh_sta_free_cb)(struct sta_info *sta);
|
||||||
|
struct wpabuf *mesh_pending_auth;
|
||||||
|
struct os_reltime mesh_pending_auth_time;
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
#ifdef CONFIG_SQLITE
|
#ifdef CONFIG_SQLITE
|
||||||
|
|
|
@ -889,6 +889,16 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
if (hapd->conf->mesh & MESH_ENABLED) {
|
if (hapd->conf->mesh & MESH_ENABLED) {
|
||||||
/* if the mesh peer is not available, we don't do auth.
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
|
@ -583,6 +583,29 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
|
||||||
if (ssid && ssid->no_auto_peer) {
|
if (ssid && ssid->no_auto_peer) {
|
||||||
wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
|
wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
|
||||||
MACSTR " because of no_auto_peer", MAC2STR(addr));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue