aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-07 08:37:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:30 -0400
commit3e5d7649a64e558e4146ddfad4dfcf13fc65dd47 (patch)
treefa51725ca07cf682e6694ba5f107d8614d9f0972
parent2ffa5fede379091bf62a732462b829e4b51af054 (diff)
cfg80211: let SME control reassociation vs. association
Since we don't really know that well in the kernel, let's let the SME control whether it wants to use reassociation or not, by allowing it to give the previous BSSID in the associate() parameters. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/nl80211.h5
-rw-r--r--include/net/cfg80211.h3
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/mlme.c7
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/mlme.c4
-rw-r--r--net/wireless/nl80211.c10
-rw-r--r--net/wireless/sme.c8
8 files changed, 32 insertions, 14 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index b34c17f52f3e..e496a2daf7ef 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -564,6 +564,9 @@ enum nl80211_commands {
564 * @NL80211_ATTR_RESP_IE: (Re)association response information elements as 564 * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
565 * sent by peer, for ROAM and successful CONNECT events. 565 * sent by peer, for ROAM and successful CONNECT events.
566 * 566 *
567 * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
568 * commands to specify using a reassociate frame
569 *
567 * @NL80211_ATTR_MAX: highest attribute number currently defined 570 * @NL80211_ATTR_MAX: highest attribute number currently defined
568 * @__NL80211_ATTR_AFTER_LAST: internal use 571 * @__NL80211_ATTR_AFTER_LAST: internal use
569 */ 572 */
@@ -687,6 +690,8 @@ enum nl80211_attrs {
687 NL80211_ATTR_REQ_IE, 690 NL80211_ATTR_REQ_IE,
688 NL80211_ATTR_RESP_IE, 691 NL80211_ATTR_RESP_IE,
689 692
693 NL80211_ATTR_PREV_BSSID,
694
690 /* add attributes here, update the policy in nl80211.c */ 695 /* add attributes here, update the policy in nl80211.c */
691 696
692 __NL80211_ATTR_AFTER_LAST, 697 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ca986cc91098..71847d3c2640 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -664,10 +664,11 @@ struct cfg80211_auth_request {
664 * @ie_len: Length of ie buffer in octets 664 * @ie_len: Length of ie buffer in octets
665 * @use_mfp: Use management frame protection (IEEE 802.11w) in this association 665 * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
666 * @crypto: crypto settings 666 * @crypto: crypto settings
667 * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
667 */ 668 */
668struct cfg80211_assoc_request { 669struct cfg80211_assoc_request {
669 struct cfg80211_bss *bss; 670 struct cfg80211_bss *bss;
670 const u8 *ie; 671 const u8 *ie, *prev_bssid;
671 size_t ie_len; 672 size_t ie_len;
672 struct cfg80211_crypto_settings crypto; 673 struct cfg80211_crypto_settings crypto;
673 bool use_mfp; 674 bool use_mfp;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0f29cd0580c9..e6d8860f26f2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1256,6 +1256,12 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1256 sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED; 1256 sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
1257 } 1257 }
1258 1258
1259 if (req->prev_bssid) {
1260 sdata->u.mgd.flags |= IEEE80211_STA_PREV_BSSID_SET;
1261 memcpy(sdata->u.mgd.prev_bssid, req->prev_bssid, ETH_ALEN);
1262 } else
1263 sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1264
1259 if (req->crypto.control_port) 1265 if (req->crypto.control_port)
1260 sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT; 1266 sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
1261 else 1267 else
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index aa1829ae431d..24486455e505 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -879,9 +879,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
879 ieee80211_rx_bss_put(local, bss); 879 ieee80211_rx_bss_put(local, bss);
880 } 880 }
881 881
882 ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET;
883 memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN);
884
885 ifmgd->last_probe = jiffies; 882 ifmgd->last_probe = jiffies;
886 ieee80211_led_assoc(local, 1); 883 ieee80211_led_assoc(local, 1);
887 884
@@ -1470,10 +1467,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1470 if (status_code != WLAN_STATUS_SUCCESS) { 1467 if (status_code != WLAN_STATUS_SUCCESS) {
1471 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", 1468 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1472 sdata->dev->name, status_code); 1469 sdata->dev->name, status_code);
1473 /* if this was a reassociation, ensure we try a "full"
1474 * association next time. This works around some broken APs
1475 * which do not correctly reject reassociation requests. */
1476 ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1477 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len, 1470 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len,
1478 GFP_KERNEL); 1471 GFP_KERNEL);
1479 /* Wait for SME to decide what to do next */ 1472 /* Wait for SME to decide what to do next */
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 82918f5896a5..4554453c116a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -202,7 +202,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
202 const u8 *ie, int ie_len); 202 const u8 *ie, int ie_len);
203int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 203int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
204 struct net_device *dev, struct ieee80211_channel *chan, 204 struct net_device *dev, struct ieee80211_channel *chan,
205 const u8 *bssid, const u8 *ssid, int ssid_len, 205 const u8 *bssid, const u8 *prev_bssid,
206 const u8 *ssid, int ssid_len,
206 const u8 *ie, int ie_len, bool use_mfp, 207 const u8 *ie, int ie_len, bool use_mfp,
207 struct cfg80211_crypto_settings *crypt); 208 struct cfg80211_crypto_settings *crypt);
208int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 209int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 020f33b38467..087d3377958f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -335,7 +335,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
335 335
336int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 336int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
337 struct net_device *dev, struct ieee80211_channel *chan, 337 struct net_device *dev, struct ieee80211_channel *chan,
338 const u8 *bssid, const u8 *ssid, int ssid_len, 338 const u8 *bssid, const u8 *prev_bssid,
339 const u8 *ssid, int ssid_len,
339 const u8 *ie, int ie_len, bool use_mfp, 340 const u8 *ie, int ie_len, bool use_mfp,
340 struct cfg80211_crypto_settings *crypt) 341 struct cfg80211_crypto_settings *crypt)
341{ 342{
@@ -353,6 +354,7 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
353 req.ie_len = ie_len; 354 req.ie_len = ie_len;
354 memcpy(&req.crypto, crypt, sizeof(req.crypto)); 355 memcpy(&req.crypto, crypt, sizeof(req.crypto));
355 req.use_mfp = use_mfp; 356 req.use_mfp = use_mfp;
357 req.prev_bssid = prev_bssid;
356 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 358 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
357 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 359 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
358 if (!req.bss) 360 if (!req.bss)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 723512b48f2e..44c520c264fc 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -71,6 +71,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
71 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, 71 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
72 72
73 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, 73 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
74 [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
74 75
75 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, 76 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
76 .len = WLAN_MAX_KEY_LEN }, 77 .len = WLAN_MAX_KEY_LEN },
@@ -3187,7 +3188,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3187 struct net_device *dev; 3188 struct net_device *dev;
3188 struct cfg80211_crypto_settings crypto; 3189 struct cfg80211_crypto_settings crypto;
3189 struct ieee80211_channel *chan; 3190 struct ieee80211_channel *chan;
3190 const u8 *bssid, *ssid, *ie = NULL; 3191 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
3191 int err, ssid_len, ie_len = 0; 3192 int err, ssid_len, ie_len = 0;
3192 bool use_mfp = false; 3193 bool use_mfp = false;
3193 3194
@@ -3248,10 +3249,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3248 } 3249 }
3249 } 3250 }
3250 3251
3252 if (info->attrs[NL80211_ATTR_PREV_BSSID])
3253 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3254
3251 err = nl80211_crypto_settings(info, &crypto, 1); 3255 err = nl80211_crypto_settings(info, &crypto, 1);
3252 if (!err) 3256 if (!err)
3253 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, ssid, 3257 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
3254 ssid_len, ie, ie_len, use_mfp, 3258 ssid, ssid_len, ie, ie_len, use_mfp,
3255 &crypto); 3259 &crypto);
3256 3260
3257out: 3261out:
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 412161f7b08e..066a19ef9d73 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -125,8 +125,14 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
125 case CFG80211_CONN_ASSOCIATE_NEXT: 125 case CFG80211_CONN_ASSOCIATE_NEXT:
126 BUG_ON(!drv->ops->assoc); 126 BUG_ON(!drv->ops->assoc);
127 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 127 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
128 /*
129 * We could, later, implement roaming here and then actually
130 * set prev_bssid to non-NULL. But then we need to be aware
131 * that some APs don't like that -- so we'd need to retry
132 * the association.
133 */
128 err = cfg80211_mlme_assoc(drv, wdev->netdev, 134 err = cfg80211_mlme_assoc(drv, wdev->netdev,
129 params->channel, params->bssid, 135 params->channel, params->bssid, NULL,
130 params->ssid, params->ssid_len, 136 params->ssid, params->ssid_len,
131 params->ie, params->ie_len, 137 params->ie, params->ie_len,
132 false, &params->crypto); 138 false, &params->crypto);