aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-08 06:32:09 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:07 -0500
commit63a5ab82255a4ff5d0783f16427210f1d45d7ec8 (patch)
treeb10fe227645c9c4c6ee044a1873e0aad34c3a016
parent97ebe12a035e11f8af7a06a34f4d848f9b2f0b49 (diff)
mac80211: 802.11w - Implement Association Comeback processing
When MFP is enabled, the AP does not allow a STA to associate if an existing security association exists without first going through SA Query process. When this happens, the association request is denied with a new status code ("temporarily rejected") ans Association Comeback IE is used to notify when the association may be tried again (i.e., when the SA Query procedure has timed out). Use the comeback time to update the mac80211 client MLME timer for next association attempt to minimize waiting time if association is temporarily rejected. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/ieee80211.h4
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/util.c4
4 files changed, 27 insertions, 3 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 9fe1948d28d3..7800e20f197f 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -914,6 +914,9 @@ enum ieee80211_statuscode {
914 /* 802.11g */ 914 /* 802.11g */
915 WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, 915 WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
916 WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, 916 WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
917 /* 802.11w */
918 WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30,
919 WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
917 /* 802.11i */ 920 /* 802.11i */
918 WLAN_STATUS_INVALID_IE = 40, 921 WLAN_STATUS_INVALID_IE = 40,
919 WLAN_STATUS_INVALID_GROUP_CIPHER = 41, 922 WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
@@ -1034,6 +1037,7 @@ enum ieee80211_eid {
1034 /* 802.11i */ 1037 /* 802.11i */
1035 WLAN_EID_RSN = 48, 1038 WLAN_EID_RSN = 48,
1036 WLAN_EID_MMIE = 76 /* 802.11w */, 1039 WLAN_EID_MMIE = 76 /* 802.11w */,
1040 WLAN_EID_ASSOC_COMEBACK_TIME = 77,
1037 WLAN_EID_WPA = 221, 1041 WLAN_EID_WPA = 221,
1038 WLAN_EID_GENERIC = 221, 1042 WLAN_EID_GENERIC = 221,
1039 WLAN_EID_VENDOR_SPECIFIC = 221, 1043 WLAN_EID_VENDOR_SPECIFIC = 221,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 212c732fbba7..9112c5247c35 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -820,6 +820,7 @@ struct ieee802_11_elems {
820 u8 *country_elem; 820 u8 *country_elem;
821 u8 *pwr_constr_elem; 821 u8 *pwr_constr_elem;
822 u8 *quiet_elem; /* first quite element */ 822 u8 *quiet_elem; /* first quite element */
823 u8 *assoc_comeback;
823 824
824 /* length of them, respectively */ 825 /* length of them, respectively */
825 u8 ssid_len; 826 u8 ssid_len;
@@ -847,6 +848,7 @@ struct ieee802_11_elems {
847 u8 pwr_constr_elem_len; 848 u8 pwr_constr_elem_len;
848 u8 quiet_elem_len; 849 u8 quiet_elem_len;
849 u8 num_of_quiet_elem; /* can be more the one */ 850 u8 num_of_quiet_elem; /* can be more the one */
851 u8 assoc_comeback_len;
850}; 852};
851 853
852static inline struct ieee80211_local *hw_to_local( 854static inline struct ieee80211_local *hw_to_local(
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 42c5f981c715..82c598a83687 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1275,6 +1275,23 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1275 sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, 1275 sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
1276 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); 1276 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
1277 1277
1278 pos = mgmt->u.assoc_resp.variable;
1279 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1280
1281 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1282 elems.assoc_comeback && elems.assoc_comeback_len == 4) {
1283 u32 tu, ms;
1284 tu = get_unaligned_le32(elems.assoc_comeback);
1285 ms = tu * 1024 / 1000;
1286 printk(KERN_DEBUG "%s: AP rejected association temporarily; "
1287 "comeback duration %u TU (%u ms)\n",
1288 sdata->dev->name, tu, ms);
1289 if (ms > IEEE80211_ASSOC_TIMEOUT)
1290 mod_timer(&ifsta->timer,
1291 jiffies + msecs_to_jiffies(ms));
1292 return;
1293 }
1294
1278 if (status_code != WLAN_STATUS_SUCCESS) { 1295 if (status_code != WLAN_STATUS_SUCCESS) {
1279 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", 1296 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1280 sdata->dev->name, status_code); 1297 sdata->dev->name, status_code);
@@ -1290,9 +1307,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1290 "set\n", sdata->dev->name, aid); 1307 "set\n", sdata->dev->name, aid);
1291 aid &= ~(BIT(15) | BIT(14)); 1308 aid &= ~(BIT(15) | BIT(14));
1292 1309
1293 pos = mgmt->u.assoc_resp.variable;
1294 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1295
1296 if (!elems.supp_rates) { 1310 if (!elems.supp_rates) {
1297 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", 1311 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
1298 sdata->dev->name); 1312 sdata->dev->name);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5cd430333f08..963e0473205c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -653,6 +653,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
653 elems->pwr_constr_elem = pos; 653 elems->pwr_constr_elem = pos;
654 elems->pwr_constr_elem_len = elen; 654 elems->pwr_constr_elem_len = elen;
655 break; 655 break;
656 case WLAN_EID_ASSOC_COMEBACK_TIME:
657 elems->assoc_comeback = pos;
658 elems->assoc_comeback_len = elen;
659 break;
656 default: 660 default:
657 break; 661 break;
658 } 662 }