1 /**
2 * Copyright 2020 Espressif Systems (Shanghai) PTE LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "utils/includes.h"
18
19 #include "utils/common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/wpa_supplicant_i.h"
22 #include "utils/wpa_debug.h"
23 #include "esp_wifi_driver.h"
24 #include "esp_wifi_types.h"
25 #include "drivers/driver.h"
26 #include "common/scan.h"
27 #include "common/bss.h"
28 #include "common/rrm.h"
29 #include "common/ieee802_11_common.h"
30 #include "esp_supplicant/esp_common_i.h"
31 #include "common/wnm_sta.h"
32
33 extern struct wpa_supplicant g_wpa_supp;
34
esp_scan_done_event_handler(void * arg,esp_event_base_t event_base,int32_t event_id,void * event_data)35 static void esp_scan_done_event_handler(void* arg, esp_event_base_t event_base,
36 int32_t event_id, void* event_data)
37 {
38 struct wpa_supplicant *wpa_s = &g_wpa_supp;
39 if (!wpa_s->scanning) {
40 /* update last scan time */
41 wpa_s->scan_start_tsf = esp_wifi_get_tsf_time(WIFI_IF_STA);
42 wpa_printf(MSG_DEBUG, "scan not triggered by supplicant, ignore");
43 return;
44 }
45 wpa_s->type &= ~(1 << WLAN_FC_STYPE_BEACON) & ~(1 << WLAN_FC_STYPE_PROBE_RESP);
46 esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
47 esp_supplicant_post_evt(SIG_SUPPLICANT_SCAN_DONE, 0);
48
49 }
50
esp_supp_handle_wnm_scan_done(struct wpa_supplicant * wpa_s)51 static void esp_supp_handle_wnm_scan_done(struct wpa_supplicant *wpa_s)
52 {
53 struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss);
54
55 if (wpa_s->wnm_neighbor_report_elements) {
56 wnm_scan_process(wpa_s, 1);
57 } else if (wpa_s->wnm_dissoc_timer) {
58 if (wpa_s->num_bss == 1) {
59 wpa_printf(MSG_INFO, "not able to find another candidate, do nothing");
60 return;
61 }
62 /* this is a already matched bss */
63 if (bss) {
64 wnm_bss_tm_connect(wpa_s, bss, NULL, 1);
65 }
66 }
67 }
68
esp_supp_scan_done_cleanup(struct wpa_supplicant * wpa_s)69 static void esp_supp_scan_done_cleanup(struct wpa_supplicant *wpa_s)
70 {
71 uint16_t number = 1;
72 wifi_ap_record_t ap_records;
73
74 wpa_s->scanning = 0;
75 wpa_s->scan_reason = 0;
76 /* clean scan list from net80211 */
77 esp_wifi_scan_get_ap_records(&number, &ap_records);
78 }
79
esp_supplicant_handle_scan_done_evt(void)80 void esp_supplicant_handle_scan_done_evt(void)
81 {
82 struct wpa_supplicant *wpa_s = &g_wpa_supp;
83
84 wpa_printf(MSG_INFO, "scan done received");
85 /* Check which module started this, call the respective function */
86 if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) {
87 wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf);
88 } else if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) {
89 esp_supp_handle_wnm_scan_done(wpa_s);
90 }
91 esp_supp_scan_done_cleanup(wpa_s);
92 wpa_bss_update_end(wpa_s);
93 #ifndef SCAN_CACHE_SUPPORTED
94 wpa_bss_flush(wpa_s);
95 #endif
96 }
97
esp_scan_init(struct wpa_supplicant * wpa_s)98 void esp_scan_init(struct wpa_supplicant *wpa_s)
99 {
100 wpa_s->scanning = 0;
101 wpa_bss_init(wpa_s);
102 wpa_s->last_scan_res = NULL;
103 esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE,
104 &esp_scan_done_event_handler, NULL);
105 }
106
esp_scan_deinit(struct wpa_supplicant * wpa_s)107 void esp_scan_deinit(struct wpa_supplicant *wpa_s)
108 {
109 wpa_bss_deinit(wpa_s);
110 }
111
esp_handle_beacon_probe(u8 type,u8 * frame,size_t len,u8 * sender,u32 rssi,u8 channel,u64 current_tsf)112 int esp_handle_beacon_probe(u8 type, u8 *frame, size_t len, u8 *sender,
113 u32 rssi, u8 channel, u64 current_tsf)
114 {
115 struct wpa_supplicant *wpa_s = &g_wpa_supp;
116 struct os_reltime now;
117 struct wpa_scan_res *res;
118 u8 *ptr;
119
120 if (len < 12) {
121 wpa_printf(MSG_ERROR, "beacon/probe is having short len=%d\n", len);
122 return -1;
123 }
124
125 res = os_zalloc(sizeof(struct wpa_scan_res) + len - 12);
126 if (!res) {
127 wpa_printf(MSG_ERROR, "failed to allocate memory");
128 return -1;
129 }
130
131 ptr = (u8 *)res;
132 os_get_time(&now);
133 os_memcpy(res->bssid, sender, ETH_ALEN);
134 res->tsf = WPA_GET_LE64(frame);
135 frame += 8;
136 len -= 8;
137
138 if ((wpa_s->scan_start_tsf == 0) &&
139 wpa_s->current_bss &&
140 (os_memcmp(wpa_s->current_bss, sender, ETH_ALEN) == 0)) {
141 wpa_s->scan_start_tsf = res->tsf;
142 os_memcpy(wpa_s->tsf_bssid, sender, ETH_ALEN);
143 }
144 res->beacon_int = WPA_GET_LE16(frame);
145
146 frame += 2;
147 len -= 2;
148 res->caps = WPA_GET_LE16(frame);
149 frame += 2;
150 len -= 2;
151
152 res->chan = channel;
153 res->noise = 0;
154 res->level = rssi;
155 os_memcpy(res->tsf_bssid, wpa_s->tsf_bssid, ETH_ALEN);
156 res->parent_tsf = current_tsf - wpa_s->scan_start_tsf;
157 if (type == WLAN_FC_STYPE_PROBE_RESP)
158 res->ie_len = len;
159 else if (type == WLAN_FC_STYPE_BEACON)
160 res->beacon_ie_len = len;
161
162 ptr += sizeof(struct wpa_scan_res);
163
164 /* update rest of the frame */
165 os_memcpy(ptr, frame, len);
166 wpa_bss_update_scan_res(wpa_s, res, &now);
167 os_free(res);
168
169 return 0;
170 }
171
esp_issue_scan(struct wpa_supplicant * wpa_s,struct wpa_driver_scan_params * scan_params)172 static int esp_issue_scan(struct wpa_supplicant *wpa_s,
173 struct wpa_driver_scan_params *scan_params)
174 {
175 wifi_scan_config_t *params = NULL;
176 int ret = 0;
177 u64 scan_start_tsf = esp_wifi_get_tsf_time(WIFI_IF_STA);
178
179 /* TODO: Directly try to connect if scan results are recent */
180 if ((scan_start_tsf - wpa_s->scan_start_tsf) > 100000) {
181 wpa_printf(MSG_DEBUG, "flushing old scan cache %llu",
182 (scan_start_tsf - wpa_s->scan_start_tsf));
183 wpa_bss_flush(wpa_s);
184 }
185
186 esp_wifi_get_macaddr_internal(WIFI_IF_STA, wpa_s->tsf_bssid);
187
188 if (scan_params) {
189 params = os_zalloc(sizeof(wifi_scan_config_t));
190 if (!params) {
191 wpa_printf(MSG_ERROR, "failed to allocate memory");
192 return -1;
193 }
194 if (scan_params->num_ssids) {
195 params->ssid = os_zalloc(scan_params->ssids[0].ssid_len + 1);
196 if (!params->ssid) {
197 wpa_printf(MSG_ERROR, "failed to allocate memory");
198 return -1;
199 }
200 os_memcpy(params->ssid, scan_params->ssids[0].ssid, scan_params->ssids[0].ssid_len);
201 params->scan_type = WIFI_SCAN_TYPE_ACTIVE;
202 } else
203 params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
204
205 if (scan_params->bssid) {
206 params->bssid = os_zalloc(ETH_ALEN);
207 if (!params->bssid) {
208 wpa_printf(MSG_ERROR, "failed to allocate memory");
209 return -1;
210 }
211 os_memcpy(params->bssid, scan_params->bssid, ETH_ALEN);
212 }
213 if (scan_params->channel) {
214 params->channel = scan_params->channel;
215 }
216
217 if (scan_params->duration) {
218 params->scan_time.passive = scan_params->duration;
219 params->scan_time.active.min = scan_params->duration;
220 params->scan_time.active.max = scan_params->duration;
221 }
222 }
223
224 wpa_s->scan_start_tsf = scan_start_tsf;
225 /* Register frames to come to supplicant when we park on channel */
226 wpa_s->type |= (1 << WLAN_FC_STYPE_BEACON) | (1 << WLAN_FC_STYPE_PROBE_RESP);
227 esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
228
229 /* issue scan */
230 if (esp_wifi_scan_start(params, false) < 0) {
231 ret = -1;
232 goto cleanup;
233 }
234 wpa_s->scanning = 1;
235 wpa_bss_update_start(wpa_s);
236 wpa_printf(MSG_INFO, "scan issued at time=%llu", wpa_s->scan_start_tsf);
237
238 cleanup:
239 if (params->ssid)
240 os_free(params->ssid);
241 if (params->bssid)
242 os_free(params->bssid);
243 os_free(params);
244
245 return ret;
246 }
247
248 /**
249 * wpa_supplicant_trigger_scan - Request driver to start a scan
250 * @wpa_s: Pointer to wpa_supplicant data
251 * @params: Scan parameters
252 * Returns: 0 on success, -1 on failure
253 */
wpa_supplicant_trigger_scan(struct wpa_supplicant * wpa_s,struct wpa_driver_scan_params * params)254 int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
255 struct wpa_driver_scan_params *params)
256 {
257 return esp_issue_scan(wpa_s, params);
258 }
259
wpa_scan_results_free(struct wpa_scan_results * res)260 void wpa_scan_results_free(struct wpa_scan_results *res)
261 {
262 size_t i;
263
264 if (res == NULL)
265 return;
266
267 for (i = 0; i < res->num; i++)
268 os_free(res->res[i]);
269 os_free(res->res);
270 os_free(res);
271 }
272