300-cfg80211-support-immediate-reconnect-request-hint.patch 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. From: Johannes Berg <[email protected]>
  2. Date: Sun, 6 Dec 2020 14:54:42 +0200
  3. Subject: [PATCH] cfg80211: support immediate reconnect request hint
  4. There are cases where it's necessary to disconnect, but an
  5. immediate reconnection is desired. Support a hint to userspace
  6. that this is the case, by including a new attribute in the
  7. deauth or disassoc event.
  8. Signed-off-by: Luca Coelho <[email protected]>
  9. Link: https://lore.kernel.org/r/iwlwifi.20201206145305.58d33941fb9d.I0e7168c205c7949529c8e3b86f3c9b12c01a7017@changeid
  10. Signed-off-by: Johannes Berg <[email protected]>
  11. ---
  12. --- a/include/net/cfg80211.h
  13. +++ b/include/net/cfg80211.h
  14. @@ -6410,13 +6410,15 @@ void cfg80211_abandon_assoc(struct net_d
  15. * @dev: network device
  16. * @buf: 802.11 frame (header + body)
  17. * @len: length of the frame data
  18. + * @reconnect: immediate reconnect is desired (include the nl80211 attribute)
  19. *
  20. * This function is called whenever deauthentication has been processed in
  21. * station mode. This includes both received deauthentication frames and
  22. * locally generated ones. This function may sleep. The caller must hold the
  23. * corresponding wdev's mutex.
  24. */
  25. -void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len);
  26. +void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
  27. + bool reconnect);
  28. /**
  29. * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
  30. --- a/net/mac80211/mlme.c
  31. +++ b/net/mac80211/mlme.c
  32. @@ -2725,7 +2725,7 @@ static void ieee80211_report_disconnect(
  33. };
  34. if (tx)
  35. - cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);
  36. + cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false);
  37. else
  38. cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
  39. @@ -4719,7 +4719,8 @@ void ieee80211_mgd_quiesce(struct ieee80
  40. if (ifmgd->auth_data)
  41. ieee80211_destroy_auth_data(sdata, false);
  42. cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
  43. - IEEE80211_DEAUTH_FRAME_LEN);
  44. + IEEE80211_DEAUTH_FRAME_LEN,
  45. + false);
  46. }
  47. /* This is a bit of a hack - we should find a better and more generic
  48. --- a/net/wireless/mlme.c
  49. +++ b/net/wireless/mlme.c
  50. @@ -4,7 +4,7 @@
  51. *
  52. * Copyright (c) 2009, Jouni Malinen <[email protected]>
  53. * Copyright (c) 2015 Intel Deutschland GmbH
  54. - * Copyright (C) 2019 Intel Corporation
  55. + * Copyright (C) 2019-2020 Intel Corporation
  56. */
  57. #include <linux/kernel.h>
  58. @@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct
  59. }
  60. static void cfg80211_process_deauth(struct wireless_dev *wdev,
  61. - const u8 *buf, size_t len)
  62. + const u8 *buf, size_t len,
  63. + bool reconnect)
  64. {
  65. struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
  66. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  67. @@ -89,7 +90,7 @@ static void cfg80211_process_deauth(stru
  68. u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
  69. bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
  70. - nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
  71. + nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL);
  72. if (!wdev->current_bss ||
  73. !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
  74. @@ -100,7 +101,8 @@ static void cfg80211_process_deauth(stru
  75. }
  76. static void cfg80211_process_disassoc(struct wireless_dev *wdev,
  77. - const u8 *buf, size_t len)
  78. + const u8 *buf, size_t len,
  79. + bool reconnect)
  80. {
  81. struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
  82. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  83. @@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(st
  84. u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
  85. bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
  86. - nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL);
  87. + nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect,
  88. + GFP_KERNEL);
  89. if (WARN_ON(!wdev->current_bss ||
  90. !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
  91. @@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_de
  92. if (ieee80211_is_auth(mgmt->frame_control))
  93. cfg80211_process_auth(wdev, buf, len);
  94. else if (ieee80211_is_deauth(mgmt->frame_control))
  95. - cfg80211_process_deauth(wdev, buf, len);
  96. + cfg80211_process_deauth(wdev, buf, len, false);
  97. else if (ieee80211_is_disassoc(mgmt->frame_control))
  98. - cfg80211_process_disassoc(wdev, buf, len);
  99. + cfg80211_process_disassoc(wdev, buf, len, false);
  100. }
  101. EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
  102. @@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_d
  103. }
  104. EXPORT_SYMBOL(cfg80211_abandon_assoc);
  105. -void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
  106. +void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
  107. + bool reconnect)
  108. {
  109. struct wireless_dev *wdev = dev->ieee80211_ptr;
  110. struct ieee80211_mgmt *mgmt = (void *)buf;
  111. ASSERT_WDEV_LOCK(wdev);
  112. - trace_cfg80211_tx_mlme_mgmt(dev, buf, len);
  113. + trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect);
  114. if (WARN_ON(len < 2))
  115. return;
  116. if (ieee80211_is_deauth(mgmt->frame_control))
  117. - cfg80211_process_deauth(wdev, buf, len);
  118. + cfg80211_process_deauth(wdev, buf, len, reconnect);
  119. else
  120. - cfg80211_process_disassoc(wdev, buf, len);
  121. + cfg80211_process_disassoc(wdev, buf, len, reconnect);
  122. }
  123. EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
  124. --- a/net/wireless/nl80211.c
  125. +++ b/net/wireless/nl80211.c
  126. @@ -736,6 +736,7 @@ static const struct nla_policy nl80211_p
  127. NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
  128. [NL80211_ATTR_S1G_CAPABILITY_MASK] =
  129. NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
  130. + [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
  131. };
  132. /* policy for the key attributes */
  133. @@ -15902,7 +15903,7 @@ static void nl80211_send_mlme_event(stru
  134. const u8 *buf, size_t len,
  135. enum nl80211_commands cmd, gfp_t gfp,
  136. int uapsd_queues, const u8 *req_ies,
  137. - size_t req_ies_len)
  138. + size_t req_ies_len, bool reconnect)
  139. {
  140. struct sk_buff *msg;
  141. void *hdr;
  142. @@ -15924,6 +15925,9 @@ static void nl80211_send_mlme_event(stru
  143. nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
  144. goto nla_put_failure;
  145. + if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
  146. + goto nla_put_failure;
  147. +
  148. if (uapsd_queues >= 0) {
  149. struct nlattr *nla_wmm =
  150. nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
  151. @@ -15952,7 +15956,8 @@ void nl80211_send_rx_auth(struct cfg8021
  152. size_t len, gfp_t gfp)
  153. {
  154. nl80211_send_mlme_event(rdev, netdev, buf, len,
  155. - NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
  156. + NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
  157. + false);
  158. }
  159. void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
  160. @@ -15962,23 +15967,25 @@ void nl80211_send_rx_assoc(struct cfg802
  161. {
  162. nl80211_send_mlme_event(rdev, netdev, buf, len,
  163. NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
  164. - req_ies, req_ies_len);
  165. + req_ies, req_ies_len, false);
  166. }
  167. void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
  168. struct net_device *netdev, const u8 *buf,
  169. - size_t len, gfp_t gfp)
  170. + size_t len, bool reconnect, gfp_t gfp)
  171. {
  172. nl80211_send_mlme_event(rdev, netdev, buf, len,
  173. - NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
  174. + NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
  175. + reconnect);
  176. }
  177. void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
  178. struct net_device *netdev, const u8 *buf,
  179. - size_t len, gfp_t gfp)
  180. + size_t len, bool reconnect, gfp_t gfp)
  181. {
  182. nl80211_send_mlme_event(rdev, netdev, buf, len,
  183. - NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
  184. + NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
  185. + reconnect);
  186. }
  187. void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
  188. @@ -16009,7 +16016,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct
  189. trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
  190. nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
  191. - NULL, 0);
  192. + NULL, 0, false);
  193. }
  194. EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
  195. --- a/net/wireless/nl80211.h
  196. +++ b/net/wireless/nl80211.h
  197. @@ -1,7 +1,7 @@
  198. /* SPDX-License-Identifier: GPL-2.0 */
  199. /*
  200. * Portions of this file
  201. - * Copyright (C) 2018 Intel Corporation
  202. + * Copyright (C) 2018, 2020 Intel Corporation
  203. */
  204. #ifndef __NET_WIRELESS_NL80211_H
  205. #define __NET_WIRELESS_NL80211_H
  206. @@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg802
  207. const u8 *req_ies, size_t req_ies_len);
  208. void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
  209. struct net_device *netdev,
  210. - const u8 *buf, size_t len, gfp_t gfp);
  211. + const u8 *buf, size_t len,
  212. + bool reconnect, gfp_t gfp);
  213. void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
  214. struct net_device *netdev,
  215. - const u8 *buf, size_t len, gfp_t gfp);
  216. + const u8 *buf, size_t len,
  217. + bool reconnect, gfp_t gfp);
  218. void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
  219. struct net_device *netdev,
  220. const u8 *addr, gfp_t gfp);
  221. --- a/net/wireless/trace.h
  222. +++ b/net/wireless/trace.h
  223. @@ -2684,19 +2684,23 @@ DEFINE_EVENT(netdev_frame_event, cfg8021
  224. );
  225. TRACE_EVENT(cfg80211_tx_mlme_mgmt,
  226. - TP_PROTO(struct net_device *netdev, const u8 *buf, int len),
  227. - TP_ARGS(netdev, buf, len),
  228. + TP_PROTO(struct net_device *netdev, const u8 *buf, int len,
  229. + bool reconnect),
  230. + TP_ARGS(netdev, buf, len, reconnect),
  231. TP_STRUCT__entry(
  232. NETDEV_ENTRY
  233. __dynamic_array(u8, frame, len)
  234. + __field(int, reconnect)
  235. ),
  236. TP_fast_assign(
  237. NETDEV_ASSIGN;
  238. memcpy(__get_dynamic_array(frame), buf, len);
  239. + __entry->reconnect = reconnect;
  240. ),
  241. - TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x",
  242. + TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d",
  243. NETDEV_PR_ARG,
  244. - le16_to_cpup((__le16 *)__get_dynamic_array(frame)))
  245. + le16_to_cpup((__le16 *)__get_dynamic_array(frame)),
  246. + __entry->reconnect)
  247. );
  248. DECLARE_EVENT_CLASS(netdev_mac_evt,