nl80211: Ignore "DEAUTH" messages from APs we are not associated to
authorPaul Stewart <pstew@google.com>
Mon, 16 Aug 2010 18:27:26 +0000 (21:27 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 16 Aug 2010 18:27:26 +0000 (21:27 +0300)
DEAUTH messages can come from a number of different sources. The one
that's hurting us currently is DEAUTH netlink messages coming to us
from compat-wireless in response to local_state_change DEAUTH messages
we sent as a part of cleaning up state in driver_nl80211's
clear_state_mismatch() function. However, DEAUTH messages can come
from a variety of unwanted sources, including directed denial-of-service
attacks (although MAC verification doesn't place that high a barrier),
so this validation is actually generically useful, I think.

The downside to this method is that without a kernel based approach
"iw dev wlan0 link" no longer works correctly after clear_state_mismatch()
is done.  This will be pursued with the kernel folks.

src/drivers/driver_nl80211.c

index 018fc84..d725f92 100644 (file)
@@ -718,12 +718,28 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
        const u8 *bssid = NULL;
        u16 reason_code = 0;
 
+       mgmt = (const struct ieee80211_mgmt *) frame;
+       if (len >= 24) {
+               bssid = mgmt->bssid;
+
+               if (drv->associated != 0 &&
+                   os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
+                   os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
+                       /*
+                        * We have presumably received this deauth as a
+                        * response to a clear_state_mismatch() outgoing
+                        * deauth.  Don't let it take us offline!
+                        */
+                       wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
+                                  "from Unknown BSSID " MACSTR " -- ignoring",
+                                  MAC2STR(bssid));
+                       return;
+               }
+       }
+
        drv->associated = 0;
        os_memset(&event, 0, sizeof(event));
 
-       mgmt = (const struct ieee80211_mgmt *) frame;
-       if (len >= 24)
-               bssid = mgmt->bssid;
        /* Note: Same offset for Reason Code in both frame subtypes */
        if (len >= 24 + sizeof(mgmt->u.deauth))
                reason_code = le_to_host16(mgmt->u.deauth.reason_code);