aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-08 13:32:09 +0200
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:07 -0500
commit63a5ab82255a4ff5d0783f16427210f1d45d7ec8 (patch)
treeb10fe227645c9c4c6ee044a1873e0aad34c3a016
parent97ebe12a035e11f8af7a06a34f4d848f9b2f0b49 (diff)
downloadkernel_goldelico_gta04-63a5ab82255a4ff5d0783f16427210f1d45d7ec8.zip
kernel_goldelico_gta04-63a5ab82255a4ff5d0783f16427210f1d45d7ec8.tar.gz
kernel_goldelico_gta04-63a5ab82255a4ff5d0783f16427210f1d45d7ec8.tar.bz2
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 9fe1948d..7800e20 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -914,6 +914,9 @@ enum ieee80211_statuscode {
/* 802.11g */
WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+ /* 802.11w */
+ WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30,
+ WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
/* 802.11i */
WLAN_STATUS_INVALID_IE = 40,
WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
@@ -1034,6 +1037,7 @@ enum ieee80211_eid {
/* 802.11i */
WLAN_EID_RSN = 48,
WLAN_EID_MMIE = 76 /* 802.11w */,
+ WLAN_EID_ASSOC_COMEBACK_TIME = 77,
WLAN_EID_WPA = 221,
WLAN_EID_GENERIC = 221,
WLAN_EID_VENDOR_SPECIFIC = 221,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 212c732..9112c52 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -820,6 +820,7 @@ struct ieee802_11_elems {
u8 *country_elem;
u8 *pwr_constr_elem;
u8 *quiet_elem; /* first quite element */
+ u8 *assoc_comeback;
/* length of them, respectively */
u8 ssid_len;
@@ -847,6 +848,7 @@ struct ieee802_11_elems {
u8 pwr_constr_elem_len;
u8 quiet_elem_len;
u8 num_of_quiet_elem; /* can be more the one */
+ u8 assoc_comeback_len;
};
static inline struct ieee80211_local *hw_to_local(
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 42c5f98..82c598a 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,
sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+ pos = mgmt->u.assoc_resp.variable;
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+
+ if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
+ elems.assoc_comeback && elems.assoc_comeback_len == 4) {
+ u32 tu, ms;
+ tu = get_unaligned_le32(elems.assoc_comeback);
+ ms = tu * 1024 / 1000;
+ printk(KERN_DEBUG "%s: AP rejected association temporarily; "
+ "comeback duration %u TU (%u ms)\n",
+ sdata->dev->name, tu, ms);
+ if (ms > IEEE80211_ASSOC_TIMEOUT)
+ mod_timer(&ifsta->timer,
+ jiffies + msecs_to_jiffies(ms));
+ return;
+ }
+
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
sdata->dev->name, status_code);
@@ -1290,9 +1307,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
"set\n", sdata->dev->name, aid);
aid &= ~(BIT(15) | BIT(14));
- pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-
if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
sdata->dev->name);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5cd4303..963e047 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,
elems->pwr_constr_elem = pos;
elems->pwr_constr_elem_len = elen;
break;
+ case WLAN_EID_ASSOC_COMEBACK_TIME:
+ elems->assoc_comeback = pos;
+ elems->assoc_comeback_len = elen;
+ break;
default:
break;
}