550-hostapd-Add-Multi-AP-protocol-support.patch 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. From 9c06f0f6aed26c1628acaa74df0232dd7b345e9a Mon Sep 17 00:00:00 2001
  2. From: Venkateswara Naralasetty <[email protected]>
  3. Date: Wed, 5 Dec 2018 11:23:51 +0100
  4. Subject: [PATCH] hostapd: Add Multi-AP protocol support
  5. The purpose of Multi-AP specification is to enable inter-operability
  6. across Wi-Fi access points (APs) from different vendors.
  7. This patch introduces one new configuration parameter 'multi_ap' to
  8. enable Multi-AP functionality and to configure the BSS as a backhaul
  9. and/or fronthaul BSS.
  10. Advertise vendor specific Multi-AP capabilities in (Re)Association
  11. Response frame, if Multi-AP functionality is enabled through the
  12. configuration parameter.
  13. A backhaul AP must support receiving both 3addr and 4addr frames from a
  14. backhaul STA, so create a VLAN for it just like is done for WDS, i.e.,
  15. by calling hostapd_set_wds_sta(). Since Multi-AP requires WPA2 (never
  16. WEP), we can safely call hostapd_set_wds_encryption() as well and we can
  17. reuse the entire WDS condition.
  18. To parse the Multi-AP Extension subelement, we use get_ie(): even though
  19. that function is meant for parsing IEs, it works for subelements.
  20. Signed-off-by: Venkateswara Naralasetty <[email protected]>
  21. Signed-off-by: Jouni Malinen <[email protected]>
  22. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <[email protected]>
  23. ---
  24. hostapd/config_file.c | 10 +++++
  25. hostapd/hostapd.conf | 7 ++++
  26. src/ap/ap_config.h | 4 ++
  27. src/ap/ieee802_11.c | 77 +++++++++++++++++++++++++++++++++-
  28. src/ap/sta_info.c | 2 +-
  29. src/ap/sta_info.h | 1 +
  30. src/common/ieee802_11_common.c | 24 +++++++++++
  31. src/common/ieee802_11_common.h | 4 ++
  32. src/common/ieee802_11_defs.h | 7 ++++
  33. 9 files changed, 134 insertions(+), 2 deletions(-)
  34. --- a/hostapd/config_file.c
  35. +++ b/hostapd/config_file.c
  36. @@ -4115,6 +4115,16 @@ static int hostapd_config_fill(struct ho
  37. } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
  38. bss->coloc_intf_reporting = atoi(pos);
  39. #endif /* CONFIG_OWE */
  40. + } else if (os_strcmp(buf, "multi_ap") == 0) {
  41. + int val = atoi(pos);
  42. +
  43. + if (val < 0 || val > 3) {
  44. + wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'",
  45. + line, buf);
  46. + return -1;
  47. + }
  48. +
  49. + bss->multi_ap = val;
  50. } else {
  51. wpa_printf(MSG_ERROR,
  52. "Line %d: unknown configuration item '%s'",
  53. --- a/hostapd/hostapd.conf
  54. +++ b/hostapd/hostapd.conf
  55. @@ -438,6 +438,13 @@ wmm_ac_vo_txop_limit=47
  56. wmm_ac_vo_acm=0
  57. # Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
  58. +# Enable Multi-AP functionality
  59. +# 0 = disabled (default)
  60. +# 1 = AP support backhaul BSS
  61. +# 2 = AP support fronthaul BSS
  62. +# 3 = AP supports both backhaul BSS and fronthaul BSS
  63. +#multi_ap=0
  64. +
  65. # Static WEP key configuration
  66. #
  67. # The key number to use when transmitting.
  68. --- a/src/ap/ap_config.h
  69. +++ b/src/ap/ap_config.h
  70. @@ -688,6 +688,10 @@ struct hostapd_bss_config {
  71. #endif /* CONFIG_OWE */
  72. int coloc_intf_reporting;
  73. +
  74. +#define BACKHAUL_BSS 1
  75. +#define FRONTHAUL_BSS 2
  76. + int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
  77. };
  78. /**
  79. --- a/src/ap/ieee802_11.c
  80. +++ b/src/ap/ieee802_11.c
  81. @@ -62,6 +62,22 @@ prepare_auth_resp_fils(struct hostapd_da
  82. int *is_pub);
  83. #endif /* CONFIG_FILS */
  84. +
  85. +u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
  86. +{
  87. + u8 multi_ap_val = 0;
  88. +
  89. + if (!hapd->conf->multi_ap)
  90. + return eid;
  91. + if (hapd->conf->multi_ap & BACKHAUL_BSS)
  92. + multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
  93. + if (hapd->conf->multi_ap & FRONTHAUL_BSS)
  94. + multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
  95. +
  96. + return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
  97. +}
  98. +
  99. +
  100. u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
  101. {
  102. u8 *pos = eid;
  103. @@ -2210,6 +2226,57 @@ static u16 check_wmm(struct hostapd_data
  104. return WLAN_STATUS_SUCCESS;
  105. }
  106. +static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
  107. + const u8 *multi_ap_ie, size_t multi_ap_len)
  108. +{
  109. + u8 multi_ap_value = 0;
  110. +
  111. + sta->flags &= ~WLAN_STA_MULTI_AP;
  112. +
  113. + if (!hapd->conf->multi_ap)
  114. + return WLAN_STATUS_SUCCESS;
  115. +
  116. + if (multi_ap_ie) {
  117. + const u8 *multi_ap_subelem;
  118. +
  119. + multi_ap_subelem = get_ie(multi_ap_ie + 4,
  120. + multi_ap_len - 4,
  121. + MULTI_AP_SUB_ELEM_TYPE);
  122. + if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
  123. + multi_ap_value = multi_ap_subelem[2];
  124. + } else {
  125. + hostapd_logger(hapd, sta->addr,
  126. + HOSTAPD_MODULE_IEEE80211,
  127. + HOSTAPD_LEVEL_INFO,
  128. + "Multi-AP IE has missing or invalid Multi-AP subelement");
  129. + return WLAN_STATUS_INVALID_IE;
  130. + }
  131. + }
  132. +
  133. + if (multi_ap_value == MULTI_AP_BACKHAUL_STA)
  134. + sta->flags |= WLAN_STA_MULTI_AP;
  135. +
  136. + if ((hapd->conf->multi_ap & BACKHAUL_BSS) &&
  137. + multi_ap_value == MULTI_AP_BACKHAUL_STA)
  138. + return WLAN_STATUS_SUCCESS;
  139. +
  140. + if (hapd->conf->multi_ap & FRONTHAUL_BSS) {
  141. + if (multi_ap_value == MULTI_AP_BACKHAUL_STA) {
  142. + hostapd_logger(hapd, sta->addr,
  143. + HOSTAPD_MODULE_IEEE80211,
  144. + HOSTAPD_LEVEL_INFO,
  145. + "Backhaul STA tries to associate with fronthaul-only BSS");
  146. + return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
  147. + }
  148. + return WLAN_STATUS_SUCCESS;
  149. + }
  150. +
  151. + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
  152. + HOSTAPD_LEVEL_INFO,
  153. + "Non-Multi-AP STA tries to associate with backhaul-only BSS");
  154. + return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
  155. +}
  156. +
  157. static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
  158. struct ieee802_11_elems *elems)
  159. @@ -2466,6 +2533,11 @@ static u16 check_assoc_ies(struct hostap
  160. resp = copy_supp_rates(hapd, sta, &elems);
  161. if (resp != WLAN_STATUS_SUCCESS)
  162. return resp;
  163. +
  164. + resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
  165. + if (resp != WLAN_STATUS_SUCCESS)
  166. + return resp;
  167. +
  168. #ifdef CONFIG_IEEE80211N
  169. resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
  170. if (resp != WLAN_STATUS_SUCCESS)
  171. @@ -2996,6 +3068,9 @@ static u16 send_assoc_resp(struct hostap
  172. }
  173. #endif /* CONFIG_WPS */
  174. + if (sta && (sta->flags & WLAN_STA_MULTI_AP))
  175. + p = hostapd_eid_multi_ap(hapd, p);
  176. +
  177. #ifdef CONFIG_P2P
  178. if (sta && sta->p2p_ie && hapd->p2p_group) {
  179. struct wpabuf *p2p_resp_ie;
  180. @@ -4236,7 +4311,7 @@ static void handle_assoc_cb(struct hosta
  181. sta->flags |= WLAN_STA_WDS;
  182. }
  183. - if (sta->flags & WLAN_STA_WDS) {
  184. + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
  185. int ret;
  186. char ifname_wds[IFNAMSIZ + 1];
  187. --- a/src/ap/sta_info.c
  188. +++ b/src/ap/sta_info.c
  189. @@ -166,7 +166,7 @@ void ap_free_sta(struct hostapd_data *ha
  190. /* just in case */
  191. ap_sta_set_authorized(hapd, sta, 0);
  192. - if (sta->flags & WLAN_STA_WDS)
  193. + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
  194. hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
  195. if (sta->ipaddr)
  196. --- a/src/ap/sta_info.h
  197. +++ b/src/ap/sta_info.h
  198. @@ -36,6 +36,7 @@
  199. #define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
  200. #define WLAN_STA_VENDOR_VHT BIT(21)
  201. #define WLAN_STA_PENDING_FILS_ERP BIT(22)
  202. +#define WLAN_STA_MULTI_AP BIT(23)
  203. #define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
  204. #define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
  205. #define WLAN_STA_NONERP BIT(31)
  206. --- a/src/common/ieee802_11_common.c
  207. +++ b/src/common/ieee802_11_common.c
  208. @@ -126,6 +126,10 @@ static int ieee802_11_parse_vendor_speci
  209. elems->roaming_cons_sel = pos;
  210. elems->roaming_cons_sel_len = elen;
  211. break;
  212. + case MULTI_AP_OUI_TYPE:
  213. + elems->multi_ap = pos;
  214. + elems->multi_ap_len = elen;
  215. + break;
  216. default:
  217. wpa_printf(MSG_MSGDUMP, "Unknown WFA "
  218. "information element ignored "
  219. @@ -1519,6 +1523,26 @@ size_t mbo_add_ie(u8 *buf, size_t len, c
  220. }
  221. +size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
  222. +{
  223. + u8 *pos = buf;
  224. +
  225. + if (len < 9)
  226. + return 0;
  227. +
  228. + *pos++ = WLAN_EID_VENDOR_SPECIFIC;
  229. + *pos++ = 7; /* len */
  230. + WPA_PUT_BE24(pos, OUI_WFA);
  231. + pos += 3;
  232. + *pos++ = MULTI_AP_OUI_TYPE;
  233. + *pos++ = MULTI_AP_SUB_ELEM_TYPE;
  234. + *pos++ = 1; /* len */
  235. + *pos++ = value;
  236. +
  237. + return pos - buf;
  238. +}
  239. +
  240. +
  241. static const struct country_op_class us_op_class[] = {
  242. { 1, 115 },
  243. { 2, 118 },
  244. --- a/src/common/ieee802_11_common.h
  245. +++ b/src/common/ieee802_11_common.h
  246. @@ -84,6 +84,7 @@ struct ieee802_11_elems {
  247. const u8 *power_capab;
  248. const u8 *roaming_cons_sel;
  249. const u8 *password_id;
  250. + const u8 *multi_ap;
  251. u8 ssid_len;
  252. u8 supp_rates_len;
  253. @@ -130,6 +131,7 @@ struct ieee802_11_elems {
  254. u8 power_capab_len;
  255. u8 roaming_cons_sel_len;
  256. u8 password_id_len;
  257. + u8 multi_ap_len;
  258. struct mb_ies_info mb_ies;
  259. };
  260. @@ -189,6 +191,8 @@ const u8 * get_ie_ext(const u8 *ies, siz
  261. size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
  262. +size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
  263. +
  264. struct country_op_class {
  265. u8 country_op_class;
  266. u8 global_op_class;
  267. --- a/src/common/ieee802_11_defs.h
  268. +++ b/src/common/ieee802_11_defs.h
  269. @@ -1210,6 +1210,13 @@ struct ieee80211_ampe_ie {
  270. #define MBO_OUI_TYPE 22
  271. #define OWE_IE_VENDOR_TYPE 0x506f9a1c
  272. #define OWE_OUI_TYPE 28
  273. +#define MULTI_AP_OUI_TYPE 0x1B
  274. +
  275. +#define MULTI_AP_SUB_ELEM_TYPE 0x06
  276. +#define MULTI_AP_TEAR_DOWN BIT(4)
  277. +#define MULTI_AP_FRONTHAUL_BSS BIT(5)
  278. +#define MULTI_AP_BACKHAUL_BSS BIT(6)
  279. +#define MULTI_AP_BACKHAUL_STA BIT(7)
  280. #define WMM_OUI_TYPE 2
  281. #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0