Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cfg80211: Report Association Request frame IEs in association events

This extends the NL80211_CMD_ASSOCIATE event case to report
NL80211_ATTR_REQ_IE similarly to what is already done with the
NL80211_CMD_CONNECT events if the driver provides this information. In
practice, this adds (Re)Association Request frame information element
reporting to mac80211 drivers for the cases where user space SME is
used.

This provides more information for user space to figure out which
capabilities were negotiated for the association. For example, this can
be used to determine whether HT, VHT, or HE is used.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Jouni Malinen and committed by
Johannes Berg
4d9ec73d 76763741

+46 -16
+5 -2
include/net/cfg80211.h
··· 5676 5676 * @dev: network device 5677 5677 * @bss: the BSS that association was requested with, ownership of the pointer 5678 5678 * moves to cfg80211 in this call 5679 - * @buf: authentication frame (header + body) 5679 + * @buf: (Re)Association Response frame (header + body) 5680 5680 * @len: length of the frame data 5681 5681 * @uapsd_queues: bitmap of queues configured for uapsd. Same format 5682 5682 * as the AC bitmap in the QoS info field 5683 + * @req_ies: information elements from the (Re)Association Request frame 5684 + * @req_ies_len: length of req_ies data 5683 5685 * 5684 5686 * After being asked to associate via cfg80211_ops::assoc() the driver must 5685 5687 * call either this function or cfg80211_auth_timeout(). ··· 5691 5689 void cfg80211_rx_assoc_resp(struct net_device *dev, 5692 5690 struct cfg80211_bss *bss, 5693 5691 const u8 *buf, size_t len, 5694 - int uapsd_queues); 5692 + int uapsd_queues, 5693 + const u8 *req_ies, size_t req_ies_len); 5695 5694 5696 5695 /** 5697 5696 * cfg80211_assoc_timeout - notification of timed out association
+6
net/mac80211/ieee80211_i.h
··· 556 556 * get stuck in a downgraded situation and flush takes forever. 557 557 */ 558 558 struct delayed_work tx_tspec_wk; 559 + 560 + /* Information elements from the last transmitted (Re)Association 561 + * Request frame. 562 + */ 563 + u8 *assoc_req_ies; 564 + size_t assoc_req_ies_len; 559 565 }; 560 566 561 567 struct ieee80211_if_ibss {
+12 -2
net/mac80211/mlme.c
··· 644 644 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; 645 645 struct sk_buff *skb; 646 646 struct ieee80211_mgmt *mgmt; 647 - u8 *pos, qos_info; 647 + u8 *pos, qos_info, *ie_start; 648 648 size_t offset = 0, noffset; 649 649 int i, count, rates_len, supp_rates_len, shift; 650 650 u16 capab; ··· 752 752 753 753 /* SSID */ 754 754 pos = skb_put(skb, 2 + assoc_data->ssid_len); 755 + ie_start = pos; 755 756 *pos++ = WLAN_EID_SSID; 756 757 *pos++ = assoc_data->ssid_len; 757 758 memcpy(pos, assoc_data->ssid, assoc_data->ssid_len); ··· 976 975 dev_kfree_skb(skb); 977 976 return; 978 977 } 978 + 979 + pos = skb_tail_pointer(skb); 980 + kfree(ifmgd->assoc_req_ies); 981 + ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC); 982 + ifmgd->assoc_req_ies_len = pos - ie_start; 979 983 980 984 drv_mgd_prepare_tx(local, sdata, 0); 981 985 ··· 3550 3544 uapsd_queues |= ieee80211_ac_to_qos_mask[ac]; 3551 3545 } 3552 3546 3553 - cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues); 3547 + cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues, 3548 + ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len); 3554 3549 } 3555 3550 3556 3551 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ··· 5583 5576 ifmgd->teardown_skb = NULL; 5584 5577 ifmgd->orig_teardown_skb = NULL; 5585 5578 } 5579 + kfree(ifmgd->assoc_req_ies); 5580 + ifmgd->assoc_req_ies = NULL; 5581 + ifmgd->assoc_req_ies_len = 0; 5586 5582 spin_unlock_bh(&ifmgd->teardown_lock); 5587 5583 del_timer_sync(&ifmgd->timer); 5588 5584 sdata_unlock(sdata);
+6 -2
net/wireless/mlme.c
··· 21 21 22 22 23 23 void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, 24 - const u8 *buf, size_t len, int uapsd_queues) 24 + const u8 *buf, size_t len, int uapsd_queues, 25 + const u8 *req_ies, size_t req_ies_len) 25 26 { 26 27 struct wireless_dev *wdev = dev->ieee80211_ptr; 27 28 struct wiphy *wiphy = wdev->wiphy; ··· 34 33 cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code); 35 34 cr.bssid = mgmt->bssid; 36 35 cr.bss = bss; 36 + cr.req_ie = req_ies; 37 + cr.req_ie_len = req_ies_len; 37 38 cr.resp_ie = mgmt->u.assoc_resp.variable; 38 39 cr.resp_ie_len = 39 40 len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); ··· 55 52 return; 56 53 } 57 54 58 - nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues); 55 + nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues, 56 + req_ies, req_ies_len); 59 57 /* update current_bss etc., consumes the bss reference */ 60 58 __cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS); 61 59 }
+15 -9
net/wireless/nl80211.c
··· 14491 14491 struct net_device *netdev, 14492 14492 const u8 *buf, size_t len, 14493 14493 enum nl80211_commands cmd, gfp_t gfp, 14494 - int uapsd_queues) 14494 + int uapsd_queues, const u8 *req_ies, 14495 + size_t req_ies_len) 14495 14496 { 14496 14497 struct sk_buff *msg; 14497 14498 void *hdr; 14498 14499 14499 - msg = nlmsg_new(100 + len, gfp); 14500 + msg = nlmsg_new(100 + len + req_ies_len, gfp); 14500 14501 if (!msg) 14501 14502 return; 14502 14503 ··· 14509 14508 14510 14509 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || 14511 14510 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || 14512 - nla_put(msg, NL80211_ATTR_FRAME, len, buf)) 14511 + nla_put(msg, NL80211_ATTR_FRAME, len, buf) || 14512 + (req_ies && 14513 + nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies))) 14513 14514 goto nla_put_failure; 14514 14515 14515 14516 if (uapsd_queues >= 0) { ··· 14542 14539 size_t len, gfp_t gfp) 14543 14540 { 14544 14541 nl80211_send_mlme_event(rdev, netdev, buf, len, 14545 - NL80211_CMD_AUTHENTICATE, gfp, -1); 14542 + NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0); 14546 14543 } 14547 14544 14548 14545 void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 14549 14546 struct net_device *netdev, const u8 *buf, 14550 - size_t len, gfp_t gfp, int uapsd_queues) 14547 + size_t len, gfp_t gfp, int uapsd_queues, 14548 + const u8 *req_ies, size_t req_ies_len) 14551 14549 { 14552 14550 nl80211_send_mlme_event(rdev, netdev, buf, len, 14553 - NL80211_CMD_ASSOCIATE, gfp, uapsd_queues); 14551 + NL80211_CMD_ASSOCIATE, gfp, uapsd_queues, 14552 + req_ies, req_ies_len); 14554 14553 } 14555 14554 14556 14555 void nl80211_send_deauth(struct cfg80211_registered_device *rdev, ··· 14560 14555 size_t len, gfp_t gfp) 14561 14556 { 14562 14557 nl80211_send_mlme_event(rdev, netdev, buf, len, 14563 - NL80211_CMD_DEAUTHENTICATE, gfp, -1); 14558 + NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0); 14564 14559 } 14565 14560 14566 14561 void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, ··· 14568 14563 size_t len, gfp_t gfp) 14569 14564 { 14570 14565 nl80211_send_mlme_event(rdev, netdev, buf, len, 14571 - NL80211_CMD_DISASSOCIATE, gfp, -1); 14566 + NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0); 14572 14567 } 14573 14568 14574 14569 void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, ··· 14589 14584 cmd = NL80211_CMD_UNPROT_DISASSOCIATE; 14590 14585 14591 14586 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); 14592 - nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1); 14587 + nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1, 14588 + NULL, 0); 14593 14589 } 14594 14590 EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); 14595 14591
+2 -1
net/wireless/nl80211.h
··· 67 67 void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 68 68 struct net_device *netdev, 69 69 const u8 *buf, size_t len, gfp_t gfp, 70 - int uapsd_queues); 70 + int uapsd_queues, 71 + const u8 *req_ies, size_t req_ies_len); 71 72 void nl80211_send_deauth(struct cfg80211_registered_device *rdev, 72 73 struct net_device *netdev, 73 74 const u8 *buf, size_t len, gfp_t gfp);