|
@@ -42,7 +42,7 @@ struct cfg80211_conn {
|
|
CFG80211_CONN_CONNECTED,
|
|
CFG80211_CONN_CONNECTED,
|
|
} state;
|
|
} state;
|
|
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
|
|
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
|
|
- u8 *ie;
|
|
|
|
|
|
+ const u8 *ie;
|
|
size_t ie_len;
|
|
size_t ie_len;
|
|
bool auto_auth, prev_bssid_valid;
|
|
bool auto_auth, prev_bssid_valid;
|
|
};
|
|
};
|
|
@@ -423,6 +423,62 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
|
|
schedule_work(&rdev->conn_work);
|
|
schedule_work(&rdev->conn_work);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
|
|
|
|
+ const u8 *ies, size_t ies_len,
|
|
|
|
+ const u8 **out_ies, size_t *out_ies_len)
|
|
|
|
+{
|
|
|
|
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
|
|
|
+ u8 *buf;
|
|
|
|
+ size_t offs;
|
|
|
|
+
|
|
|
|
+ if (!rdev->wiphy.extended_capabilities_len ||
|
|
|
|
+ (ies && cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len))) {
|
|
|
|
+ *out_ies = kmemdup(ies, ies_len, GFP_KERNEL);
|
|
|
|
+ if (!*out_ies)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ *out_ies_len = ies_len;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buf = kmalloc(ies_len + rdev->wiphy.extended_capabilities_len + 2,
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!buf)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ if (ies_len) {
|
|
|
|
+ static const u8 before_extcapa[] = {
|
|
|
|
+ /* not listing IEs expected to be created by driver */
|
|
|
|
+ WLAN_EID_RSN,
|
|
|
|
+ WLAN_EID_QOS_CAPA,
|
|
|
|
+ WLAN_EID_RRM_ENABLED_CAPABILITIES,
|
|
|
|
+ WLAN_EID_MOBILITY_DOMAIN,
|
|
|
|
+ WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
|
|
|
+ WLAN_EID_BSS_COEX_2040,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ offs = ieee80211_ie_split(ies, ies_len, before_extcapa,
|
|
|
|
+ ARRAY_SIZE(before_extcapa), 0);
|
|
|
|
+ memcpy(buf, ies, offs);
|
|
|
|
+ /* leave a whole for extended capabilities IE */
|
|
|
|
+ memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
|
|
|
|
+ ies + offs, ies_len - offs);
|
|
|
|
+ } else {
|
|
|
|
+ offs = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* place extended capabilities IE (with only driver capabilities) */
|
|
|
|
+ buf[offs] = WLAN_EID_EXT_CAPABILITY;
|
|
|
|
+ buf[offs + 1] = rdev->wiphy.extended_capabilities_len;
|
|
|
|
+ memcpy(buf + offs + 2,
|
|
|
|
+ rdev->wiphy.extended_capabilities,
|
|
|
|
+ rdev->wiphy.extended_capabilities_len);
|
|
|
|
+
|
|
|
|
+ *out_ies = buf;
|
|
|
|
+ *out_ies_len = ies_len + rdev->wiphy.extended_capabilities_len + 2;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int cfg80211_sme_connect(struct wireless_dev *wdev,
|
|
static int cfg80211_sme_connect(struct wireless_dev *wdev,
|
|
struct cfg80211_connect_params *connect,
|
|
struct cfg80211_connect_params *connect,
|
|
const u8 *prev_bssid)
|
|
const u8 *prev_bssid)
|
|
@@ -453,16 +509,14 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
|
|
memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
|
|
memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
|
|
}
|
|
}
|
|
|
|
|
|
- if (connect->ie) {
|
|
|
|
- wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
|
|
|
|
- GFP_KERNEL);
|
|
|
|
- wdev->conn->params.ie = wdev->conn->ie;
|
|
|
|
- if (!wdev->conn->ie) {
|
|
|
|
- kfree(wdev->conn);
|
|
|
|
- wdev->conn = NULL;
|
|
|
|
- return -ENOMEM;
|
|
|
|
- }
|
|
|
|
|
|
+ if (cfg80211_sme_get_conn_ies(wdev, connect->ie, connect->ie_len,
|
|
|
|
+ &wdev->conn->ie,
|
|
|
|
+ &wdev->conn->params.ie_len)) {
|
|
|
|
+ kfree(wdev->conn);
|
|
|
|
+ wdev->conn = NULL;
|
|
|
|
+ return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
+ wdev->conn->params.ie = wdev->conn->ie;
|
|
|
|
|
|
if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
|
|
if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
|
|
wdev->conn->auto_auth = true;
|
|
wdev->conn->auto_auth = true;
|