summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h7
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/mlme.c14
-rw-r--r--net/wireless/mlme.c8
-rw-r--r--net/wireless/nl80211.c24
-rw-r--r--net/wireless/nl80211.h3
6 files changed, 46 insertions, 16 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f81677f2f051..7a29b709077f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5676,10 +5676,12 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
* @dev: network device
* @bss: the BSS that association was requested with, ownership of the pointer
* moves to cfg80211 in this call
- * @buf: authentication frame (header + body)
+ * @buf: (Re)Association Response frame (header + body)
* @len: length of the frame data
* @uapsd_queues: bitmap of queues configured for uapsd. Same format
* as the AC bitmap in the QoS info field
+ * @req_ies: information elements from the (Re)Association Request frame
+ * @req_ies_len: length of req_ies data
*
* After being asked to associate via cfg80211_ops::assoc() the driver must
* call either this function or cfg80211_auth_timeout().
@@ -5689,7 +5691,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
void cfg80211_rx_assoc_resp(struct net_device *dev,
struct cfg80211_bss *bss,
const u8 *buf, size_t len,
- int uapsd_queues);
+ int uapsd_queues,
+ const u8 *req_ies, size_t req_ies_len);
/**
* cfg80211_assoc_timeout - notification of timed out association
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5795eef98771..afce50da6fd6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -556,6 +556,12 @@ struct ieee80211_if_managed {
* get stuck in a downgraded situation and flush takes forever.
*/
struct delayed_work tx_tspec_wk;
+
+ /* Information elements from the last transmitted (Re)Association
+ * Request frame.
+ */
+ u8 *assoc_req_ies;
+ size_t assoc_req_ies_len;
};
struct ieee80211_if_ibss {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a49fbb3f3ed7..df5d4b90616d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -644,7 +644,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- u8 *pos, qos_info;
+ u8 *pos, qos_info, *ie_start;
size_t offset = 0, noffset;
int i, count, rates_len, supp_rates_len, shift;
u16 capab;
@@ -752,6 +752,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
/* SSID */
pos = skb_put(skb, 2 + assoc_data->ssid_len);
+ ie_start = pos;
*pos++ = WLAN_EID_SSID;
*pos++ = assoc_data->ssid_len;
memcpy(pos, assoc_data->ssid, assoc_data->ssid_len);
@@ -976,6 +977,11 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
return;
}
+ pos = skb_tail_pointer(skb);
+ kfree(ifmgd->assoc_req_ies);
+ ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC);
+ ifmgd->assoc_req_ies_len = pos - ie_start;
+
drv_mgd_prepare_tx(local, sdata, 0);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -3544,7 +3550,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
}
- cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
+ cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues,
+ ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -5576,6 +5583,9 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
ifmgd->teardown_skb = NULL;
ifmgd->orig_teardown_skb = NULL;
}
+ kfree(ifmgd->assoc_req_ies);
+ ifmgd->assoc_req_ies = NULL;
+ ifmgd->assoc_req_ies_len = 0;
spin_unlock_bh(&ifmgd->teardown_lock);
del_timer_sync(&ifmgd->timer);
sdata_unlock(sdata);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 1615e503f8e3..f9462010575f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -21,7 +21,8 @@
void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
- const u8 *buf, size_t len, int uapsd_queues)
+ const u8 *buf, size_t len, int uapsd_queues,
+ const u8 *req_ies, size_t req_ies_len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -33,6 +34,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code);
cr.bssid = mgmt->bssid;
cr.bss = bss;
+ cr.req_ie = req_ies;
+ cr.req_ie_len = req_ies_len;
cr.resp_ie = mgmt->u.assoc_resp.variable;
cr.resp_ie_len =
len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
@@ -52,7 +55,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
return;
}
- nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues);
+ nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues,
+ req_ies, req_ies_len);
/* update current_bss etc., consumes the bss reference */
__cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS);
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 80878b431584..d5badbbb28a3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14491,12 +14491,13 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len,
enum nl80211_commands cmd, gfp_t gfp,
- int uapsd_queues)
+ int uapsd_queues, const u8 *req_ies,
+ size_t req_ies_len)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(100 + len, gfp);
+ msg = nlmsg_new(100 + len + req_ies_len, gfp);
if (!msg)
return;
@@ -14508,7 +14509,9 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
- nla_put(msg, NL80211_ATTR_FRAME, len, buf))
+ nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
+ (req_ies &&
+ nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
goto nla_put_failure;
if (uapsd_queues >= 0) {
@@ -14539,15 +14542,17 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_AUTHENTICATE, gfp, -1);
+ NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
}
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *buf,
- size_t len, gfp_t gfp, int uapsd_queues)
+ size_t len, gfp_t gfp, int uapsd_queues,
+ const u8 *req_ies, size_t req_ies_len)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
+ NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
+ req_ies, req_ies_len);
}
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
@@ -14555,7 +14560,7 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DEAUTHENTICATE, gfp, -1);
+ NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
}
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
@@ -14563,7 +14568,7 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DISASSOCIATE, gfp, -1);
+ NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
}
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
@@ -14584,7 +14589,8 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
- nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
+ nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
+ NULL, 0);
}
EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 531c82dcba6b..a41e94a49a89 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -67,7 +67,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len, gfp_t gfp,
- int uapsd_queues);
+ int uapsd_queues,
+ const u8 *req_ies, size_t req_ies_len);
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len, gfp_t gfp);