OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | @@ -4236,7 +4311,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 |