1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 *
4 * This software may be distributed under the terms of the BSD license.
5 * See README for more details.
6 */
7 #include "wpa_magiclink.h"
8 #include <net/if.h>
9 #include "includes.h"
10 #include "common.h"
11 #include "common/ieee802_11_common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "wps/wps_i.h"
14 #include "eap_peer/eap.h"
15
16 #include "wpa_supplicant_i.h"
17 #include "p2p_supplicant.h"
18 #include "bss.h"
19 #include "ctrl_iface.h"
20 #include "../wpa_supplicant/config.h"
21 #include "notify.h"
22 #include "securec.h"
23 #ifdef BRCM_VE
24 #include "wpa.h"
25 #include "wpa_i.h"
26 #include "wpa_supplicant_i.h"
27 #include "driver_i.h"
28 #endif /* BRCM_VE */
29
30 #define MANUFACTURER_LEN 32
31 #define MODEL_NAME_LEN 32
32 #define MODEL_NUMBER_LEN 16
33 #define DEVICE_NAME_LEN 64
34
35 #define HW_PENDING_EAPOL_EXPIRE_TIME_DEF 500 /* ms */
36 /*
37 * used in wps_vendor_specific_ies(wpa_supplicant/scan.c)
38 * wps vendor specific ies,
39 */
40 struct wps_vendor_ies {
41 char manufacturer[MANUFACTURER_LEN];
42 char model_name[MODEL_NAME_LEN];
43 char model_number[MODEL_NUMBER_LEN];
44 char device_name[DEVICE_NAME_LEN];
45 };
46
47 #if defined(CONFIG_MAGICLINK)
48 /*lint -restore*/
49 #ifdef CONFIG_MAGICLINK_PC
hw_magiclink_gen_scan_res(const u8 * bssid,int freqency,int noGc)50 static struct wpa_scan_res *hw_magiclink_gen_scan_res(const u8 *bssid, int freqency, int noGc)
51 {
52 #else
53 static struct wpa_scan_res *hw_magiclink_gen_scan_res(const u8 *bssid, int freqency)
54 {
55 #endif
56 struct wpa_scan_res* res = NULL;
57 unsigned char ie_data[] = {
58 48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0,
59 15, 172, 4, 1, 0, 0, 15, 172, 2, 12, 0 }; // RSN IE
60
61 res = os_zalloc(sizeof(*res) + sizeof(ie_data) + sizeof(ie_data));
62 if (!res) {
63 wpa_printf(MSG_ERROR, "P2P: Failed to allocate memory for magiclink");
64 return NULL;
65 }
66
67 res->flags = 11;
68 #ifdef CONFIG_MAGICLINK_PC
69 if (noGc == 1) {
70 res->legacyGO = 1;
71 } else {
72 res->legacyGO = 0;
73 }
74 #endif
75 os_memcpy(res->bssid, bssid, ETH_ALEN);
76
77 res->freq = freqency;
78 res->beacon_int = 100;
79 res->caps = 1297;
80 res->qual = 0;
81 res->noise = 0;
82 res->level = 0;
83 res->tsf = 0;
84 res->age = 0;
85 res->ie_len = sizeof(ie_data);
86 res->beacon_ie_len = sizeof(ie_data);
87 os_memcpy(res + 1, ie_data, sizeof(ie_data));
88 os_memcpy((char*)(res + 1) + res->ie_len, ie_data, sizeof(ie_data));
89
90 return res;
91 }
92
93 static int hw_magiclink_get_ht40_mode(int channel)
94 {
95 for (int op = 0; global_op_class[op].op_class; op++) {
96 const struct oper_class_map *o = &global_op_class[op];
97 u8 ch;
98
99 if (o->mode != HOSTAPD_MODE_IEEE80211A)
100 continue;
101
102 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
103 if ((o->bw != BW40PLUS && o->bw != BW40MINUS) ||
104 ch != channel)
105 continue;
106 return (o->bw == BW40MINUS) ? -1 : 1;
107 }
108 }
109 return 0;
110 }
111
112 static int hw_magiclink_scan_param(struct wpa_supplicant *wpa_s)
113 {
114 if (wpa_s == NULL) {
115 wpa_printf(MSG_ERROR, "Parameter error,wpa_s == NULL");
116 return -1;
117 }
118
119 wpa_s->scan_req = MANUAL_SCAN_REQ;
120
121 int pri_chan = 0;
122 enum hostapd_hw_mode hw_mode = ieee80211_freq_to_chan(wpa_s->magic_link_freq,
123 (u8 *)&pri_chan);
124 if (hw_mode == NUM_HOSTAPD_MODES) {
125 wpa_printf(MSG_ERROR, "frequency(%d MHz) error", wpa_s->magic_link_freq);
126 return -1;
127 }
128 os_free(wpa_s->manual_scan_freqs);
129 // 3:Number of channels:primary channel,secondary channel,0
130 wpa_s->manual_scan_freqs = os_zalloc(3 * sizeof(int));
131 if (wpa_s->manual_scan_freqs == NULL) {
132 wpa_printf(MSG_ERROR, "alloc wpa_s->manual_scan_freqs failed");
133 return -1;
134 }
135 wpa_s->manual_scan_freqs[0] = wpa_s->magic_link_freq;
136 if (wpa_s->normal_scans && hw_mode == HOSTAPD_MODE_IEEE80211A) {
137 int behavior = hw_magiclink_get_ht40_mode(pri_chan);
138 // 5G channel to freq
139 int sec_freq = 5000 + (pri_chan + behavior * 4) * 5;
140
141 switch (behavior) {
142 case -1:
143 wpa_s->manual_scan_freqs[0] = sec_freq;
144 wpa_s->manual_scan_freqs[1] = wpa_s->magic_link_freq;
145 break;
146 case 1:
147 wpa_s->manual_scan_freqs[1] = sec_freq;
148 break;
149 default:
150 break;
151 }
152 }
153 wpa_printf(MSG_DEBUG, "%s: freq[0]=%d, freq[1]=%d", __func__, wpa_s->manual_scan_freqs[0],
154 wpa_s->manual_scan_freqs[1]);
155 return 0;
156 }
157
158 void hw_magiclink_scan(struct wpa_supplicant *wpa_s)
159 {
160 if (!wpa_s) {
161 wpa_msg(wpa_s, MSG_DEBUG,
162 "magiclink: Start scan for network selection fail");
163 return;
164 }
165 wpa_s->normal_scans = 0;
166 hw_magiclink_scan_param(wpa_s);
167 wpa_supplicant_req_scan(wpa_s, 0, 0);
168 return;
169 }
170
171 void magiclink_prepare_scan(struct wpa_supplicant *wpa_s, int *timeout_usec)
172 {
173 if (!wpa_s) {
174 wpa_printf(MSG_ERROR, "Parameter error");
175 return;
176 }
177 if (timeout_usec != NULL) {
178 *timeout_usec = 50000;
179 }
180 if (wpa_s->normal_scans > 4) {
181 return;
182 }
183 hw_magiclink_scan_param(wpa_s);
184 }
185
186 static int hw_magiclink_add_new_scan_res(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int freq, int noGc)
187 {
188 #define DEFAULT_SCAN_RES_SIZE 32
189 struct os_reltime fetch_time;
190 struct wpa_bss *bss = NULL;
191 struct wpa_scan_res *res = NULL;
192 struct wpa_bss **n = NULL;
193 unsigned int siz = DEFAULT_SCAN_RES_SIZE;
194
195 #ifdef CONFIG_MAGICLINK_PC
196 res = hw_magiclink_gen_scan_res(ssid->bssid, freq, noGc);
197 #else
198 res = hw_magiclink_gen_scan_res(ssid->bssid, freq);
199 #endif
200
201 if (!res) {
202 wpa_printf(MSG_ERROR, "P2P: Failed to generate scan result");
203 return -1;
204 }
205
206 os_get_reltime(&fetch_time);
207 bss = hw_magiclink_bss_add(wpa_s, ssid->ssid, ssid->ssid_len, res, &fetch_time);
208 if (!bss) {
209 os_free(res);
210 return -1;
211 }
212
213 n = os_realloc_array(wpa_s->last_scan_res, siz, sizeof(struct wpa_bss *));
214 if (!n) {
215 os_free(res);
216 return -1;
217 }
218 wpa_s->last_scan_res = n;
219 wpa_s->last_scan_res_size = siz;
220 wpa_s->last_scan_res[0] = bss;
221 wpa_s->last_scan_res_used = 1;
222 os_free(res);
223 return 0;
224 }
225
226 static int hw_magiclink_connect_parse_param(struct wpa_supplicant *wpa_s, const char *cmd,
227 char **ppsk, char **pbssid, char **pfreq, int *noGc)
228 {
229 char *pos = NULL;
230
231 if (!wpa_s || !cmd || !ppsk || !pbssid || !pfreq || !noGc) {
232 wpa_printf(MSG_ERROR, "%s param is null", __func__);
233 return -1;
234 }
235 // ssid
236 pos = os_strstr(cmd, "\n");
237 if (!pos) {
238 return -1;
239 }
240 *pos = '\0';
241
242 // bssid
243 *pbssid = pos + 1;
244 pos = os_strstr(pos + 1, "\n");
245 if (!pos) {
246 return -1;
247 }
248 *pos = '\0';
249
250 // password
251 *ppsk = pos + 1;
252 pos = os_strstr(pos + 1, "\n");
253 if (!pos) {
254 return -1;
255 }
256 *pos = '\0';
257 // frequency
258 *pfreq = pos + 1;
259
260 #ifdef CONFIG_MAGICLINK_PC
261 // noGc
262 pos = os_strstr(pos + 1, "\n");
263 if (pos != NULL) {
264 *pos = '\0';
265 *noGc = atoi(pos + 1);
266 wpa_msg(wpa_s, MSG_INFO, "wpa_magiclink noGc is %d", *noGc);
267 }
268 #endif
269
270 return 0;
271 }
272
273 static struct wpa_ssid *hw_magiclink_add_network(struct wpa_supplicant *wpa_s, char *pssid,
274 const char *pbssid, char *ppsk)
275 {
276 struct wpa_ssid *ssid = wpa_config_add_network(wpa_s->conf);
277 if (!ssid) {
278 return NULL;
279 }
280
281 wpa_config_set_network_defaults(ssid);
282 hw_magiclink_ctrl_iface_update_network(wpa_s, ssid, "ssid", pssid);
283 hw_magiclink_ctrl_iface_update_network(wpa_s, ssid, "priority", "0");
284
285 if (strcmp(ppsk, "\"\"") == 0) {
286 wpa_printf(MSG_DEBUG, "key_mgmt is NONE");
287 hw_magiclink_ctrl_iface_update_network(wpa_s, ssid, "key_mgmt", "NONE");
288 } else {
289 hw_magiclink_ctrl_iface_update_network(wpa_s, ssid, "key_mgmt", "WPA-PSK");
290 hw_magiclink_ctrl_iface_update_network(wpa_s, ssid, "psk", ppsk);
291 }
292 if (hwaddr_aton(pbssid, ssid->bssid)) {
293 wpa_printf(MSG_ERROR, "fail to parser bssid");
294 return NULL;
295 }
296 ssid->bssid_set = 1;
297 return ssid;
298 }
299
300 static int hw_magiclink_connect_known_ap(struct wpa_supplicant *wpa_s, char *cmd)
301 {
302 /* cmd: "SSID BSSID PASSWORD FREQUENCY"
303 "P"DIRECT-xx-xxxx" xx:xx:xx:xx:xx:xx "xxxxxxxx" 2412|2437|2462"
304 "P\"DIRECT-XA-send\" 5a:7f:66:ae:a1:66 \"d9hHbPv0\" 2412" */
305 char *pfreq = NULL;
306 char *ppsk = NULL;
307 char *pbssid = NULL;
308 char *pssid = cmd;
309 int freq;
310 int noGc = 0xFF;
311
312 if (hw_magiclink_connect_parse_param(wpa_s, cmd, &ppsk, &pbssid, &pfreq, &noGc)) {
313 wpa_printf(MSG_DEBUG, "hw_magiclink_connect_parse_param failed");
314 return -1;
315 }
316 struct wpa_ssid *ssid = hw_magiclink_add_network(wpa_s, pssid, pbssid, ppsk);
317 if (!ssid) {
318 wpa_printf(MSG_ERROR, "hw_magiclink_add_network failed");
319 return -1;
320 }
321 freq = atoi(pfreq);
322 if (hw_magiclink_add_new_scan_res(wpa_s, ssid, freq, noGc)) {
323 wpa_printf(MSG_ERROR, "hw_magiclink_add_new_scan_res failed");
324 return -1;
325 }
326
327 struct os_reltime now;
328 os_get_reltime(&now);
329 wpa_s->last_scan = now;
330 wpa_s->magic_link_freq = freq;
331 hw_magiclink_scan(wpa_s);
332 wpa_s->disconnected = 0;
333 wpa_s->reassociate = 1;
334 ssid->p2p_group = 1;
335 wpa_s->show_group_started = 1;
336 return 0;
337 }
338
339 int hw_magiclink_p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd)
340 {
341 enum wpa_driver_if_type iftype;
342 char p[256];
343 wpa_printf(MSG_ERROR, "hw_magiclink_p2p_ctrl_connect");
344 if (!wpa_s || !cmd) {
345 wpa_printf(MSG_ERROR, "%s:wpa_s or cmd is null", __func__);
346 return -1;
347 }
348
349 os_memset(p, 0, sizeof(p));
350 wpa_s->create_p2p_iface = hw_magiclink_create_iface(wpa_s);
351 iftype = WPA_IF_P2P_GROUP;
352 /*
353 * reltek chip don not support create p2p interface, use p2p0
354 */
355 #ifdef CONFIG_SUPPORT_PLATEFORM_REALTEK
356 struct wpa_supplicant *magiclink_wpa_s = wpa_s;
357 #else
358 if (hw_magiclink_add_group_interface(wpa_s, iftype) < 0) {
359 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
360 "interface for the group");
361 return -1;
362 }
363
364 struct wpa_supplicant *magiclink_wpa_s = hw_magiclink_init_group_interface(wpa_s, 0);
365 if (!magiclink_wpa_s) {
366 wpa_printf(MSG_ERROR, "P2P: Failed to get magiclink interface");
367 return -1;
368 }
369 #endif
370
371 wpa_msg(wpa_s, MSG_INFO, "P2P-INTERFACE-CREATED GC %s", magiclink_wpa_s->ifname);
372 os_snprintf(p, sizeof(p), "P2P-INTERFACE-CREATED GC %s", magiclink_wpa_s->ifname);
373 #ifdef MTK_SET_MAGIC_LINK_FLAG
374 magiclink_wpa_s->is_magic_link = 1;
375 #endif
376 wpa_s->global->p2p_group_formation = NULL;
377 return hw_magiclink_connect_known_ap(magiclink_wpa_s, cmd);
378 }
379
380 int hw_wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int network_id,
381 int persistent, int freq, int max_band) {
382 int vht = wpa_s->conf->p2p_go_vht;
383 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
384 struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
385 if (ssid == NULL) {
386 return wpas_p2p_group_add(wpa_s, persistent, freq, 0, ht40, vht, max_band,
387 0, 0, false);
388 } else if (ssid->disabled == 2) {
389 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, ht40, vht,
390 max_band, 0, 0, NULL, 0, 0, false);
391 }
392 return -1;
393 }
394 #endif
395
396