1 /*
2 * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "utils/includes.h"
8 #include "utils/common.h"
9 #include "esp_event.h"
10 #include "esp_wifi.h"
11 #include "esp_wifi_types.h"
12 #include "esp_wifi_driver.h"
13 #include "drivers/driver.h"
14 #include "common/bss.h"
15 #include "common/rrm.h"
16 #include "common/wnm_sta.h"
17 #include "common/wpa_supplicant_i.h"
18 #include "esp_scan_i.h"
19 #include "esp_common_i.h"
20 #include "common/ieee802_11_common.h"
21 #include "esp_rrm.h"
22 #include "esp_wnm.h"
23 #include "rsn_supp/wpa_i.h"
24 #include "rsn_supp/wpa.h"
25 #include "esp_private/wifi.h"
26
27 /* Utility Functions */
esp_supplicant_str_to_mac(const char * str,uint8_t dest[6])28 esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6])
29 {
30 if (hwaddr_aton2(str, dest) < 0) {
31 return ESP_FAIL;
32 }
33
34 return ESP_OK;
35 }
36
37 struct wpa_supplicant g_wpa_supp;
38 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
39
40 #ifdef CONFIG_SUPPLICANT_TASK
41 static void *s_supplicant_task_hdl = NULL;
42 static void *s_supplicant_evt_queue = NULL;
43 static void *s_supplicant_api_lock = NULL;
44 static bool s_supplicant_task_init_done;
45 #define SUPPLICANT_API_LOCK() os_mutex_lock(s_supplicant_api_lock)
46 #define SUPPLICANT_API_UNLOCK() os_mutex_unlock(s_supplicant_api_lock)
47 #define SUPPLICANT_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD)
48
handle_action_frm(u8 * frame,size_t len,u8 * sender,int8_t rssi,u8 channel)49 static int handle_action_frm(u8 *frame, size_t len,
50 u8 *sender, int8_t rssi, u8 channel)
51 {
52 struct ieee_mgmt_frame *frm = os_malloc(sizeof(struct ieee_mgmt_frame) + len);
53
54 if (!frm) {
55 wpa_printf(MSG_ERROR, "memory allocation failed");
56 return -1;
57 }
58
59 os_memcpy(frm->sender, sender, ETH_ALEN);
60 frm->len = len;
61 frm->channel = channel;
62 frm->rssi = rssi;
63
64 os_memcpy(frm->payload, frame, len);
65 if (esp_supplicant_post_evt(SIG_SUPPLICANT_RX_ACTION, (u32)frm) != 0) {
66 os_free(frm);
67 return -1;
68 }
69
70 return 0;
71 }
72 #endif /* CONFIG_SUPPLICANT_TASK */
73
74 #if defined(CONFIG_IEEE80211KV)
handle_rrm_frame(struct wpa_supplicant * wpa_s,u8 * sender,u8 * payload,size_t len,int8_t rssi)75 static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
76 u8 *payload, size_t len, int8_t rssi)
77 {
78 if (payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) {
79 /* neighbor report parsing */
80 wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, len - 1);
81 } else if (payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
82 /* Beacon measurement */
83 wpas_rrm_handle_radio_measurement_request(wpa_s, NULL,
84 sender, payload + 1, len - 1);
85 } else if (payload[0] == WLAN_RRM_LINK_MEASUREMENT_REQUEST) {
86 /* Link measurement */
87 wpas_rrm_handle_link_measurement_request(wpa_s, NULL,
88 payload + 1, len - 1, rssi);
89 }
90 }
91
mgmt_rx_action(u8 * frame,size_t len,u8 * sender,int8_t rssi,u8 channel)92 static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel)
93 {
94 u8 category;
95 u8 bssid[ETH_ALEN];
96 struct wpa_supplicant *wpa_s = &g_wpa_supp;
97 int ret = esp_wifi_get_assoc_bssid_internal(bssid);
98
99 if (ret < 0) {
100 wpa_printf(MSG_INFO, "STA not associated");
101 return -1;
102 }
103
104 category = *frame++;
105 len--;
106 if (category == WLAN_ACTION_WNM) {
107 ieee802_11_rx_wnm_action(wpa_s, sender, frame, len);
108 } else if (category == WLAN_ACTION_RADIO_MEASUREMENT) {
109 handle_rrm_frame(wpa_s, sender, frame, len, rssi);
110 }
111
112 return 0;
113 }
114 #endif /* defined(CONFIG_IEEE80211KV) */
115
116 #ifdef CONFIG_SUPPLICANT_TASK
btm_rrm_task(void * pvParameters)117 static void btm_rrm_task(void *pvParameters)
118 {
119 supplicant_event_t *evt;
120 bool task_del = false;
121
122 while(1) {
123 if (os_queue_recv(s_supplicant_evt_queue, &evt, OS_BLOCK) != TRUE)
124 continue;
125
126 /* event validation failed */
127 if (evt->id >= SIG_SUPPLICANT_MAX) {
128 os_free(evt);
129 continue;
130 }
131
132 switch (evt->id) {
133 case SIG_SUPPLICANT_RX_ACTION:
134 {
135 struct ieee_mgmt_frame *frm = (struct ieee_mgmt_frame *)evt->data;
136 mgmt_rx_action(frm->payload, frm->len, frm->sender, frm->rssi, frm->channel);
137 os_free(frm);
138 break;
139 }
140
141 case SIG_SUPPLICANT_SCAN_DONE:
142 esp_supplicant_handle_scan_done_evt();
143 break;
144 case SIG_SUPPLICANT_DEL_TASK:
145 task_del = true;
146 break;
147 default:
148 break;
149 }
150
151 os_free(evt);
152
153 if (task_del)
154 break;
155 }
156
157 os_queue_delete(s_supplicant_evt_queue);
158 s_supplicant_evt_queue = NULL;
159
160 /* At this point, we completed */
161 os_task_delete(NULL);
162 }
163 #endif /* CONFIG_SUPPLICANT_TASK */
164
clear_bssid_flag(struct wpa_supplicant * wpa_s)165 static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
166 {
167 wifi_config_t *config;
168
169 /* Reset only if btm is enabled */
170 if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA) == false)
171 return;
172
173 config = os_zalloc(sizeof(wifi_config_t));
174
175 if (!config) {
176 wpa_printf(MSG_ERROR, "failed to allocate memory");
177 return;
178 }
179
180 esp_wifi_get_config(WIFI_IF_STA, config);
181 if (config->sta.bssid_set) {
182 config->sta.bssid_set = 0;
183 esp_wifi_set_config(WIFI_IF_STA, config);
184 }
185 os_free(config);
186 wpa_printf(MSG_DEBUG, "cleared bssid flag");
187 }
188
register_mgmt_frames(struct wpa_supplicant * wpa_s)189 static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
190 {
191 wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION);
192 /* subtype is defined only for action frame */
193 wpa_s->subtype = 0;
194
195 #ifdef CONFIG_IEEE80211KV
196 /* current supported features in supplicant: rrm and btm */
197 if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA))
198 wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT;
199 if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA))
200 wpa_s->subtype |= 1 << WLAN_ACTION_WNM;
201
202 if (wpa_s->subtype)
203 wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION;
204 #endif /* CONFIG_IEEE80211KV */
205
206 #ifdef CONFIG_IEEE80211R
207 /* register auth/assoc frames if FT is enabled */
208 if (esp_wifi_is_ft_enabled_internal(ESP_IF_WIFI_STA))
209 wpa_s->type |= (1 << WLAN_FC_STYPE_AUTH) |
210 (1 << WLAN_FC_STYPE_ASSOC_RESP) |
211 (1 << WLAN_FC_STYPE_REASSOC_RESP);
212 #endif /* CONFIG_IEEE80211R */
213 esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
214 }
215
216 #ifdef CONFIG_IEEE80211R
handle_auth_frame(u8 * frame,size_t len,u8 * sender,int8_t rssi,u8 channel)217 static int handle_auth_frame(u8 *frame, size_t len,
218 u8 *sender, int8_t rssi, u8 channel)
219 {
220 if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) {
221 if (gWpaSm.ft_protocol) {
222 if (wpa_ft_process_response(&gWpaSm, frame + 6,
223 len - 6, 0, sender, NULL, 0) < 0) {
224 wpa_sm_set_ft_params(&gWpaSm, NULL, 0);
225 return -1;
226 }
227 }
228 }
229 return 0;
230 }
231
handle_assoc_frame(u8 * frame,size_t len,u8 * sender,int8_t rssi,u8 channel)232 static int handle_assoc_frame(u8 *frame, size_t len,
233 u8 *sender, int8_t rssi, u8 channel)
234 {
235 if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) {
236 if (gWpaSm.ft_protocol) {
237 if (wpa_ft_validate_reassoc_resp(&gWpaSm, frame + 6, len - 6, sender)) {
238 wpa_sm_set_ft_params(&gWpaSm, NULL, 0);
239 return -1;
240 }
241 }
242 wpa_sm_set_ft_params(&gWpaSm, frame + 6, len - 6);
243 }
244 return 0;
245 }
246 #endif /* CONFIG_IEEE80211R */
247 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
248
esp_supplicant_unset_all_appie(void)249 void esp_supplicant_unset_all_appie(void)
250 {
251 uint8_t appie;
252 for (appie = WIFI_APPIE_PROBEREQ; appie < WIFI_APPIE_RAM_MAX; appie++) {
253 esp_wifi_unset_appie_internal(appie);
254 }
255 }
256
ieee80211_handle_rx_frm(u8 type,u8 * frame,size_t len,u8 * sender,int8_t rssi,u8 channel,u64 current_tsf)257 static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
258 int8_t rssi, u8 channel, u64 current_tsf)
259 {
260 int ret = 0;
261
262 switch (type) {
263 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211KV)
264 case WLAN_FC_STYPE_BEACON:
265 case WLAN_FC_STYPE_PROBE_RESP:
266 ret = esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf);
267 break;
268 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
269 #ifdef CONFIG_IEEE80211R
270 case WLAN_FC_STYPE_AUTH:
271 ret = handle_auth_frame(frame, len, sender, rssi, channel);
272 break;
273 #endif /* CONFIG_IEEE80211R */
274 case WLAN_FC_STYPE_ASSOC_RESP:
275 case WLAN_FC_STYPE_REASSOC_RESP:
276 wpa_sm_notify_assoc(&gWpaSm, sender);
277 #ifdef CONFIG_IEEE80211R
278 ret = handle_assoc_frame(frame, len, sender, rssi, channel);
279 #endif /* CONFIG_IEEE80211R */
280 break;
281 #if defined(CONFIG_IEEE80211KV)
282 case WLAN_FC_STYPE_ACTION:
283 #ifdef CONFIG_SUPPLICANT_TASK
284 ret = handle_action_frm(frame, len, sender, rssi, channel);
285 #else /* CONFIG_SUPPLICANT_TASK */
286 ret = mgmt_rx_action(frame, len, sender, rssi, channel);
287 #endif /* CONFIG_SUPPLICANT_TASK */
288 break;
289 #endif /* defined(CONFIG_IEEE80211KV) */
290 default:
291 ret = -1;
292 break;
293 }
294
295 return ret;
296 }
297
298 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
299 #ifdef CONFIG_MBO
mbo_bss_profile_match(u8 * bssid)300 bool mbo_bss_profile_match(u8 *bssid)
301 {
302 /* Incase supplicant wants drivers to skip this BSS, return false */
303 struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid);
304 if (!bss) {
305 return true;
306 }
307 const u8 *assoc_disallow = wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_ASSOC_DISALLOW);
308 if (assoc_disallow && assoc_disallow[1] >= 1) {
309 wpa_printf(MSG_DEBUG,
310 "skip - MBO association disallowed (reason %u)", assoc_disallow[2]);
311 return false;
312 }
313
314 if (wpa_is_bss_tmp_disallowed(&g_wpa_supp, bss)) {
315 wpa_printf(MSG_DEBUG,
316 "skip - BSS is temporary disallowed");
317 return false;
318 }
319
320 return true;
321 }
322 #endif /* CONFIG_MBO */
323
324 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
325
esp_supplicant_common_init(struct wpa_funcs * wpa_cb)326 int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
327 {
328 struct wpa_supplicant *wpa_s = &g_wpa_supp;
329 int ret = 0;
330
331 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
332 #ifdef CONFIG_SUPPLICANT_TASK
333 if (!s_supplicant_api_lock) {
334 s_supplicant_api_lock = os_recursive_mutex_create();
335 }
336
337 if (!s_supplicant_api_lock) {
338 wpa_printf(MSG_ERROR, "%s: failed to create Supplicant API lock", __func__);
339 ret = -1;
340 goto err;
341 }
342
343 s_supplicant_evt_queue = os_queue_create(3, sizeof(supplicant_event_t));
344
345 if (!s_supplicant_evt_queue) {
346 wpa_printf(MSG_ERROR, "%s: failed to create Supplicant event queue", __func__);
347 ret = -1;
348 goto err;
349 }
350 ret = os_task_create(btm_rrm_task, "btm_rrm_t", SUPPLICANT_TASK_STACK_SIZE, NULL, 2, &s_supplicant_task_hdl);
351 if (ret != TRUE) {
352 wpa_printf(MSG_ERROR, "btm: failed to create task");
353 ret = -1;
354 goto err;
355 }
356 s_supplicant_task_init_done = true;
357 #endif /* CONFIG_SUPPLICANT_TASK */
358 #ifdef CONFIG_IEEE80211KV
359 wpas_rrm_reset(wpa_s);
360 wpas_clear_beacon_rep_data(wpa_s);
361 #endif /* CONFIG_IEEE80211KV */
362 esp_scan_init(wpa_s);
363
364 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
365 wpa_s->type = 0;
366 wpa_s->subtype = 0;
367 wpa_s->type |= (1 << WLAN_FC_STYPE_ASSOC_RESP) | (1 << WLAN_FC_STYPE_REASSOC_RESP) | (1 << WLAN_FC_STYPE_AUTH);
368 if (esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype) != ESP_OK) {
369 ret = -1;
370 goto err;
371 }
372 wpa_cb->wpa_sta_rx_mgmt = ieee80211_handle_rx_frm;
373
374 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
375 #ifdef CONFIG_MBO
376 dl_list_init(&wpa_s->bss_tmp_disallowed);
377 #endif /* CONFIG_MBO */
378 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
379 return 0;
380 err:
381 esp_supplicant_common_deinit();
382 return ret;
383 }
384
esp_supplicant_common_deinit(void)385 void esp_supplicant_common_deinit(void)
386 {
387 struct wpa_supplicant *wpa_s = &g_wpa_supp;
388
389 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
390 esp_scan_deinit(wpa_s);
391 #ifdef CONFIG_IEEE80211KV
392 wpas_rrm_reset(wpa_s);
393 wpas_clear_beacon_rep_data(wpa_s);
394 #endif /* CONFIG_IEEE80211KV */
395 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
396 if (wpa_s->type) {
397 wpa_s->type = 0;
398 esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
399 }
400 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
401 #ifdef CONFIG_SUPPLICANT_TASK
402 /* We have failed to create task, delete queue and exit */
403 if (!s_supplicant_task_hdl) {
404 if (s_supplicant_evt_queue) {
405 os_queue_delete(s_supplicant_evt_queue);
406 s_supplicant_evt_queue = NULL;
407 }
408 if (s_supplicant_api_lock) {
409 os_mutex_delete(s_supplicant_api_lock);
410 s_supplicant_api_lock = NULL;
411 }
412 } else if (esp_supplicant_post_evt(SIG_SUPPLICANT_DEL_TASK, 0) != 0) {
413 /* failed to post delete event, just delete event queue and exit */
414 if (s_supplicant_evt_queue) {
415 os_queue_delete(s_supplicant_evt_queue);
416 s_supplicant_evt_queue = NULL;
417 }
418 }
419 s_supplicant_task_init_done = false;
420 #endif /* CONFIG_SUPPLICANT_TASK */
421 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
422 }
423
supplicant_sta_conn_handler(uint8_t * bssid)424 void supplicant_sta_conn_handler(uint8_t *bssid)
425 {
426 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
427 u8 *ie;
428 struct wpa_supplicant *wpa_s = &g_wpa_supp;
429 struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid);
430 if (!bss) {
431 wpa_printf(MSG_INFO, "connected bss entry not present in scan cache");
432 return;
433 }
434 wpa_s->current_bss = bss;
435 ie = (u8 *)bss;
436 ie += sizeof(struct wpa_bss);
437 ieee802_11_parse_elems(wpa_s, ie, bss->ie_len);
438 wpa_bss_flush(wpa_s);
439 /* Register for mgmt frames */
440 register_mgmt_frames(wpa_s);
441 /* clear set bssid flag */
442 clear_bssid_flag(wpa_s);
443 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
444 }
445
supplicant_sta_disconn_handler(void)446 void supplicant_sta_disconn_handler(void)
447 {
448 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
449 struct wpa_supplicant *wpa_s = &g_wpa_supp;
450
451 #ifdef CONFIG_IEEE80211KV
452 wpas_rrm_reset(wpa_s);
453 wpas_clear_beacon_rep_data(wpa_s);
454 #endif /* CONFIG_IEEE80211KV */
455 if (wpa_s->current_bss) {
456 wpa_s->current_bss = NULL;
457 }
458 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
459 }
460
461 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
462 #ifdef CONFIG_IEEE80211KV
esp_rrm_is_rrm_supported_connection(void)463 bool esp_rrm_is_rrm_supported_connection(void)
464 {
465 struct wpa_supplicant *wpa_s = &g_wpa_supp;
466
467 if (!wpa_s->current_bss) {
468 wpa_printf(MSG_DEBUG, "STA not associated, return");
469 return false;
470 }
471
472 if (!(wpa_s->rrm_ie[0] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
473 wpa_printf(MSG_DEBUG,
474 "RRM: No network support for Neighbor Report.");
475 return false;
476 }
477
478 return true;
479 }
esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,void * cb_ctx)480 int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
481 void *cb_ctx)
482 {
483 struct wpa_supplicant *wpa_s = &g_wpa_supp;
484 struct wpa_ssid_value wpa_ssid = {0};
485 struct wifi_ssid *ssid;
486
487 if (!wpa_s->current_bss) {
488 wpa_printf(MSG_ERROR, "STA not associated, return");
489 return -2;
490 }
491
492 if (!(wpa_s->rrm_ie[0] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
493 wpa_printf(MSG_ERROR,
494 "RRM: No network support for Neighbor Report.");
495 return -1;
496 }
497
498 ssid = esp_wifi_sta_get_prof_ssid_internal();
499
500 os_memcpy(wpa_ssid.ssid, ssid->ssid, ssid->len);
501 wpa_ssid.ssid_len = ssid->len;
502
503 return wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx);
504 }
505
esp_wnm_is_btm_supported_connection(void)506 bool esp_wnm_is_btm_supported_connection(void)
507 {
508 struct wpa_supplicant *wpa_s = &g_wpa_supp;
509
510 if (!wpa_s->current_bss) {
511 wpa_printf(MSG_DEBUG, "STA not associated, return");
512 return false;
513 }
514
515 if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_BSS_TRANSITION)) {
516 wpa_printf(MSG_DEBUG, "AP doesn't support BTM, return");
517 return false;
518 }
519
520 return true;
521 }
522
esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,const char * btm_candidates,int cand_list)523 int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
524 const char *btm_candidates,
525 int cand_list)
526 {
527 struct wpa_supplicant *wpa_s = &g_wpa_supp;
528
529 if (!wpa_s->current_bss) {
530 wpa_printf(MSG_ERROR, "STA not associated, return");
531 return -2;
532 }
533
534 if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_BSS_TRANSITION)) {
535 wpa_printf(MSG_ERROR, "AP doesn't support BTM, return");
536 return -1;
537 }
538 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, btm_candidates, cand_list);
539 }
540
541 #ifdef CONFIG_MBO
esp_mbo_update_non_pref_chan(struct non_pref_chan_s * non_pref_chan)542 int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
543 {
544 int ret = wpas_mbo_update_non_pref_chan(&g_wpa_supp, non_pref_chan);
545
546 return ret;
547 }
548 #endif /* CONFIG_MBO */
549
wpa_supplicant_connect(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,char * ssid)550 void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
551 struct wpa_bss *bss, char *ssid)
552 {
553 wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
554
555 if (!config) {
556 wpa_printf(MSG_ERROR, "failed to allocate memory");
557 return;
558 }
559
560 esp_wifi_get_config(WIFI_IF_STA, config);
561 /* We only support roaming in same ESS, therefore only bssid setting is needed */
562 os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN);
563 config->sta.bssid_set = 1;
564 /* supplicant connect will only be called in case of bss transition(roaming) */
565 esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC);
566 esp_wifi_set_config(WIFI_IF_STA, config);
567 os_free(config);
568 esp_wifi_connect();
569 }
570
get_rm_enabled_ie(uint8_t * ie,size_t len)571 static size_t get_rm_enabled_ie(uint8_t *ie, size_t len)
572 {
573 uint8_t rrm_ie[7] = {0};
574 uint8_t rrm_ie_len = 5;
575 uint8_t *pos = rrm_ie;
576
577 if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) {
578 return 0;
579 }
580
581 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
582 *pos++ = rrm_ie_len;
583 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
584
585 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
586 #ifdef SCAN_CACHE_SUPPORTED
587 WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
588 #endif /* SCAN_CACHE_SUPPORTED */
589 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
590
591 os_memcpy(ie, rrm_ie, sizeof(rrm_ie));
592
593 return rrm_ie_len + 2;
594 }
595
596 #ifdef CONFIG_MBO
get_mbo_oce_scan_ie(uint8_t * ie,size_t len)597 static size_t get_mbo_oce_scan_ie(uint8_t *ie, size_t len)
598 {
599 uint8_t mbo_ie[32] = {0};
600 uint8_t mbo_ie_len = 32;
601
602 /* Return if MBO IE is not enabled in driver */
603 if (!esp_wifi_is_mbo_enabled_internal(WIFI_IF_STA)) {
604 return 0;
605 }
606
607 struct wpabuf *default_ies = NULL;
608 if (wpabuf_resize(&default_ies, 18) == 0) {
609 wpas_mbo_scan_ie(&g_wpa_supp, default_ies);
610 os_memcpy(mbo_ie, wpabuf_head_u8(default_ies), wpabuf_len(default_ies));
611 mbo_ie_len = wpabuf_len(default_ies);
612 wpabuf_free(default_ies);
613 }
614 os_memcpy(ie, mbo_ie, mbo_ie_len);
615 return mbo_ie_len;
616 }
617
get_mbo_oce_assoc_ie(uint8_t * ie,size_t len)618 static size_t get_mbo_oce_assoc_ie(uint8_t *ie, size_t len)
619 {
620 uint8_t mbo_ie[32] = {0};
621 uint8_t mbo_ie_len = 32;
622
623 /* Return if MBO IE is not enabled in driver */
624 if (!esp_wifi_is_mbo_enabled_internal(WIFI_IF_STA)) {
625 return 0;
626 }
627
628 mbo_ie_len = wpas_mbo_ie(&g_wpa_supp, mbo_ie, mbo_ie_len, 0);
629 os_memcpy(ie, mbo_ie, mbo_ie_len);
630
631 return mbo_ie_len;
632 }
633
get_operating_class_ie(uint8_t * ie,size_t len)634 static uint8_t get_operating_class_ie(uint8_t *ie, size_t len)
635 {
636 uint8_t op_class_ie[4] = {0};
637 uint8_t op_class_ie_len = 2;
638 uint8_t *pos = op_class_ie;
639
640 *pos++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES;
641 *pos++ = op_class_ie_len;
642 #define OPER_CLASS 0x51
643 /* Current Operating Class */
644 *pos++ = OPER_CLASS;
645 #undef OPER_CLASS
646 *pos = 0;
647 os_memcpy(ie, op_class_ie, sizeof(op_class_ie));
648
649 return op_class_ie_len + 2;
650 }
651 #endif /* CONFIG_MBO */
652
get_extended_caps_ie(uint8_t * ie,size_t len)653 static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
654 {
655 uint8_t ext_caps_ie[5] = {0};
656 uint8_t ext_caps_ie_len = 3;
657 uint8_t *pos = ext_caps_ie;
658 wifi_ioctl_config_t cfg = {0};
659 esp_err_t err = 0;
660
661 if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) {
662 return 0;
663 }
664
665 *pos++ = WLAN_EID_EXT_CAPAB;
666 *pos++ = ext_caps_ie_len;
667
668 err = esp_wifi_internal_ioctl(WIFI_IOCTL_GET_STA_HT2040_COEX, &cfg);
669 if (err == ESP_OK && cfg.data.ht2040_coex.enable) {
670 *pos++ |= BIT(WLAN_EXT_CAPAB_20_40_COEX);
671 } else {
672 *pos++ = 0;
673 }
674 *pos ++ = 0;
675 #define CAPAB_BSS_TRANSITION BIT(3)
676 *pos |= CAPAB_BSS_TRANSITION;
677 #undef CAPAB_BSS_TRANSITION
678 os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie));
679
680 return ext_caps_ie_len + 2;
681 }
682
683 #endif /* CONFIG_IEEE80211KV */
684
esp_set_scan_ie(void)685 void esp_set_scan_ie(void)
686 {
687 #ifdef CONFIG_IEEE80211KV
688 #define SCAN_IE_LEN 64
689 uint8_t *ie, *pos;
690 size_t len = SCAN_IE_LEN, ie_len;
691
692 ie = os_malloc(SCAN_IE_LEN);
693 if (!ie) {
694 wpa_printf(MSG_ERROR, "failed to allocate ie");
695 return;
696 }
697 pos = ie;
698 ie_len = get_extended_caps_ie(pos, len);
699 pos += ie_len;
700 len -= ie_len;
701 #ifdef CONFIG_MBO
702 ie_len = get_mbo_oce_scan_ie(pos, len);
703 pos += ie_len;
704 len -= ie_len;
705 #endif /* CONFIG_MBO */
706 esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ);
707 esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0);
708 os_free(ie);
709 #undef SCAN_IE_LEN
710 #endif /* CONFIG_IEEE80211KV */
711 }
712
713 #ifdef CONFIG_IEEE80211R
add_mdie(uint8_t * bssid,uint8_t * ie,size_t len)714 static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len)
715 {
716 size_t mdie_len = 0;
717 struct wpa_sm *sm = &gWpaSm;
718
719 /* Return if MBO IE is not enabled in driver */
720 if (!esp_wifi_is_ft_enabled_internal(WIFI_IF_STA)) {
721 return 0;
722 }
723
724 struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid);
725 if (bss && wpa_key_mgmt_ft(sm->key_mgmt)) {
726 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
727
728 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
729 const u8 *md = mdie + 2;
730 const u8 *wpa_md = wpa_sm_get_ft_md(sm);
731
732 if (os_memcmp(md, wpa_md,
733 MOBILITY_DOMAIN_ID_LEN) == 0) {
734 /* Add mobility domain IE */
735 mdie_len = wpa_ft_add_mdie(
736 sm, ie,
737 len, mdie);
738 }
739 }
740 }
741
742 return mdie_len;
743 }
744 #endif /* CONFIG_IEEE80211R */
745
746
747 #ifdef CONFIG_IEEE80211R
wpa_sm_update_ft_ies(struct wpa_sm * sm,const u8 * md,const u8 * ies,size_t ies_len,bool auth_ie)748 int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
749 const u8 *ies, size_t ies_len, bool auth_ie)
750 {
751 wpa_printf(MSG_INFO, "Updating FT IEs (len=%d)", ies_len);
752 if (os_memcmp(sm->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN) != 0) {
753 return 0;
754 }
755 /* Update auth IEs to be used in FT association */
756 if (auth_ie) {
757 esp_wifi_set_appie_internal(WIFI_APPIE_RAM_STA_AUTH, (u8 *)ies, ies_len, 0);
758 } else {
759 esp_set_assoc_ie(sm->bssid, ies, ies_len, false);
760 }
761 wpa_printf(MSG_INFO, "Updated FT IEs (len=%d) auth_ie=%d", ies_len, auth_ie);
762
763 return 0;
764 }
765 #endif /* CONFIG_IEEE80211R */
766
esp_get_tx_power(uint8_t * tx_power)767 void esp_get_tx_power(uint8_t *tx_power)
768 {
769 #define DEFAULT_MAX_TX_POWER 19 /* max tx power is 19.5 dbm */
770 s8 power;
771 /* esp sends management frames at max tx power configured */
772 int ret = esp_wifi_get_max_tx_power(&power);
773 if (ret != 0) {
774 wpa_printf(MSG_ERROR, "failed to get tx power");
775 *tx_power = DEFAULT_MAX_TX_POWER;
776 return;
777 }
778 *tx_power = power/4;
779 #undef DEFAULT_MAX_TX_POWER
780 }
781
wpa_drv_send_action(struct wpa_supplicant * wpa_s,unsigned int channel,unsigned int wait,const u8 * data,size_t data_len,int no_cck)782 int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
783 unsigned int channel,
784 unsigned int wait,
785 const u8 *data, size_t data_len,
786 int no_cck)
787 {
788 int ret = 0;
789 wifi_mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + data_len);;
790 if (!req)
791 return -1;
792
793 if (!wpa_s->current_bss) {
794 wpa_printf(MSG_ERROR, "STA not associated, return");
795 ret = -1;
796 goto cleanup;
797 }
798
799 req->ifx = WIFI_IF_STA;
800 req->subtype = (WLAN_FC_STYPE_ACTION << 4);
801 req->data_len = data_len;
802 os_memcpy(req->data, data, req->data_len);
803
804 if (esp_wifi_send_mgmt_frm_internal(req) != 0) {
805 wpa_printf(MSG_ERROR, "action frame sending failed");
806 ret = -1;
807 goto cleanup;
808 }
809 wpa_printf(MSG_INFO, "action frame sent");
810
811 cleanup:
812 os_free(req);
813 return ret;
814 }
815
816 #ifdef CONFIG_SUPPLICANT_TASK
esp_supplicant_post_evt(uint32_t evt_id,uint32_t data)817 int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
818 {
819 supplicant_event_t *evt = os_zalloc(sizeof(supplicant_event_t));
820 if (!evt) {
821 wpa_printf(MSG_ERROR, "Failed to allocated memory");
822 return -1;
823 }
824 evt->id = evt_id;
825 evt->data = data;
826
827 /* Make sure lock exists before taking it */
828 SUPPLICANT_API_LOCK();
829
830 /* Make sure no event can be sent when deletion event is sent or task not initialized */
831 if (!s_supplicant_task_init_done) {
832 SUPPLICANT_API_UNLOCK();
833 os_free(evt);
834 return -1;
835 }
836
837 if (os_queue_send(s_supplicant_evt_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
838 SUPPLICANT_API_UNLOCK();
839 os_free(evt);
840 return -1;
841 }
842 if (evt_id == SIG_SUPPLICANT_DEL_TASK) {
843 s_supplicant_task_init_done = false;
844 }
845 SUPPLICANT_API_UNLOCK();
846 return 0;
847 }
848 #endif /* CONFIG_SUPPLICANT_TASK */
849 #else /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,void * cb_ctx)850 int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
851 void *cb_ctx)
852 {
853 return -1;
854 }
855
esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,const char * btm_candidates,int cand_list)856 int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
857 const char *btm_candidates,
858 int cand_list)
859 {
860 return -1;
861 }
862
esp_set_scan_ie(void)863 void esp_set_scan_ie(void) { }
864 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
865
866 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE)
esp_set_assoc_ie(uint8_t * bssid,const u8 * ies,size_t ies_len,bool mdie)867 void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
868 {
869 #define ASSOC_IE_LEN 128
870 uint8_t *ie, *pos;
871 size_t len = ASSOC_IE_LEN;
872 #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
873 size_t ie_len;
874 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
875 ie = os_malloc(ASSOC_IE_LEN + ies_len);
876 if (!ie) {
877 wpa_printf(MSG_ERROR, "failed to allocate ie");
878 return;
879 }
880 pos = ie;
881 #ifdef CONFIG_IEEE80211KV
882 ie_len = get_rm_enabled_ie(pos, len);
883 pos += ie_len;
884 len -= ie_len;
885 #ifdef CONFIG_MBO
886 ie_len = get_operating_class_ie(pos, len);
887 pos += ie_len;
888 len -= ie_len;
889 ie_len = get_mbo_oce_assoc_ie(pos, len);
890 pos += ie_len;
891 len -= ie_len;
892 #endif /* CONFIG_MBO */
893 #endif /* CONFIG_IEEE80211KV */
894 #ifdef CONFIG_IEEE80211R
895 if (mdie) {
896 ie_len = add_mdie(bssid, pos, len);
897 pos += ie_len;
898 len -= ie_len;
899 }
900 #endif /* CONFIG_IEEE80211R */
901 if (ies_len) {
902 os_memcpy(pos, ies, ies_len);
903 pos += ies_len;
904 len -= ies_len;
905 }
906 esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_REQ, ie, ASSOC_IE_LEN - len, 0);
907 os_free(ie);
908 #undef ASSOC_IE_LEN
909 }
910 #else
esp_set_assoc_ie(uint8_t * bssid,const u8 * ies,size_t ies_len,bool mdie)911 void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
912 #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */
913