aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-03-31 10:09:13 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-04-07 07:56:45 -0400
commit46b9d180141dac76cd6065bf497cec44816ab4c6 (patch)
treeab6d2ed8a24793dcb5096b61e965286f9b116ec5
parent29464ccc78f1e8f77b8c37ddbe95af46d13c2ec2 (diff)
cfg80211: send extended capabilities IE in connect
If the connect request from userspace didn't include an extended capabilities IE, create one using the driver capabilities. This fixes VHT associations, since those need to set the operating mode notification capability. Reviewed-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/wireless/sme.c74
1 files changed, 64 insertions, 10 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index ea1da6621ff0..d11454f87bac 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -42,7 +42,7 @@ struct cfg80211_conn {
42 CFG80211_CONN_CONNECTED, 42 CFG80211_CONN_CONNECTED,
43 } state; 43 } state;
44 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; 44 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
45 u8 *ie; 45 const u8 *ie;
46 size_t ie_len; 46 size_t ie_len;
47 bool auto_auth, prev_bssid_valid; 47 bool auto_auth, prev_bssid_valid;
48}; 48};
@@ -423,6 +423,62 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
423 schedule_work(&rdev->conn_work); 423 schedule_work(&rdev->conn_work);
424} 424}
425 425
426static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
427 const u8 *ies, size_t ies_len,
428 const u8 **out_ies, size_t *out_ies_len)
429{
430 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
431 u8 *buf;
432 size_t offs;
433
434 if (!rdev->wiphy.extended_capabilities_len ||
435 (ies && cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len))) {
436 *out_ies = kmemdup(ies, ies_len, GFP_KERNEL);
437 if (!*out_ies)
438 return -ENOMEM;
439 *out_ies_len = ies_len;
440 return 0;
441 }
442
443 buf = kmalloc(ies_len + rdev->wiphy.extended_capabilities_len + 2,
444 GFP_KERNEL);
445 if (!buf)
446 return -ENOMEM;
447
448 if (ies_len) {
449 static const u8 before_extcapa[] = {
450 /* not listing IEs expected to be created by driver */
451 WLAN_EID_RSN,
452 WLAN_EID_QOS_CAPA,
453 WLAN_EID_RRM_ENABLED_CAPABILITIES,
454 WLAN_EID_MOBILITY_DOMAIN,
455 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
456 WLAN_EID_BSS_COEX_2040,
457 };
458
459 offs = ieee80211_ie_split(ies, ies_len, before_extcapa,
460 ARRAY_SIZE(before_extcapa), 0);
461 memcpy(buf, ies, offs);
462 /* leave a whole for extended capabilities IE */
463 memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
464 ies + offs, ies_len - offs);
465 } else {
466 offs = 0;
467 }
468
469 /* place extended capabilities IE (with only driver capabilities) */
470 buf[offs] = WLAN_EID_EXT_CAPABILITY;
471 buf[offs + 1] = rdev->wiphy.extended_capabilities_len;
472 memcpy(buf + offs + 2,
473 rdev->wiphy.extended_capabilities,
474 rdev->wiphy.extended_capabilities_len);
475
476 *out_ies = buf;
477 *out_ies_len = ies_len + rdev->wiphy.extended_capabilities_len + 2;
478
479 return 0;
480}
481
426static int cfg80211_sme_connect(struct wireless_dev *wdev, 482static int cfg80211_sme_connect(struct wireless_dev *wdev,
427 struct cfg80211_connect_params *connect, 483 struct cfg80211_connect_params *connect,
428 const u8 *prev_bssid) 484 const u8 *prev_bssid)
@@ -453,16 +509,14 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
453 memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN); 509 memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
454 } 510 }
455 511
456 if (connect->ie) { 512 if (cfg80211_sme_get_conn_ies(wdev, connect->ie, connect->ie_len,
457 wdev->conn->ie = kmemdup(connect->ie, connect->ie_len, 513 &wdev->conn->ie,
458 GFP_KERNEL); 514 &wdev->conn->params.ie_len)) {
459 wdev->conn->params.ie = wdev->conn->ie; 515 kfree(wdev->conn);
460 if (!wdev->conn->ie) { 516 wdev->conn = NULL;
461 kfree(wdev->conn); 517 return -ENOMEM;
462 wdev->conn = NULL;
463 return -ENOMEM;
464 }
465 } 518 }
519 wdev->conn->params.ie = wdev->conn->ie;
466 520
467 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { 521 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
468 wdev->conn->auto_auth = true; 522 wdev->conn->auto_auth = true;