551-wpa_supplicant-Add-Multi-AP-protocol-support-to-supp.patch 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. From 5abc7823bd01f69b8afbe1fd19f65fff86137c44 Mon Sep 17 00:00:00 2001
  2. From: Venkateswara Naralasetty <[email protected]>
  3. Date: Wed, 5 Dec 2018 11:23:53 +0100
  4. Subject: [PATCH] wpa_supplicant: Add Multi-AP backhaul STA support
  5. Advertise vendor specific Multi-AP IE in (Re)Association Request frames
  6. and process Multi-AP IE from (Re)Association Response frames if the user
  7. enables Multi-AP fuctionality. If the (Re)Association Response frame
  8. does not contain the Multi-AP IE, disassociate.
  9. This adds a new configuration parameter 'multi_ap_backhaul_sta' to
  10. enable/disable Multi-AP functionality.
  11. Enable 4-address mode after association (if the Association Response
  12. frame contains the Multi-AP IE). Also enable the bridge in that case.
  13. This is necessary because wpa_supplicant only enables the bridge in
  14. wpa_drv_if_add(), which only gets called when an interface is added
  15. through the control interface, not when it is configured from the
  16. command line.
  17. Signed-off-by: Venkateswara Naralasetty <[email protected]>
  18. Signed-off-by: Jouni Malinen <[email protected]>
  19. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <[email protected]>
  20. ---
  21. src/drivers/driver.h | 9 ++++++
  22. src/drivers/driver_nl80211.c | 44 ++++++++++++++++++++++++++
  23. wpa_supplicant/config.c | 1 +
  24. wpa_supplicant/config_ssid.h | 7 +++++
  25. wpa_supplicant/driver_i.h | 8 +++++
  26. wpa_supplicant/events.c | 50 ++++++++++++++++++++++++++++++
  27. wpa_supplicant/sme.c | 16 ++++++++++
  28. wpa_supplicant/wpa_supplicant.c | 18 +++++++++++
  29. wpa_supplicant/wpa_supplicant.conf | 7 +++++
  30. wpa_supplicant/wpa_supplicant_i.h | 1 +
  31. 10 files changed, 161 insertions(+)
  32. --- a/src/drivers/driver.h
  33. +++ b/src/drivers/driver.h
  34. @@ -4100,6 +4100,15 @@ struct wpa_driver_ops {
  35. */
  36. int (*send_external_auth_status)(void *priv,
  37. struct external_auth *params);
  38. +
  39. + /**
  40. + * set_4addr_mode - Set 4-address mode
  41. + * @priv: Private driver interface data
  42. + * @bridge_ifname: Bridge interface name
  43. + * @val: 0 - disable 4addr mode, 1 - enable 4addr mode
  44. + * Returns: 0 on success, < 0 on failure
  45. + */
  46. + int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val);
  47. };
  48. /**
  49. --- a/src/drivers/driver_nl80211.c
  50. +++ b/src/drivers/driver_nl80211.c
  51. @@ -10728,6 +10728,49 @@ fail:
  52. }
  53. +static int nl80211_set_4addr_mode(void *priv, const char *bridge_ifname,
  54. + int val)
  55. +{
  56. + struct i802_bss *bss = priv;
  57. + struct wpa_driver_nl80211_data *drv = bss->drv;
  58. + struct nl_msg *msg;
  59. + int ret = -ENOBUFS;
  60. +
  61. + wpa_printf(MSG_DEBUG, "nl80211: %s 4addr mode (bridge_ifname: %s)",
  62. + val ? "Enable" : "Disable", bridge_ifname);
  63. +
  64. + msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE);
  65. + if (!msg || nla_put_u8(msg, NL80211_ATTR_4ADDR, val))
  66. + goto fail;
  67. +
  68. + if (bridge_ifname[0] && bss->added_if_into_bridge && !val) {
  69. + if (linux_br_del_if(drv->global->ioctl_sock,
  70. + bridge_ifname, bss->ifname)) {
  71. + wpa_printf(MSG_ERROR,
  72. + "nl80211: Failed to remove interface %s from bridge %s",
  73. + bss->ifname, bridge_ifname);
  74. + return -1;
  75. + }
  76. + bss->added_if_into_bridge = 0;
  77. + }
  78. +
  79. + ret = send_and_recv_msgs(drv, msg, NULL, NULL);
  80. + msg = NULL;
  81. + if (!ret) {
  82. + if (bridge_ifname[0] && val &&
  83. + i802_check_bridge(drv, bss, bridge_ifname, bss->ifname) < 0)
  84. + return -1;
  85. + return 0;
  86. + }
  87. +
  88. +fail:
  89. + nlmsg_free(msg);
  90. + wpa_printf(MSG_ERROR, "nl80211: Failed to enable/disable 4addr");
  91. +
  92. + return ret;
  93. +}
  94. +
  95. +
  96. const struct wpa_driver_ops wpa_driver_nl80211_ops = {
  97. .name = "nl80211",
  98. .desc = "Linux nl80211/cfg80211",
  99. @@ -10856,4 +10899,5 @@ const struct wpa_driver_ops wpa_driver_n
  100. .get_ext_capab = nl80211_get_ext_capab,
  101. .update_connect_params = nl80211_update_connection_params,
  102. .send_external_auth_status = nl80211_send_external_auth_status,
  103. + .set_4addr_mode = nl80211_set_4addr_mode,
  104. };
  105. --- a/wpa_supplicant/config.c
  106. +++ b/wpa_supplicant/config.c
  107. @@ -2416,6 +2416,7 @@ static const struct parse_data ssid_fiel
  108. #endif /* CONFIG_DPP */
  109. { INT_RANGE(owe_group, 0, 65535) },
  110. { INT_RANGE(owe_only, 0, 1) },
  111. + { INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
  112. };
  113. #undef OFFSET
  114. --- a/wpa_supplicant/config_ssid.h
  115. +++ b/wpa_supplicant/config_ssid.h
  116. @@ -950,6 +950,13 @@ struct wpa_ssid {
  117. * the selection attempts for OWE BSS exceed the configured threshold.
  118. */
  119. int owe_transition_bss_select_count;
  120. +
  121. + /**
  122. + * multi_ap_backhaul_sta - Multi-AP backhaul STA
  123. + * 0 = normal (non-Multi-AP) station
  124. + * 1 = Multi-AP backhaul station
  125. + */
  126. + int multi_ap_backhaul_sta;
  127. };
  128. #endif /* CONFIG_SSID_H */
  129. --- a/wpa_supplicant/driver_i.h
  130. +++ b/wpa_supplicant/driver_i.h
  131. @@ -1046,4 +1046,12 @@ wpa_drv_send_external_auth_status(struct
  132. params);
  133. }
  134. +static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val)
  135. +{
  136. + if (!wpa_s->driver->set_4addr_mode)
  137. + return -1;
  138. + return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv,
  139. + wpa_s->bridge_ifname, val);
  140. +}
  141. +
  142. #endif /* DRIVER_I_H */
  143. --- a/wpa_supplicant/events.c
  144. +++ b/wpa_supplicant/events.c
  145. @@ -324,6 +324,9 @@ void wpa_supplicant_mark_disassoc(struct
  146. os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk));
  147. #endif /* CONFIG_TESTING_OPTIONS */
  148. wpa_s->ieee80211ac = 0;
  149. +
  150. + if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
  151. + wpa_s->enabled_4addr_mode = 0;
  152. }
  153. @@ -2267,6 +2270,50 @@ static void interworking_process_assoc_r
  154. #endif /* CONFIG_INTERWORKING */
  155. +static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
  156. + const u8 *ies, size_t ies_len)
  157. +{
  158. + struct ieee802_11_elems elems;
  159. + const u8 *map_sub_elem, *pos;
  160. + size_t len;
  161. +
  162. + if (!wpa_s->current_ssid ||
  163. + !wpa_s->current_ssid->multi_ap_backhaul_sta ||
  164. + !ies ||
  165. + ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
  166. + return;
  167. +
  168. + if (!elems.multi_ap || elems.multi_ap_len < 7) {
  169. + wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
  170. + goto fail;
  171. + }
  172. +
  173. + pos = elems.multi_ap + 4;
  174. + len = elems.multi_ap_len - 4;
  175. +
  176. + map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
  177. + if (!map_sub_elem || map_sub_elem[1] < 1) {
  178. + wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
  179. + goto fail;
  180. + }
  181. +
  182. + if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
  183. + wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS");
  184. + goto fail;
  185. + }
  186. +
  187. + if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) {
  188. + wpa_printf(MSG_ERROR, "Failed to set 4addr mode");
  189. + goto fail;
  190. + }
  191. + wpa_s->enabled_4addr_mode = 1;
  192. + return;
  193. +
  194. +fail:
  195. + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
  196. +}
  197. +
  198. +
  199. #ifdef CONFIG_FST
  200. static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
  201. const u8 *ie, size_t ie_len)
  202. @@ -2343,6 +2390,9 @@ static int wpa_supplicant_event_associnf
  203. get_ie(data->assoc_info.resp_ies,
  204. data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
  205. wpa_s->ieee80211ac = 1;
  206. +
  207. + multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
  208. + data->assoc_info.resp_ies_len);
  209. }
  210. if (data->assoc_info.beacon_ies)
  211. wpa_hexdump(MSG_DEBUG, "beacon_ies",
  212. --- a/wpa_supplicant/sme.c
  213. +++ b/wpa_supplicant/sme.c
  214. @@ -1552,6 +1552,22 @@ void sme_associate(struct wpa_supplicant
  215. }
  216. #endif /* CONFIG_OWE */
  217. + if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
  218. + size_t multi_ap_ie_len;
  219. +
  220. + multi_ap_ie_len = add_multi_ap_ie(
  221. + wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
  222. + sizeof(wpa_s->sme.assoc_req_ie) -
  223. + wpa_s->sme.assoc_req_ie_len,
  224. + MULTI_AP_BACKHAUL_STA);
  225. + if (multi_ap_ie_len == 0) {
  226. + wpa_printf(MSG_ERROR,
  227. + "Multi-AP: Failed to build Multi-AP IE");
  228. + return;
  229. + }
  230. + wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
  231. + }
  232. +
  233. params.bssid = bssid;
  234. params.ssid = wpa_s->sme.ssid;
  235. params.ssid_len = wpa_s->sme.ssid_len;
  236. --- a/wpa_supplicant/wpa_supplicant.c
  237. +++ b/wpa_supplicant/wpa_supplicant.c
  238. @@ -2893,6 +2893,21 @@ static u8 * wpas_populate_assoc_ies(
  239. }
  240. #endif /* CONFIG_IEEE80211R */
  241. + if (ssid->multi_ap_backhaul_sta) {
  242. + size_t multi_ap_ie_len;
  243. +
  244. + multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
  245. + max_wpa_ie_len - wpa_ie_len,
  246. + MULTI_AP_BACKHAUL_STA);
  247. + if (multi_ap_ie_len == 0) {
  248. + wpa_printf(MSG_ERROR,
  249. + "Multi-AP: Failed to build Multi-AP IE");
  250. + os_free(wpa_ie);
  251. + return NULL;
  252. + }
  253. + wpa_ie_len += multi_ap_ie_len;
  254. + }
  255. +
  256. params->wpa_ie = wpa_ie;
  257. params->wpa_ie_len = wpa_ie_len;
  258. params->auth_alg = algs;
  259. @@ -3377,6 +3392,9 @@ void wpa_supplicant_deauthenticate(struc
  260. zero_addr = 1;
  261. }
  262. + if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
  263. + wpa_s->enabled_4addr_mode = 0;
  264. +
  265. #ifdef CONFIG_TDLS
  266. wpa_tdls_teardown_peers(wpa_s->wpa);
  267. #endif /* CONFIG_TDLS */
  268. --- a/wpa_supplicant/wpa_supplicant.conf
  269. +++ b/wpa_supplicant/wpa_supplicant.conf
  270. @@ -1399,6 +1399,13 @@ fast_reauth=1
  271. # 2: MCS 0-9
  272. # 3: not supported
  273. +# multi_ap_backhaul_sta: Multi-AP backhaul STA functionality
  274. +# 0 = normal STA (default)
  275. +# 1 = backhaul STA
  276. +# A backhaul STA sends the Multi-AP IE, fails to associate if the AP does not
  277. +# support Multi-AP, and sets 4-address mode if it does. Thus, the netdev can be
  278. +# added to a bridge to allow forwarding frames over this backhaul link.
  279. +
  280. ##### Fast Session Transfer (FST) support #####################################
  281. #
  282. # The options in this section are only available when the build configuration
  283. --- a/wpa_supplicant/wpa_supplicant_i.h
  284. +++ b/wpa_supplicant/wpa_supplicant_i.h
  285. @@ -1242,6 +1242,7 @@ struct wpa_supplicant {
  286. unsigned int disable_fils:1;
  287. #endif /* CONFIG_FILS */
  288. unsigned int ieee80211ac:1;
  289. + unsigned int enabled_4addr_mode:1;
  290. };