diff options
-rw-r--r-- | include/linux/nl80211.h | 5 | ||||
-rw-r--r-- | include/net/cfg80211.h | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 7 | ||||
-rw-r--r-- | net/wireless/core.h | 3 | ||||
-rw-r--r-- | net/wireless/mlme.c | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 10 | ||||
-rw-r--r-- | net/wireless/sme.c | 8 |
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 | */ |
668 | struct cfg80211_assoc_request { | 669 | struct 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); |
203 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 203 | int 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); |
208 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 209 | int 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 | ||
336 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 336 | int 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 | ||
3257 | out: | 3261 | out: |
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, ¶ms->crypto); | 138 | false, ¶ms->crypto); |