UPnP: Removed shadowed variable
[wpasupplicant] / hostapd / ieee802_11.c
index 39cc837..7968850 100644 (file)
@@ -34,7 +34,7 @@
 #include "wme.h"
 #include "ap_list.h"
 #include "accounting.h"
-#include "driver.h"
+#include "driver_i.h"
 #include "mlme.h"
 
 
@@ -298,12 +298,21 @@ static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
                                            struct sta_info *sta, u8 *eid)
 {
        u8 *pos = eid;
-       u32 timeout;
-
-       *pos++ = WLAN_EID_ASSOC_COMEBACK_TIME;
-       *pos++ = 4;
-       timeout = (hapd->conf->assoc_ping_attempts - sta->ping_count + 1) *
-               hapd->conf->assoc_ping_timeout;
+       u32 timeout, tu;
+       struct os_time now, passed;
+
+       *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+       *pos++ = 5;
+       *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
+       os_get_time(&now);
+       os_time_sub(&now, &sta->sa_query_start, &passed);
+       tu = (passed.sec * 1000000 + passed.usec) / 1024;
+       if (hapd->conf->assoc_sa_query_max_timeout > tu)
+               timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
+       else
+               timeout = 0;
+       if (timeout < hapd->conf->assoc_sa_query_max_timeout)
+               timeout++; /* add some extra time for local timers */
        WPA_PUT_LE32(pos, timeout);
        pos += 4;
 
@@ -327,6 +336,12 @@ void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
 }
 
 
+/**
+ * ieee802_11_send_deauth - Send Deauthentication frame
+ * @hapd: hostapd BSS data
+ * @addr: Address of the destination STA
+ * @reason: Reason code for Deauthentication
+ */
 void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
 {
        struct ieee80211_mgmt mgmt;
@@ -882,9 +897,9 @@ static void handle_assoc(struct hostapd_data *hapd,
                        resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
 #ifdef CONFIG_IEEE80211W
                else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
-                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE; /* FIX */
+                       resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
                else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
-                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE; /* FIX */
+                       resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
 #endif /* CONFIG_IEEE80211W */
                else if (res == WPA_INVALID_MDIE)
                        resp = WLAN_STATUS_INVALID_MDIE;
@@ -893,16 +908,20 @@ static void handle_assoc(struct hostapd_data *hapd,
                if (resp != WLAN_STATUS_SUCCESS)
                        goto fail;
 #ifdef CONFIG_IEEE80211W
-               if ((sta->flags & WLAN_STA_MFP) && !sta->ping_timed_out) {
+               if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+                   sta->sa_query_count > 0)
+                       ap_check_sa_query_timeout(hapd, sta);
+               if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+                   (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
                        /*
-                        * STA has already been associated with MFP and ping
-                        * timeout has not been reached. Reject the
-                        * association attempt temporarily and start ping, if
-                        * one is not pending.
+                        * STA has already been associated with MFP and SA
+                        * Query timeout has not been reached. Reject the
+                        * association attempt temporarily and start SA Query,
+                        * if one is not pending.
                         */
 
-                       if (sta->ping_count == 0)
-                               ap_sta_start_ping(hapd, sta);
+                       if (sta->sa_query_count == 0)
+                               ap_sta_start_sa_query(hapd, sta);
 
                        resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
                        goto fail;
@@ -930,6 +949,16 @@ static void handle_assoc(struct hostapd_data *hapd,
                                goto fail;
                }
 #endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211N
+               if ((sta->flags & WLAN_STA_HT) &&
+                   wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
+                       wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to "
+                                  "use TKIP with HT association",
+                                  MAC2STR(sta->addr));
+                       resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+                       goto fail;
+               }
+#endif /* CONFIG_IEEE80211N */
        } else
                wpa_auth_sta_no_wpa(sta->wpa_sm);
 
@@ -1039,6 +1068,19 @@ static void handle_assoc(struct hostapd_data *hapd,
        /* Station will be marked associated, after it acknowledges AssocResp
         */
 
+#ifdef CONFIG_IEEE80211W
+       if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
+               wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
+                          "SA Query procedure", reassoc ? "re" : "");
+               /* TODO: Send a protected Disassociate frame to the STA using
+                * the old key and Reason Code "Previous Authentication no
+                * longer valid". Make sure this is only sent protected since
+                * unprotected frame would be received by the STA that is now
+                * trying to associate.
+                */
+       }
+#endif /* CONFIG_IEEE80211W */
+
        if (reassoc) {
                os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap,
                          ETH_ALEN);
@@ -1215,51 +1257,78 @@ static void handle_beacon(struct hostapd_data *hapd,
 
 
 #ifdef CONFIG_IEEE80211W
-static void hostapd_ping_action(struct hostapd_data *hapd,
-                               struct ieee80211_mgmt *mgmt, size_t len)
+
+/* MLME-SAQuery.request */
+void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
+                                 const u8 *addr, const u8 *trans_id)
+{
+       struct ieee80211_mgmt mgmt;
+       u8 *end;
+
+       os_memset(&mgmt, 0, sizeof(mgmt));
+       mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+                                         WLAN_FC_STYPE_ACTION);
+       os_memcpy(mgmt.da, addr, ETH_ALEN);
+       os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
+       os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
+       mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
+       mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
+       os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
+                 WLAN_SA_QUERY_TR_ID_LEN);
+       end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
+       if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
+               perror("ieee802_11_send_sa_query_req: send");
+}
+
+
+static void hostapd_sa_query_action(struct hostapd_data *hapd,
+                                   struct ieee80211_mgmt *mgmt, size_t len)
 {
        struct sta_info *sta;
        u8 *end;
        int i;
 
-       end = mgmt->u.action.u.ping_resp.trans_id + WLAN_PING_TRANS_ID_LEN;
+       end = mgmt->u.action.u.sa_query_resp.trans_id +
+               WLAN_SA_QUERY_TR_ID_LEN;
        if (((u8 *) mgmt) + len < end) {
-               wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short Ping Action "
+               wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
                           "frame (len=%lu)", (unsigned long) len);
                return;
        }
 
