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