History

cfg80211: support immediate reconnect request hint

There are cases where it's necessary to disconnect, but an immediate reconnection is desired. Support a hint to userspace that this is the case, by including a new attribute in the deauth or disassoc event.

Johannes Berg committed 5 years ago

Commit 3bb02141 parent a5a55037 files · +55 −29Browse files

Unified · Split

7 files
  1. include/net/cfg80211.h +3 −1
  2. include/uapi/linux/nl80211.h +6 −0
  3. net/mac80211/mlme.c +3 −2
  4. net/wireless/mlme.c +15 −11
  5. net/wireless/nl80211.c +15 −8
  6. net/wireless/nl80211.h +5 −3
  7. net/wireless/trace.h +8 −4
include/net/cfg80211.h+3−1
@@ -6406,13 +6406,15 @@ void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss); · 6405 unmodified lines
6406 * @dev: network device6406 * @dev: network device
6407 * @buf: 802.11 frame (header + body)6407 * @buf: 802.11 frame (header + body)
6408 * @len: length of the frame data6408 * @len: length of the frame data
6409 * @reconnect: immediate reconnect is desired (include the nl80211 attribute)
6409 *6410 *
6410 * This function is called whenever deauthentication has been processed in6411 * This function is called whenever deauthentication has been processed in
6411 * station mode. This includes both received deauthentication frames and6412 * station mode. This includes both received deauthentication frames and
6412 * locally generated ones. This function may sleep. The caller must hold the6413 * locally generated ones. This function may sleep. The caller must hold the
6413 * corresponding wdev's mutex.6414 * corresponding wdev's mutex.
6414 */6415 */
6415void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len);6416void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
6417 bool reconnect);
6416 6418
6417/**6419/**
6418 * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame6420 * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
include/uapi/linux/nl80211.h+6−0
@@ -2535,6 +2535,10 @@ enum nl80211_commands { · 2534 unmodified lines
2535 * This is a u8 attribute that encapsulates one of the values from2535 * This is a u8 attribute that encapsulates one of the values from
2536 * &enum nl80211_sae_pwe_mechanism.2536 * &enum nl80211_sae_pwe_mechanism.
2537 *2537 *
2538 * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and
2539 * disassoc events to indicate that an immediate reconnect to the AP
2540 * is desired.
2541 *
2538 * @NUM_NL80211_ATTR: total number of nl80211_attrs available2542 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
2539 * @NL80211_ATTR_MAX: highest attribute number currently defined2543 * @NL80211_ATTR_MAX: highest attribute number currently defined
2540 * @__NL80211_ATTR_AFTER_LAST: internal use2544 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3026,6 +3030,8 @@ enum nl80211_attrs { · 485 unmodified lines
3026 3030
3027 NL80211_ATTR_SAE_PWE,3031 NL80211_ATTR_SAE_PWE,
3028 3032
3033 NL80211_ATTR_RECONNECT_REQUESTED,
3034
3029 /* add attributes here, update the policy in nl80211.c */3035 /* add attributes here, update the policy in nl80211.c */
3030 3036
3031 __NL80211_ATTR_AFTER_LAST,3037 __NL80211_ATTR_AFTER_LAST,
net/mac80211/mlme.c+3−2
@@ -2741,7 +2741,7 @@ static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, · 2740 unmodified lines
2741 };2741 };
2742 2742
2743 if (tx)2743 if (tx)
2744 cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);2744 cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false);
2745 else2745 else
2746 cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);2746 cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
2747 2747
@@ -4721,7 +4721,8 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) · 1973 unmodified lines
4721 if (ifmgd->auth_data)4721 if (ifmgd->auth_data)
4722 ieee80211_destroy_auth_data(sdata, false);4722 ieee80211_destroy_auth_data(sdata, false);
4723 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,4723 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4724 IEEE80211_DEAUTH_FRAME_LEN);4724 IEEE80211_DEAUTH_FRAME_LEN,
4725 false);
4725 }4726 }
4726 4727
4727 /* This is a bit of a hack - we should find a better and more generic4728 /* This is a bit of a hack - we should find a better and more generic
net/wireless/mlme.c+15−11
@@ -4,7 +4,7 @@ · 3 unmodified lines
4 *4 *
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 * Copyright (c) 2015 Intel Deutschland GmbH6 * Copyright (c) 2015 Intel Deutschland GmbH
7 * Copyright (C) 2019 Intel Corporation7 * Copyright (C) 2019-2020 Intel Corporation
8 */8 */
9 9
10#include <linux/kernel.h>10#include <linux/kernel.h>
@@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct wireless_dev *wdev, · 70 unmodified lines
81}81}
82 82
83static void cfg80211_process_deauth(struct wireless_dev *wdev,83static void cfg80211_process_deauth(struct wireless_dev *wdev,
84 const u8 *buf, size_t len)84 const u8 *buf, size_t len,
85 bool reconnect)
85{86{
86 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);87 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
87 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;88 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
@@ -89,7 +90,7 @@ static void cfg80211_process_deauth(struct wireless_dev *wdev, · 1 unmodified line
89 u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);90 u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
90 bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);91 bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
91 92
92 nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL);93 nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL);
93 94
94 if (!wdev->current_bss ||95 if (!wdev->current_bss ||
95 !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))96 !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
@@ -100,7 +101,8 @@ static void cfg80211_process_deauth(struct wireless_dev *wdev, · 4 unmodified lines
100}101}
101 102
102static void cfg80211_process_disassoc(struct wireless_dev *wdev,103static void cfg80211_process_disassoc(struct wireless_dev *wdev,
103 const u8 *buf, size_t len)104 const u8 *buf, size_t len,
105 bool reconnect)
104{106{
105 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);107 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
106 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;108 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
@@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(struct wireless_dev *wdev, · 1 unmodified line
108 u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);110 u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
109 bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);111 bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
110 112
111 nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL);113 nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect,
114 GFP_KERNEL);
112 115
113 if (WARN_ON(!wdev->current_bss ||116 if (WARN_ON(!wdev->current_bss ||
114 !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))117 !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
@@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) · 18 unmodified lines
133 if (ieee80211_is_auth(mgmt->frame_control))136 if (ieee80211_is_auth(mgmt->frame_control))
134 cfg80211_process_auth(wdev, buf, len);137 cfg80211_process_auth(wdev, buf, len);
135 else if (ieee80211_is_deauth(mgmt->frame_control))138 else if (ieee80211_is_deauth(mgmt->frame_control))
136 cfg80211_process_deauth(wdev, buf, len);139 cfg80211_process_deauth(wdev, buf, len, false);
137 else if (ieee80211_is_disassoc(mgmt->frame_control))140 else if (ieee80211_is_disassoc(mgmt->frame_control))
138 cfg80211_process_disassoc(wdev, buf, len);141 cfg80211_process_disassoc(wdev, buf, len, false);
139}142}
140EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);143EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
141 144
@@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss) · 38 unmodified lines
180}183}
181EXPORT_SYMBOL(cfg80211_abandon_assoc);184EXPORT_SYMBOL(cfg80211_abandon_assoc);
182 185
183void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)186void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
187 bool reconnect)
184{188{
185 struct wireless_dev *wdev = dev->ieee80211_ptr;189 struct wireless_dev *wdev = dev->ieee80211_ptr;
186 struct ieee80211_mgmt *mgmt = (void *)buf;190 struct ieee80211_mgmt *mgmt = (void *)buf;
187 191
188 ASSERT_WDEV_LOCK(wdev);192 ASSERT_WDEV_LOCK(wdev);
189 193
190 trace_cfg80211_tx_mlme_mgmt(dev, buf, len);194 trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect);
191 195
192 if (WARN_ON(len < 2))196 if (WARN_ON(len < 2))
193 return;197 return;
194 198
195 if (ieee80211_is_deauth(mgmt->frame_control))199 if (ieee80211_is_deauth(mgmt->frame_control))
196 cfg80211_process_deauth(wdev, buf, len);200 cfg80211_process_deauth(wdev, buf, len, reconnect);
197 else201 else
198 cfg80211_process_disassoc(wdev, buf, len);202 cfg80211_process_disassoc(wdev, buf, len, reconnect);
199}203}
200EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);204EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
201 205
net/wireless/nl80211.c+15−8
@@ -718,6 +718,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 717 unmodified lines
718 [NL80211_ATTR_SAE_PWE] =718 [NL80211_ATTR_SAE_PWE] =
719 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,719 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
720 NL80211_SAE_PWE_BOTH),720 NL80211_SAE_PWE_BOTH),
721 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
721};722};
722 723
723/* policy for the key attributes */724/* policy for the key attributes */
@@ -15855,7 +15856,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, · 15131 unmodified lines
15855 const u8 *buf, size_t len,15856 const u8 *buf, size_t len,
15856 enum nl80211_commands cmd, gfp_t gfp,15857 enum nl80211_commands cmd, gfp_t gfp,
15857 int uapsd_queues, const u8 *req_ies,15858 int uapsd_queues, const u8 *req_ies,
15858 size_t req_ies_len)15859 size_t req_ies_len, bool reconnect)
15859{15860{
15860 struct sk_buff *msg;15861 struct sk_buff *msg;
15861 void *hdr;15862 void *hdr;
@@ -15877,6 +15878,9 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, · 15 unmodified lines
15877 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))15878 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
15878 goto nla_put_failure;15879 goto nla_put_failure;
15879 15880
15881 if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
15882 goto nla_put_failure;
15883
15880 if (uapsd_queues >= 0) {15884 if (uapsd_queues >= 0) {
15881 struct nlattr *nla_wmm =15885 struct nlattr *nla_wmm =
15882 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);15886 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
@@ -15905,7 +15909,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, · 22 unmodified lines
15905 size_t len, gfp_t gfp)15909 size_t len, gfp_t gfp)
15906{15910{
15907 nl80211_send_mlme_event(rdev, netdev, buf, len,15911 nl80211_send_mlme_event(rdev, netdev, buf, len,
15908 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);15912 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
15913 false);
15909}15914}
15910 15915
15911void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,15916void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
@@ -15915,23 +15920,25 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, · 3 unmodified lines
15915{15920{
15916 nl80211_send_mlme_event(rdev, netdev, buf, len,15921 nl80211_send_mlme_event(rdev, netdev, buf, len,
15917 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,15922 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
15918 req_ies, req_ies_len);15923 req_ies, req_ies_len, false);
15919}15924}
15920 15925
15921void nl80211_send_deauth(struct cfg80211_registered_device *rdev,15926void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
15922 struct net_device *netdev, const u8 *buf,15927 struct net_device *netdev, const u8 *buf,
15923 size_t len, gfp_t gfp)15928 size_t len, bool reconnect, gfp_t gfp)
15924{15929{
15925 nl80211_send_mlme_event(rdev, netdev, buf, len,15930 nl80211_send_mlme_event(rdev, netdev, buf, len,
15926 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);15931 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
15932 reconnect);
15927}15933}
15928 15934
15929void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,15935void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
15930 struct net_device *netdev, const u8 *buf,15936 struct net_device *netdev, const u8 *buf,
15931 size_t len, gfp_t gfp)15937 size_t len, bool reconnect, gfp_t gfp)
15932{15938{
15933 nl80211_send_mlme_event(rdev, netdev, buf, len,15939 nl80211_send_mlme_event(rdev, netdev, buf, len,
15934 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);15940 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
15941 reconnect);
15935}15942}
15936 15943
15937void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,15944void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
@@ -15962,7 +15969,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, · 24 unmodified lines
15962 15969
15963 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);15970 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
15964 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,15971 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
15965 NULL, 0);15972 NULL, 0, false);
15966}15973}
15967EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);15974EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
15968 15975
net/wireless/nl80211.h+5−3
@@ -1,7 +1,7 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*2/*
3 * Portions of this file3 * Portions of this file
4 * Copyright (C) 2018 Intel Corporation4 * Copyright (C) 2018, 2020 Intel Corporation
5 */5 */
6#ifndef __NET_WIRELESS_NL80211_H6#ifndef __NET_WIRELESS_NL80211_H
7#define __NET_WIRELESS_NL80211_H7#define __NET_WIRELESS_NL80211_H
@@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, · 61 unmodified lines
69 const u8 *req_ies, size_t req_ies_len);69 const u8 *req_ies, size_t req_ies_len);
70void nl80211_send_deauth(struct cfg80211_registered_device *rdev,70void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
71 struct net_device *netdev,71 struct net_device *netdev,
72 const u8 *buf, size_t len, gfp_t gfp);72 const u8 *buf, size_t len,
73 bool reconnect, gfp_t gfp);
73void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,74void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
74 struct net_device *netdev,75 struct net_device *netdev,
75 const u8 *buf, size_t len, gfp_t gfp);76 const u8 *buf, size_t len,
77 bool reconnect, gfp_t gfp);
76void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,78void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
77 struct net_device *netdev,79 struct net_device *netdev,
78 const u8 *addr, gfp_t gfp);80 const u8 *addr, gfp_t gfp);
net/wireless/trace.h+8−4
@@ -2679,19 +2679,23 @@ DEFINE_EVENT(netdev_frame_event, cfg80211_rx_mlme_mgmt, · 2678 unmodified lines
2679);2679);
2680 2680
2681TRACE_EVENT(cfg80211_tx_mlme_mgmt,2681TRACE_EVENT(cfg80211_tx_mlme_mgmt,
2682 TP_PROTO(struct net_device *netdev, const u8 *buf, int len),2682 TP_PROTO(struct net_device *netdev, const u8 *buf, int len,
2683 TP_ARGS(netdev, buf, len),2683 bool reconnect),
2684 TP_ARGS(netdev, buf, len, reconnect),
2684 TP_STRUCT__entry(2685 TP_STRUCT__entry(
2685 NETDEV_ENTRY2686 NETDEV_ENTRY
2686 __dynamic_array(u8, frame, len)2687 __dynamic_array(u8, frame, len)
2688 __field(int, reconnect)
2687 ),2689 ),
2688 TP_fast_assign(2690 TP_fast_assign(
2689 NETDEV_ASSIGN;2691 NETDEV_ASSIGN;
2690 memcpy(__get_dynamic_array(frame), buf, len);2692 memcpy(__get_dynamic_array(frame), buf, len);
2693 __entry->reconnect = reconnect;
2691 ),2694 ),
2692 TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x",2695 TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d",
2693 NETDEV_PR_ARG,2696 NETDEV_PR_ARG,
2694 le16_to_cpup((__le16 *)__get_dynamic_array(frame)))2697 le16_to_cpup((__le16 *)__get_dynamic_array(frame)),
2698 __entry->reconnect)
2695);2699);
2696 2700
2697DECLARE_EVENT_CLASS(netdev_mac_evt,2701DECLARE_EVENT_CLASS(netdev_mac_evt,