-       if (mgmt->u.action.u.ping_resp.action != WLAN_PING_RESPONSE) {
-               wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected Ping Action %d",
-                          mgmt->u.action.u.ping_resp.action);
+       if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) {
+               wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
+                          "Action %d", mgmt->u.action.u.sa_query_resp.action);
                return;
        }
 
-       /* MLME-PING.confirm */
+       /* MLME-SAQuery.confirm */
 
        sta = ap_get_sta(hapd, mgmt->sa);
-       if (sta == NULL || sta->ping_trans_id == NULL) {
+       if (sta == NULL || sta->sa_query_trans_id == NULL) {
                wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
-                          "pending ping request found");
+                          "pending SA Query request found");
                return;
        }
 
-       for (i = 0; i < sta->ping_count; i++) {
-               if (os_memcmp(sta->ping_trans_id + i * WLAN_PING_TRANS_ID_LEN,
-                             mgmt->u.action.u.ping_resp.trans_id,
-                             WLAN_PING_TRANS_ID_LEN) == 0)
+       for (i = 0; i < sta->sa_query_count; i++) {
+               if (os_memcmp(sta->sa_query_trans_id +
+                             i * WLAN_SA_QUERY_TR_ID_LEN,
+                             mgmt->u.action.u.sa_query_resp.trans_id,
+                             WLAN_SA_QUERY_TR_ID_LEN) == 0)
                        break;
        }
 
-       if (i >= sta->ping_count) {
-               wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching ping "
+       if (i >= sta->sa_query_count) {
+               wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
                           "transaction identifier found");
                return;
        }
 
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
-                      HOSTAPD_LEVEL_DEBUG, "Reply to pending ping received");
-       ap_sta_stop_ping(hapd, sta);
+                      HOSTAPD_LEVEL_DEBUG,
+                      "Reply to pending SA Query received");
+       ap_sta_stop_sa_query(hapd, sta);
 }
 #endif /* CONFIG_IEEE80211W */
 
