Browse Source

Updated SA Query procedure to use timeouts per 802.11w/D7.0

The previous max_attempts * timeout is now replaced with two timeouts
(one for each retry, the other one for maximum wait).
Jouni Malinen 16 years ago
parent
commit
45c94154a6
7 changed files with 78 additions and 40 deletions
  1. 1 0
      hostapd/ap.h
  2. 14 12
      hostapd/config.c
  3. 4 4
      hostapd/config.h
  4. 9 7
      hostapd/hostapd.conf
  5. 14 3
      hostapd/ieee802_11.c
  6. 35 14
      hostapd/sta_info.c
  7. 1 0
      hostapd/sta_info.h

+ 1 - 0
hostapd/ap.h

@@ -106,6 +106,7 @@ struct sta_info {
 	u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
 				* sa_query_count octets of pending SA Query
 				* transaction identifiers */
+	struct os_time sa_query_start;
 #endif /* CONFIG_IEEE80211W */
 
 	struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */

+ 14 - 12
hostapd/config.c

@@ -184,8 +184,8 @@ static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 	bss->max_listen_interval = 65535;
 
 #ifdef CONFIG_IEEE80211W
-	bss->assoc_ping_timeout = 1000;
-	bss->assoc_ping_attempts = 3;
+	bss->assoc_sa_query_max_timeout = 1000;
+	bss->assoc_sa_query_retry_timeout = 201;
 #endif /* CONFIG_IEEE80211W */
 #ifdef EAP_FAST
 	 /* both anonymous and authenticated provisioning */
@@ -2064,18 +2064,20 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 #ifdef CONFIG_IEEE80211W
 		} else if (os_strcmp(buf, "ieee80211w") == 0) {
 			bss->ieee80211w = atoi(pos);
-		} else if (os_strcmp(buf, "assoc_ping_timeout") == 0) {
-			bss->assoc_ping_timeout = atoi(pos);
-			if (bss->assoc_ping_timeout == 0) {
-				printf("Line %d: invalid assoc_ping_timeout\n",
-					line);
+		} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
+			bss->assoc_sa_query_max_timeout = atoi(pos);
+			if (bss->assoc_sa_query_max_timeout == 0) {
+				printf("Line %d: invalid "
+				       "assoc_sa_query_max_timeout\n",
+				       line);
 				errors++;
 			}
-		} else if (os_strcmp(buf, "assoc_ping_attempts") == 0) {
-			bss->assoc_ping_timeout = atoi(pos);
-			if (bss->assoc_ping_timeout == 0) {
-				printf("Line %d: invalid assoc_ping_attempts "
-				       "(valid range: 1..255)\n",
+		} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0)
+		{
+			bss->assoc_sa_query_retry_timeout = atoi(pos);
+			if (bss->assoc_sa_query_retry_timeout == 0) {
+				printf("Line %d: invalid "
+				       "assoc_sa_query_retry_timeout\n",
 				       line);
 				errors++;
 			}

+ 4 - 4
hostapd/config.h

@@ -210,10 +210,10 @@ struct hostapd_bss_config {
 		IEEE80211W_OPTIONAL = 1,
 		IEEE80211W_REQUIRED = 2
 	} ieee80211w;
-	/* dot11AssociationPingResponseTimeout (in TU) */
-	unsigned int assoc_ping_timeout;
-	/* dot11AssociationMaximumPingAttempts */
-	int assoc_ping_attempts;
+	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
+	unsigned int assoc_sa_query_max_timeout;
+	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
+	int assoc_sa_query_retry_timeout;
 #endif /* CONFIG_IEEE80211W */
 	int wpa_pairwise;
 	int wpa_group;

+ 9 - 7
hostapd/hostapd.conf

@@ -755,13 +755,15 @@ own_ip_addr=127.0.0.1
 # 2 = required
 #ieee80211w=0
 
-# Association ping timeout (in TU = 1.024 ms; for MFP)
-# dot11AssociationPingResponseTimeout, 1...4294967295
-#assoc_ping_timeout=1000
-
-# Maximum number of association pings
-# dot11AssociationMaximumPingAttempts , 1...255
-#assoc_ping_attempts=3
+# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
+# (maximum time to wait for a SA Query response)
+# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
+#assoc_sa_query_max_timeout=1000
+
+# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)
+# (time between two subsequent SA Query requests)
+# dot11AssociationSAQueryRetryTimeout, 1...4294967295
+#assoc_sa_query_retry_timeout=201
 
 
 # okc: Opportunistic Key Caching (aka Proactive Key Caching)

+ 14 - 3
hostapd/ieee802_11.c

@@ -298,12 +298,20 @@ static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
 					    struct sta_info *sta, u8 *eid)
 {
 	u8 *pos = eid;
-	u32 timeout;
+	u32 timeout, tu;
+	struct os_time now, passed;
 
 	*pos++ = WLAN_EID_ASSOC_COMEBACK_TIME;
 	*pos++ = 4;
-	timeout = (hapd->conf->assoc_ping_attempts - sta->sa_query_count + 1) *
-		hapd->conf->assoc_ping_timeout;
+	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;
 
@@ -893,6 +901,9 @@ 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->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) {
 			/*
 			 * STA has already been associated with MFP and SA

+ 35 - 14
hostapd/sta_info.c

@@ -637,44 +637,65 @@ static void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
 }
 
 
-static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 {
-	struct hostapd_data *hapd = eloop_ctx;
-	struct sta_info *sta = timeout_ctx;
-	unsigned int timeout, sec, usec;
-	u8 *trans_id, *nbuf;
-
-	if (sta->sa_query_count >= hapd->conf->assoc_ping_attempts) {
-		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+	u32 tu;
+	struct os_time now, passed;
+	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) {
+		hostapd_logger(hapd, sta->addr,
+			       HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_DEBUG,
 			       "association SA Query timed out");
 		sta->sa_query_timed_out = 1;
 		os_free(sta->sa_query_trans_id);
 		sta->sa_query_trans_id = NULL;
 		sta->sa_query_count = 0;
-		return;
+		eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
+		return 1;
 	}
 
+	return 0;
+}
+
+
+static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct sta_info *sta = timeout_ctx;
+	unsigned int timeout, sec, usec;
+	u8 *trans_id, *nbuf;
+
+	if (sta->sa_query_count > 0 &&
+	    ap_check_sa_query_timeout(hapd, sta))
+		return;
+
 	nbuf = os_realloc(sta->sa_query_trans_id,
 			  (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
 	if (nbuf == NULL)
 		return;
+	if (sta->sa_query_count == 0) {
+		/* Starting a new SA Query procedure */
+		os_get_time(&sta->sa_query_start);
+	}
 	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
 	sta->sa_query_trans_id = nbuf;
 	sta->sa_query_count++;
 
 	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
 
+	timeout = hapd->conf->assoc_sa_query_retry_timeout;
+	sec = ((timeout / 1000) * 1024) / 1000;
+	usec = (timeout % 1000) * 1024;
+	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
+
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG,
 		       "association SA Query attempt %d", sta->sa_query_count);
 
 	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
-
-	timeout = hapd->conf->assoc_ping_timeout;
-	sec = ((timeout / 1000) * 1024) / 1000;
-	usec = (timeout % 1000) * 1024;
-	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
 }
 
 

+ 1 - 0
hostapd/sta_info.h

@@ -38,5 +38,6 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
 		     int old_vlanid);
 void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
 void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
 
 #endif /* STA_INFO_H */