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