@@ -1300,8 +1369,8 @@ static void handle_action(struct hostapd_data *hapd,
                hostapd_wme_action(hapd, mgmt, len);
                return;
 #ifdef CONFIG_IEEE80211W
-       case WLAN_ACTION_PING:
-               hostapd_ping_action(hapd, mgmt, len);
+       case WLAN_ACTION_SA_QUERY:
+               hostapd_sa_query_action(hapd, mgmt, len);
                return;
 #endif /* CONFIG_IEEE80211W */
        }
@@ -1337,6 +1406,7 @@ static void handle_action(struct hostapd_data *hapd,
  * @buf: management frame data (starting from IEEE 802.11 header)
  * @len: length of frame data in octets
  * @stype: management frame subtype from frame control field
+ * @fi: meta data about received frame (signal level, etc.)
  *
  * Process all incoming IEEE 802.11 management frames. This will be called for
  * each frame received from the kernel driver through wlan#ap interface. In
@@ -1519,7 +1589,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
 #endif /* CONFIG_IEEE80211N */
 
 #ifdef CONFIG_IEEE80211W
-       sta->ping_timed_out = 0;
+       sta->sa_query_timed_out = 0;
 #endif /* CONFIG_IEEE80211W */
 
        if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
@@ -1568,6 +1638,15 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
 }
 
 
+/**
+ * ieee802_11_mgmt_cb - Process management frame TX status callback
+ * @hapd: hostapd BSS data structure (the BSS from which the management frame
+ * was sent from)
+ * @buf: management frame data (starting from IEEE 802.11 header)
+ * @len: length of frame data in octets
+ * @stype: management frame subtype from frame control field
+ * @ok: Whether the frame was ACK'ed
+ */
 void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
                        u16 stype, int ok)
 {
@@ -1602,76 +1681,6 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
 }
 
 
-static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
-                                               void *timeout_ctx)
-{
-       struct hostapd_data *hapd = eloop_ctx;
-       hapd->tkip_countermeasures = 0;
-       hostapd_set_countermeasures(hapd, 0);
-       hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-                      HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
-}
-
-
-static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
-{
-       struct sta_info *sta;
-
-       hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-                      HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
-
-       wpa_auth_countermeasures_start(hapd->wpa_auth);
-       hapd->tkip_countermeasures = 1;
-       hostapd_set_countermeasures(hapd, 1);
-       wpa_gtk_rekey(hapd->wpa_auth);
-       eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
-       eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
-                              hapd, NULL);
-       for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
-               hostapd_sta_deauth(hapd, sta->addr,
-                                  WLAN_REASON_MICHAEL_MIC_FAILURE);
-               sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
-                               WLAN_STA_AUTHORIZED);
-               hostapd_sta_remove(hapd, sta->addr);
-       }
-}
-
-
-void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr,
-                                  int local)
-{
-       time_t now;
-
-       if (addr && local) {
-               struct sta_info *sta = ap_get_sta(hapd, addr);
-               if (sta != NULL) {
-                       wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
-                       hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-                                      HOSTAPD_LEVEL_INFO,
-                                      "Michael MIC failure detected in "
-                                      "received frame");
-                       mlme_michaelmicfailure_indication(hapd, addr);
-               } else {
-                       wpa_printf(MSG_DEBUG,
-                                  "MLME-MICHAELMICFAILURE.indication "
-                                  "for not associated STA (" MACSTR
-                                  ") ignored", MAC2STR(addr));
-                       return;
-               }
-       }
-
-       time(&now);
-       if (now > hapd->michael_mic_failure + 60) {
-               hapd->michael_mic_failures = 1;
-       } else {
-               hapd->michael_mic_failures++;
-               if (hapd->michael_mic_failures > 1)
-                       ieee80211_tkip_countermeasures_start(hapd);
-       }
-       hapd->michael_mic_failure = now;
-}
-
-
 int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
 {
        /* TODO */