diff mbox

4addr: fix reconnecting client on connection lost

Message ID 20161202110047.GA4128@w1.fi
State Accepted
Headers show

Commit Message

Jouni Malinen Dec. 2, 2016, 11 a.m. UTC
On Sun, Jul 24, 2016 at 11:03:30PM +0200, Matthias May wrote:
> On 07/23/2016 08:01 PM, Jouni Malinen wrote:
> > On Tue, Jul 05, 2016 at 03:00:43PM +0200, Matthias May wrote:
> >> When a 4addr client suddenly looses its connection (no deauth/deassoc)
> >> the AP still thinks it is connected.
> >> If the client reconnects before the AP timeoutes the client, traffic
> >> cannot flow.
> >>
> >> Fix this by making sure the WLAN_STA_WDS flag is unset in the sta->flags
> >> when the client completes association.

It looks like this can be fixed by moving around the code a bit so that
the handle_assoc_cb() WDS special case gets executed only after setting
the kernel STA flags to associated state.

> >> diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
> >> @@ -2829,6 +2829,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
> >>  	sta->flags |= WLAN_STA_ASSOC;
> >>  	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
> >> +	sta->flags &= ~WLAN_STA_WDS;

This on the other hand causes regressions into previously working cases.
I now have full set of mac80211_hwsim test cases to show this and also
show the issue you reported and how it can be fixed with that code move
mentioned above.

> > This looks a bit strange taken into account this same handle_assoc_cb()
> > function is using the WLAN_STA_WDS flag just below this:
> > 
> >     if (sta->flags & WLAN_STA_WDS) {
...
> > All that would become dead code if this patch were applied.

> ieee802_11_rx_from_unknown is the function which sets WLAN_STA_WDS bit
> once the WLAN_STA_ASSOC is set.
> Wouldn't this mean that this is already dead code now?

No, that is not dead code; that gets executed if a STA that used 4addr
format (i.e., gets that WLAN_STA_WDS flag) during the previous
association reassociates with the same AP without going through
deauthentication. That is correct thing to do here, but it just did not
seem to work when done before the hostapd_set_sta_flags(hapd, sta)
call.

This seems to fix the issue:
diff mbox

Patch

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 3e65fd3..1cecc80 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3232,16 +3232,6 @@  static void handle_assoc_cb(struct hostapd_data *hapd,
 	sta->sa_query_timed_out = 0;
 #endif /* CONFIG_IEEE80211W */
 
-	if (sta->flags & WLAN_STA_WDS) {
-		int ret;
-		char ifname_wds[IFNAMSIZ + 1];
-
-		ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
-					  sta->aid, 1);
-		if (!ret)
-			hostapd_set_wds_encryption(hapd, sta, ifname_wds);
-	}
-
 	if (sta->eapol_sm == NULL) {
 		/*
 		 * This STA does not use RADIUS server for EAP authentication,
@@ -3258,6 +3248,19 @@  static void handle_assoc_cb(struct hostapd_data *hapd,
 
 	hostapd_set_sta_flags(hapd, sta);
 
+	if (sta->flags & WLAN_STA_WDS) {
+		int ret;
+		char ifname_wds[IFNAMSIZ + 1];
+
+		wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
+			   MACSTR " (aid %u)",
+			   MAC2STR(sta->addr), sta->aid);
+		ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
+					  sta->aid, 1);
+		if (!ret)
+			hostapd_set_wds_encryption(hapd, sta, ifname_wds);
+	}
+
 	if (sta->auth_alg == WLAN_AUTH_FT)
 		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
 	else