1 /*
2 * WPA Supplicant / Control interface (shared code for all backends)
3 * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10 #ifdef CONFIG_TESTING_OPTIONS
11 #include <netinet/ip.h>
12 #endif /* CONFIG_TESTING_OPTIONS */
13
14 #include "utils/common.h"
15 #include "utils/eloop.h"
16 #include "utils/uuid.h"
17 #include "utils/module_tests.h"
18 #include "common/version.h"
19 #include "common/ieee802_11_defs.h"
20 #include "common/ieee802_11_common.h"
21 #include "common/wpa_ctrl.h"
22 #ifdef CONFIG_DPP
23 #include "common/dpp.h"
24 #endif /* CONFIG_DPP */
25 #include "common/nan_de.h"
26 #include "common/ptksa_cache.h"
27 #include "crypto/tls.h"
28 #include "ap/hostapd.h"
29 #include "eap_peer/eap.h"
30 #include "eapol_supp/eapol_supp_sm.h"
31 #include "rsn_supp/wpa.h"
32 #include "rsn_supp/preauth.h"
33 #include "rsn_supp/pmksa_cache.h"
34 #include "l2_packet/l2_packet.h"
35 #include "wps/wps.h"
36 #include "fst/fst.h"
37 #include "fst/fst_ctrl_iface.h"
38 #include "config.h"
39 #include "wpa_supplicant_i.h"
40 #include "driver_i.h"
41 #include "wps_supplicant.h"
42 #include "ibss_rsn.h"
43 #include "wpas_glue.h"
44 #include "ap.h"
45 #include "p2p_supplicant.h"
46 #include "p2p/p2p.h"
47 #include "hs20_supplicant.h"
48 #include "wifi_display.h"
49 #include "notify.h"
50 #include "bss.h"
51 #include "scan.h"
52 #include "ctrl_iface.h"
53 #include "interworking.h"
54 #include "bssid_ignore.h"
55 #include "autoscan.h"
56 #include "wnm_sta.h"
57 #include "offchannel.h"
58 #include "drivers/driver.h"
59 #include "mesh.h"
60 #include "dpp_supplicant.h"
61 #include "sme.h"
62 #include "nan_usd.h"
63
64 #ifdef __NetBSD__
65 #include <net/if_ether.h>
66 #elif defined(__ZEPHYR__)
67 #include <zephyr/net/ethernet.h>
68 #include <supp_events.h>
69 #endif
70
71 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
72 char *buf, int len);
73 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
74 const char *input,
75 char *buf, int len);
76 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
77 char *val);
78
79
set_bssid_filter(struct wpa_supplicant * wpa_s,char * val)80 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
81 {
82 char *pos;
83 u8 addr[ETH_ALEN], *filter = NULL, *n;
84 size_t count = 0;
85
86 pos = val;
87 while (pos) {
88 if (*pos == '\0')
89 break;
90 if (hwaddr_aton(pos, addr)) {
91 os_free(filter);
92 return -1;
93 }
94 n = os_realloc_array(filter, count + 1, ETH_ALEN);
95 if (n == NULL) {
96 os_free(filter);
97 return -1;
98 }
99 filter = n;
100 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
101 count++;
102
103 pos = os_strchr(pos, ' ');
104 if (pos)
105 pos++;
106 }
107
108 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
109 os_free(wpa_s->bssid_filter);
110 wpa_s->bssid_filter = filter;
111 wpa_s->bssid_filter_count = count;
112
113 return 0;
114 }
115
116
set_disallow_aps(struct wpa_supplicant * wpa_s,char * val)117 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
118 {
119 char *pos;
120 u8 addr[ETH_ALEN], *bssid = NULL, *n;
121 struct wpa_ssid_value *ssid = NULL, *ns;
122 size_t count = 0, ssid_count = 0;
123 struct wpa_ssid *c;
124
125 /*
126 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
127 * SSID_SPEC ::= ssid <SSID_HEX>
128 * BSSID_SPEC ::= bssid <BSSID_HEX>
129 */
130
131 pos = val;
132 while (pos) {
133 if (*pos == '\0')
134 break;
135 if (os_strncmp(pos, "bssid ", 6) == 0) {
136 int res;
137 pos += 6;
138 res = hwaddr_aton2(pos, addr);
139 if (res < 0) {
140 os_free(ssid);
141 os_free(bssid);
142 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
143 "BSSID value '%s'", pos);
144 return -1;
145 }
146 pos += res;
147 n = os_realloc_array(bssid, count + 1, ETH_ALEN);
148 if (n == NULL) {
149 os_free(ssid);
150 os_free(bssid);
151 return -1;
152 }
153 bssid = n;
154 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
155 count++;
156 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
157 char *end;
158 pos += 5;
159
160 end = pos;
161 while (*end) {
162 if (*end == '\0' || *end == ' ')
163 break;
164 end++;
165 }
166
167 ns = os_realloc_array(ssid, ssid_count + 1,
168 sizeof(struct wpa_ssid_value));
169 if (ns == NULL) {
170 os_free(ssid);
171 os_free(bssid);
172 return -1;
173 }
174 ssid = ns;
175
176 if ((end - pos) & 0x01 ||
177 end - pos > 2 * SSID_MAX_LEN ||
178 hexstr2bin(pos, ssid[ssid_count].ssid,
179 (end - pos) / 2) < 0) {
180 os_free(ssid);
181 os_free(bssid);
182 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
183 "SSID value '%s'", pos);
184 return -1;
185 }
186 ssid[ssid_count].ssid_len = (end - pos) / 2;
187 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
188 ssid[ssid_count].ssid,
189 ssid[ssid_count].ssid_len);
190 ssid_count++;
191 pos = end;
192 } else {
193 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
194 "'%s'", pos);
195 os_free(ssid);
196 os_free(bssid);
197 return -1;
198 }
199
200 pos = os_strchr(pos, ' ');
201 if (pos)
202 pos++;
203 }
204
205 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
206 os_free(wpa_s->disallow_aps_bssid);
207 wpa_s->disallow_aps_bssid = bssid;
208 wpa_s->disallow_aps_bssid_count = count;
209
210 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
211 os_free(wpa_s->disallow_aps_ssid);
212 wpa_s->disallow_aps_ssid = ssid;
213 wpa_s->disallow_aps_ssid_count = ssid_count;
214
215 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
216 return 0;
217
218 c = wpa_s->current_ssid;
219 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
220 return 0;
221
222 if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
223 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
224 return 0;
225
226 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
227 "because current AP was marked disallowed");
228
229 #ifdef CONFIG_SME
230 wpa_s->sme.prev_bssid_set = 0;
231 #endif /* CONFIG_SME */
232 wpa_s->reassociate = 1;
233 wpa_s->own_disconnect_req = 1;
234 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
235 wpa_supplicant_req_scan(wpa_s, 0, 0);
236
237 return 0;
238 }
239
240
241 #ifndef CONFIG_NO_CONFIG_BLOBS
wpas_ctrl_set_blob(struct wpa_supplicant * wpa_s,char * pos)242 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
243 {
244 char *name = pos;
245 struct wpa_config_blob *blob;
246 size_t len;
247
248 pos = os_strchr(pos, ' ');
249 if (pos == NULL)
250 return -1;
251 *pos++ = '\0';
252 len = os_strlen(pos);
253 if (len & 1)
254 return -1;
255
256 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
257 blob = os_zalloc(sizeof(*blob));
258 if (blob == NULL)
259 return -1;
260 blob->name = os_strdup(name);
261 blob->data = os_malloc(len / 2);
262 if (blob->name == NULL || blob->data == NULL) {
263 wpa_config_free_blob(blob);
264 return -1;
265 }
266
267 if (hexstr2bin(pos, blob->data, len / 2) < 0) {
268 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
269 wpa_config_free_blob(blob);
270 return -1;
271 }
272 blob->len = len / 2;
273
274 wpa_config_set_blob(wpa_s->conf, blob);
275
276 return 0;
277 }
278 #endif /* CONFIG_NO_CONFIG_BLOBS */
279
280
wpas_ctrl_pno(struct wpa_supplicant * wpa_s,char * cmd)281 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
282 {
283 char *params;
284 char *pos;
285 int *freqs = NULL;
286 int ret;
287
288 if (atoi(cmd)) {
289 params = os_strchr(cmd, ' ');
290 os_free(wpa_s->manual_sched_scan_freqs);
291 if (params) {
292 params++;
293 pos = os_strstr(params, "freq=");
294 if (pos)
295 freqs = freq_range_to_channel_list(wpa_s,
296 pos + 5);
297 }
298 wpa_s->manual_sched_scan_freqs = freqs;
299 ret = wpas_start_pno(wpa_s);
300 } else {
301 ret = wpas_stop_pno(wpa_s);
302 }
303 return ret;
304 }
305
306
wpas_ctrl_set_band(struct wpa_supplicant * wpa_s,char * bands)307 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
308 {
309 union wpa_event_data event;
310 u32 setband_mask = WPA_SETBAND_AUTO;
311
312 /*
313 * For example:
314 * SET setband 2G,6G
315 * SET setband 5G
316 * SET setband AUTO
317 */
318 if (!os_strstr(bands, "AUTO")) {
319 if (os_strstr(bands, "5G"))
320 setband_mask |= WPA_SETBAND_5G;
321 if (os_strstr(bands, "6G"))
322 setband_mask |= WPA_SETBAND_6G;
323 if (os_strstr(bands, "2G"))
324 setband_mask |= WPA_SETBAND_2G;
325 if (setband_mask == WPA_SETBAND_AUTO)
326 return -1;
327 }
328
329 wpa_s->setband_mask = setband_mask;
330 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
331 os_memset(&event, 0, sizeof(event));
332 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
333 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
334 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
335 }
336
337 return 0;
338 }
339
340
wpas_ctrl_iface_set_lci(struct wpa_supplicant * wpa_s,const char * cmd)341 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
342 const char *cmd)
343 {
344 struct wpabuf *lci;
345
346 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
347 wpabuf_free(wpa_s->lci);
348 wpa_s->lci = NULL;
349 return 0;
350 }
351
352 lci = wpabuf_parse_bin(cmd);
353 if (!lci)
354 return -1;
355
356 if (os_get_reltime(&wpa_s->lci_time)) {
357 wpabuf_free(lci);
358 return -1;
359 }
360
361 wpabuf_free(wpa_s->lci);
362 wpa_s->lci = lci;
363
364 return 0;
365 }
366
367
368 static int
wpas_ctrl_set_relative_rssi(struct wpa_supplicant * wpa_s,const char * cmd)369 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
370 {
371 int relative_rssi;
372
373 if (os_strcmp(cmd, "disable") == 0) {
374 wpa_s->srp.relative_rssi_set = 0;
375 return 0;
376 }
377
378 relative_rssi = atoi(cmd);
379 if (relative_rssi < 0 || relative_rssi > 100)
380 return -1;
381 wpa_s->srp.relative_rssi = relative_rssi;
382 wpa_s->srp.relative_rssi_set = 1;
383 return 0;
384 }
385
386
wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant * wpa_s,const char * cmd)387 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
388 const char *cmd)
389 {
390 char *pos;
391 int adjust_rssi;
392
393 /* <band>:adjust_value */
394 pos = os_strchr(cmd, ':');
395 if (!pos)
396 return -1;
397 pos++;
398 adjust_rssi = atoi(pos);
399 if (adjust_rssi < -100 || adjust_rssi > 100)
400 return -1;
401
402 if (os_strncmp(cmd, "2G", 2) == 0)
403 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
404 else if (os_strncmp(cmd, "5G", 2) == 0)
405 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
406 else
407 return -1;
408
409 wpa_s->srp.relative_adjust_rssi = adjust_rssi;
410
411 return 0;
412 }
413
414
wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant * wpa_s,const char * cmd)415 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
416 const char *cmd)
417 {
418 struct wpabuf *ric_ies;
419
420 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
421 wpabuf_free(wpa_s->ric_ies);
422 wpa_s->ric_ies = NULL;
423 return 0;
424 }
425
426 ric_ies = wpabuf_parse_bin(cmd);
427 if (!ric_ies)
428 return -1;
429
430 wpabuf_free(wpa_s->ric_ies);
431 wpa_s->ric_ies = ric_ies;
432
433 return 0;
434 }
435
436
437 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_set_dso(struct wpa_supplicant * wpa_s,const char * val)438 static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
439 const char *val)
440 {
441 u8 bssid[ETH_ALEN];
442 const char *pos = val;
443 struct driver_signal_override *dso = NULL, *tmp, parsed;
444
445 if (hwaddr_aton(pos, bssid))
446 return -1;
447 pos = os_strchr(pos, ' ');
448
449 dl_list_for_each(tmp, &wpa_s->drv_signal_override,
450 struct driver_signal_override, list) {
451 if (ether_addr_equal(bssid, tmp->bssid)) {
452 dso = tmp;
453 break;
454 }
455 }
456
457 if (!pos) {
458 /* Remove existing entry */
459 if (dso) {
460 dl_list_del(&dso->list);
461 os_free(dso);
462 }
463 return 0;
464 }
465 pos++;
466
467 /* Update an existing entry or add a new one */
468 os_memset(&parsed, 0, sizeof(parsed));
469 if (sscanf(pos, "%d %d %d %d %d",
470 &parsed.si_current_signal,
471 &parsed.si_avg_signal,
472 &parsed.si_avg_beacon_signal,
473 &parsed.si_current_noise,
474 &parsed.scan_level) != 5)
475 return -1;
476
477 if (!dso) {
478 dso = os_zalloc(sizeof(*dso));
479 if (!dso)
480 return -1;
481 os_memcpy(dso->bssid, bssid, ETH_ALEN);
482 dl_list_add(&wpa_s->drv_signal_override, &dso->list);
483 }
484 dso->si_current_signal = parsed.si_current_signal;
485 dso->si_avg_signal = parsed.si_avg_signal;
486 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
487 dso->si_current_noise = parsed.si_current_noise;
488 dso->scan_level = parsed.scan_level;
489
490 return 0;
491 }
492 #endif /* CONFIG_TESTING_OPTIONS */
493
494
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)495 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
496 char *cmd)
497 {
498 char *value;
499 int ret = 0;
500
501 value = os_strchr(cmd, ' ');
502 if (value == NULL)
503 return -1;
504 *value++ = '\0';
505
506 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
507 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
508 eapol_sm_configure(wpa_s->eapol,
509 atoi(value), -1, -1, -1);
510 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
511 eapol_sm_configure(wpa_s->eapol,
512 -1, atoi(value), -1, -1);
513 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
514 eapol_sm_configure(wpa_s->eapol,
515 -1, -1, atoi(value), -1);
516 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
517 eapol_sm_configure(wpa_s->eapol,
518 -1, -1, -1, atoi(value));
519 #ifdef CONFIG_TESTING_OPTIONS
520 } else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
521 if (os_strcmp(value, "Auto") == 0)
522 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
523 else if (os_strcmp(value, "ForceUnauthorized") == 0)
524 eapol_sm_notify_portControl(wpa_s->eapol,
525 ForceUnauthorized);
526 else if (os_strcmp(value, "ForceAuthorized") == 0)
527 eapol_sm_notify_portControl(wpa_s->eapol,
528 ForceAuthorized);
529 else
530 ret = -1;
531 #endif /* CONFIG_TESTING_OPTIONS */
532 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
533 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
534 atoi(value))) {
535 ret = -1;
536 } else {
537 value[-1] = '=';
538 wpa_config_process_global(wpa_s->conf, cmd, -1);
539 }
540 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
541 0) {
542 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
543 atoi(value))) {
544 ret = -1;
545 } else {
546 value[-1] = '=';
547 wpa_config_process_global(wpa_s->conf, cmd, -1);
548 }
549 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
550 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
551 atoi(value))) {
552 ret = -1;
553 } else {
554 value[-1] = '=';
555 wpa_config_process_global(wpa_s->conf, cmd, -1);
556 }
557 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
558 wpa_s->wps_fragment_size = atoi(value);
559 #ifdef CONFIG_WPS_TESTING
560 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
561 long int val;
562 val = strtol(value, NULL, 0);
563 if (val < 0 || val > 0xff) {
564 ret = -1;
565 wpa_printf(MSG_DEBUG, "WPS: Invalid "
566 "wps_version_number %ld", val);
567 } else {
568 wps_version_number = val;
569 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
570 "version %u.%u",
571 (wps_version_number & 0xf0) >> 4,
572 wps_version_number & 0x0f);
573 }
574 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
575 wps_testing_stub_cred = atoi(value);
576 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
577 wps_testing_stub_cred);
578 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
579 wps_corrupt_pkhash = atoi(value);
580 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
581 wps_corrupt_pkhash);
582 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
583 if (value[0] == '\0') {
584 wps_force_auth_types_in_use = 0;
585 } else {
586 wps_force_auth_types = strtol(value, NULL, 0);
587 wps_force_auth_types_in_use = 1;
588 }
589 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
590 if (value[0] == '\0') {
591 wps_force_encr_types_in_use = 0;
592 } else {
593 wps_force_encr_types = strtol(value, NULL, 0);
594 wps_force_encr_types_in_use = 1;
595 }
596 #endif /* CONFIG_WPS_TESTING */
597 } else if (os_strcasecmp(cmd, "ampdu") == 0) {
598 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
599 ret = -1;
600 #ifdef CONFIG_TDLS
601 #ifdef CONFIG_TDLS_TESTING
602 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
603 tdls_testing = strtol(value, NULL, 0);
604 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
605 #endif /* CONFIG_TDLS_TESTING */
606 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
607 int disabled = atoi(value);
608 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
609 if (disabled) {
610 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
611 ret = -1;
612 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
613 ret = -1;
614 wpa_tdls_enable(wpa_s->wpa, !disabled);
615 #endif /* CONFIG_TDLS */
616 } else if (os_strcasecmp(cmd, "pno") == 0) {
617 ret = wpas_ctrl_pno(wpa_s, value);
618 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
619 int disabled = atoi(value);
620 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
621 ret = -1;
622 else if (disabled)
623 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
624 } else if (os_strcasecmp(cmd, "uapsd") == 0) {
625 if (os_strcmp(value, "disable") == 0)
626 wpa_s->set_sta_uapsd = 0;
627 else {
628 int be, bk, vi, vo;
629 char *pos;
630 /* format: BE,BK,VI,VO;max SP Length */
631 be = atoi(value);
632 pos = os_strchr(value, ',');
633 if (pos == NULL)
634 return -1;
635 pos++;
636 bk = atoi(pos);
637 pos = os_strchr(pos, ',');
638 if (pos == NULL)
639 return -1;
640 pos++;
641 vi = atoi(pos);
642 pos = os_strchr(pos, ',');
643 if (pos == NULL)
644 return -1;
645 pos++;
646 vo = atoi(pos);
647 /* ignore max SP Length for now */
648
649 wpa_s->set_sta_uapsd = 1;
650 wpa_s->sta_uapsd = 0;
651 if (be)
652 wpa_s->sta_uapsd |= BIT(0);
653 if (bk)
654 wpa_s->sta_uapsd |= BIT(1);
655 if (vi)
656 wpa_s->sta_uapsd |= BIT(2);
657 if (vo)
658 wpa_s->sta_uapsd |= BIT(3);
659 }
660 } else if (os_strcasecmp(cmd, "ps") == 0) {
661 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
662 #ifdef CONFIG_WIFI_DISPLAY
663 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
664 int enabled = !!atoi(value);
665 if (enabled && !wpa_s->global->p2p)
666 ret = -1;
667 else
668 wifi_display_enable(wpa_s->global, enabled);
669 #endif /* CONFIG_WIFI_DISPLAY */
670 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
671 ret = set_bssid_filter(wpa_s, value);
672 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
673 ret = set_disallow_aps(wpa_s, value);
674 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
675 wpa_s->no_keep_alive = !!atoi(value);
676 #ifdef CONFIG_DPP
677 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
678 os_free(wpa_s->dpp_configurator_params);
679 wpa_s->dpp_configurator_params = os_strdup(value);
680 #ifdef CONFIG_DPP2
681 dpp_controller_set_params(wpa_s->dpp, value);
682 #endif /* CONFIG_DPP2 */
683 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
684 wpa_s->dpp_init_max_tries = atoi(value);
685 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
686 wpa_s->dpp_init_retry_time = atoi(value);
687 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
688 wpa_s->dpp_resp_wait_time = atoi(value);
689 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
690 wpa_s->dpp_resp_max_tries = atoi(value);
691 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
692 wpa_s->dpp_resp_retry_time = atoi(value);
693 #ifdef CONFIG_TESTING_OPTIONS
694 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
695 if (hwaddr_aton(value, dpp_pkex_own_mac_override))
696 ret = -1;
697 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
698 if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
699 ret = -1;
700 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
701 size_t hex_len = os_strlen(value);
702
703 if (hex_len >
704 2 * sizeof(dpp_pkex_ephemeral_key_override))
705 ret = -1;
706 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
707 hex_len / 2))
708 ret = -1;
709 else
710 dpp_pkex_ephemeral_key_override_len = hex_len / 2;
711 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
712 size_t hex_len = os_strlen(value);
713
714 if (hex_len > 2 * sizeof(dpp_protocol_key_override))
715 ret = -1;
716 else if (hexstr2bin(value, dpp_protocol_key_override,
717 hex_len / 2))
718 ret = -1;
719 else
720 dpp_protocol_key_override_len = hex_len / 2;
721 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
722 size_t hex_len = os_strlen(value);
723
724 if (hex_len > 2 * sizeof(dpp_nonce_override))
725 ret = -1;
726 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
727 ret = -1;
728 else
729 dpp_nonce_override_len = hex_len / 2;
730 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
731 dpp_version_override = atoi(value);
732 #endif /* CONFIG_TESTING_OPTIONS */
733 #endif /* CONFIG_DPP */
734 #ifdef CONFIG_TESTING_OPTIONS
735 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
736 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
737 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
738 wpa_s->ext_eapol_frame_io = !!atoi(value);
739 #ifdef CONFIG_AP
740 if (wpa_s->ap_iface) {
741 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
742 wpa_s->ext_eapol_frame_io;
743 }
744 #endif /* CONFIG_AP */
745 } else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) {
746 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2,
747 !!atoi(value));
748 } else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) {
749 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4,
750 !!atoi(value));
751 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
752 wpa_s->extra_roc_dur = atoi(value);
753 } else if (os_strcasecmp(cmd, "test_failure") == 0) {
754 wpa_s->test_failure = atoi(value);
755 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
756 wpa_s->p2p_go_csa_on_inv = !!atoi(value);
757 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
758 wpa_s->ignore_auth_resp = !!atoi(value);
759 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
760 wpa_s->ignore_assoc_disallow = !!atoi(value);
761 wpa_drv_ignore_assoc_disallow(wpa_s,
762 wpa_s->ignore_assoc_disallow);
763 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
764 wpa_s->disable_sa_query = !!atoi(value);
765 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
766 wpa_s->ignore_sae_h2e_only = !!atoi(value);
767 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
768 char *pos;
769
770 os_free(wpa_s->extra_sae_rejected_groups);
771 wpa_s->extra_sae_rejected_groups = NULL;
772 pos = value;
773 while (pos && pos[0]) {
774 int group;
775
776 group = atoi(pos);
777 wpa_printf(MSG_DEBUG,
778 "TESTING: Extra rejection of SAE group %d",
779 group);
780 if (group)
781 int_array_add_unique(
782 &wpa_s->extra_sae_rejected_groups,
783 group);
784 pos = os_strchr(pos, ' ');
785 if (!pos)
786 break;
787 pos++;
788 }
789 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
790 wpa_s->ft_rsnxe_used = atoi(value);
791 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
792 wpa_s->oci_freq_override_eapol = atoi(value);
793 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
794 wpa_s->oci_freq_override_saquery_req = atoi(value);
795 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
796 wpa_s->oci_freq_override_saquery_resp = atoi(value);
797 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
798 wpa_s->oci_freq_override_eapol_g2 = atoi(value);
799 /* Populate value to wpa_sm if already associated. */
800 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
801 wpa_s->oci_freq_override_eapol_g2);
802 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
803 wpa_s->oci_freq_override_ft_assoc = atoi(value);
804 /* Populate value to wpa_sm if already associated. */
805 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
806 wpa_s->oci_freq_override_ft_assoc);
807 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
808 wpa_s->oci_freq_override_fils_assoc = atoi(value);
809 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
810 wpa_s->oci_freq_override_wnm_sleep = atoi(value);
811 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
812 wpabuf_free(wpa_s->rsne_override_eapol);
813 if (os_strcmp(value, "NULL") == 0)
814 wpa_s->rsne_override_eapol = NULL;
815 else
816 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
817 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
818 wpabuf_free(wpa_s->rsnxe_override_assoc);
819 if (os_strcmp(value, "NULL") == 0)
820 wpa_s->rsnxe_override_assoc = NULL;
821 else
822 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
823 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
824 wpabuf_free(wpa_s->rsnxe_override_eapol);
825 if (os_strcmp(value, "NULL") == 0)
826 wpa_s->rsnxe_override_eapol = NULL;
827 else
828 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
829 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
830 wpa_s->reject_btm_req_reason = atoi(value);
831 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
832 os_free(wpa_s->get_pref_freq_list_override);
833 if (!value[0])
834 wpa_s->get_pref_freq_list_override = NULL;
835 else
836 wpa_s->get_pref_freq_list_override = os_strdup(value);
837 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
838 wpabuf_free(wpa_s->sae_commit_override);
839 if (value[0] == '\0')
840 wpa_s->sae_commit_override = NULL;
841 else
842 wpa_s->sae_commit_override = wpabuf_parse_bin(value);
843 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
844 ret = wpas_ctrl_iface_set_dso(wpa_s, value);
845 #ifndef CONFIG_NO_ROBUST_AV
846 } else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
847 wpa_s->disable_scs_support = !!atoi(value);
848 } else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
849 wpa_s->disable_mscs_support = !!atoi(value);
850 #endif /* CONFIG_NO_ROBUST_AV */
851 } else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
852 wpa_s->disable_eapol_g2_tx = !!atoi(value);
853 /* Populate value to wpa_sm if already associated. */
854 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
855 wpa_s->disable_eapol_g2_tx);
856 } else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) {
857 wpa_s->test_assoc_comeback_type = atoi(value);
858 #ifdef CONFIG_DPP
859 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
860 os_free(wpa_s->dpp_config_obj_override);
861 if (value[0] == '\0')
862 wpa_s->dpp_config_obj_override = NULL;
863 else
864 wpa_s->dpp_config_obj_override = os_strdup(value);
865 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
866 os_free(wpa_s->dpp_discovery_override);
867 if (value[0] == '\0')
868 wpa_s->dpp_discovery_override = NULL;
869 else
870 wpa_s->dpp_discovery_override = os_strdup(value);
871 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
872 os_free(wpa_s->dpp_groups_override);
873 if (value[0] == '\0')
874 wpa_s->dpp_groups_override = NULL;
875 else
876 wpa_s->dpp_groups_override = os_strdup(value);
877 } else if (os_strcasecmp(cmd,
878 "dpp_ignore_netaccesskey_mismatch") == 0) {
879 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
880 } else if (os_strcasecmp(cmd, "dpp_discard_public_action") == 0) {
881 wpa_s->dpp_discard_public_action = atoi(value);
882 } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
883 dpp_test = atoi(value);
884 #endif /* CONFIG_DPP */
885 #endif /* CONFIG_TESTING_OPTIONS */
886 #ifdef CONFIG_FILS
887 } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
888 wpa_s->disable_fils = !!atoi(value);
889 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
890 wpa_supplicant_set_default_scan_ies(wpa_s);
891 #endif /* CONFIG_FILS */
892 #ifndef CONFIG_NO_CONFIG_BLOBS
893 } else if (os_strcmp(cmd, "blob") == 0) {
894 ret = wpas_ctrl_set_blob(wpa_s, value);
895 #endif /* CONFIG_NO_CONFIG_BLOBS */
896 } else if (os_strcasecmp(cmd, "setband") == 0) {
897 ret = wpas_ctrl_set_band(wpa_s, value);
898 #ifdef CONFIG_MBO
899 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
900 ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
901 if (ret == 0) {
902 value[-1] = '=';
903 wpa_config_process_global(wpa_s->conf, cmd, -1);
904 }
905 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
906 int val = atoi(value);
907
908 if (val < MBO_CELL_CAPA_AVAILABLE ||
909 val > MBO_CELL_CAPA_NOT_SUPPORTED)
910 return -1;
911
912 wpas_mbo_update_cell_capa(wpa_s, val);
913 } else if (os_strcasecmp(cmd, "oce") == 0) {
914 int val = atoi(value);
915
916 if (val < 0 || val > 3)
917 return -1;
918
919 wpa_s->conf->oce = val;
920 if (wpa_s->conf->oce) {
921 if ((wpa_s->conf->oce & OCE_STA) &&
922 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
923 wpa_s->enable_oce = OCE_STA;
924
925 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
926 (wpa_s->drv_flags &
927 WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
928 /* TODO: Need to add STA-CFON support */
929 wpa_printf(MSG_ERROR,
930 "OCE STA-CFON feature is not yet supported");
931 return -1;
932 }
933 } else {
934 wpa_s->enable_oce = 0;
935 }
936 wpa_supplicant_set_default_scan_ies(wpa_s);
937 #endif /* CONFIG_MBO */
938 } else if (os_strcasecmp(cmd, "lci") == 0) {
939 ret = wpas_ctrl_iface_set_lci(wpa_s, value);
940 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
941 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
942 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
943 ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
944 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
945 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
946 } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
947 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
948 } else if (os_strcasecmp(cmd, "roaming") == 0) {
949 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
950 #ifdef CONFIG_WNM
951 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
952 struct wpabuf *elems;
953
954 elems = wpabuf_parse_bin(value);
955 if (!elems)
956 return -1;
957 wnm_set_coloc_intf_elems(wpa_s, elems);
958 #endif /* CONFIG_WNM */
959 #ifndef CONFIG_NO_ROBUST_AV
960 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
961 wpa_s->enable_dscp_policy_capa = !!atoi(value);
962 #endif /* CONFIG_NO_ROBUST_AV */
963 } else {
964 value[-1] = '=';
965 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
966 if (ret == 0)
967 wpa_supplicant_update_config(wpa_s);
968 else if (ret == 1)
969 ret = 0;
970 }
971
972 return ret;
973 }
974
975
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)976 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
977 char *cmd, char *buf, size_t buflen)
978 {
979 int res = -1;
980
981 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
982
983 if (os_strcmp(cmd, "version") == 0) {
984 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
985 } else if (os_strcasecmp(cmd, "max_command_len") == 0) {
986 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
987 } else if (os_strcasecmp(cmd, "country") == 0) {
988 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
989 res = os_snprintf(buf, buflen, "%c%c",
990 wpa_s->conf->country[0],
991 wpa_s->conf->country[1]);
992 #ifdef CONFIG_WIFI_DISPLAY
993 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
994 int enabled;
995 if (wpa_s->global->p2p == NULL ||
996 wpa_s->global->p2p_disabled)
997 enabled = 0;
998 else
999 enabled = wpa_s->global->wifi_display;
1000 res = os_snprintf(buf, buflen, "%d", enabled);
1001 #endif /* CONFIG_WIFI_DISPLAY */
1002 #ifdef CONFIG_TESTING_GET_GTK
1003 } else if (os_strcmp(cmd, "gtk") == 0) {
1004 if (wpa_s->last_gtk_len == 0)
1005 return -1;
1006 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
1007 wpa_s->last_gtk_len);
1008 return res;
1009 #endif /* CONFIG_TESTING_GET_GTK */
1010 } else if (os_strcmp(cmd, "tls_library") == 0) {
1011 res = tls_get_library_version(buf, buflen);
1012 #ifdef CONFIG_TESTING_OPTIONS
1013 } else if (os_strcmp(cmd, "anonce") == 0) {
1014 return wpa_snprintf_hex(buf, buflen,
1015 wpa_sm_get_anonce(wpa_s->wpa),
1016 WPA_NONCE_LEN);
1017 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
1018 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
1019 #endif /* CONFIG_TESTING_OPTIONS */
1020 } else {
1021 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
1022 }
1023
1024 if (os_snprintf_error(buflen, res))
1025 return -1;
1026 return res;
1027 }
1028
1029
1030 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)1031 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1032 char *addr)
1033 {
1034 u8 bssid[ETH_ALEN];
1035 struct wpa_ssid *ssid = wpa_s->current_ssid;
1036
1037 if (hwaddr_aton(addr, bssid)) {
1038 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1039 "'%s'", addr);
1040 return -1;
1041 }
1042
1043 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1044 rsn_preauth_deinit(wpa_s->wpa);
1045 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1046 return -1;
1047
1048 return 0;
1049 }
1050 #endif /* IEEE8021X_EAPOL */
1051
1052
1053 #ifdef CONFIG_TDLS
1054
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)1055 static int wpa_supplicant_ctrl_iface_tdls_discover(
1056 struct wpa_supplicant *wpa_s, char *addr)
1057 {
1058 u8 peer[ETH_ALEN];
1059 int ret;
1060
1061 if (hwaddr_aton(addr, peer)) {
1062 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1063 "address '%s'", addr);
1064 return -1;
1065 }
1066
1067 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1068 MAC2STR(peer));
1069
1070 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1071 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1072 else
1073 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1074
1075 return ret;
1076 }
1077
1078
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)1079 static int wpa_supplicant_ctrl_iface_tdls_setup(
1080 struct wpa_supplicant *wpa_s, char *addr)
1081 {
1082 u8 peer[ETH_ALEN];
1083 int ret;
1084
1085 if (hwaddr_aton(addr, peer)) {
1086 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1087 "address '%s'", addr);
1088 return -1;
1089 }
1090
1091 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1092 MAC2STR(peer));
1093
1094 if ((wpa_s->conf->tdls_external_control) &&
1095 wpa_tdls_is_external_setup(wpa_s->wpa))
1096 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1097
1098 wpa_tdls_remove(wpa_s->wpa, peer);
1099
1100 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1101 ret = wpa_tdls_start(wpa_s->wpa, peer);
1102 else
1103 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1104
1105 return ret;
1106 }
1107
1108
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)1109 static int wpa_supplicant_ctrl_iface_tdls_teardown(
1110 struct wpa_supplicant *wpa_s, char *addr)
1111 {
1112 u8 peer[ETH_ALEN];
1113 int ret;
1114
1115 if (os_strcmp(addr, "*") == 0) {
1116 /* remove everyone */
1117 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1118 wpa_tdls_teardown_peers(wpa_s->wpa);
1119 return 0;
1120 }
1121
1122 if (hwaddr_aton(addr, peer)) {
1123 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1124 "address '%s'", addr);
1125 return -1;
1126 }
1127
1128 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1129 MAC2STR(peer));
1130
1131 if ((wpa_s->conf->tdls_external_control) &&
1132 wpa_tdls_is_external_setup(wpa_s->wpa))
1133 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1134
1135 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1136 ret = wpa_tdls_teardown_link(
1137 wpa_s->wpa, peer,
1138 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1139 else
1140 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1141
1142 return ret;
1143 }
1144
1145
ctrl_iface_get_capability_tdls(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1146 static int ctrl_iface_get_capability_tdls(
1147 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1148 {
1149 int ret;
1150
1151 ret = os_snprintf(buf, buflen, "%s\n",
1152 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1153 (wpa_s->drv_flags &
1154 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1155 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
1156 if (os_snprintf_error(buflen, ret))
1157 return -1;
1158 return ret;
1159 }
1160
1161
wpa_supplicant_ctrl_iface_tdls_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1162 static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1163 struct wpa_supplicant *wpa_s, char *cmd)
1164 {
1165 u8 peer[ETH_ALEN];
1166 struct hostapd_freq_params freq_params;
1167 u8 oper_class;
1168 char *pos, *end;
1169
1170 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1171 wpa_printf(MSG_INFO,
1172 "tdls_chanswitch: Only supported with external setup");
1173 return -1;
1174 }
1175
1176 os_memset(&freq_params, 0, sizeof(freq_params));
1177
1178 pos = os_strchr(cmd, ' ');
1179 if (pos == NULL)
1180 return -1;
1181 *pos++ = '\0';
1182
1183 oper_class = strtol(pos, &end, 10);
1184 if (pos == end) {
1185 wpa_printf(MSG_INFO,
1186 "tdls_chanswitch: Invalid op class provided");
1187 return -1;
1188 }
1189
1190 pos = end;
1191 freq_params.freq = atoi(pos);
1192 if (freq_params.freq == 0) {
1193 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1194 return -1;
1195 }
1196
1197 #define SET_FREQ_SETTING(str) \
1198 do { \
1199 const char *pos2 = os_strstr(pos, " " #str "="); \
1200 if (pos2) { \
1201 pos2 += sizeof(" " #str "=") - 1; \
1202 freq_params.str = atoi(pos2); \
1203 } \
1204 } while (0)
1205
1206 SET_FREQ_SETTING(center_freq1);
1207 SET_FREQ_SETTING(center_freq2);
1208 SET_FREQ_SETTING(bandwidth);
1209 SET_FREQ_SETTING(sec_channel_offset);
1210 #undef SET_FREQ_SETTING
1211
1212 freq_params.ht_enabled = !!os_strstr(pos, " ht");
1213 freq_params.vht_enabled = !!os_strstr(pos, " vht");
1214
1215 if (hwaddr_aton(cmd, peer)) {
1216 wpa_printf(MSG_DEBUG,
1217 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1218 cmd);
1219 return -1;
1220 }
1221
1222 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1223 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1224 MAC2STR(peer), oper_class, freq_params.freq,
1225 freq_params.center_freq1, freq_params.center_freq2,
1226 freq_params.bandwidth, freq_params.sec_channel_offset,
1227 freq_params.ht_enabled ? " HT" : "",
1228 freq_params.vht_enabled ? " VHT" : "");
1229
1230 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1231 &freq_params);
1232 }
1233
1234
wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1235 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1236 struct wpa_supplicant *wpa_s, char *cmd)
1237 {
1238 u8 peer[ETH_ALEN];
1239
1240 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1241 wpa_printf(MSG_INFO,
1242 "tdls_chanswitch: Only supported with external setup");
1243 return -1;
1244 }
1245
1246 if (hwaddr_aton(cmd, peer)) {
1247 wpa_printf(MSG_DEBUG,
1248 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1249 cmd);
1250 return -1;
1251 }
1252
1253 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1254 MAC2STR(peer));
1255
1256 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1257 }
1258
1259
wpa_supplicant_ctrl_iface_tdls_link_status(struct wpa_supplicant * wpa_s,const char * addr,char * buf,size_t buflen)1260 static int wpa_supplicant_ctrl_iface_tdls_link_status(
1261 struct wpa_supplicant *wpa_s, const char *addr,
1262 char *buf, size_t buflen)
1263 {
1264 u8 peer[ETH_ALEN];
1265 const char *tdls_status;
1266 int ret;
1267
1268 if (hwaddr_aton(addr, peer)) {
1269 wpa_printf(MSG_DEBUG,
1270 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1271 addr);
1272 return -1;
1273 }
1274 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1275 MAC2STR(peer));
1276
1277 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1278 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1279 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1280 if (os_snprintf_error(buflen, ret))
1281 return -1;
1282
1283 return ret;
1284 }
1285
1286 #endif /* CONFIG_TDLS */
1287
1288
1289 #ifndef CONFIG_NO_WMM_AC
wmm_ac_ctrl_addts(struct wpa_supplicant * wpa_s,char * cmd)1290 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1291 {
1292 char *token, *context = NULL;
1293 struct wmm_ac_ts_setup_params params = {
1294 .tsid = 0xff,
1295 .direction = 0xff,
1296 };
1297
1298 while ((token = str_token(cmd, " ", &context))) {
1299 if (sscanf(token, "tsid=%i", ¶ms.tsid) == 1 ||
1300 sscanf(token, "up=%i", ¶ms.user_priority) == 1 ||
1301 sscanf(token, "nominal_msdu_size=%i",
1302 ¶ms.nominal_msdu_size) == 1 ||
1303 sscanf(token, "mean_data_rate=%i",
1304 ¶ms.mean_data_rate) == 1 ||
1305 sscanf(token, "min_phy_rate=%i",
1306 ¶ms.minimum_phy_rate) == 1 ||
1307 sscanf(token, "sba=%i",
1308 ¶ms.surplus_bandwidth_allowance) == 1)
1309 continue;
1310
1311 if (os_strcasecmp(token, "downlink") == 0) {
1312 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1313 } else if (os_strcasecmp(token, "uplink") == 0) {
1314 params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1315 } else if (os_strcasecmp(token, "bidi") == 0) {
1316 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1317 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1318 params.fixed_nominal_msdu = 1;
1319 } else {
1320 wpa_printf(MSG_DEBUG,
1321 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1322 token);
1323 return -1;
1324 }
1325
1326 }
1327
1328 return wpas_wmm_ac_addts(wpa_s, ¶ms);
1329 }
1330
1331
wmm_ac_ctrl_delts(struct wpa_supplicant * wpa_s,char * cmd)1332 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1333 {
1334 u8 tsid = atoi(cmd);
1335
1336 return wpas_wmm_ac_delts(wpa_s, tsid);
1337 }
1338
1339 #endif /* CONFIG_NO_WMM_AC */
1340
1341 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)1342 static int wpa_supplicant_ctrl_iface_ft_ds(
1343 struct wpa_supplicant *wpa_s, char *addr)
1344 {
1345 u8 target_ap[ETH_ALEN];
1346 struct wpa_bss *bss;
1347 const u8 *mdie;
1348 bool force = os_strstr(addr, " force") != NULL;
1349
1350 if (hwaddr_aton(addr, target_ap)) {
1351 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1352 "address '%s'", addr);
1353 return -1;
1354 }
1355
1356 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1357
1358 bss = wpa_bss_get_bssid(wpa_s, target_ap);
1359 if (bss)
1360 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1361 else
1362 mdie = NULL;
1363
1364 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force);
1365 }
1366 #endif /* CONFIG_IEEE80211R */
1367
1368
1369 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)1370 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1371 char *cmd)
1372 {
1373 u8 bssid[ETH_ALEN], *_bssid = bssid;
1374 #ifdef CONFIG_P2P
1375 u8 p2p_dev_addr[ETH_ALEN];
1376 #endif /* CONFIG_P2P */
1377 #ifdef CONFIG_AP
1378 u8 *_p2p_dev_addr = NULL;
1379 #endif /* CONFIG_AP */
1380 char *pos;
1381 int multi_ap = 0;
1382
1383 if (!cmd || os_strcmp(cmd, "any") == 0 ||
1384 os_strncmp(cmd, "any ", 4) == 0) {
1385 _bssid = NULL;
1386 #ifdef CONFIG_P2P
1387 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1388 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1389 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1390 "P2P Device Address '%s'",
1391 cmd + 13);
1392 return -1;
1393 }
1394 _p2p_dev_addr = p2p_dev_addr;
1395 #endif /* CONFIG_P2P */
1396 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1397 _bssid = NULL;
1398 multi_ap = atoi(cmd + 9);
1399 } else if (hwaddr_aton(cmd, bssid)) {
1400 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1401 cmd);
1402 return -1;
1403 }
1404
1405 if (cmd) {
1406 pos = os_strstr(cmd, " multi_ap=");
1407 if (pos) {
1408 pos += 10;
1409 multi_ap = atoi(pos);
1410 }
1411 }
1412
1413 #ifdef CONFIG_AP
1414 if (wpa_s->ap_iface)
1415 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1416 #endif /* CONFIG_AP */
1417
1418 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
1419 }
1420
1421
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1422 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1423 char *cmd, char *buf,
1424 size_t buflen)
1425 {
1426 u8 bssid[ETH_ALEN], *_bssid = bssid;
1427 char *pin;
1428 int ret;
1429
1430 pin = os_strchr(cmd, ' ');
1431 if (pin)
1432 *pin++ = '\0';
1433
1434 if (os_strcmp(cmd, "any") == 0)
1435 _bssid = NULL;
1436 else if (os_strcmp(cmd, "get") == 0) {
1437 if (wps_generate_pin((unsigned int *) &ret) < 0)
1438 return -1;
1439 goto done;
1440 } else if (hwaddr_aton(cmd, bssid)) {
1441 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1442 cmd);
1443 return -1;
1444 }
1445
1446 #ifdef CONFIG_AP
1447 if (wpa_s->ap_iface) {
1448 int timeout = 0;
1449 char *pos;
1450
1451 if (pin) {
1452 pos = os_strchr(pin, ' ');
1453 if (pos) {
1454 *pos++ = '\0';
1455 timeout = atoi(pos);
1456 }
1457 }
1458
1459 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
1460 buf, buflen, timeout);
1461 }
1462 #endif /* CONFIG_AP */
1463
1464 if (pin) {
1465 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1466 DEV_PW_DEFAULT);
1467 if (ret < 0)
1468 return -1;
1469 ret = os_snprintf(buf, buflen, "%s", pin);
1470 if (os_snprintf_error(buflen, ret))
1471 return -1;
1472 return ret;
1473 }
1474
1475 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1476 if (ret < 0)
1477 return -1;
1478
1479 done:
1480 /* Return the generated PIN */
1481 ret = os_snprintf(buf, buflen, "%08d", ret);
1482 if (os_snprintf_error(buflen, ret))
1483 return -1;
1484 return ret;
1485 }
1486
1487
wpa_supplicant_ctrl_iface_wps_check_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1488 static int wpa_supplicant_ctrl_iface_wps_check_pin(
1489 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1490 {
1491 char pin[9];
1492 size_t len;
1493 char *pos;
1494 int ret;
1495
1496 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1497 (u8 *) cmd, os_strlen(cmd));
1498 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1499 if (*pos < '0' || *pos > '9')
1500 continue;
1501 pin[len++] = *pos;
1502 if (len == 9) {
1503 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1504 return -1;
1505 }
1506 }
1507 if (len != 4 && len != 8) {
1508 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1509 return -1;
1510 }
1511 pin[len] = '\0';
1512
1513 if (len == 8) {
1514 unsigned int pin_val;
1515 pin_val = atoi(pin);
1516 if (!wps_pin_valid(pin_val)) {
1517 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1518 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
1519 if (os_snprintf_error(buflen, ret))
1520 return -1;
1521 return ret;
1522 }
1523 }
1524
1525 ret = os_snprintf(buf, buflen, "%s", pin);
1526 if (os_snprintf_error(buflen, ret))
1527 return -1;
1528
1529 return ret;
1530 }
1531
1532
1533 #ifdef CONFIG_WPS_NFC
1534
wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant * wpa_s,char * cmd)1535 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1536 char *cmd)
1537 {
1538 u8 bssid[ETH_ALEN], *_bssid = bssid;
1539
1540 if (cmd == NULL || cmd[0] == '\0')
1541 _bssid = NULL;
1542 else if (hwaddr_aton(cmd, bssid))
1543 return -1;
1544
1545 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1546 0, 0);
1547 }
1548
1549
wpa_supplicant_ctrl_iface_wps_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1550 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1551 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1552 {
1553 int ndef;
1554 struct wpabuf *buf;
1555 int res;
1556 char *pos;
1557
1558 pos = os_strchr(cmd, ' ');
1559 if (pos)
1560 *pos++ = '\0';
1561 if (os_strcmp(cmd, "WPS") == 0)
1562 ndef = 0;
1563 else if (os_strcmp(cmd, "NDEF") == 0)
1564 ndef = 1;
1565 else
1566 return -1;
1567
1568 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1569 if (buf == NULL)
1570 return -1;
1571
1572 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1573 wpabuf_len(buf));
1574 reply[res++] = '\n';
1575 reply[res] = '\0';
1576
1577 wpabuf_free(buf);
1578
1579 return res;
1580 }
1581
1582
wpa_supplicant_ctrl_iface_wps_nfc_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1583 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1584 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1585 {
1586 int ndef;
1587 struct wpabuf *buf;
1588 int res;
1589
1590 if (os_strcmp(cmd, "WPS") == 0)
1591 ndef = 0;
1592 else if (os_strcmp(cmd, "NDEF") == 0)
1593 ndef = 1;
1594 else
1595 return -1;
1596
1597 buf = wpas_wps_nfc_token(wpa_s, ndef);
1598 if (buf == NULL)
1599 return -1;
1600
1601 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1602 wpabuf_len(buf));
1603 reply[res++] = '\n';
1604 reply[res] = '\0';
1605
1606 wpabuf_free(buf);
1607
1608 return res;
1609 }
1610
1611
wpa_supplicant_ctrl_iface_wps_nfc_tag_read(struct wpa_supplicant * wpa_s,char * pos)1612 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1613 struct wpa_supplicant *wpa_s, char *pos)
1614 {
1615 size_t len;
1616 struct wpabuf *buf;
1617 int ret;
1618 char *freq;
1619 int forced_freq = 0;
1620
1621 freq = strstr(pos, " freq=");
1622 if (freq) {
1623 *freq = '\0';
1624 freq += 6;
1625 forced_freq = atoi(freq);
1626 }
1627
1628 len = os_strlen(pos);
1629 if (len & 0x01)
1630 return -1;
1631 len /= 2;
1632
1633 buf = wpabuf_alloc(len);
1634 if (buf == NULL)
1635 return -1;
1636 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1637 wpabuf_free(buf);
1638 return -1;
1639 }
1640
1641 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1642 wpabuf_free(buf);
1643
1644 return ret;
1645 }
1646
1647
wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1648 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1649 char *reply, size_t max_len,
1650 int ndef)
1651 {
1652 struct wpabuf *buf;
1653 int res;
1654
1655 buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1656 if (buf == NULL)
1657 return -1;
1658
1659 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1660 wpabuf_len(buf));
1661 reply[res++] = '\n';
1662 reply[res] = '\0';
1663
1664 wpabuf_free(buf);
1665
1666 return res;
1667 }
1668
1669
1670 #ifdef CONFIG_P2P
wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1671 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1672 char *reply, size_t max_len,
1673 int ndef)
1674 {
1675 struct wpabuf *buf;
1676 int res;
1677
1678 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1679 if (buf == NULL) {
1680 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1681 return -1;
1682 }
1683
1684 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1685 wpabuf_len(buf));
1686 reply[res++] = '\n';
1687 reply[res] = '\0';
1688
1689 wpabuf_free(buf);
1690
1691 return res;
1692 }
1693 #endif /* CONFIG_P2P */
1694
1695
wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1696 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1697 char *cmd, char *reply,
1698 size_t max_len)
1699 {
1700 char *pos;
1701 int ndef;
1702
1703 pos = os_strchr(cmd, ' ');
1704 if (pos == NULL)
1705 return -1;
1706 *pos++ = '\0';
1707
1708 if (os_strcmp(cmd, "WPS") == 0)
1709 ndef = 0;
1710 else if (os_strcmp(cmd, "NDEF") == 0)
1711 ndef = 1;
1712 else
1713 return -1;
1714
1715 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1716 if (!ndef)
1717 return -1;
1718 return wpas_ctrl_nfc_get_handover_req_wps(
1719 wpa_s, reply, max_len, ndef);
1720 }
1721
1722 #ifdef CONFIG_P2P
1723 if (os_strcmp(pos, "P2P-CR") == 0) {
1724 return wpas_ctrl_nfc_get_handover_req_p2p(
1725 wpa_s, reply, max_len, ndef);
1726 }
1727 #endif /* CONFIG_P2P */
1728
1729 return -1;
1730 }
1731
1732
wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef,int cr,char * uuid)1733 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1734 char *reply, size_t max_len,
1735 int ndef, int cr, char *uuid)
1736 {
1737 struct wpabuf *buf;
1738 int res;
1739
1740 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1741 if (buf == NULL)
1742 return -1;
1743
1744 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1745 wpabuf_len(buf));
1746 reply[res++] = '\n';
1747 reply[res] = '\0';
1748
1749 wpabuf_free(buf);
1750
1751 return res;
1752 }
1753
1754
1755 #ifdef CONFIG_P2P
wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef,int tag)1756 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1757 char *reply, size_t max_len,
1758 int ndef, int tag)
1759 {
1760 struct wpabuf *buf;
1761 int res;
1762
1763 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1764 if (buf == NULL)
1765 return -1;
1766
1767 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1768 wpabuf_len(buf));
1769 reply[res++] = '\n';
1770 reply[res] = '\0';
1771
1772 wpabuf_free(buf);
1773
1774 return res;
1775 }
1776 #endif /* CONFIG_P2P */
1777
1778
wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1779 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1780 char *cmd, char *reply,
1781 size_t max_len)
1782 {
1783 char *pos, *pos2;
1784 int ndef;
1785
1786 pos = os_strchr(cmd, ' ');
1787 if (pos == NULL)
1788 return -1;
1789 *pos++ = '\0';
1790
1791 if (os_strcmp(cmd, "WPS") == 0)
1792 ndef = 0;
1793 else if (os_strcmp(cmd, "NDEF") == 0)
1794 ndef = 1;
1795 else
1796 return -1;
1797
1798 pos2 = os_strchr(pos, ' ');
1799 if (pos2)
1800 *pos2++ = '\0';
1801 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1802 if (!ndef)
1803 return -1;
1804 return wpas_ctrl_nfc_get_handover_sel_wps(
1805 wpa_s, reply, max_len, ndef,
1806 os_strcmp(pos, "WPS-CR") == 0, pos2);
1807 }
1808
1809 #ifdef CONFIG_P2P
1810 if (os_strcmp(pos, "P2P-CR") == 0) {
1811 return wpas_ctrl_nfc_get_handover_sel_p2p(
1812 wpa_s, reply, max_len, ndef, 0);
1813 }
1814
1815 if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1816 return wpas_ctrl_nfc_get_handover_sel_p2p(
1817 wpa_s, reply, max_len, ndef, 1);
1818 }
1819 #endif /* CONFIG_P2P */
1820
1821 return -1;
1822 }
1823
1824
wpas_ctrl_nfc_report_handover(struct wpa_supplicant * wpa_s,char * cmd)1825 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1826 char *cmd)
1827 {
1828 size_t len;
1829 struct wpabuf *req, *sel;
1830 int ret;
1831 char *pos, *role, *type, *pos2;
1832 #ifdef CONFIG_P2P
1833 char *freq;
1834 int forced_freq = 0;
1835
1836 freq = strstr(cmd, " freq=");
1837 if (freq) {
1838 *freq = '\0';
1839 freq += 6;
1840 forced_freq = atoi(freq);
1841 }
1842 #endif /* CONFIG_P2P */
1843
1844 role = cmd;
1845 pos = os_strchr(role, ' ');
1846 if (pos == NULL) {
1847 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1848 return -1;
1849 }
1850 *pos++ = '\0';
1851
1852 type = pos;
1853 pos = os_strchr(type, ' ');
1854 if (pos == NULL) {
1855 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1856 return -1;
1857 }
1858 *pos++ = '\0';
1859
1860 pos2 = os_strchr(pos, ' ');
1861 if (pos2 == NULL) {
1862 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1863 return -1;
1864 }
1865 *pos2++ = '\0';
1866
1867 len = os_strlen(pos);
1868 if (len & 0x01) {
1869 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1870 return -1;
1871 }
1872 len /= 2;
1873
1874 req = wpabuf_alloc(len);
1875 if (req == NULL) {
1876 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1877 return -1;
1878 }
1879 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1880 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1881 wpabuf_free(req);
1882 return -1;
1883 }
1884
1885 len = os_strlen(pos2);
1886 if (len & 0x01) {
1887 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1888 wpabuf_free(req);
1889 return -1;
1890 }
1891 len /= 2;
1892
1893 sel = wpabuf_alloc(len);
1894 if (sel == NULL) {
1895 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1896 wpabuf_free(req);
1897 return -1;
1898 }
1899 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1900 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1901 wpabuf_free(req);
1902 wpabuf_free(sel);
1903 return -1;
1904 }
1905
1906 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1907 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1908
1909 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1910 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1911 #ifdef CONFIG_AP
1912 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1913 {
1914 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1915 if (ret < 0)
1916 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1917 #endif /* CONFIG_AP */
1918 #ifdef CONFIG_P2P
1919 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1920 {
1921 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1922 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1923 {
1924 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1925 forced_freq);
1926 #endif /* CONFIG_P2P */
1927 } else {
1928 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1929 "reported: role=%s type=%s", role, type);
1930 ret = -1;
1931 }
1932 wpabuf_free(req);
1933 wpabuf_free(sel);
1934
1935 if (ret)
1936 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1937
1938 return ret;
1939 }
1940
1941 #endif /* CONFIG_WPS_NFC */
1942
1943
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)1944 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1945 char *cmd)
1946 {
1947 u8 bssid[ETH_ALEN];
1948 char *pin;
1949 char *new_ssid;
1950 char *new_auth;
1951 char *new_encr;
1952 char *new_key;
1953 struct wps_new_ap_settings ap;
1954
1955 pin = os_strchr(cmd, ' ');
1956 if (pin == NULL)
1957 return -1;
1958 *pin++ = '\0';
1959
1960 if (hwaddr_aton(cmd, bssid)) {
1961 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1962 cmd);
1963 return -1;
1964 }
1965
1966 new_ssid = os_strchr(pin, ' ');
1967 if (new_ssid == NULL)
1968 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1969 *new_ssid++ = '\0';
1970
1971 new_auth = os_strchr(new_ssid, ' ');
1972 if (new_auth == NULL)
1973 return -1;
1974 *new_auth++ = '\0';
1975
1976 new_encr = os_strchr(new_auth, ' ');
1977 if (new_encr == NULL)
1978 return -1;
1979 *new_encr++ = '\0';
1980
1981 new_key = os_strchr(new_encr, ' ');
1982 if (new_key == NULL)
1983 return -1;
1984 *new_key++ = '\0';
1985
1986 os_memset(&ap, 0, sizeof(ap));
1987 ap.ssid_hex = new_ssid;
1988 ap.auth = new_auth;
1989 ap.encr = new_encr;
1990 ap.key_hex = new_key;
1991 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1992 }
1993
1994
1995 #ifdef CONFIG_AP
wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1996 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1997 char *cmd, char *buf,
1998 size_t buflen)
1999 {
2000 int timeout = 300;
2001 char *pos;
2002 const char *pin_txt;
2003
2004 if (!wpa_s->ap_iface)
2005 return -1;
2006
2007 pos = os_strchr(cmd, ' ');
2008 if (pos)
2009 *pos++ = '\0';
2010
2011 if (os_strcmp(cmd, "disable") == 0) {
2012 wpas_wps_ap_pin_disable(wpa_s);
2013 return os_snprintf(buf, buflen, "OK\n");
2014 }
2015
2016 if (os_strcmp(cmd, "random") == 0) {
2017 if (pos)
2018 timeout = atoi(pos);
2019 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
2020 if (pin_txt == NULL)
2021 return -1;
2022 return os_snprintf(buf, buflen, "%s", pin_txt);
2023 }
2024
2025 if (os_strcmp(cmd, "get") == 0) {
2026 pin_txt = wpas_wps_ap_pin_get(wpa_s);
2027 if (pin_txt == NULL)
2028 return -1;
2029 return os_snprintf(buf, buflen, "%s", pin_txt);
2030 }
2031
2032 if (os_strcmp(cmd, "set") == 0) {
2033 char *pin;
2034 if (pos == NULL)
2035 return -1;
2036 pin = pos;
2037 pos = os_strchr(pos, ' ');
2038 if (pos) {
2039 *pos++ = '\0';
2040 timeout = atoi(pos);
2041 }
2042 if (os_strlen(pin) > buflen)
2043 return -1;
2044 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2045 return -1;
2046 return os_snprintf(buf, buflen, "%s", pin);
2047 }
2048
2049 return -1;
2050 }
2051 #endif /* CONFIG_AP */
2052
2053
2054 #ifdef CONFIG_WPS_ER
wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant * wpa_s,char * cmd)2055 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2056 char *cmd)
2057 {
2058 char *uuid = cmd, *pin, *pos;
2059 u8 addr_buf[ETH_ALEN], *addr = NULL;
2060 pin = os_strchr(uuid, ' ');
2061 if (pin == NULL)
2062 return -1;
2063 *pin++ = '\0';
2064 pos = os_strchr(pin, ' ');
2065 if (pos) {
2066 *pos++ = '\0';
2067 if (hwaddr_aton(pos, addr_buf) == 0)
2068 addr = addr_buf;
2069 }
2070 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2071 }
2072
2073
wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant * wpa_s,char * cmd)2074 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2075 char *cmd)
2076 {
2077 char *uuid = cmd, *pin;
2078 pin = os_strchr(uuid, ' ');
2079 if (pin == NULL)
2080 return -1;
2081 *pin++ = '\0';
2082 return wpas_wps_er_learn(wpa_s, uuid, pin);
2083 }
2084
2085
wpa_supplicant_ctrl_iface_wps_er_set_config(struct wpa_supplicant * wpa_s,char * cmd)2086 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2087 struct wpa_supplicant *wpa_s, char *cmd)
2088 {
2089 char *uuid = cmd, *id;
2090 id = os_strchr(uuid, ' ');
2091 if (id == NULL)
2092 return -1;
2093 *id++ = '\0';
2094 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2095 }
2096
2097
wpa_supplicant_ctrl_iface_wps_er_config(struct wpa_supplicant * wpa_s,char * cmd)2098 static int wpa_supplicant_ctrl_iface_wps_er_config(
2099 struct wpa_supplicant *wpa_s, char *cmd)
2100 {
2101 char *pin;
2102 char *new_ssid;
2103 char *new_auth;
2104 char *new_encr;
2105 char *new_key;
2106 struct wps_new_ap_settings ap;
2107
2108 pin = os_strchr(cmd, ' ');
2109 if (pin == NULL)
2110 return -1;
2111 *pin++ = '\0';
2112
2113 new_ssid = os_strchr(pin, ' ');
2114 if (new_ssid == NULL)
2115 return -1;
2116 *new_ssid++ = '\0';
2117
2118 new_auth = os_strchr(new_ssid, ' ');
2119 if (new_auth == NULL)
2120 return -1;
2121 *new_auth++ = '\0';
2122
2123 new_encr = os_strchr(new_auth, ' ');
2124 if (new_encr == NULL)
2125 return -1;
2126 *new_encr++ = '\0';
2127
2128 new_key = os_strchr(new_encr, ' ');
2129 if (new_key == NULL)
2130 return -1;
2131 *new_key++ = '\0';
2132
2133 os_memset(&ap, 0, sizeof(ap));
2134 ap.ssid_hex = new_ssid;
2135 ap.auth = new_auth;
2136 ap.encr = new_encr;
2137 ap.key_hex = new_key;
2138 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2139 }
2140
2141
2142 #ifdef CONFIG_WPS_NFC
wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)2143 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2144 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2145 {
2146 int ndef;
2147 struct wpabuf *buf;
2148 int res;
2149 char *uuid;
2150
2151 uuid = os_strchr(cmd, ' ');
2152 if (uuid == NULL)
2153 return -1;
2154 *uuid++ = '\0';
2155
2156 if (os_strcmp(cmd, "WPS") == 0)
2157 ndef = 0;
2158 else if (os_strcmp(cmd, "NDEF") == 0)
2159 ndef = 1;
2160 else
2161 return -1;
2162
2163 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2164 if (buf == NULL)
2165 return -1;
2166
2167 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2168 wpabuf_len(buf));
2169 reply[res++] = '\n';
2170 reply[res] = '\0';
2171
2172 wpabuf_free(buf);
2173
2174 return res;
2175 }
2176 #endif /* CONFIG_WPS_NFC */
2177 #endif /* CONFIG_WPS_ER */
2178
2179 #endif /* CONFIG_WPS */
2180
2181
2182 #ifdef CONFIG_IBSS_RSN
wpa_supplicant_ctrl_iface_ibss_rsn(struct wpa_supplicant * wpa_s,char * addr)2183 static int wpa_supplicant_ctrl_iface_ibss_rsn(
2184 struct wpa_supplicant *wpa_s, char *addr)
2185 {
2186 u8 peer[ETH_ALEN];
2187
2188 if (hwaddr_aton(addr, peer)) {
2189 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2190 "address '%s'", addr);
2191 return -1;
2192 }
2193
2194 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2195 MAC2STR(peer));
2196
2197 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2198 }
2199 #endif /* CONFIG_IBSS_RSN */
2200
2201
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)2202 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2203 char *rsp)
2204 {
2205 #ifdef IEEE8021X_EAPOL
2206 char *pos, *id_pos;
2207 int id;
2208 struct wpa_ssid *ssid;
2209
2210 pos = os_strchr(rsp, '-');
2211 if (pos == NULL)
2212 return -1;
2213 *pos++ = '\0';
2214 id_pos = pos;
2215 pos = os_strchr(pos, ':');
2216 if (pos == NULL)
2217 return -1;
2218 *pos++ = '\0';
2219 id = atoi(id_pos);
2220 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2221 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2222 (u8 *) pos, os_strlen(pos));
2223
2224 ssid = wpa_config_get_network(wpa_s->conf, id);
2225 if (ssid == NULL) {
2226 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2227 "to update", id);
2228 return -1;
2229 }
2230
2231 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2232 pos);
2233 #else /* IEEE8021X_EAPOL */
2234 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2235 return -1;
2236 #endif /* IEEE8021X_EAPOL */
2237 }
2238
2239
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)2240 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2241 const char *params,
2242 char *buf, size_t buflen)
2243 {
2244 char *pos, *end, tmp[30];
2245 int res, verbose, wps, ret;
2246 #ifdef CONFIG_HS20
2247 const u8 *hs20;
2248 #endif /* CONFIG_HS20 */
2249 const u8 *sess_id;
2250 size_t sess_id_len;
2251
2252 if (os_strcmp(params, "-DRIVER") == 0)
2253 return wpa_drv_status(wpa_s, buf, buflen);
2254 verbose = os_strcmp(params, "-VERBOSE") == 0;
2255 wps = os_strcmp(params, "-WPS") == 0;
2256 pos = buf;
2257 end = buf + buflen;
2258 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2259 struct wpa_ssid *ssid = wpa_s->current_ssid;
2260 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2261 MAC2STR(wpa_s->bssid));
2262 if (os_snprintf_error(end - pos, ret))
2263 return pos - buf;
2264 pos += ret;
2265 ret = os_snprintf(pos, end - pos, "freq=%u\n",
2266 wpa_s->assoc_freq);
2267 if (os_snprintf_error(end - pos, ret))
2268 return pos - buf;
2269 pos += ret;
2270 if (ssid) {
2271 u8 *_ssid = ssid->ssid;
2272 size_t ssid_len = ssid->ssid_len;
2273 u8 ssid_buf[SSID_MAX_LEN];
2274 if (ssid_len == 0) {
2275 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2276 if (_res < 0)
2277 ssid_len = 0;
2278 else
2279 ssid_len = _res;
2280 _ssid = ssid_buf;
2281 }
2282 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2283 wpa_ssid_txt(_ssid, ssid_len),
2284 ssid->id);
2285 if (os_snprintf_error(end - pos, ret))
2286 return pos - buf;
2287 pos += ret;
2288
2289 if (wps && ssid->passphrase &&
2290 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2291 (ssid->mode == WPAS_MODE_AP ||
2292 ssid->mode == WPAS_MODE_P2P_GO)) {
2293 ret = os_snprintf(pos, end - pos,
2294 "passphrase=%s\n",
2295 ssid->passphrase);
2296 if (os_snprintf_error(end - pos, ret))
2297 return pos - buf;
2298 pos += ret;
2299 }
2300 if (ssid->id_str) {
2301 ret = os_snprintf(pos, end - pos,
2302 "id_str=%s\n",
2303 ssid->id_str);
2304 if (os_snprintf_error(end - pos, ret))
2305 return pos - buf;
2306 pos += ret;
2307 }
2308
2309 switch (ssid->mode) {
2310 case WPAS_MODE_INFRA:
2311 ret = os_snprintf(pos, end - pos,
2312 "mode=station\n");
2313 break;
2314 case WPAS_MODE_IBSS:
2315 ret = os_snprintf(pos, end - pos,
2316 "mode=IBSS\n");
2317 break;
2318 case WPAS_MODE_AP:
2319 ret = os_snprintf(pos, end - pos,
2320 "mode=AP\n");
2321 break;
2322 case WPAS_MODE_P2P_GO:
2323 ret = os_snprintf(pos, end - pos,
2324 "mode=P2P GO\n");
2325 break;
2326 case WPAS_MODE_P2P_GROUP_FORMATION:
2327 ret = os_snprintf(pos, end - pos,
2328 "mode=P2P GO - group "
2329 "formation\n");
2330 break;
2331 case WPAS_MODE_MESH:
2332 ret = os_snprintf(pos, end - pos,
2333 "mode=mesh\n");
2334 break;
2335 default:
2336 ret = 0;
2337 break;
2338 }
2339 if (os_snprintf_error(end - pos, ret))
2340 return pos - buf;
2341 pos += ret;
2342 }
2343
2344 if (wpa_s->connection_set &&
2345 (wpa_s->connection_ht || wpa_s->connection_vht ||
2346 wpa_s->connection_he || wpa_s->connection_eht)) {
2347 ret = os_snprintf(pos, end - pos,
2348 "wifi_generation=%u\n",
2349 wpa_s->connection_eht ? 7 :
2350 (wpa_s->connection_he ? 6 :
2351 (wpa_s->connection_vht ? 5 : 4)));
2352 if (os_snprintf_error(end - pos, ret))
2353 return pos - buf;
2354 pos += ret;
2355 }
2356
2357 #ifdef CONFIG_AP
2358 if (wpa_s->ap_iface) {
2359 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2360 end - pos,
2361 verbose);
2362 } else
2363 #endif /* CONFIG_AP */
2364 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2365 }
2366 #ifdef CONFIG_SME
2367 #ifdef CONFIG_SAE
2368 if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
2369 #ifdef CONFIG_AP
2370 !wpa_s->ap_iface &&
2371 #endif /* CONFIG_AP */
2372 wpa_s->sme.sae.state == SAE_ACCEPTED) {
2373 ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2374 "sae_h2e=%d\n"
2375 "sae_pk=%d\n",
2376 wpa_s->sme.sae.group,
2377 wpa_s->sme.sae.h2e,
2378 wpa_s->sme.sae.pk);
2379 if (os_snprintf_error(end - pos, ret))
2380 return pos - buf;
2381 pos += ret;
2382 }
2383 #endif /* CONFIG_SAE */
2384 #endif /* CONFIG_SME */
2385 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2386 wpa_supplicant_state_txt(wpa_s->wpa_state));
2387 if (os_snprintf_error(end - pos, ret))
2388 return pos - buf;
2389 pos += ret;
2390
2391 if (wpa_s->l2 &&
2392 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2393 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
2394 if (os_snprintf_error(end - pos, ret))
2395 return pos - buf;
2396 pos += ret;
2397 }
2398
2399 #ifdef CONFIG_P2P
2400 if (wpa_s->global->p2p) {
2401 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2402 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
2403 if (os_snprintf_error(end - pos, ret))
2404 return pos - buf;
2405 pos += ret;
2406 }
2407 #endif /* CONFIG_P2P */
2408
2409 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2410 MAC2STR(wpa_s->own_addr));
2411 if (os_snprintf_error(end - pos, ret))
2412 return pos - buf;
2413 pos += ret;
2414
2415 if (wpa_s->valid_links) {
2416 ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n",
2417 MAC2STR(wpa_s->ap_mld_addr));
2418 if (os_snprintf_error(end - pos, ret))
2419 return pos - buf;
2420 pos += ret;
2421 }
2422
2423 #ifdef CONFIG_HS20
2424 if (wpa_s->current_bss &&
2425 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2426 HS20_IE_VENDOR_TYPE)) &&
2427 wpa_s->wpa_proto == WPA_PROTO_RSN &&
2428 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2429 int release = 1;
2430 if (hs20[1] >= 5) {
2431 u8 rel_num = (hs20[6] & 0xf0) >> 4;
2432 release = rel_num + 1;
2433 }
2434 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
2435 if (os_snprintf_error(end - pos, ret))
2436 return pos - buf;
2437 pos += ret;
2438 }
2439
2440 if (wpa_s->current_ssid) {
2441 struct wpa_cred *cred;
2442 char *type;
2443
2444 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2445 size_t i;
2446
2447 if (wpa_s->current_ssid->parent_cred != cred)
2448 continue;
2449
2450 if (cred->provisioning_sp) {
2451 ret = os_snprintf(pos, end - pos,
2452 "provisioning_sp=%s\n",
2453 cred->provisioning_sp);
2454 if (os_snprintf_error(end - pos, ret))
2455 return pos - buf;
2456 pos += ret;
2457 }
2458
2459 if (!cred->domain)
2460 goto no_domain;
2461
2462 i = 0;
2463 if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2464 struct wpabuf *names =
2465 wpa_s->current_bss->anqp->domain_name;
2466 for (i = 0; names && i < cred->num_domain; i++)
2467 {
2468 if (domain_name_list_contains(
2469 names, cred->domain[i], 1))
2470 break;
2471 }
2472 if (i == cred->num_domain)
2473 i = 0; /* show first entry by default */
2474 }
2475 ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2476 cred->domain[i]);
2477 if (os_snprintf_error(end - pos, ret))
2478 return pos - buf;
2479 pos += ret;
2480
2481 no_domain:
2482 if (wpa_s->current_bss == NULL ||
2483 wpa_s->current_bss->anqp == NULL)
2484 res = -1;
2485 else
2486 res = interworking_home_sp_cred(
2487 wpa_s, cred,
2488 wpa_s->current_bss->anqp->domain_name);
2489 if (res > 0)
2490 type = "home";
2491 else if (res == 0)
2492 type = "roaming";
2493 else
2494 type = "unknown";
2495
2496 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
2497 if (os_snprintf_error(end - pos, ret))
2498 return pos - buf;
2499 pos += ret;
2500
2501 break;
2502 }
2503 }
2504 #endif /* CONFIG_HS20 */
2505
2506 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2507 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2508 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2509 verbose);
2510 if (res >= 0)
2511 pos += res;
2512 }
2513
2514 #ifdef CONFIG_MACSEC
2515 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2516 if (res > 0)
2517 pos += res;
2518 #endif /* CONFIG_MACSEC */
2519
2520 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2521 if (sess_id) {
2522 char *start = pos;
2523
2524 ret = os_snprintf(pos, end - pos, "eap_session_id=");
2525 if (os_snprintf_error(end - pos, ret))
2526 return start - buf;
2527 pos += ret;
2528 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2529 if (ret <= 0)
2530 return start - buf;
2531 pos += ret;
2532 ret = os_snprintf(pos, end - pos, "\n");
2533 if (os_snprintf_error(end - pos, ret))
2534 return start - buf;
2535 pos += ret;
2536 }
2537
2538 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2539 if (res >= 0)
2540 pos += res;
2541
2542 #ifdef CONFIG_WPS
2543 {
2544 char uuid_str[100];
2545 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2546 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
2547 if (os_snprintf_error(end - pos, ret))
2548 return pos - buf;
2549 pos += ret;
2550 }
2551 #endif /* CONFIG_WPS */
2552
2553 if (wpa_s->ieee80211ac) {
2554 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2555 if (os_snprintf_error(end - pos, ret))
2556 return pos - buf;
2557 pos += ret;
2558 }
2559
2560 #ifdef CONFIG_SME
2561 if (wpa_s->sme.bss_max_idle_period) {
2562 ret = os_snprintf(pos, end - pos, "bss_max_idle_period=%d\n",
2563 wpa_s->sme.bss_max_idle_period);
2564 if (os_snprintf_error(end - pos, ret))
2565 return pos - buf;
2566 pos += ret;
2567 }
2568 #endif /* CONFIG_SME */
2569
2570 if (wpa_s->ssid_verified) {
2571 ret = os_snprintf(pos, end - pos, "ssid_verified=1\n");
2572 if (os_snprintf_error(end - pos, ret))
2573 return pos - buf;
2574 pos += ret;
2575 }
2576
2577 if (wpa_s->bigtk_set) {
2578 ret = os_snprintf(pos, end - pos, "bigtk_set=1\n");
2579 if (os_snprintf_error(end - pos, ret))
2580 return pos - buf;
2581 pos += ret;
2582 }
2583
2584 #ifdef ANDROID
2585 /*
2586 * Allow using the STATUS command with default behavior, say for debug,
2587 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2588 * events with STATUS-NO_EVENTS.
2589 */
2590 if (os_strcmp(params, "-NO_EVENTS")) {
2591 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2592 "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2593 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2594 wpa_s->wpa_state,
2595 MAC2STR(wpa_s->bssid),
2596 wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2597 wpa_ssid_txt(wpa_s->current_ssid->ssid,
2598 wpa_s->current_ssid->ssid_len) : "");
2599 if (wpa_s->wpa_state == WPA_COMPLETED) {
2600 struct wpa_ssid *ssid = wpa_s->current_ssid;
2601 char mld_addr[50];
2602
2603 mld_addr[0] = '\0';
2604 if (wpa_s->valid_links)
2605 os_snprintf(mld_addr, sizeof(mld_addr),
2606 " ap_mld_addr=" MACSTR,
2607 MAC2STR(wpa_s->ap_mld_addr));
2608
2609 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2610 "- connection to " MACSTR
2611 " completed %s [id=%d id_str=%s]%s",
2612 MAC2STR(wpa_s->bssid), "(auth)",
2613 ssid ? ssid->id : -1,
2614 ssid && ssid->id_str ? ssid->id_str : "",
2615 mld_addr);
2616 }
2617 }
2618 #endif /* ANDROID */
2619
2620 return pos - buf;
2621 }
2622
2623
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)2624 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2625 char *cmd)
2626 {
2627 char *pos;
2628 int id;
2629 struct wpa_ssid *ssid;
2630 u8 bssid[ETH_ALEN];
2631
2632 /* cmd: "<network id> <BSSID>" */
2633 pos = os_strchr(cmd, ' ');
2634 if (pos == NULL)
2635 return -1;
2636 *pos++ = '\0';
2637 id = atoi(cmd);
2638 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2639 if (hwaddr_aton(pos, bssid)) {
2640 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2641 return -1;
2642 }
2643
2644 ssid = wpa_config_get_network(wpa_s->conf, id);
2645 if (ssid == NULL) {
2646 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2647 "to update", id);
2648 return -1;
2649 }
2650
2651 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2652 ssid->bssid_set = !is_zero_ether_addr(bssid);
2653
2654 return 0;
2655 }
2656
2657
wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2658 static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2659 char *cmd, char *buf,
2660 size_t buflen)
2661 {
2662 u8 bssid[ETH_ALEN];
2663 struct wpa_bssid_ignore *e;
2664 char *pos, *end;
2665 int ret;
2666
2667 /* cmd: "BSSID_IGNORE [<BSSID>]" */
2668 if (*cmd == '\0') {
2669 pos = buf;
2670 end = buf + buflen;
2671 e = wpa_s->bssid_ignore;
2672 while (e) {
2673 ret = os_snprintf(pos, end - pos, MACSTR "\n",
2674 MAC2STR(e->bssid));
2675 if (os_snprintf_error(end - pos, ret))
2676 return pos - buf;
2677 pos += ret;
2678 e = e->next;
2679 }
2680 return pos - buf;
2681 }
2682
2683 cmd++;
2684 if (os_strncmp(cmd, "clear", 5) == 0) {
2685 wpa_bssid_ignore_clear(wpa_s);
2686 os_memcpy(buf, "OK\n", 3);
2687 return 3;
2688 }
2689
2690 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
2691 if (hwaddr_aton(cmd, bssid)) {
2692 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2693 return -1;
2694 }
2695
2696 /*
2697 * Add the BSSID twice, so its count will be 2, causing it to be
2698 * skipped when processing scan results.
2699 */
2700 ret = wpa_bssid_ignore_add(wpa_s, bssid);
2701 if (ret < 0)
2702 return -1;
2703 ret = wpa_bssid_ignore_add(wpa_s, bssid);
2704 if (ret < 0)
2705 return -1;
2706 os_memcpy(buf, "OK\n", 3);
2707 return 3;
2708 }
2709
2710
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2711 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2712 char *cmd, char *buf,
2713 size_t buflen)
2714 {
2715 char *pos, *end, *stamp;
2716 int ret;
2717
2718 /* cmd: "LOG_LEVEL [<level>]" */
2719 if (*cmd == '\0') {
2720 pos = buf;
2721 end = buf + buflen;
2722 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2723 "Timestamp: %d\n",
2724 debug_level_str(wpa_debug_level),
2725 wpa_debug_timestamp);
2726 if (os_snprintf_error(end - pos, ret))
2727 ret = 0;
2728
2729 return ret;
2730 }
2731
2732 while (*cmd == ' ')
2733 cmd++;
2734
2735 stamp = os_strchr(cmd, ' ');
2736 if (stamp) {
2737 *stamp++ = '\0';
2738 while (*stamp == ' ') {
2739 stamp++;
2740 }
2741 }
2742
2743 if (os_strlen(cmd)) {
2744 int level = str_to_debug_level(cmd);
2745 if (level < 0)
2746 return -1;
2747 wpa_debug_level = level;
2748 }
2749
2750 if (stamp && os_strlen(stamp))
2751 wpa_debug_timestamp = atoi(stamp);
2752
2753 os_memcpy(buf, "OK\n", 3);
2754 return 3;
2755 }
2756
2757
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2758 static int wpa_supplicant_ctrl_iface_list_networks(
2759 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2760 {
2761 char *pos, *end, *prev;
2762 struct wpa_ssid *ssid;
2763 int ret;
2764
2765 pos = buf;
2766 end = buf + buflen;
2767 ret = os_snprintf(pos, end - pos,
2768 "network id / ssid / bssid / flags\n");
2769 if (os_snprintf_error(end - pos, ret))
2770 return pos - buf;
2771 pos += ret;
2772
2773 ssid = wpa_s->conf->ssid;
2774
2775 /* skip over ssids until we find next one */
2776 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2777 int last_id = atoi(cmd + 8);
2778 if (last_id != -1) {
2779 while (ssid != NULL && ssid->id <= last_id) {
2780 ssid = ssid->next;
2781 }
2782 }
2783 }
2784
2785 while (ssid) {
2786 prev = pos;
2787 ret = os_snprintf(pos, end - pos, "%d\t%s",
2788 ssid->id,
2789 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2790 if (os_snprintf_error(end - pos, ret))
2791 return prev - buf;
2792 pos += ret;
2793 if (ssid->bssid_set) {
2794 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2795 MAC2STR(ssid->bssid));
2796 } else {
2797 ret = os_snprintf(pos, end - pos, "\tany");
2798 }
2799 if (os_snprintf_error(end - pos, ret))
2800 return prev - buf;
2801 pos += ret;
2802 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2803 ssid == wpa_s->current_ssid ?
2804 "[CURRENT]" : "",
2805 ssid->disabled ? "[DISABLED]" : "",
2806 ssid->disabled_until.sec ?
2807 "[TEMP-DISABLED]" : "",
2808 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2809 "");
2810 if (os_snprintf_error(end - pos, ret))
2811 return prev - buf;
2812 pos += ret;
2813 ret = os_snprintf(pos, end - pos, "\n");
2814 if (os_snprintf_error(end - pos, ret))
2815 return prev - buf;
2816 pos += ret;
2817
2818 ssid = ssid->next;
2819 }
2820
2821 return pos - buf;
2822 }
2823
2824
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)2825 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2826 {
2827 int ret;
2828 ret = os_snprintf(pos, end - pos, "-");
2829 if (os_snprintf_error(end - pos, ret))
2830 return pos;
2831 pos += ret;
2832 ret = wpa_write_ciphers(pos, end, cipher, "+");
2833 if (ret < 0)
2834 return pos;
2835 pos += ret;
2836 return pos;
2837 }
2838
2839
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)2840 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2841 const u8 *ie, size_t ie_len)
2842 {
2843 struct wpa_ie_data data;
2844 char *start;
2845 int ret;
2846
2847 ret = os_snprintf(pos, end - pos, "[%s-", proto);
2848 if (os_snprintf_error(end - pos, ret))
2849 return pos;
2850 pos += ret;
2851
2852 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2853 ret = os_snprintf(pos, end - pos, "?]");
2854 if (os_snprintf_error(end - pos, ret))
2855 return pos;
2856 pos += ret;
2857 return pos;
2858 }
2859
2860 start = pos;
2861 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2862 ret = os_snprintf(pos, end - pos, "%sEAP",
2863 pos == start ? "" : "+");
2864 if (os_snprintf_error(end - pos, ret))
2865 return pos;
2866 pos += ret;
2867 }
2868 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2869 ret = os_snprintf(pos, end - pos, "%sPSK",
2870 pos == start ? "" : "+");
2871 if (os_snprintf_error(end - pos, ret))
2872 return pos;
2873 pos += ret;
2874 }
2875 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2876 ret = os_snprintf(pos, end - pos, "%sNone",
2877 pos == start ? "" : "+");
2878 if (os_snprintf_error(end - pos, ret))
2879 return pos;
2880 pos += ret;
2881 }
2882 if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2883 ret = os_snprintf(pos, end - pos, "%sSAE",
2884 pos == start ? "" : "+");
2885 if (os_snprintf_error(end - pos, ret))
2886 return pos;
2887 pos += ret;
2888 }
2889 if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
2890 ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY",
2891 pos == start ? "" : "+");
2892 if (os_snprintf_error(end - pos, ret))
2893 return pos;
2894 pos += ret;
2895 }
2896 #ifdef CONFIG_IEEE80211R
2897 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2898 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2899 pos == start ? "" : "+");
2900 if (os_snprintf_error(end - pos, ret))
2901 return pos;
2902 pos += ret;
2903 }
2904 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2905 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2906 pos == start ? "" : "+");
2907 if (os_snprintf_error(end - pos, ret))
2908 return pos;
2909 pos += ret;
2910 }
2911 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2912 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2913 pos == start ? "" : "+");
2914 if (os_snprintf_error(end - pos, ret))
2915 return pos;
2916 pos += ret;
2917 }
2918 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
2919 ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY",
2920 pos == start ? "" : "+");
2921 if (os_snprintf_error(end - pos, ret))
2922 return pos;
2923 pos += ret;
2924 }
2925 #endif /* CONFIG_IEEE80211R */
2926 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2927 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2928 pos == start ? "" : "+");
2929 if (os_snprintf_error(end - pos, ret))
2930 return pos;
2931 pos += ret;
2932 }
2933 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2934 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2935 pos == start ? "" : "+");
2936 if (os_snprintf_error(end - pos, ret))
2937 return pos;
2938 pos += ret;
2939 }
2940
2941 #ifdef CONFIG_SUITEB
2942 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2943 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2944 pos == start ? "" : "+");
2945 if (os_snprintf_error(end - pos, ret))
2946 return pos;
2947 pos += ret;
2948 }
2949 #endif /* CONFIG_SUITEB */
2950
2951 #ifdef CONFIG_SUITEB192
2952 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2953 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2954 pos == start ? "" : "+");
2955 if (os_snprintf_error(end - pos, ret))
2956 return pos;
2957 pos += ret;
2958 }
2959 #endif /* CONFIG_SUITEB192 */
2960
2961 #ifdef CONFIG_FILS
2962 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2963 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2964 pos == start ? "" : "+");
2965 if (os_snprintf_error(end - pos, ret))
2966 return pos;
2967 pos += ret;
2968 }
2969 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2970 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2971 pos == start ? "" : "+");
2972 if (os_snprintf_error(end - pos, ret))
2973 return pos;
2974 pos += ret;
2975 }
2976 #ifdef CONFIG_IEEE80211R
2977 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2978 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2979 pos == start ? "" : "+");
2980 if (os_snprintf_error(end - pos, ret))
2981 return pos;
2982 pos += ret;
2983 }
2984 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2985 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2986 pos == start ? "" : "+");
2987 if (os_snprintf_error(end - pos, ret))
2988 return pos;
2989 pos += ret;
2990 }
2991 #endif /* CONFIG_IEEE80211R */
2992 #endif /* CONFIG_FILS */
2993
2994 #ifdef CONFIG_OWE
2995 if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2996 ret = os_snprintf(pos, end - pos, "%sOWE",
2997 pos == start ? "" : "+");
2998 if (os_snprintf_error(end - pos, ret))
2999 return pos;
3000 pos += ret;
3001 }
3002 #endif /* CONFIG_OWE */
3003
3004 #ifdef CONFIG_DPP
3005 if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
3006 ret = os_snprintf(pos, end - pos, "%sDPP",
3007 pos == start ? "" : "+");
3008 if (os_snprintf_error(end - pos, ret))
3009 return pos;
3010 pos += ret;
3011 }
3012 #endif /* CONFIG_DPP */
3013
3014 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
3015 ret = os_snprintf(pos, end - pos, "%sOSEN",
3016 pos == start ? "" : "+");
3017 if (os_snprintf_error(end - pos, ret))
3018 return pos;
3019 pos += ret;
3020 }
3021
3022 #ifdef CONFIG_SHA384
3023 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
3024 ret = os_snprintf(pos, end - pos, "%sEAP-SHA384",
3025 pos == start ? "" : "+");
3026 if (os_snprintf_error(end - pos, ret))
3027 return pos;
3028 pos += ret;
3029 }
3030 #endif /* CONFIG_SHA384 */
3031
3032 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
3033
3034 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
3035 ret = os_snprintf(pos, end - pos, "-preauth");
3036 if (os_snprintf_error(end - pos, ret))
3037 return pos;
3038 pos += ret;
3039 }
3040
3041 ret = os_snprintf(pos, end - pos, "]");
3042 if (os_snprintf_error(end - pos, ret))
3043 return pos;
3044 pos += ret;
3045
3046 return pos;
3047 }
3048
3049
3050 #ifdef CONFIG_WPS
wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant * wpa_s,char * pos,char * end,struct wpabuf * wps_ie)3051 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
3052 char *pos, char *end,
3053 struct wpabuf *wps_ie)
3054 {
3055 int ret;
3056 const char *txt;
3057
3058 if (wps_ie == NULL)
3059 return pos;
3060 if (wps_is_selected_pbc_registrar(wps_ie))
3061 txt = "[WPS-PBC]";
3062 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
3063 txt = "[WPS-AUTH]";
3064 else if (wps_is_selected_pin_registrar(wps_ie))
3065 txt = "[WPS-PIN]";
3066 else
3067 txt = "[WPS]";
3068
3069 ret = os_snprintf(pos, end - pos, "%s", txt);
3070 if (!os_snprintf_error(end - pos, ret))
3071 pos += ret;
3072 wpabuf_free(wps_ie);
3073 return pos;
3074 }
3075 #endif /* CONFIG_WPS */
3076
3077
wpa_supplicant_wps_ie_txt(struct wpa_supplicant * wpa_s,char * pos,char * end,const struct wpa_bss * bss)3078 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
3079 char *pos, char *end,
3080 const struct wpa_bss *bss)
3081 {
3082 #ifdef CONFIG_WPS
3083 struct wpabuf *wps_ie;
3084 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
3085 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
3086 #else /* CONFIG_WPS */
3087 return pos;
3088 #endif /* CONFIG_WPS */
3089 }
3090
3091
3092 /* Format one result on one text line into a buffer. */
wpa_supplicant_ctrl_iface_scan_result(struct wpa_supplicant * wpa_s,const struct wpa_bss * bss,char * buf,size_t buflen)3093 static int wpa_supplicant_ctrl_iface_scan_result(
3094 struct wpa_supplicant *wpa_s,
3095 const struct wpa_bss *bss, char *buf, size_t buflen)
3096 {
3097 char *pos, *end;
3098 int ret;
3099 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
3100
3101 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
3102 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
3103 if (!p2p)
3104 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
3105 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3106 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3107 0)
3108 return 0; /* Do not show P2P listen discovery results here */
3109
3110 pos = buf;
3111 end = buf + buflen;
3112
3113 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3114 MAC2STR(bss->bssid), bss->freq, bss->level);
3115 if (os_snprintf_error(end - pos, ret))
3116 return -1;
3117 pos += ret;
3118 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3119 if (ie)
3120 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
3121 ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
3122 if (ie2) {
3123 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3124 ie2, 2 + ie2[1]);
3125 }
3126 rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
3127 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3128 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3129 if (os_snprintf_error(end - pos, ret))
3130 return -1;
3131 pos += ret;
3132 }
3133 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3134 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3135 if (os_snprintf_error(end - pos, ret))
3136 return -1;
3137 pos += ret;
3138 }
3139 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3140 if (osen_ie)
3141 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3142 osen_ie, 2 + osen_ie[1]);
3143 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3144 if (owe) {
3145 ret = os_snprintf(pos, end - pos,
3146 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3147 if (os_snprintf_error(end - pos, ret))
3148 return -1;
3149 pos += ret;
3150 }
3151 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3152 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
3153 ret = os_snprintf(pos, end - pos, "[WEP]");
3154 if (os_snprintf_error(end - pos, ret))
3155 return -1;
3156 pos += ret;
3157 }
3158 if (mesh) {
3159 ret = os_snprintf(pos, end - pos, "[MESH]");
3160 if (os_snprintf_error(end - pos, ret))
3161 return -1;
3162 pos += ret;
3163 }
3164 if (bss_is_dmg(bss)) {
3165 const char *s;
3166
3167 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
3168 ret = os_snprintf(pos, end - pos, "[EDMG]");
3169 if (os_snprintf_error(end - pos, ret))
3170 return -1;
3171 pos += ret;
3172 }
3173
3174 ret = os_snprintf(pos, end - pos, "[DMG]");
3175 if (os_snprintf_error(end - pos, ret))
3176 return -1;
3177 pos += ret;
3178 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3179 case IEEE80211_CAP_DMG_IBSS:
3180 s = "[IBSS]";
3181 break;
3182 case IEEE80211_CAP_DMG_AP:
3183 s = "[ESS]";
3184 break;
3185 case IEEE80211_CAP_DMG_PBSS:
3186 s = "[PBSS]";
3187 break;
3188 default:
3189 s = "";
3190 break;
3191 }
3192 ret = os_snprintf(pos, end - pos, "%s", s);
3193 if (os_snprintf_error(end - pos, ret))
3194 return -1;
3195 pos += ret;
3196 } else {
3197 if (bss->caps & IEEE80211_CAP_IBSS) {
3198 ret = os_snprintf(pos, end - pos, "[IBSS]");
3199 if (os_snprintf_error(end - pos, ret))
3200 return -1;
3201 pos += ret;
3202 }
3203 if (bss->caps & IEEE80211_CAP_ESS) {
3204 ret = os_snprintf(pos, end - pos, "[ESS]");
3205 if (os_snprintf_error(end - pos, ret))
3206 return -1;
3207 pos += ret;
3208 }
3209 }
3210 if (p2p) {
3211 ret = os_snprintf(pos, end - pos, "[P2P]");
3212 if (os_snprintf_error(end - pos, ret))
3213 return -1;
3214 pos += ret;
3215 }
3216 #ifdef CONFIG_HS20
3217 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
3218 ret = os_snprintf(pos, end - pos, "[HS20]");
3219 if (os_snprintf_error(end - pos, ret))
3220 return -1;
3221 pos += ret;
3222 }
3223 #endif /* CONFIG_HS20 */
3224 #ifdef CONFIG_FILS
3225 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3226 ret = os_snprintf(pos, end - pos, "[FILS]");
3227 if (os_snprintf_error(end - pos, ret))
3228 return -1;
3229 pos += ret;
3230 }
3231 #endif /* CONFIG_FILS */
3232 #ifdef CONFIG_FST
3233 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3234 ret = os_snprintf(pos, end - pos, "[FST]");
3235 if (os_snprintf_error(end - pos, ret))
3236 return -1;
3237 pos += ret;
3238 }
3239 #endif /* CONFIG_FST */
3240 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3241 ret = os_snprintf(pos, end - pos, "[UTF-8]");
3242 if (os_snprintf_error(end - pos, ret))
3243 return -1;
3244 pos += ret;
3245 }
3246
3247 ret = os_snprintf(pos, end - pos, "\t%s",
3248 wpa_ssid_txt(bss->ssid, bss->ssid_len));
3249 if (os_snprintf_error(end - pos, ret))
3250 return -1;
3251 pos += ret;
3252
3253 ret = os_snprintf(pos, end - pos, "\n");
3254 if (os_snprintf_error(end - pos, ret))
3255 return -1;
3256 pos += ret;
3257
3258 return pos - buf;
3259 }
3260
3261
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3262 static int wpa_supplicant_ctrl_iface_scan_results(
3263 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3264 {
3265 char *pos, *end;
3266 struct wpa_bss *bss;
3267 int ret;
3268
3269 pos = buf;
3270 end = buf + buflen;
3271 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3272 "flags / ssid\n");
3273 if (os_snprintf_error(end - pos, ret))
3274 return pos - buf;
3275 pos += ret;
3276
3277 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3278 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3279 end - pos);
3280 if (ret < 0 || ret >= end - pos)
3281 return pos - buf;
3282 pos += ret;
3283 }
3284
3285 return pos - buf;
3286 }
3287
3288
3289 #ifdef CONFIG_MESH
3290
wpa_supplicant_ctrl_iface_mesh_interface_add(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)3291 static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3292 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3293 {
3294 char *pos, ifname[IFNAMSIZ + 1];
3295
3296 ifname[0] = '\0';
3297
3298 pos = os_strstr(cmd, "ifname=");
3299 if (pos) {
3300 pos += 7;
3301 os_strlcpy(ifname, pos, sizeof(ifname));
3302 }
3303
3304 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3305 return -1;
3306
3307 os_strlcpy(reply, ifname, max_len);
3308 return os_strlen(ifname);
3309 }
3310
3311
wpa_supplicant_ctrl_iface_mesh_group_add(struct wpa_supplicant * wpa_s,char * cmd)3312 static int wpa_supplicant_ctrl_iface_mesh_group_add(
3313 struct wpa_supplicant *wpa_s, char *cmd)
3314 {
3315 int id;
3316 struct wpa_ssid *ssid;
3317
3318 id = atoi(cmd);
3319 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3320
3321 ssid = wpa_config_get_network(wpa_s->conf, id);
3322 if (ssid == NULL) {
3323 wpa_printf(MSG_DEBUG,
3324 "CTRL_IFACE: Could not find network id=%d", id);
3325 return -1;
3326 }
3327 if (ssid->mode != WPAS_MODE_MESH) {
3328 wpa_printf(MSG_DEBUG,
3329 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3330 return -1;
3331 }
3332 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3333 ssid->key_mgmt != WPA_KEY_MGMT_SAE &&
3334 ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) {
3335 wpa_printf(MSG_ERROR,
3336 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3337 return -1;
3338 }
3339
3340 /*
3341 * TODO: If necessary write our own group_add function,
3342 * for now we can reuse select_network
3343 */
3344 wpa_supplicant_select_network(wpa_s, ssid);
3345
3346 return 0;
3347 }
3348
3349
wpa_supplicant_ctrl_iface_mesh_group_remove(struct wpa_supplicant * wpa_s,char * cmd)3350 static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3351 struct wpa_supplicant *wpa_s, char *cmd)
3352 {
3353 struct wpa_supplicant *orig;
3354 struct wpa_global *global;
3355 int found = 0;
3356
3357 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3358
3359 global = wpa_s->global;
3360 orig = wpa_s;
3361
3362 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3363 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3364 found = 1;
3365 break;
3366 }
3367 }
3368 if (!found) {
3369 wpa_printf(MSG_ERROR,
3370 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3371 cmd);
3372 return -1;
3373 }
3374 if (wpa_s->mesh_if_created && wpa_s == orig) {
3375 wpa_printf(MSG_ERROR,
3376 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3377 return -1;
3378 }
3379
3380 wpa_s->reassociate = 0;
3381 wpa_s->disconnected = 1;
3382 wpa_supplicant_cancel_sched_scan(wpa_s);
3383 wpa_supplicant_cancel_scan(wpa_s);
3384
3385 /*
3386 * TODO: If necessary write our own group_remove function,
3387 * for now we can reuse deauthenticate
3388 */
3389 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3390
3391 if (wpa_s->mesh_if_created)
3392 wpa_supplicant_remove_iface(global, wpa_s, 0);
3393
3394 return 0;
3395 }
3396
3397
wpa_supplicant_ctrl_iface_mesh_peer_remove(struct wpa_supplicant * wpa_s,char * cmd)3398 static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3399 struct wpa_supplicant *wpa_s, char *cmd)
3400 {
3401 u8 addr[ETH_ALEN];
3402
3403 if (hwaddr_aton(cmd, addr) < 0)
3404 return -1;
3405
3406 return wpas_mesh_peer_remove(wpa_s, addr);
3407 }
3408
3409
wpa_supplicant_ctrl_iface_mesh_peer_add(struct wpa_supplicant * wpa_s,char * cmd)3410 static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3411 struct wpa_supplicant *wpa_s, char *cmd)
3412 {
3413 u8 addr[ETH_ALEN];
3414 int duration;
3415 char *pos;
3416
3417 pos = os_strstr(cmd, " duration=");
3418 if (pos) {
3419 *pos = '\0';
3420 duration = atoi(pos + 10);
3421 } else {
3422 duration = -1;
3423 }
3424
3425 if (hwaddr_aton(cmd, addr))
3426 return -1;
3427
3428 return wpas_mesh_peer_add(wpa_s, addr, duration);
3429 }
3430
3431
wpa_supplicant_ctrl_iface_mesh_link_probe(struct wpa_supplicant * wpa_s,char * cmd)3432 static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3433 struct wpa_supplicant *wpa_s, char *cmd)
3434 {
3435 struct ether_header *eth;
3436 u8 addr[ETH_ALEN];
3437 u8 *buf;
3438 char *pos;
3439 size_t payload_len = 0, len;
3440 int ret = -1;
3441
3442 if (hwaddr_aton(cmd, addr))
3443 return -1;
3444
3445 pos = os_strstr(cmd, " payload=");
3446 if (pos) {
3447 pos = pos + 9;
3448 payload_len = os_strlen(pos);
3449 if (payload_len & 1)
3450 return -1;
3451
3452 payload_len /= 2;
3453 }
3454
3455 len = ETH_HLEN + payload_len;
3456 buf = os_malloc(len);
3457 if (!buf)
3458 return -1;
3459
3460 eth = (struct ether_header *) buf;
3461 os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3462 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3463 eth->ether_type = htons(ETH_P_802_3);
3464
3465 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3466 goto fail;
3467
3468 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3469 fail:
3470 os_free(buf);
3471 return -ret;
3472 }
3473
3474 #endif /* CONFIG_MESH */
3475
3476
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)3477 static int wpa_supplicant_ctrl_iface_select_network(
3478 struct wpa_supplicant *wpa_s, char *cmd)
3479 {
3480 int id;
3481 struct wpa_ssid *ssid;
3482 char *pos;
3483
3484 /* cmd: "<network id>" or "any" */
3485 if (os_strncmp(cmd, "any", 3) == 0) {
3486 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3487 ssid = NULL;
3488 } else {
3489 id = atoi(cmd);
3490 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3491
3492 ssid = wpa_config_get_network(wpa_s->conf, id);
3493 if (ssid == NULL) {
3494 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3495 "network id=%d", id);
3496 return -1;
3497 }
3498 if (ssid->disabled == 2) {
3499 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3500 "SELECT_NETWORK with persistent P2P group");
3501 return -1;
3502 }
3503 }
3504
3505 pos = os_strstr(cmd, " freq=");
3506 if (pos) {
3507 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3508 if (freqs) {
3509 os_free(wpa_s->select_network_scan_freqs);
3510 wpa_s->select_network_scan_freqs = freqs;
3511 }
3512 }
3513
3514 wpa_s->scan_min_time.sec = 0;
3515 wpa_s->scan_min_time.usec = 0;
3516 wpa_supplicant_select_network(wpa_s, ssid);
3517
3518 return 0;
3519 }
3520
3521
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)3522 static int wpa_supplicant_ctrl_iface_enable_network(
3523 struct wpa_supplicant *wpa_s, char *cmd)
3524 {
3525 int id;
3526 struct wpa_ssid *ssid;
3527
3528 /* cmd: "<network id>" or "all" */
3529 if (os_strcmp(cmd, "all") == 0) {
3530 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3531 ssid = NULL;
3532 } else {
3533 id = atoi(cmd);
3534 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3535
3536 ssid = wpa_config_get_network(wpa_s->conf, id);
3537 if (ssid == NULL) {
3538 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3539 "network id=%d", id);
3540 return -1;
3541 }
3542 if (ssid->disabled == 2) {
3543 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3544 "ENABLE_NETWORK with persistent P2P group");
3545 return -1;
3546 }
3547
3548 if (os_strstr(cmd, " no-connect")) {
3549 ssid->disabled = 0;
3550 return 0;
3551 }
3552 }
3553 wpa_s->scan_min_time.sec = 0;
3554 wpa_s->scan_min_time.usec = 0;
3555 wpa_supplicant_enable_network(wpa_s, ssid);
3556
3557 return 0;
3558 }
3559
3560
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)3561 static int wpa_supplicant_ctrl_iface_disable_network(
3562 struct wpa_supplicant *wpa_s, char *cmd)
3563 {
3564 int id;
3565 struct wpa_ssid *ssid;
3566
3567 /* cmd: "<network id>" or "all" */
3568 if (os_strcmp(cmd, "all") == 0) {
3569 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3570 ssid = NULL;
3571 } else {
3572 id = atoi(cmd);
3573 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3574
3575 ssid = wpa_config_get_network(wpa_s->conf, id);
3576 if (ssid == NULL) {
3577 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3578 "network id=%d", id);
3579 return -1;
3580 }
3581 if (ssid->disabled == 2) {
3582 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3583 "DISABLE_NETWORK with persistent P2P "
3584 "group");
3585 return -1;
3586 }
3587 }
3588 wpa_supplicant_disable_network(wpa_s, ssid);
3589
3590 return 0;
3591 }
3592
3593
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3594 static int wpa_supplicant_ctrl_iface_add_network(
3595 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3596 {
3597 struct wpa_ssid *ssid;
3598 int ret;
3599
3600 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3601
3602 ssid = wpa_supplicant_add_network(wpa_s);
3603 if (ssid == NULL)
3604 return -1;
3605
3606 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
3607 if (os_snprintf_error(buflen, ret))
3608 return -1;
3609 return ret;
3610 }
3611
3612
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)3613 static int wpa_supplicant_ctrl_iface_remove_network(
3614 struct wpa_supplicant *wpa_s, char *cmd)
3615 {
3616 int id;
3617 int result;
3618
3619 /* cmd: "<network id>" or "all" */
3620 if (os_strcmp(cmd, "all") == 0) {
3621 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
3622 return wpa_supplicant_remove_all_networks(wpa_s);
3623 }
3624
3625 id = atoi(cmd);
3626 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3627
3628 result = wpa_supplicant_remove_network(wpa_s, id);
3629 if (result == -1) {
3630 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3631 "id=%d", id);
3632 return -1;
3633 }
3634 if (result == -2) {
3635 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3636 "network id=%d", id);
3637 return -1;
3638 }
3639 return 0;
3640 }
3641
3642
wpa_supplicant_ctrl_iface_update_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,char * name,char * value)3643 static int wpa_supplicant_ctrl_iface_update_network(
3644 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3645 char *name, char *value)
3646 {
3647 int ret;
3648
3649 ret = wpa_config_set(ssid, name, value, 0);
3650 if (ret < 0) {
3651 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3652 "variable '%s'", name);
3653 return -1;
3654 }
3655 if (ret == 1)
3656 return 0; /* No change to the previously configured value */
3657
3658 #ifdef CONFIG_BGSCAN
3659 if (os_strcmp(name, "bgscan") == 0) {
3660 /*
3661 * Reset the bgscan parameters for the current network and
3662 * return. There's no need to flush caches for bgscan parameter
3663 * changes.
3664 */
3665 if (wpa_s->current_ssid == ssid &&
3666 wpa_s->wpa_state == WPA_COMPLETED)
3667 wpa_supplicant_reset_bgscan(wpa_s);
3668 return 0;
3669 }
3670 #endif /* CONFIG_BGSCAN */
3671
3672 if (os_strcmp(name, "bssid") != 0 &&
3673 os_strncmp(name, "bssid_", 6) != 0 &&
3674 os_strcmp(name, "scan_freq") != 0 &&
3675 os_strcmp(name, "priority") != 0) {
3676 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3677
3678 if (wpa_s->current_ssid == ssid ||
3679 wpa_s->current_ssid == NULL) {
3680 /*
3681 * Invalidate the EAP session cache if anything in the
3682 * current or previously used configuration changes.
3683 */
3684 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3685 }
3686 }
3687
3688 if ((os_strcmp(name, "psk") == 0 &&
3689 value[0] == '"' && ssid->ssid_len) ||
3690 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3691 wpa_config_update_psk(ssid);
3692 else if (os_strcmp(name, "priority") == 0)
3693 wpa_config_update_prio_list(wpa_s->conf);
3694
3695 return 0;
3696 }
3697
3698
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)3699 static int wpa_supplicant_ctrl_iface_set_network(
3700 struct wpa_supplicant *wpa_s, char *cmd)
3701 {
3702 int id, ret, prev_bssid_set, prev_disabled;
3703 struct wpa_ssid *ssid;
3704 char *name, *value;
3705 u8 prev_bssid[ETH_ALEN];
3706
3707 /* cmd: "<network id> <variable name> <value>" */
3708 name = os_strchr(cmd, ' ');
3709 if (name == NULL)
3710 return -1;
3711 *name++ = '\0';
3712
3713 value = os_strchr(name, ' ');
3714 if (value == NULL)
3715 return -1;
3716 *value++ = '\0';
3717
3718 id = atoi(cmd);
3719 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3720 id, name);
3721 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3722 (u8 *) value, os_strlen(value));
3723
3724 ssid = wpa_config_get_network(wpa_s->conf, id);
3725 if (ssid == NULL) {
3726 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3727 "id=%d", id);
3728 return -1;
3729 }
3730
3731 prev_bssid_set = ssid->bssid_set;
3732 prev_disabled = ssid->disabled;
3733 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3734 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3735 value);
3736 if (ret == 0 &&
3737 (ssid->bssid_set != prev_bssid_set ||
3738 !ether_addr_equal(ssid->bssid, prev_bssid)))
3739 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
3740
3741 if (prev_disabled != ssid->disabled &&
3742 (prev_disabled == 2 || ssid->disabled == 2))
3743 wpas_notify_network_type_changed(wpa_s, ssid);
3744
3745 return ret;
3746 }
3747
3748
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3749 static int wpa_supplicant_ctrl_iface_get_network(
3750 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3751 {
3752 int id;
3753 size_t res;
3754 struct wpa_ssid *ssid;
3755 char *name, *value;
3756
3757 /* cmd: "<network id> <variable name>" */
3758 name = os_strchr(cmd, ' ');
3759 if (name == NULL || buflen == 0)
3760 return -1;
3761 *name++ = '\0';
3762
3763 id = atoi(cmd);
3764 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3765 id, name);
3766
3767 ssid = wpa_config_get_network(wpa_s->conf, id);
3768 if (ssid == NULL) {
3769 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
3770 "id=%d", id);
3771 return -1;
3772 }
3773
3774 value = wpa_config_get_no_key(ssid, name);
3775 if (value == NULL) {
3776 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
3777 "variable '%s'", name);
3778 return -1;
3779 }
3780
3781 res = os_strlcpy(buf, value, buflen);
3782 if (res >= buflen) {
3783 os_free(value);
3784 return -1;
3785 }
3786
3787 os_free(value);
3788
3789 return res;
3790 }
3791
3792
wpa_supplicant_ctrl_iface_dup_network(struct wpa_supplicant * wpa_s,char * cmd,struct wpa_supplicant * dst_wpa_s)3793 static int wpa_supplicant_ctrl_iface_dup_network(
3794 struct wpa_supplicant *wpa_s, char *cmd,
3795 struct wpa_supplicant *dst_wpa_s)
3796 {
3797 struct wpa_ssid *ssid_s, *ssid_d;
3798 char *name, *id, *value;
3799 int id_s, id_d, ret;
3800
3801 /* cmd: "<src network id> <dst network id> <variable name>" */
3802 id = os_strchr(cmd, ' ');
3803 if (id == NULL)
3804 return -1;
3805 *id++ = '\0';
3806
3807 name = os_strchr(id, ' ');
3808 if (name == NULL)
3809 return -1;
3810 *name++ = '\0';
3811
3812 id_s = atoi(cmd);
3813 id_d = atoi(id);
3814
3815 wpa_printf(MSG_DEBUG,
3816 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3817 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
3818
3819 ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3820 if (ssid_s == NULL) {
3821 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3822 "network id=%d", id_s);
3823 return -1;
3824 }
3825
3826 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
3827 if (ssid_d == NULL) {
3828 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3829 "network id=%d", id_d);
3830 return -1;
3831 }
3832
3833 value = wpa_config_get(ssid_s, name);
3834 if (value == NULL) {
3835 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3836 "variable '%s'", name);
3837 return -1;
3838 }
3839
3840 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
3841 value);
3842
3843 os_free(value);
3844
3845 return ret;
3846 }
3847
3848
wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3849 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3850 char *buf, size_t buflen)
3851 {
3852 char *pos, *end;
3853 struct wpa_cred *cred;
3854 int ret;
3855
3856 pos = buf;
3857 end = buf + buflen;
3858 ret = os_snprintf(pos, end - pos,
3859 "cred id / realm / username / domain / imsi\n");
3860 if (os_snprintf_error(end - pos, ret))
3861 return pos - buf;
3862 pos += ret;
3863
3864 cred = wpa_s->conf->cred;
3865 while (cred) {
3866 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3867 cred->id, cred->realm ? cred->realm : "",
3868 cred->username ? cred->username : "",
3869 cred->domain ? cred->domain[0] : "",
3870 cred->imsi ? cred->imsi : "");
3871 if (os_snprintf_error(end - pos, ret))
3872 return pos - buf;
3873 pos += ret;
3874
3875 cred = cred->next;
3876 }
3877
3878 return pos - buf;
3879 }
3880
3881
wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3882 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3883 char *buf, size_t buflen)
3884 {
3885 struct wpa_cred *cred;
3886 int ret;
3887
3888 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3889
3890 cred = wpa_config_add_cred(wpa_s->conf);
3891 if (cred == NULL)
3892 return -1;
3893
3894 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3895
3896 ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3897 if (os_snprintf_error(buflen, ret))
3898 return -1;
3899 return ret;
3900 }
3901
3902
wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant * wpa_s,char * cmd)3903 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3904 char *cmd)
3905 {
3906 int id;
3907 struct wpa_cred *cred, *prev;
3908
3909 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3910 * "provisioning_sp=<FQDN> */
3911 if (os_strcmp(cmd, "all") == 0) {
3912 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3913 return wpas_remove_all_creds(wpa_s);
3914 }
3915
3916 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3917 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3918 cmd + 8);
3919 cred = wpa_s->conf->cred;
3920 while (cred) {
3921 prev = cred;
3922 cred = cred->next;
3923 if (prev->domain) {
3924 size_t i;
3925 for (i = 0; i < prev->num_domain; i++) {
3926 if (os_strcmp(prev->domain[i], cmd + 8)
3927 != 0)
3928 continue;
3929 wpas_remove_cred(wpa_s, prev);
3930 break;
3931 }
3932 }
3933 }
3934 return 0;
3935 }
3936
3937 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3938 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3939 cmd + 16);
3940 cred = wpa_s->conf->cred;
3941 while (cred) {
3942 prev = cred;
3943 cred = cred->next;
3944 if (prev->provisioning_sp &&
3945 os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3946 wpas_remove_cred(wpa_s, prev);
3947 }
3948 return 0;
3949 }
3950
3951 id = atoi(cmd);
3952 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3953
3954 cred = wpa_config_get_cred(wpa_s->conf, id);
3955 return wpas_remove_cred(wpa_s, cred);
3956 }
3957
3958
wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant * wpa_s,char * cmd)3959 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3960 char *cmd)
3961 {
3962 int id;
3963 struct wpa_cred *cred;
3964 char *name, *value;
3965
3966 /* cmd: "<cred id> <variable name> <value>" */
3967 name = os_strchr(cmd, ' ');
3968 if (name == NULL)
3969 return -1;
3970 *name++ = '\0';
3971
3972 value = os_strchr(name, ' ');
3973 if (value == NULL)
3974 return -1;
3975 *value++ = '\0';
3976
3977 id = atoi(cmd);
3978 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3979 id, name);
3980 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3981 (u8 *) value, os_strlen(value));
3982
3983 cred = wpa_config_get_cred(wpa_s->conf, id);
3984 if (cred == NULL) {
3985 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3986 id);
3987 return -1;
3988 }
3989
3990 if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3991 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3992 "variable '%s'", name);
3993 return -1;
3994 }
3995
3996 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3997
3998 return 0;
3999 }
4000
4001
wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)4002 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
4003 char *cmd, char *buf,
4004 size_t buflen)
4005 {
4006 int id;
4007 size_t res;
4008 struct wpa_cred *cred;
4009 char *name, *value;
4010
4011 /* cmd: "<cred id> <variable name>" */
4012 name = os_strchr(cmd, ' ');
4013 if (name == NULL)
4014 return -1;
4015 *name++ = '\0';
4016
4017 id = atoi(cmd);
4018 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
4019 id, name);
4020
4021 cred = wpa_config_get_cred(wpa_s->conf, id);
4022 if (cred == NULL) {
4023 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4024 id);
4025 return -1;
4026 }
4027
4028 value = wpa_config_get_cred_no_key(cred, name);
4029 if (value == NULL) {
4030 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
4031 name);
4032 return -1;
4033 }
4034
4035 res = os_strlcpy(buf, value, buflen);
4036 if (res >= buflen) {
4037 os_free(value);
4038 return -1;
4039 }
4040
4041 os_free(value);
4042
4043 return res;
4044 }
4045
4046
4047 #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)4048 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
4049 {
4050 int ret;
4051
4052 if (!wpa_s->conf->update_config) {
4053 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
4054 "to update configuration (update_config=0)");
4055 return -1;
4056 }
4057
4058 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
4059 if (ret) {
4060 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
4061 "update configuration");
4062 } else {
4063 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
4064 " updated");
4065 }
4066
4067 return ret;
4068 }
4069 #endif /* CONFIG_NO_CONFIG_WRITE */
4070
4071
4072 struct cipher_info {
4073 unsigned int capa;
4074 const char *name;
4075 int group_only;
4076 };
4077
4078 static const struct cipher_info ciphers[] = {
4079 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4080 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4081 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4082 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
4083 #ifndef CONFIG_NO_TKIP
4084 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
4085 #endif /* CONFIG_NO_TKIP */
4086 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
4087 #ifdef CONFIG_WEP
4088 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4089 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
4090 #endif /* CONFIG_WEP */
4091 };
4092
4093 static const struct cipher_info ciphers_group_mgmt[] = {
4094 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4095 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4096 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4097 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4098 };
4099
4100
ctrl_iface_get_capability_pairwise(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4101 static int ctrl_iface_get_capability_pairwise(int res, bool strict,
4102 struct wpa_driver_capa *capa,
4103 char *buf, size_t buflen)
4104 {
4105 int ret;
4106 char *pos, *end;
4107 size_t len;
4108 unsigned int i;
4109
4110 pos = buf;
4111 end = pos + buflen;
4112
4113 if (res < 0) {
4114 if (strict)
4115 return 0;
4116 #ifdef CONFIG_NO_TKIP
4117 len = os_strlcpy(buf, "CCMP NONE", buflen);
4118 #else /* CONFIG_NO_TKIP */
4119 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
4120 #endif /* CONFIG_NO_TKIP */
4121 if (len >= buflen)
4122 return -1;
4123 return len;
4124 }
4125
4126 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4127 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4128 ret = os_snprintf(pos, end - pos, "%s%s",
4129 pos == buf ? "" : " ",
4130 ciphers[i].name);
4131 if (os_snprintf_error(end - pos, ret))
4132 return pos - buf;
4133 pos += ret;
4134 }
4135 }
4136
4137 return pos - buf;
4138 }
4139
4140
ctrl_iface_get_capability_group(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4141 static int ctrl_iface_get_capability_group(int res, bool strict,
4142 struct wpa_driver_capa *capa,
4143 char *buf, size_t buflen)
4144 {
4145 int ret;
4146 char *pos, *end;
4147 size_t len;
4148 unsigned int i;
4149
4150 pos = buf;
4151 end = pos + buflen;
4152
4153 if (res < 0) {
4154 if (strict)
4155 return 0;
4156 #ifdef CONFIG_WEP
4157 #ifdef CONFIG_NO_TKIP
4158 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4159 #else /* CONFIG_NO_TKIP */
4160 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
4161 #endif /* CONFIG_NO_TKIP */
4162 #else /* CONFIG_WEP */
4163 #ifdef CONFIG_NO_TKIP
4164 len = os_strlcpy(buf, "CCMP", buflen);
4165 #else /* CONFIG_NO_TKIP */
4166 len = os_strlcpy(buf, "CCMP TKIP", buflen);
4167 #endif /* CONFIG_NO_TKIP */
4168 #endif /* CONFIG_WEP */
4169 if (len >= buflen)
4170 return -1;
4171 return len;
4172 }
4173
4174 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4175 if (capa->enc & ciphers[i].capa) {
4176 ret = os_snprintf(pos, end - pos, "%s%s",
4177 pos == buf ? "" : " ",
4178 ciphers[i].name);
4179 if (os_snprintf_error(end - pos, ret))
4180 return pos - buf;
4181 pos += ret;
4182 }
4183 }
4184
4185 return pos - buf;
4186 }
4187
4188
ctrl_iface_get_capability_group_mgmt(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4189 static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
4190 struct wpa_driver_capa *capa,
4191 char *buf, size_t buflen)
4192 {
4193 int ret;
4194 char *pos, *end;
4195 unsigned int i;
4196
4197 pos = buf;
4198 end = pos + buflen;
4199
4200 if (res < 0)
4201 return 0;
4202
4203 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4204 if (capa->enc & ciphers_group_mgmt[i].capa) {
4205 ret = os_snprintf(pos, end - pos, "%s%s",
4206 pos == buf ? "" : " ",
4207 ciphers_group_mgmt[i].name);
4208 if (os_snprintf_error(end - pos, ret))
4209 return pos - buf;
4210 pos += ret;
4211 }
4212 }
4213
4214 return pos - buf;
4215 }
4216
4217
iftype_str_to_index(const char * iftype_str)4218 static int iftype_str_to_index(const char *iftype_str)
4219 {
4220 if (!iftype_str)
4221 return WPA_IF_MAX;
4222
4223 if (os_strcmp(iftype_str, "STATION") == 0)
4224 return WPA_IF_STATION;
4225
4226 if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4227 return WPA_IF_AP_VLAN;
4228
4229 if (os_strcmp(iftype_str, "AP") == 0)
4230 return WPA_IF_AP_BSS;
4231
4232 if (os_strcmp(iftype_str, "P2P_GO") == 0)
4233 return WPA_IF_P2P_GO;
4234
4235 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4236 return WPA_IF_P2P_CLIENT;
4237
4238 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4239 return WPA_IF_P2P_DEVICE;
4240
4241 if (os_strcmp(iftype_str, "MESH") == 0)
4242 return WPA_IF_MESH;
4243
4244 if (os_strcmp(iftype_str, "IBSS") == 0)
4245 return WPA_IF_IBSS;
4246
4247 if (os_strcmp(iftype_str, "NAN") == 0)
4248 return WPA_IF_NAN;
4249
4250 return WPA_IF_MAX;
4251 }
4252
4253
ctrl_iface_get_capability_key_mgmt(int res,bool strict,struct wpa_driver_capa * capa,const char * iftype_str,char * buf,size_t buflen)4254 static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
4255 struct wpa_driver_capa *capa,
4256 const char *iftype_str,
4257 char *buf, size_t buflen)
4258 {
4259 int ret;
4260 unsigned int key_mgmt;
4261 char *pos, *end;
4262 size_t len;
4263
4264 pos = buf;
4265 end = pos + buflen;
4266
4267 if (res < 0) {
4268 if (strict)
4269 return 0;
4270 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4271 "NONE", buflen);
4272 if (len >= buflen)
4273 return -1;
4274 return len;
4275 }
4276
4277 if (iftype_str) {
4278 enum wpa_driver_if_type iftype;
4279
4280 iftype = iftype_str_to_index(iftype_str);
4281 if (iftype == WPA_IF_MAX)
4282 return -1;
4283 key_mgmt = capa->key_mgmt_iftype[iftype];
4284 } else {
4285 key_mgmt = capa->key_mgmt;
4286 }
4287
4288 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
4289 if (os_snprintf_error(end - pos, ret))
4290 return pos - buf;
4291 pos += ret;
4292
4293 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4294 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
4295 ret = os_snprintf(pos, end - pos, " WPA-EAP");
4296 if (os_snprintf_error(end - pos, ret))
4297 return pos - buf;
4298 pos += ret;
4299 }
4300
4301 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4302 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4303 ret = os_snprintf(pos, end - pos, " WPA-PSK");
4304 if (os_snprintf_error(end - pos, ret))
4305 return pos - buf;
4306 pos += ret;
4307 }
4308
4309 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
4310 ret = os_snprintf(pos, end - pos, " WPA-NONE");
4311 if (os_snprintf_error(end - pos, ret))
4312 return pos - buf;
4313 pos += ret;
4314 }
4315
4316 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4317 ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4318 if (os_snprintf_error(end - pos, ret))
4319 return pos - buf;
4320 pos += ret;
4321 }
4322
4323 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4324 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4325 if (os_snprintf_error(end - pos, ret))
4326 return pos - buf;
4327 pos += ret;
4328 }
4329
4330 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4331 ret = os_snprintf(pos, end - pos, " CCKM");
4332 if (os_snprintf_error(end - pos, ret))
4333 return pos - buf;
4334 pos += ret;
4335 }
4336
4337 #ifdef CONFIG_SUITEB
4338 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
4339 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4340 if (os_snprintf_error(end - pos, ret))
4341 return pos - buf;
4342 pos += ret;
4343 }
4344 #endif /* CONFIG_SUITEB */
4345 #ifdef CONFIG_SUITEB192
4346 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
4347 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4348 if (os_snprintf_error(end - pos, ret))
4349 return pos - buf;
4350 pos += ret;
4351 }
4352 #endif /* CONFIG_SUITEB192 */
4353 #ifdef CONFIG_OWE
4354 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
4355 ret = os_snprintf(pos, end - pos, " OWE");
4356 if (os_snprintf_error(end - pos, ret))
4357 return pos - buf;
4358 pos += ret;
4359 }
4360 #endif /* CONFIG_OWE */
4361 #ifdef CONFIG_DPP
4362 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
4363 ret = os_snprintf(pos, end - pos, " DPP");
4364 if (os_snprintf_error(end - pos, ret))
4365 return pos - buf;
4366 pos += ret;
4367 }
4368 #endif /* CONFIG_DPP */
4369 #ifdef CONFIG_FILS
4370 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
4371 ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4372 if (os_snprintf_error(end - pos, ret))
4373 return pos - buf;
4374 pos += ret;
4375 }
4376 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
4377 ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4378 if (os_snprintf_error(end - pos, ret))
4379 return pos - buf;
4380 pos += ret;
4381 }
4382 #ifdef CONFIG_IEEE80211R
4383 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
4384 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4385 if (os_snprintf_error(end - pos, ret))
4386 return pos - buf;
4387 pos += ret;
4388 }
4389 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
4390 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4391 if (os_snprintf_error(end - pos, ret))
4392 return pos - buf;
4393 pos += ret;
4394 }
4395 #endif /* CONFIG_IEEE80211R */
4396 #endif /* CONFIG_FILS */
4397 #ifdef CONFIG_IEEE80211R
4398 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
4399 ret = os_snprintf(pos, end - pos, " FT-PSK");
4400 if (os_snprintf_error(end - pos, ret))
4401 return pos - buf;
4402 pos += ret;
4403 }
4404 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4405 ret = os_snprintf(pos, end - pos, " FT-EAP");
4406 if (os_snprintf_error(end - pos, ret))
4407 return pos - buf;
4408 pos += ret;
4409 }
4410 #ifdef CONFIG_SAE
4411 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4412 ret = os_snprintf(pos, end - pos, " FT-SAE");
4413 if (os_snprintf_error(end - pos, ret))
4414 return pos - buf;
4415 pos += ret;
4416 }
4417 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) {
4418 ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY");
4419 if (os_snprintf_error(end - pos, ret))
4420 return pos - buf;
4421 pos += ret;
4422 }
4423 #endif /* CONFIG_SAE */
4424 #ifdef CONFIG_SHA384
4425 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4426 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4427 if (os_snprintf_error(end - pos, ret))
4428 return pos - buf;
4429 pos += ret;
4430 }
4431 #endif /* CONFIG_SHA384 */
4432 #endif /* CONFIG_IEEE80211R */
4433 #ifdef CONFIG_SAE
4434 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
4435 ret = os_snprintf(pos, end - pos, " SAE");
4436 if (os_snprintf_error(end - pos, ret))
4437 return pos - buf;
4438 pos += ret;
4439 }
4440 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) {
4441 ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY");
4442 if (os_snprintf_error(end - pos, ret))
4443 return pos - buf;
4444 pos += ret;
4445 }
4446 #endif /* CONFIG_SAE */
4447 #ifdef CONFIG_SHA256
4448 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4449 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4450 if (os_snprintf_error(end - pos, ret))
4451 return pos - buf;
4452 pos += ret;
4453 }
4454
4455 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4456 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4457 if (os_snprintf_error(end - pos, ret))
4458 return pos - buf;
4459 pos += ret;
4460 }
4461 #endif /* CONFIG_SHA256 */
4462 #ifdef CONFIG_HS20
4463 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4464 ret = os_snprintf(pos, end - pos, " OSEN");
4465 if (os_snprintf_error(end - pos, ret))
4466 return pos - buf;
4467 pos += ret;
4468 }
4469 #endif /* CONFIG_HS20 */
4470
4471 return pos - buf;
4472 }
4473
4474
ctrl_iface_get_capability_proto(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4475 static int ctrl_iface_get_capability_proto(int res, bool strict,
4476 struct wpa_driver_capa *capa,
4477 char *buf, size_t buflen)
4478 {
4479 int ret;
4480 char *pos, *end;
4481 size_t len;
4482
4483 pos = buf;
4484 end = pos + buflen;
4485
4486 if (res < 0) {
4487 if (strict)
4488 return 0;
4489 len = os_strlcpy(buf, "RSN WPA", buflen);
4490 if (len >= buflen)
4491 return -1;
4492 return len;
4493 }
4494
4495 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4496 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4497 ret = os_snprintf(pos, end - pos, "%sRSN",
4498 pos == buf ? "" : " ");
4499 if (os_snprintf_error(end - pos, ret))
4500 return pos - buf;
4501 pos += ret;
4502 }
4503
4504 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4505 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
4506 ret = os_snprintf(pos, end - pos, "%sWPA",
4507 pos == buf ? "" : " ");
4508 if (os_snprintf_error(end - pos, ret))
4509 return pos - buf;
4510 pos += ret;
4511 }
4512
4513 return pos - buf;
4514 }
4515
4516
ctrl_iface_get_capability_auth_alg(struct wpa_supplicant * wpa_s,int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4517 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
4518 int res, bool strict,
4519 struct wpa_driver_capa *capa,
4520 char *buf, size_t buflen)
4521 {
4522 int ret;
4523 char *pos, *end;
4524 size_t len;
4525
4526 pos = buf;
4527 end = pos + buflen;
4528
4529 if (res < 0) {
4530 if (strict)
4531 return 0;
4532 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4533 if (len >= buflen)
4534 return -1;
4535 return len;
4536 }
4537
4538 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
4539 ret = os_snprintf(pos, end - pos, "%sOPEN",
4540 pos == buf ? "" : " ");
4541 if (os_snprintf_error(end - pos, ret))
4542 return pos - buf;
4543 pos += ret;
4544 }
4545
4546 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4547 ret = os_snprintf(pos, end - pos, "%sSHARED",
4548 pos == buf ? "" : " ");
4549 if (os_snprintf_error(end - pos, ret))
4550 return pos - buf;
4551 pos += ret;
4552 }
4553
4554 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
4555 ret = os_snprintf(pos, end - pos, "%sLEAP",
4556 pos == buf ? "" : " ");
4557 if (os_snprintf_error(end - pos, ret))
4558 return pos - buf;
4559 pos += ret;
4560 }
4561
4562 #ifdef CONFIG_SAE
4563 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4564 ret = os_snprintf(pos, end - pos, "%sSAE",
4565 pos == buf ? "" : " ");
4566 if (os_snprintf_error(end - pos, ret))
4567 return pos - buf;
4568 pos += ret;
4569 }
4570 #endif /* CONFIG_SAE */
4571
4572 #ifdef CONFIG_FILS
4573 if (wpa_is_fils_supported(wpa_s)) {
4574 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4575 pos == buf ? "" : " ");
4576 if (os_snprintf_error(end - pos, ret))
4577 return pos - buf;
4578 pos += ret;
4579 }
4580
4581 #ifdef CONFIG_FILS_SK_PFS
4582 if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4583 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4584 pos == buf ? "" : " ");
4585 if (os_snprintf_error(end - pos, ret))
4586 return pos - buf;
4587 pos += ret;
4588 }
4589 #endif /* CONFIG_FILS_SK_PFS */
4590 #endif /* CONFIG_FILS */
4591
4592 #ifdef CONFIG_PASN
4593 ret = os_snprintf(pos, end - pos, "%sPASN",
4594 pos == buf ? "" : " ");
4595 if (os_snprintf_error(end - pos, ret))
4596 return pos - buf;
4597 pos += ret;
4598
4599 #endif /* CONFIG_PASN */
4600
4601 return pos - buf;
4602 }
4603
4604
ctrl_iface_get_capability_modes(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4605 static int ctrl_iface_get_capability_modes(int res, bool strict,
4606 struct wpa_driver_capa *capa,
4607 char *buf, size_t buflen)
4608 {
4609 int ret;
4610 char *pos, *end;
4611 size_t len;
4612
4613 pos = buf;
4614 end = pos + buflen;
4615
4616 if (res < 0) {
4617 if (strict)
4618 return 0;
4619 len = os_strlcpy(buf, "IBSS AP", buflen);
4620 if (len >= buflen)
4621 return -1;
4622 return len;
4623 }
4624
4625 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
4626 ret = os_snprintf(pos, end - pos, "%sIBSS",
4627 pos == buf ? "" : " ");
4628 if (os_snprintf_error(end - pos, ret))
4629 return pos - buf;
4630 pos += ret;
4631 }
4632
4633 if (capa->flags & WPA_DRIVER_FLAGS_AP) {
4634 ret = os_snprintf(pos, end - pos, "%sAP",
4635 pos == buf ? "" : " ");
4636 if (os_snprintf_error(end - pos, ret))
4637 return pos - buf;
4638 pos += ret;
4639 }
4640
4641 #ifdef CONFIG_MESH
4642 if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4643 ret = os_snprintf(pos, end - pos, "%sMESH",
4644 pos == buf ? "" : " ");
4645 if (os_snprintf_error(end - pos, ret))
4646 return pos - buf;
4647 pos += ret;
4648 }
4649 #endif /* CONFIG_MESH */
4650
4651 return pos - buf;
4652 }
4653
4654
ctrl_iface_get_capability_channels(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4655 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4656 char *buf, size_t buflen)
4657 {
4658 struct hostapd_channel_data *chnl;
4659 int ret, i, j;
4660 char *pos, *end, *hmode;
4661
4662 pos = buf;
4663 end = pos + buflen;
4664
4665 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4666 switch (wpa_s->hw.modes[j].mode) {
4667 case HOSTAPD_MODE_IEEE80211B:
4668 hmode = "B";
4669 break;
4670 case HOSTAPD_MODE_IEEE80211G:
4671 hmode = "G";
4672 break;
4673 case HOSTAPD_MODE_IEEE80211A:
4674 hmode = "A";
4675 break;
4676 case HOSTAPD_MODE_IEEE80211AD:
4677 hmode = "AD";
4678 break;
4679 default:
4680 continue;
4681 }
4682 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
4683 if (os_snprintf_error(end - pos, ret))
4684 return pos - buf;
4685 pos += ret;
4686 chnl = wpa_s->hw.modes[j].channels;
4687 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4688 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4689 continue;
4690 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
4691 if (os_snprintf_error(end - pos, ret))
4692 return pos - buf;
4693 pos += ret;
4694 }
4695 ret = os_snprintf(pos, end - pos, "\n");
4696 if (os_snprintf_error(end - pos, ret))
4697 return pos - buf;
4698 pos += ret;
4699 }
4700
4701 return pos - buf;
4702 }
4703
4704
ctrl_iface_get_capability_freq(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4705 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4706 char *buf, size_t buflen)
4707 {
4708 struct hostapd_channel_data *chnl;
4709 int ret, i, j;
4710 char *pos, *end, *hmode;
4711
4712 pos = buf;
4713 end = pos + buflen;
4714
4715 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4716 switch (wpa_s->hw.modes[j].mode) {
4717 case HOSTAPD_MODE_IEEE80211B:
4718 hmode = "B";
4719 break;
4720 case HOSTAPD_MODE_IEEE80211G:
4721 hmode = "G";
4722 break;
4723 case HOSTAPD_MODE_IEEE80211A:
4724 hmode = "A";
4725 break;
4726 case HOSTAPD_MODE_IEEE80211AD:
4727 hmode = "AD";
4728 break;
4729 default:
4730 continue;
4731 }
4732 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4733 hmode);
4734 if (os_snprintf_error(end - pos, ret))
4735 return pos - buf;
4736 pos += ret;
4737 chnl = wpa_s->hw.modes[j].channels;
4738 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4739 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4740 continue;
4741 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
4742 chnl[i].chan, chnl[i].freq,
4743 chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4744 " (NO_IR)" : "",
4745 chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4746 " (DFS)" : "");
4747
4748 if (os_snprintf_error(end - pos, ret))
4749 return pos - buf;
4750 pos += ret;
4751 }
4752 ret = os_snprintf(pos, end - pos, "\n");
4753 if (os_snprintf_error(end - pos, ret))
4754 return pos - buf;
4755 pos += ret;
4756 }
4757
4758 return pos - buf;
4759 }
4760
4761
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)4762 static int wpa_supplicant_ctrl_iface_get_capability(
4763 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4764 size_t buflen)
4765 {
4766 struct wpa_driver_capa capa;
4767 int res;
4768 char *next_param, *curr_param, *iftype = NULL;
4769 bool strict = false;
4770 char field[50];
4771 size_t len;
4772
4773 /* Determine whether or not strict checking was requested */
4774 len = os_strlcpy(field, _field, sizeof(field));
4775 if (len >= sizeof(field))
4776 return -1;
4777
4778 next_param = os_strchr(field, ' ');
4779 while (next_param) {
4780 *next_param++ = '\0';
4781 curr_param = next_param;
4782 next_param = os_strchr(next_param, ' ');
4783
4784 if (next_param)
4785 *next_param = '\0';
4786
4787 if (os_strcmp(curr_param, "strict") == 0)
4788 strict = true;
4789 else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4790 iftype = curr_param + 7;
4791 else
4792 return -1;
4793 }
4794
4795 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4796 field, iftype ? " iftype=" : "", iftype ? iftype : "",
4797 strict ? " strict" : "");
4798
4799 if (os_strcmp(field, "eap") == 0) {
4800 return eap_get_names(buf, buflen);
4801 }
4802
4803 res = wpa_drv_get_capa(wpa_s, &capa);
4804
4805 if (os_strcmp(field, "pairwise") == 0)
4806 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4807 buf, buflen);
4808
4809 if (os_strcmp(field, "group") == 0)
4810 return ctrl_iface_get_capability_group(res, strict, &capa,
4811 buf, buflen);
4812
4813 if (os_strcmp(field, "group_mgmt") == 0)
4814 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4815 buf, buflen);
4816
4817 if (os_strcmp(field, "key_mgmt") == 0)
4818 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
4819 iftype, buf, buflen);
4820
4821 if (os_strcmp(field, "proto") == 0)
4822 return ctrl_iface_get_capability_proto(res, strict, &capa,
4823 buf, buflen);
4824
4825 if (os_strcmp(field, "auth_alg") == 0)
4826 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4827 &capa, buf, buflen);
4828
4829 if (os_strcmp(field, "modes") == 0)
4830 return ctrl_iface_get_capability_modes(res, strict, &capa,
4831 buf, buflen);
4832
4833 if (os_strcmp(field, "channels") == 0)
4834 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4835
4836 if (os_strcmp(field, "freq") == 0)
4837 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4838
4839 #ifdef CONFIG_TDLS
4840 if (os_strcmp(field, "tdls") == 0)
4841 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4842 #endif /* CONFIG_TDLS */
4843
4844 #ifdef CONFIG_ERP
4845 if (os_strcmp(field, "erp") == 0) {
4846 res = os_snprintf(buf, buflen, "ERP");
4847 if (os_snprintf_error(buflen, res))
4848 return -1;
4849 return res;
4850 }
4851 #endif /* CONFIG_EPR */
4852
4853 #ifdef CONFIG_FIPS
4854 if (os_strcmp(field, "fips") == 0) {
4855 res = os_snprintf(buf, buflen, "FIPS");
4856 if (os_snprintf_error(buflen, res))
4857 return -1;
4858 return res;
4859 }
4860 #endif /* CONFIG_FIPS */
4861
4862 #ifdef CONFIG_ACS
4863 if (os_strcmp(field, "acs") == 0) {
4864 res = os_snprintf(buf, buflen, "ACS");
4865 if (os_snprintf_error(buflen, res))
4866 return -1;
4867 return res;
4868 }
4869 #endif /* CONFIG_ACS */
4870
4871 #ifdef CONFIG_FILS
4872 if (os_strcmp(field, "fils") == 0) {
4873 #ifdef CONFIG_FILS_SK_PFS
4874 if (wpa_is_fils_supported(wpa_s) &&
4875 wpa_is_fils_sk_pfs_supported(wpa_s)) {
4876 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4877 if (os_snprintf_error(buflen, res))
4878 return -1;
4879 return res;
4880 }
4881 #endif /* CONFIG_FILS_SK_PFS */
4882
4883 if (wpa_is_fils_supported(wpa_s)) {
4884 res = os_snprintf(buf, buflen, "FILS");
4885 if (os_snprintf_error(buflen, res))
4886 return -1;
4887 return res;
4888 }
4889 }
4890 #endif /* CONFIG_FILS */
4891
4892 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4893 res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4894 if (os_snprintf_error(buflen, res))
4895 return -1;
4896 return res;
4897 }
4898
4899 #ifdef CONFIG_DPP
4900 if (os_strcmp(field, "dpp") == 0) {
4901 #ifdef CONFIG_DPP3
4902 res = os_snprintf(buf, buflen, "DPP=3");
4903 #elif defined(CONFIG_DPP2)
4904 res = os_snprintf(buf, buflen, "DPP=2");
4905 #else /* CONFIG_DPP2 */
4906 res = os_snprintf(buf, buflen, "DPP=1");
4907 #endif /* CONFIG_DPP2 */
4908 if (os_snprintf_error(buflen, res))
4909 return -1;
4910 return res;
4911 }
4912 #endif /* CONFIG_DPP */
4913
4914 #ifdef CONFIG_NAN_USD
4915 if (os_strcmp(field, "nan") == 0) {
4916 res = os_snprintf(buf, buflen, "USD");
4917 if (os_snprintf_error(buflen, res))
4918 return -1;
4919 return res;
4920 }
4921 #endif /* CONFIG_NAN_USD */
4922
4923 #ifdef CONFIG_SAE
4924 if (os_strcmp(field, "sae") == 0 &&
4925 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4926 #ifdef CONFIG_SAE_PK
4927 res = os_snprintf(buf, buflen, "H2E PK");
4928 #else /* CONFIG_SAE_PK */
4929 res = os_snprintf(buf, buflen, "H2E");
4930 #endif /* CONFIG_SAE_PK */
4931 if (os_snprintf_error(buflen, res))
4932 return -1;
4933 return res;
4934 }
4935 #endif /* CONFIG_SAE */
4936
4937 #ifdef CONFIG_OCV
4938 if (os_strcmp(field, "ocv") == 0) {
4939 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4940 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4941 res = os_snprintf(buf, buflen, "supported");
4942 else
4943 res = os_snprintf(buf, buflen, "not supported");
4944 if (os_snprintf_error(buflen, res))
4945 return -1;
4946 return res;
4947 }
4948 #endif /* CONFIG_OCV */
4949
4950 if (os_strcmp(field, "beacon_prot") == 0) {
4951 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4952 (wpa_s->drv_flags2 &
4953 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4954 res = os_snprintf(buf, buflen, "supported");
4955 else
4956 res = os_snprintf(buf, buflen, "not supported");
4957 if (os_snprintf_error(buflen, res))
4958 return -1;
4959 return res;
4960 }
4961
4962 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4963 field);
4964
4965 return -1;
4966 }
4967
4968
4969 #ifdef CONFIG_INTERWORKING
anqp_add_hex(char * pos,char * end,const char * title,struct wpabuf * data)4970 static char * anqp_add_hex(char *pos, char *end, const char *title,
4971 struct wpabuf *data)
4972 {
4973 char *start = pos;
4974 size_t i;
4975 int ret;
4976 const u8 *d;
4977
4978 if (data == NULL)
4979 return start;
4980
4981 ret = os_snprintf(pos, end - pos, "%s=", title);
4982 if (os_snprintf_error(end - pos, ret))
4983 return start;
4984 pos += ret;
4985
4986 d = wpabuf_head_u8(data);
4987 for (i = 0; i < wpabuf_len(data); i++) {
4988 ret = os_snprintf(pos, end - pos, "%02x", *d++);
4989 if (os_snprintf_error(end - pos, ret))
4990 return start;
4991 pos += ret;
4992 }
4993
4994 ret = os_snprintf(pos, end - pos, "\n");
4995 if (os_snprintf_error(end - pos, ret))
4996 return start;
4997 pos += ret;
4998
4999 return pos;
5000 }
5001 #endif /* CONFIG_INTERWORKING */
5002
5003
5004 #ifdef CONFIG_FILS
print_fils_indication(struct wpa_bss * bss,char * pos,char * end)5005 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
5006 {
5007 char *start = pos;
5008 const u8 *ie, *ie_end;
5009 u16 info, realms;
5010 int ret;
5011
5012 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
5013 if (!ie)
5014 return 0;
5015 ie_end = ie + 2 + ie[1];
5016 ie += 2;
5017 if (ie_end - ie < 2)
5018 return 0;
5019
5020 info = WPA_GET_LE16(ie);
5021 ie += 2;
5022 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
5023 if (os_snprintf_error(end - pos, ret))
5024 return 0;
5025 pos += ret;
5026
5027 if (info & BIT(7)) {
5028 /* Cache Identifier Included */
5029 if (ie_end - ie < 2)
5030 return 0;
5031 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
5032 ie[0], ie[1]);
5033 if (os_snprintf_error(end - pos, ret))
5034 return 0;
5035 pos += ret;
5036 ie += 2;
5037 }
5038
5039 if (info & BIT(8)) {
5040 /* HESSID Included */
5041 if (ie_end - ie < ETH_ALEN)
5042 return 0;
5043 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
5044 MAC2STR(ie));
5045 if (os_snprintf_error(end - pos, ret))
5046 return 0;
5047 pos += ret;
5048 ie += ETH_ALEN;
5049 }
5050
5051 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
5052 if (realms) {
5053 if (ie_end - ie < realms * 2)
5054 return 0;
5055 ret = os_snprintf(pos, end - pos, "fils_realms=");
5056 if (os_snprintf_error(end - pos, ret))
5057 return 0;
5058 pos += ret;
5059
5060 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
5061 if (ret <= 0)
5062 return 0;
5063 pos += ret;
5064 ie += realms * 2;
5065 ret = os_snprintf(pos, end - pos, "\n");
5066 if (os_snprintf_error(end - pos, ret))
5067 return 0;
5068 pos += ret;
5069 }
5070
5071 return pos - start;
5072 }
5073 #endif /* CONFIG_FILS */
5074
5075
print_rnr(struct wpa_bss * bss,char * pos,char * end)5076 static int print_rnr(struct wpa_bss *bss, char *pos, char *end)
5077 {
5078 char *start = pos;
5079 const u8 *ie, *ie_end;
5080 unsigned int n = 0;
5081 int ret;
5082
5083 ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
5084 if (!ie)
5085 return 0;
5086
5087 ie_end = ie + 2 + ie[1];
5088 ie += 2;
5089
5090 while (ie < ie_end) {
5091 const struct ieee80211_neighbor_ap_info *info =
5092 (const struct ieee80211_neighbor_ap_info *) ie;
5093 const u8 *tbtt_start;
5094 size_t left = ie_end - ie;
5095
5096 if (left < sizeof(struct ieee80211_neighbor_ap_info))
5097 return 0;
5098
5099 left -= sizeof(struct ieee80211_neighbor_ap_info);
5100 if (left < info->tbtt_info_len)
5101 return 0;
5102
5103 ret = os_snprintf(pos, end - pos,
5104 "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ",
5105 n, *ie, info->tbtt_info_len,
5106 info->op_class, info->channel);
5107 if (os_snprintf_error(end - pos, ret))
5108 return 0;
5109 pos += ret;
5110
5111 ie += sizeof(struct ieee80211_neighbor_ap_info);
5112 tbtt_start = ie;
5113 if (info->tbtt_info_len >= 1) {
5114 ret = os_snprintf(pos, end - pos,
5115 "tbtt_offset=%u, ", *ie);
5116 if (os_snprintf_error(end - pos, ret))
5117 return 0;
5118
5119 ie++;
5120 pos += ret;
5121 }
5122
5123 if (info->tbtt_info_len >= 7) {
5124 ret = os_snprintf(pos, end - pos,
5125 "bssid=" MACSTR ", ",
5126 MAC2STR(ie));
5127 if (os_snprintf_error(end - pos, ret))
5128 return 0;
5129
5130 ie += ETH_ALEN;
5131 pos += ret;
5132 }
5133
5134 if (info->tbtt_info_len >= 11) {
5135 ret = os_snprintf(pos, end - pos,
5136 "short SSID=0x%x, ",
5137 WPA_GET_LE32(ie));
5138 if (os_snprintf_error(end - pos, ret))
5139 return 0;
5140
5141 ie += 4;
5142 pos += ret;
5143 }
5144
5145 if (info->tbtt_info_len >= 12) {
5146 ret = os_snprintf(pos, end - pos,
5147 "bss_params=0x%x, ", *ie);
5148 if (os_snprintf_error(end - pos, ret))
5149 return 0;
5150
5151 ie++;
5152 pos += ret;
5153 }
5154
5155 if (info->tbtt_info_len >= 13) {
5156 ret = os_snprintf(pos, end - pos,
5157 "PSD=0x%x, ", *ie);
5158 if (os_snprintf_error(end - pos, ret))
5159 return 0;
5160
5161 ie++;
5162 pos += ret;
5163 }
5164
5165 if (info->tbtt_info_len >= 16) {
5166 ret = os_snprintf(pos, end - pos,
5167 "mld ID=%u, link ID=%u",
5168 *ie, *(ie + 1) & 0xF);
5169 if (os_snprintf_error(end - pos, ret))
5170 return 0;
5171
5172 ie += 3;
5173 pos += ret;
5174 }
5175
5176 ie = tbtt_start + info->tbtt_info_len;
5177
5178 ret = os_snprintf(pos, end - pos, "\n");
5179 if (os_snprintf_error(end - pos, ret))
5180 return 0;
5181 pos += ret;
5182
5183 n++;
5184 }
5185
5186 return pos - start;
5187 }
5188
5189
print_ml(struct wpa_bss * bss,char * pos,char * end)5190 static int print_ml(struct wpa_bss *bss, char *pos, char *end)
5191 {
5192 const struct ieee80211_eht_ml *ml;
5193 char *start = pos;
5194 const u8 *ie, *ie_end;
5195 u16 ml_control;
5196 u8 common_info_length;
5197 int ret;
5198
5199 ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len,
5200 MULTI_LINK_CONTROL_TYPE_BASIC);
5201 if (!ie)
5202 return 0;
5203
5204 ie_end = ie + 2 + ie[1];
5205 ie += 3;
5206 ml = (const struct ieee80211_eht_ml *) ie;
5207
5208 /* control + common info length + MLD MAC Address */
5209 if (ie_end - ie < 2 + 1 + ETH_ALEN)
5210 return 0;
5211
5212 ml_control = le_to_host16(ml->ml_control);
5213
5214 common_info_length = *(ie + 2);
5215 ret = os_snprintf(pos, end - pos,
5216 "multi-link: control=0x%x, common info len=%u",
5217 ml_control, common_info_length);
5218 if (os_snprintf_error(end - pos, ret))
5219 return 0;
5220 pos += ret;
5221
5222 ie += 2;
5223 if (ie_end - ie < common_info_length)
5224 return 0;
5225
5226 ie++;
5227 common_info_length--;
5228
5229 if (common_info_length < ETH_ALEN)
5230 return 0;
5231
5232 ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie));
5233 if (os_snprintf_error(end - pos, ret))
5234 return 0;
5235 pos += ret;
5236
5237 ie += ETH_ALEN;
5238 common_info_length -= ETH_ALEN;
5239
5240 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
5241 if (common_info_length < 1)
5242 return 0;
5243
5244 ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f);
5245 if (os_snprintf_error(end - pos, ret))
5246 return 0;
5247 pos += ret;
5248 ie++;
5249 common_info_length--;
5250 }
5251
5252 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
5253 if (common_info_length < 1)
5254 return 0;
5255
5256 ret = os_snprintf(pos, end - pos,
5257 ", BSS change parameters=0x%x", *ie);
5258 if (os_snprintf_error(end - pos, ret))
5259 return 0;
5260 pos += ret;
5261 ie++;
5262 common_info_length--;
5263 }
5264
5265 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
5266 if (common_info_length < 2)
5267 return 0;
5268
5269 ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x",
5270 WPA_GET_LE16(ie));
5271 if (os_snprintf_error(end - pos, ret))
5272 return 0;
5273 pos += ret;
5274 ie += 2;
5275 common_info_length -= 2;
5276 }
5277
5278 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
5279 if (common_info_length < 2)
5280 return 0;
5281
5282 ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x",
5283 WPA_GET_LE16(ie));
5284 if (os_snprintf_error(end - pos, ret))
5285 return 0;
5286 pos += ret;
5287 ie += 2;
5288 common_info_length -= 2;
5289 }
5290
5291 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
5292 if (common_info_length < 2)
5293 return 0;
5294
5295 ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x",
5296 WPA_GET_LE16(ie));
5297 if (os_snprintf_error(end - pos, ret))
5298 return 0;
5299 pos += ret;
5300 ie += 2;
5301 common_info_length -= 2;
5302 }
5303
5304 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
5305 if (common_info_length < 1)
5306 return 0;
5307
5308 ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
5309 if (os_snprintf_error(end - pos, ret))
5310 return 0;
5311 pos += ret;
5312 ie += 1;
5313 common_info_length--;
5314 }
5315
5316 ret = os_snprintf(pos, end - pos, "\n");
5317 if (os_snprintf_error(end - pos, ret))
5318 return 0;
5319 pos += ret;
5320
5321 return pos - start;
5322 }
5323
5324
print_bss_info(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,unsigned long mask,char * buf,size_t buflen)5325 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5326 unsigned long mask, char *buf, size_t buflen)
5327 {
5328 size_t i;
5329 int ret;
5330 char *pos, *end;
5331 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
5332
5333 pos = buf;
5334 end = buf + buflen;
5335
5336 if (mask & WPA_BSS_MASK_ID) {
5337 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
5338 if (os_snprintf_error(end - pos, ret))
5339 return 0;
5340 pos += ret;
5341 }
5342
5343 if (mask & WPA_BSS_MASK_BSSID) {
5344 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
5345 MAC2STR(bss->bssid));
5346 if (os_snprintf_error(end - pos, ret))
5347 return 0;
5348 pos += ret;
5349 }
5350
5351 if (mask & WPA_BSS_MASK_FREQ) {
5352 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
5353 if (os_snprintf_error(end - pos, ret))
5354 return 0;
5355 pos += ret;
5356 }
5357
5358 if (mask & WPA_BSS_MASK_BEACON_INT) {
5359 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5360 bss->beacon_int);
5361 if (os_snprintf_error(end - pos, ret))
5362 return 0;
5363 pos += ret;
5364 }
5365
5366 if (mask & WPA_BSS_MASK_CAPABILITIES) {
5367 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5368 bss->caps);
5369 if (os_snprintf_error(end - pos, ret))
5370 return 0;
5371 pos += ret;
5372 }
5373
5374 if (mask & WPA_BSS_MASK_QUAL) {
5375 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
5376 if (os_snprintf_error(end - pos, ret))
5377 return 0;
5378 pos += ret;
5379 }
5380
5381 if (mask & WPA_BSS_MASK_NOISE) {
5382 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
5383 if (os_snprintf_error(end - pos, ret))
5384 return 0;
5385 pos += ret;
5386 }
5387
5388 if (mask & WPA_BSS_MASK_LEVEL) {
5389 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
5390 if (os_snprintf_error(end - pos, ret))
5391 return 0;
5392 pos += ret;
5393 }
5394
5395 if (mask & WPA_BSS_MASK_TSF) {
5396 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5397 (unsigned long long) bss->tsf);
5398 if (os_snprintf_error(end - pos, ret))
5399 return 0;
5400 pos += ret;
5401 }
5402
5403 if (mask & WPA_BSS_MASK_AGE) {
5404 struct os_reltime now;
5405
5406 os_get_reltime(&now);
5407 ret = os_snprintf(pos, end - pos, "age=%d\n",
5408 (int) (now.sec - bss->last_update.sec));
5409 if (os_snprintf_error(end - pos, ret))
5410 return 0;
5411 pos += ret;
5412 }
5413
5414 if (mask & WPA_BSS_MASK_IE) {
5415 ret = os_snprintf(pos, end - pos, "ie=");
5416 if (os_snprintf_error(end - pos, ret))
5417 return 0;
5418 pos += ret;
5419
5420 ie = wpa_bss_ie_ptr(bss);
5421 for (i = 0; i < bss->ie_len; i++) {
5422 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5423 if (os_snprintf_error(end - pos, ret))
5424 return 0;
5425 pos += ret;
5426 }
5427
5428 ret = os_snprintf(pos, end - pos, "\n");
5429 if (os_snprintf_error(end - pos, ret))
5430 return 0;
5431 pos += ret;
5432 }
5433
5434 if (mask & WPA_BSS_MASK_FLAGS) {
5435 ret = os_snprintf(pos, end - pos, "flags=");
5436 if (os_snprintf_error(end - pos, ret))
5437 return 0;
5438 pos += ret;
5439
5440 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5441
5442 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5443 if (ie)
5444 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5445 2 + ie[1]);
5446 ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
5447 if (ie2)
5448 pos = wpa_supplicant_ie_txt(pos, end,
5449 mesh ? "RSN" : "WPA2", ie2,
5450 2 + ie2[1]);
5451 rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
5452 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5453 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5454 if (os_snprintf_error(end - pos, ret))
5455 return 0;
5456 pos += ret;
5457 }
5458 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5459 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5460 if (os_snprintf_error(end - pos, ret))
5461 return 0;
5462 pos += ret;
5463 }
5464 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5465 if (osen_ie)
5466 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5467 osen_ie, 2 + osen_ie[1]);
5468 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5469 if (owe) {
5470 ret = os_snprintf(
5471 pos, end - pos,
5472 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5473 if (os_snprintf_error(end - pos, ret))
5474 return 0;
5475 pos += ret;
5476 }
5477 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
5478 if (!ie && !ie2 && !osen_ie &&
5479 (bss->caps & IEEE80211_CAP_PRIVACY)) {
5480 ret = os_snprintf(pos, end - pos, "[WEP]");
5481 if (os_snprintf_error(end - pos, ret))
5482 return 0;
5483 pos += ret;
5484 }
5485
5486 if (mesh) {
5487 ret = os_snprintf(pos, end - pos, "[MESH]");
5488 if (os_snprintf_error(end - pos, ret))
5489 return 0;
5490 pos += ret;
5491 }
5492
5493 if (bss_is_dmg(bss)) {
5494 const char *s;
5495 ret = os_snprintf(pos, end - pos, "[DMG]");
5496 if (os_snprintf_error(end - pos, ret))
5497 return 0;
5498 pos += ret;
5499 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5500 case IEEE80211_CAP_DMG_IBSS:
5501 s = "[IBSS]";
5502 break;
5503 case IEEE80211_CAP_DMG_AP:
5504 s = "[ESS]";
5505 break;
5506 case IEEE80211_CAP_DMG_PBSS:
5507 s = "[PBSS]";
5508 break;
5509 default:
5510 s = "";
5511 break;
5512 }
5513 ret = os_snprintf(pos, end - pos, "%s", s);
5514 if (os_snprintf_error(end - pos, ret))
5515 return 0;
5516 pos += ret;
5517 } else {
5518 if (bss->caps & IEEE80211_CAP_IBSS) {
5519 ret = os_snprintf(pos, end - pos, "[IBSS]");
5520 if (os_snprintf_error(end - pos, ret))
5521 return 0;
5522 pos += ret;
5523 }
5524 if (bss->caps & IEEE80211_CAP_ESS) {
5525 ret = os_snprintf(pos, end - pos, "[ESS]");
5526 if (os_snprintf_error(end - pos, ret))
5527 return 0;
5528 pos += ret;
5529 }
5530 }
5531 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5532 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
5533 ret = os_snprintf(pos, end - pos, "[P2P]");
5534 if (os_snprintf_error(end - pos, ret))
5535 return 0;
5536 pos += ret;
5537 }
5538 #ifdef CONFIG_HS20
5539 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5540 ret = os_snprintf(pos, end - pos, "[HS20]");
5541 if (os_snprintf_error(end - pos, ret))
5542 return 0;
5543 pos += ret;
5544 }
5545 #endif /* CONFIG_HS20 */
5546 #ifdef CONFIG_FILS
5547 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5548 ret = os_snprintf(pos, end - pos, "[FILS]");
5549 if (os_snprintf_error(end - pos, ret))
5550 return 0;
5551 pos += ret;
5552 }
5553 #endif /* CONFIG_FILS */
5554 #ifdef CONFIG_FST
5555 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5556 ret = os_snprintf(pos, end - pos, "[FST]");
5557 if (os_snprintf_error(end - pos, ret))
5558 return 0;
5559 pos += ret;
5560 }
5561 #endif /* CONFIG_FST */
5562 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5563 ret = os_snprintf(pos, end - pos, "[UTF-8]");
5564 if (os_snprintf_error(end - pos, ret))
5565 return 0;
5566 pos += ret;
5567 }
5568
5569 ret = os_snprintf(pos, end - pos, "\n");
5570 if (os_snprintf_error(end - pos, ret))
5571 return 0;
5572 pos += ret;
5573 }
5574
5575 if (mask & WPA_BSS_MASK_SSID) {
5576 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5577 wpa_ssid_txt(bss->ssid, bss->ssid_len));
5578 if (os_snprintf_error(end - pos, ret))
5579 return 0;
5580 pos += ret;
5581 }
5582
5583 #ifdef CONFIG_WPS
5584 if (mask & WPA_BSS_MASK_WPS_SCAN) {
5585 ie = wpa_bss_ie_ptr(bss);
5586 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
5587 if (ret >= end - pos)
5588 return 0;
5589 if (ret > 0)
5590 pos += ret;
5591 }
5592 #endif /* CONFIG_WPS */
5593
5594 #ifdef CONFIG_P2P
5595 if (mask & WPA_BSS_MASK_P2P_SCAN) {
5596 ie = wpa_bss_ie_ptr(bss);
5597 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
5598 if (ret >= end - pos)
5599 return 0;
5600 if (ret > 0)
5601 pos += ret;
5602 }
5603 #endif /* CONFIG_P2P */
5604
5605 #ifdef CONFIG_WIFI_DISPLAY
5606 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5607 struct wpabuf *wfd;
5608
5609 ie = wpa_bss_ie_ptr(bss);
5610 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5611 WFD_IE_VENDOR_TYPE);
5612 if (wfd) {
5613 ret = os_snprintf(pos, end - pos, "wfd_subelems=");
5614 if (os_snprintf_error(end - pos, ret)) {
5615 wpabuf_free(wfd);
5616 return 0;
5617 }
5618 pos += ret;
5619
5620 pos += wpa_snprintf_hex(pos, end - pos,
5621 wpabuf_head(wfd),
5622 wpabuf_len(wfd));
5623 wpabuf_free(wfd);
5624
5625 ret = os_snprintf(pos, end - pos, "\n");
5626 if (os_snprintf_error(end - pos, ret))
5627 return 0;
5628 pos += ret;
5629 }
5630 }
5631 #endif /* CONFIG_WIFI_DISPLAY */
5632
5633 #ifdef CONFIG_INTERWORKING
5634 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5635 struct wpa_bss_anqp *anqp = bss->anqp;
5636 struct wpa_bss_anqp_elem *elem;
5637
5638 pos = anqp_add_hex(pos, end, "anqp_capability_list",
5639 anqp->capability_list);
5640 pos = anqp_add_hex(pos, end, "anqp_venue_name",
5641 anqp->venue_name);
5642 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
5643 anqp->network_auth_type);
5644 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
5645 anqp->roaming_consortium);
5646 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
5647 anqp->ip_addr_type_availability);
5648 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
5649 anqp->nai_realm);
5650 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
5651 pos = anqp_add_hex(pos, end, "anqp_domain_name",
5652 anqp->domain_name);
5653 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5654 anqp->fils_realm_info);
5655 #ifdef CONFIG_HS20
5656 pos = anqp_add_hex(pos, end, "hs20_capability_list",
5657 anqp->hs20_capability_list);
5658 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
5659 anqp->hs20_operator_friendly_name);
5660 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
5661 anqp->hs20_wan_metrics);
5662 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
5663 anqp->hs20_connection_capability);
5664 pos = anqp_add_hex(pos, end, "hs20_operating_class",
5665 anqp->hs20_operating_class);
5666 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5667 anqp->hs20_osu_providers_list);
5668 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5669 anqp->hs20_operator_icon_metadata);
5670 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5671 anqp->hs20_osu_providers_nai_list);
5672 #endif /* CONFIG_HS20 */
5673
5674 dl_list_for_each(elem, &anqp->anqp_elems,
5675 struct wpa_bss_anqp_elem, list) {
5676 char title[20];
5677
5678 os_snprintf(title, sizeof(title), "anqp[%u]",
5679 elem->infoid);
5680 pos = anqp_add_hex(pos, end, title, elem->payload);
5681 if (elem->protected_response) {
5682 ret = os_snprintf(pos, end - pos,
5683 "protected-anqp-info[%u]=1\n",
5684 elem->infoid);
5685 if (os_snprintf_error(end - pos, ret))
5686 return 0;
5687 pos += ret;
5688 }
5689 }
5690 }
5691 #endif /* CONFIG_INTERWORKING */
5692
5693 #ifdef CONFIG_MESH
5694 if (mask & WPA_BSS_MASK_MESH_SCAN) {
5695 ie = wpa_bss_ie_ptr(bss);
5696 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
5697 if (ret >= end - pos)
5698 return 0;
5699 if (ret > 0)
5700 pos += ret;
5701 }
5702 #endif /* CONFIG_MESH */
5703
5704 if (mask & WPA_BSS_MASK_SNR) {
5705 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5706 if (os_snprintf_error(end - pos, ret))
5707 return 0;
5708 pos += ret;
5709 }
5710
5711 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5712 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5713 bss->est_throughput);
5714 if (os_snprintf_error(end - pos, ret))
5715 return 0;
5716 pos += ret;
5717 }
5718
5719 #ifdef CONFIG_FST
5720 if (mask & WPA_BSS_MASK_FST) {
5721 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5722 if (ret < 0 || ret >= end - pos)
5723 return 0;
5724 pos += ret;
5725 }
5726 #endif /* CONFIG_FST */
5727
5728 if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5729 ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5730 bss->last_update_idx);
5731 if (os_snprintf_error(end - pos, ret))
5732 return 0;
5733 pos += ret;
5734 }
5735
5736 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5737 ret = os_snprintf(pos, end - pos, "beacon_ie=");
5738 if (os_snprintf_error(end - pos, ret))
5739 return 0;
5740 pos += ret;
5741
5742 ie = wpa_bss_ie_ptr(bss);
5743 ie += bss->ie_len;
5744 for (i = 0; i < bss->beacon_ie_len; i++) {
5745 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5746 if (os_snprintf_error(end - pos, ret))
5747 return 0;
5748 pos += ret;
5749 }
5750
5751 ret = os_snprintf(pos, end - pos, "\n");
5752 if (os_snprintf_error(end - pos, ret))
5753 return 0;
5754 pos += ret;
5755 }
5756
5757 #ifdef CONFIG_FILS
5758 if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5759 ret = print_fils_indication(bss, pos, end);
5760 pos += ret;
5761 }
5762 #endif /* CONFIG_FILS */
5763
5764 if (!is_zero_ether_addr(bss->mld_addr) &&
5765 (mask & WPA_BSS_MASK_AP_MLD_ADDR)) {
5766 ret = os_snprintf(pos, end - pos,
5767 "ap_mld_addr=" MACSTR "\n",
5768 MAC2STR(bss->mld_addr));
5769 if (os_snprintf_error(end - pos, ret))
5770 return 0;
5771 pos += ret;
5772 }
5773
5774 if (mask & WPA_BSS_MASK_RNR)
5775 pos += print_rnr(bss, pos, end);
5776
5777 if (mask & WPA_BSS_MASK_ML)
5778 pos += print_ml(bss, pos, end);
5779
5780 if (mask & WPA_BSS_MASK_DELIM) {
5781 ret = os_snprintf(pos, end - pos, "====\n");
5782 if (os_snprintf_error(end - pos, ret))
5783 return 0;
5784 pos += ret;
5785 }
5786
5787 return pos - buf;
5788 }
5789
5790
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)5791 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5792 const char *cmd, char *buf,
5793 size_t buflen)
5794 {
5795 u8 bssid[ETH_ALEN];
5796 size_t i;
5797 struct wpa_bss *bss;
5798 struct wpa_bss *bsslast = NULL;
5799 struct dl_list *next;
5800 int ret = 0;
5801 int len;
5802 char *ctmp, *end = buf + buflen;
5803 unsigned long mask = WPA_BSS_MASK_ALL;
5804
5805 if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5806 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5807 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
5808 list_id);
5809 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5810 list_id);
5811 } else { /* N1-N2 */
5812 unsigned int id1, id2;
5813
5814 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5815 wpa_printf(MSG_INFO, "Wrong BSS range "
5816 "format");
5817 return 0;
5818 }
5819
5820 if (*(cmd + 6) == '-')
5821 id1 = 0;
5822 else
5823 id1 = atoi(cmd + 6);
5824 ctmp++;
5825 if (*ctmp >= '0' && *ctmp <= '9')
5826 id2 = atoi(ctmp);
5827 else
5828 id2 = (unsigned int) -1;
5829 bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5830 if (id2 == (unsigned int) -1)
5831 bsslast = dl_list_last(&wpa_s->bss_id,
5832 struct wpa_bss,
5833 list_id);
5834 else {
5835 bsslast = wpa_bss_get_id(wpa_s, id2);
5836 if (bsslast == NULL && bss && id2 > id1) {
5837 struct wpa_bss *tmp = bss;
5838 for (;;) {
5839 next = tmp->list_id.next;
5840 if (next == &wpa_s->bss_id)
5841 break;
5842 tmp = dl_list_entry(
5843 next, struct wpa_bss,
5844 list_id);
5845 if (tmp->id > id2)
5846 break;
5847 bsslast = tmp;
5848 }
5849 }
5850 }
5851 }
5852 } else if (os_strncmp(cmd, "FIRST", 5) == 0)
5853 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
5854 else if (os_strncmp(cmd, "LAST", 4) == 0)
5855 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
5856 else if (os_strncmp(cmd, "ID-", 3) == 0) {
5857 i = atoi(cmd + 3);
5858 bss = wpa_bss_get_id(wpa_s, i);
5859 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5860 i = atoi(cmd + 5);
5861 bss = wpa_bss_get_id(wpa_s, i);
5862 if (bss) {
5863 next = bss->list_id.next;
5864 if (next == &wpa_s->bss_id)
5865 bss = NULL;
5866 else
5867 bss = dl_list_entry(next, struct wpa_bss,
5868 list_id);
5869 }
5870 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5871 bss = wpa_s->current_bss;
5872 #ifdef CONFIG_P2P
5873 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5874 if (hwaddr_aton(cmd + 13, bssid) == 0)
5875 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5876 else
5877 bss = NULL;
5878 #endif /* CONFIG_P2P */
5879 } else if (hwaddr_aton(cmd, bssid) == 0)
5880 bss = wpa_bss_get_bssid(wpa_s, bssid);
5881 else {
5882 struct wpa_bss *tmp;
5883 i = atoi(cmd);
5884 bss = NULL;
5885 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5886 {
5887 if (i == 0) {
5888 bss = tmp;
5889 break;
5890 }
5891 i--;
5892 }
5893 }
5894
5895 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5896 mask = strtoul(ctmp + 5, NULL, 0x10);
5897 if (mask == 0)
5898 mask = WPA_BSS_MASK_ALL;
5899 }
5900
5901 if (bss == NULL)
5902 return 0;
5903
5904 if (bsslast == NULL)
5905 bsslast = bss;
5906 do {
5907 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5908 ret += len;
5909 buf += len;
5910 buflen -= len;
5911 if (bss == bsslast) {
5912 if ((mask & WPA_BSS_MASK_DELIM) && len &&
5913 (bss == dl_list_last(&wpa_s->bss_id,
5914 struct wpa_bss, list_id))) {
5915 int res;
5916
5917 res = os_snprintf(buf - 5, end - buf + 5,
5918 "####\n");
5919 if (os_snprintf_error(end - buf + 5, res)) {
5920 wpa_printf(MSG_DEBUG,
5921 "Could not add end delim");
5922 }
5923 }
5924 break;
5925 }
5926 next = bss->list_id.next;
5927 if (next == &wpa_s->bss_id)
5928 break;
5929 bss = dl_list_entry(next, struct wpa_bss, list_id);
5930 } while (bss && len);
5931
5932 return ret;
5933 }
5934
5935
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)5936 static int wpa_supplicant_ctrl_iface_ap_scan(
5937 struct wpa_supplicant *wpa_s, char *cmd)
5938 {
5939 int ap_scan = atoi(cmd);
5940 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5941 }
5942
5943
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)5944 static int wpa_supplicant_ctrl_iface_scan_interval(
5945 struct wpa_supplicant *wpa_s, char *cmd)
5946 {
5947 int scan_int = atoi(cmd);
5948 return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
5949 }
5950
5951
wpa_supplicant_ctrl_iface_bss_expire_age(struct wpa_supplicant * wpa_s,char * cmd)5952 static int wpa_supplicant_ctrl_iface_bss_expire_age(
5953 struct wpa_supplicant *wpa_s, char *cmd)
5954 {
5955 int expire_age = atoi(cmd);
5956 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5957 }
5958
5959
wpa_supplicant_ctrl_iface_bss_expire_count(struct wpa_supplicant * wpa_s,char * cmd)5960 static int wpa_supplicant_ctrl_iface_bss_expire_count(
5961 struct wpa_supplicant *wpa_s, char *cmd)
5962 {
5963 int expire_count = atoi(cmd);
5964 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5965 }
5966
5967
wpa_supplicant_ctrl_iface_bss_flush(struct wpa_supplicant * wpa_s,char * cmd)5968 static void wpa_supplicant_ctrl_iface_bss_flush(
5969 struct wpa_supplicant *wpa_s, char *cmd)
5970 {
5971 int flush_age = atoi(cmd);
5972
5973 if (flush_age == 0)
5974 wpa_bss_flush(wpa_s);
5975 else
5976 wpa_bss_flush_by_age(wpa_s, flush_age);
5977 }
5978
5979
5980 #ifdef CONFIG_TESTING_OPTIONS
wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant * wpa_s)5981 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5982 {
5983 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5984 /* MLME-DELETEKEYS.request */
5985 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
5986 0, KEY_FLAG_GROUP);
5987 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
5988 0, KEY_FLAG_GROUP);
5989 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
5990 0, KEY_FLAG_GROUP);
5991 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
5992 0, KEY_FLAG_GROUP);
5993 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
5994 0, KEY_FLAG_GROUP);
5995 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
5996 0, KEY_FLAG_GROUP);
5997
5998 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0,
5999 NULL, 0, KEY_FLAG_PAIRWISE);
6000 if (wpa_sm_ext_key_id(wpa_s->wpa))
6001 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
6002 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
6003 /* MLME-SETPROTECTION.request(None) */
6004 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
6005 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
6006 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
6007 wpa_sm_drop_sa(wpa_s->wpa);
6008 }
6009 #endif /* CONFIG_TESTING_OPTIONS */
6010
6011
wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant * wpa_s,char * addr)6012 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
6013 char *addr)
6014 {
6015 #ifdef CONFIG_NO_SCAN_PROCESSING
6016 return -1;
6017 #else /* CONFIG_NO_SCAN_PROCESSING */
6018 u8 bssid[ETH_ALEN];
6019 struct wpa_bss *bss;
6020 struct wpa_ssid *ssid = wpa_s->current_ssid;
6021 struct wpa_radio_work *already_connecting;
6022
6023 if (hwaddr_aton(addr, bssid)) {
6024 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
6025 "address '%s'", addr);
6026 return -1;
6027 }
6028
6029 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
6030
6031 if (!ssid) {
6032 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
6033 "configuration known for the target AP");
6034 return -1;
6035 }
6036
6037 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
6038 if (!bss) {
6039 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
6040 "from BSS table");
6041 return -1;
6042 }
6043
6044 /*
6045 * TODO: Find best network configuration block from configuration to
6046 * allow roaming to other networks
6047 */
6048
6049 already_connecting = radio_work_pending(wpa_s, "sme-connect");
6050 wpa_s->reassociate = 1;
6051 wpa_supplicant_connect(wpa_s, bss, ssid);
6052
6053 /*
6054 * Indicate that an explicitly requested roam is in progress so scan
6055 * results that come in before the 'sme-connect' radio work gets
6056 * executed do not override the original connection attempt.
6057 */
6058 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
6059 wpa_s->roam_in_progress = true;
6060
6061 return 0;
6062 #endif /* CONFIG_NO_SCAN_PROCESSING */
6063 }
6064
6065
6066 #ifdef CONFIG_P2P
p2p_ctrl_find(struct wpa_supplicant * wpa_s,char * cmd)6067 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
6068 {
6069 unsigned int timeout = atoi(cmd);
6070 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
6071 u8 dev_id[ETH_ALEN], *_dev_id = NULL;
6072 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
6073 char *pos;
6074 unsigned int search_delay;
6075 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
6076 u8 seek_count = 0;
6077 int freq = 0;
6078 bool include_6ghz = false;
6079
6080 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6081 wpa_dbg(wpa_s, MSG_INFO,
6082 "Reject P2P_FIND since interface is disabled");
6083 return -1;
6084 }
6085
6086 if (os_strstr(cmd, " include_6ghz"))
6087 include_6ghz = true;
6088 if (os_strstr(cmd, "type=social"))
6089 type = P2P_FIND_ONLY_SOCIAL;
6090 else if (os_strstr(cmd, "type=progressive"))
6091 type = P2P_FIND_PROGRESSIVE;
6092
6093 pos = os_strstr(cmd, "dev_id=");
6094 if (pos) {
6095 pos += 7;
6096 if (hwaddr_aton(pos, dev_id))
6097 return -1;
6098 _dev_id = dev_id;
6099 }
6100
6101 pos = os_strstr(cmd, "dev_type=");
6102 if (pos) {
6103 pos += 9;
6104 if (wps_dev_type_str2bin(pos, dev_type) < 0)
6105 return -1;
6106 _dev_type = dev_type;
6107 }
6108
6109 pos = os_strstr(cmd, "delay=");
6110 if (pos) {
6111 pos += 6;
6112 search_delay = atoi(pos);
6113 } else
6114 search_delay = wpas_p2p_search_delay(wpa_s);
6115
6116 pos = os_strstr(cmd, "freq=");
6117 if (pos) {
6118 pos += 5;
6119 freq = atoi(pos);
6120 if (freq <= 0)
6121 return -1;
6122 }
6123
6124 /* Must be searched for last, because it adds nul termination */
6125 pos = os_strstr(cmd, " seek=");
6126 if (pos)
6127 pos += 6;
6128 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
6129 char *term;
6130
6131 _seek[seek_count++] = pos;
6132 seek = _seek;
6133 term = os_strchr(pos, ' ');
6134 if (!term)
6135 break;
6136 *term = '\0';
6137 pos = os_strstr(term + 1, "seek=");
6138 if (pos)
6139 pos += 5;
6140 }
6141 if (seek_count > P2P_MAX_QUERY_HASH) {
6142 seek[0] = NULL;
6143 seek_count = 1;
6144 }
6145
6146 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
6147 _dev_id, search_delay, seek_count, seek, freq,
6148 include_6ghz);
6149 }
6150
6151
p2ps_ctrl_parse_cpt_priority(const char * pos,u8 * cpt)6152 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
6153 {
6154 const char *last = NULL;
6155 const char *token;
6156 long int token_len;
6157 unsigned int i;
6158
6159 /* Expected predefined CPT names delimited by ':' */
6160 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
6161 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
6162 wpa_printf(MSG_ERROR,
6163 "P2PS: CPT name list is too long, expected up to %d names",
6164 P2PS_FEATURE_CAPAB_CPT_MAX);
6165 cpt[0] = 0;
6166 return -1;
6167 }
6168
6169 token_len = last - token;
6170
6171 if (token_len == 3 &&
6172 os_memcmp(token, "UDP", token_len) == 0) {
6173 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6174 } else if (token_len == 3 &&
6175 os_memcmp(token, "MAC", token_len) == 0) {
6176 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
6177 } else {
6178 wpa_printf(MSG_ERROR,
6179 "P2PS: Unsupported CPT name '%s'", token);
6180 cpt[0] = 0;
6181 return -1;
6182 }
6183
6184 if (isblank((unsigned char) *last)) {
6185 i++;
6186 break;
6187 }
6188 }
6189 cpt[i] = 0;
6190 return 0;
6191 }
6192
6193
p2p_parse_asp_provision_cmd(const char * cmd)6194 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
6195 {
6196 struct p2ps_provision *p2ps_prov;
6197 char *pos;
6198 size_t info_len = 0;
6199 char *info = NULL;
6200 u8 role = P2PS_SETUP_NONE;
6201 long long unsigned val;
6202 int i;
6203
6204 pos = os_strstr(cmd, "info=");
6205 if (pos) {
6206 pos += 5;
6207 info_len = os_strlen(pos);
6208
6209 if (info_len) {
6210 info = os_malloc(info_len + 1);
6211 if (info) {
6212 info_len = utf8_unescape(pos, info_len,
6213 info, info_len + 1);
6214 } else
6215 info_len = 0;
6216 }
6217 }
6218
6219 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
6220 if (p2ps_prov == NULL) {
6221 os_free(info);
6222 return NULL;
6223 }
6224
6225 if (info) {
6226 os_memcpy(p2ps_prov->info, info, info_len);
6227 p2ps_prov->info[info_len] = '\0';
6228 os_free(info);
6229 }
6230
6231 pos = os_strstr(cmd, "status=");
6232 if (pos)
6233 p2ps_prov->status = atoi(pos + 7);
6234 else
6235 p2ps_prov->status = -1;
6236
6237 pos = os_strstr(cmd, "adv_id=");
6238 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
6239 goto invalid_args;
6240 p2ps_prov->adv_id = val;
6241
6242 pos = os_strstr(cmd, "method=");
6243 if (pos)
6244 p2ps_prov->method = strtol(pos + 7, NULL, 16);
6245 else
6246 p2ps_prov->method = 0;
6247
6248 pos = os_strstr(cmd, "session=");
6249 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
6250 goto invalid_args;
6251 p2ps_prov->session_id = val;
6252
6253 pos = os_strstr(cmd, "adv_mac=");
6254 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
6255 goto invalid_args;
6256
6257 pos = os_strstr(cmd, "session_mac=");
6258 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
6259 goto invalid_args;
6260
6261 pos = os_strstr(cmd, "cpt=");
6262 if (pos) {
6263 if (p2ps_ctrl_parse_cpt_priority(pos + 4,
6264 p2ps_prov->cpt_priority))
6265 goto invalid_args;
6266 } else {
6267 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6268 }
6269
6270 for (i = 0; p2ps_prov->cpt_priority[i]; i++)
6271 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
6272
6273 /* force conncap with tstCap (no validity checks) */
6274 pos = os_strstr(cmd, "tstCap=");
6275 if (pos) {
6276 role = strtol(pos + 7, NULL, 16);
6277 } else {
6278 pos = os_strstr(cmd, "role=");
6279 if (pos) {
6280 role = strtol(pos + 5, NULL, 16);
6281 if (role != P2PS_SETUP_CLIENT &&
6282 role != P2PS_SETUP_GROUP_OWNER)
6283 role = P2PS_SETUP_NONE;
6284 }
6285 }
6286 p2ps_prov->role = role;
6287
6288 return p2ps_prov;
6289
6290 invalid_args:
6291 os_free(p2ps_prov);
6292 return NULL;
6293 }
6294
6295
p2p_ctrl_asp_provision_resp(struct wpa_supplicant * wpa_s,char * cmd)6296 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
6297 {
6298 u8 addr[ETH_ALEN];
6299 struct p2ps_provision *p2ps_prov;
6300 char *pos;
6301
6302 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
6303
6304 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6305
6306 if (hwaddr_aton(cmd, addr))
6307 return -1;
6308
6309 pos = cmd + 17;
6310 if (*pos != ' ')
6311 return -1;
6312
6313 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6314 if (!p2ps_prov)
6315 return -1;
6316
6317 if (p2ps_prov->status < 0) {
6318 os_free(p2ps_prov);
6319 return -1;
6320 }
6321
6322 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6323 p2ps_prov);
6324 }
6325
6326
p2p_ctrl_asp_provision(struct wpa_supplicant * wpa_s,char * cmd)6327 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
6328 {
6329 u8 addr[ETH_ALEN];
6330 struct p2ps_provision *p2ps_prov;
6331 char *pos;
6332
6333 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
6334 * session=<ses_id> mac=<ses_mac> [info=<infodata>]
6335 */
6336
6337 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6338 if (hwaddr_aton(cmd, addr))
6339 return -1;
6340
6341 pos = cmd + 17;
6342 if (*pos != ' ')
6343 return -1;
6344
6345 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6346 if (!p2ps_prov)
6347 return -1;
6348
6349 p2ps_prov->pd_seeker = 1;
6350
6351 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6352 p2ps_prov);
6353 }
6354
6355
p2p_ctrl_connect(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6356 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6357 char *buf, size_t buflen)
6358 {
6359 u8 addr[ETH_ALEN];
6360 char *pos, *pos2;
6361 char *pin = NULL;
6362 enum p2p_wps_method wps_method;
6363 int new_pin;
6364 int ret;
6365 int persistent_group, persistent_id = -1;
6366 int join;
6367 int auth;
6368 int automatic;
6369 int go_intent = -1;
6370 int freq = 0;
6371 int pd;
6372 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
6373 int edmg;
6374 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6375 size_t group_ssid_len = 0;
6376 int he;
6377 bool allow_6ghz;
6378
6379 if (!wpa_s->global->p2p_init_wpa_s)
6380 return -1;
6381 if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6382 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6383 wpa_s->global->p2p_init_wpa_s->ifname);
6384 wpa_s = wpa_s->global->p2p_init_wpa_s;
6385 }
6386
6387 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
6388 * [persistent|persistent=<network id>]
6389 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
6390 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
6391
6392 if (hwaddr_aton(cmd, addr))
6393 return -1;
6394
6395 pos = cmd + 17;
6396 if (*pos != ' ')
6397 return -1;
6398 pos++;
6399
6400 persistent_group = os_strstr(pos, " persistent") != NULL;
6401 pos2 = os_strstr(pos, " persistent=");
6402 if (pos2) {
6403 struct wpa_ssid *ssid;
6404 persistent_id = atoi(pos2 + 12);
6405 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6406 if (ssid == NULL || ssid->disabled != 2 ||
6407 ssid->mode != WPAS_MODE_P2P_GO) {
6408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6409 "SSID id=%d for persistent P2P group (GO)",
6410 persistent_id);
6411 return -1;
6412 }
6413 }
6414 join = os_strstr(pos, " join") != NULL;
6415 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
6416 auth = os_strstr(pos, " auth") != NULL;
6417 automatic = os_strstr(pos, " auto") != NULL;
6418 pd = os_strstr(pos, " provdisc") != NULL;
6419 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6420 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6421 vht;
6422 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6423 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6424
6425 pos2 = os_strstr(pos, " go_intent=");
6426 if (pos2) {
6427 pos2 += 11;
6428 go_intent = atoi(pos2);
6429 if (go_intent < 0 || go_intent > 15)
6430 return -1;
6431 }
6432
6433 pos2 = os_strstr(pos, " freq=");
6434 if (pos2) {
6435 pos2 += 6;
6436 freq = atoi(pos2);
6437 if (freq <= 0)
6438 return -1;
6439 }
6440
6441 pos2 = os_strstr(pos, " freq2=");
6442 if (pos2)
6443 freq2 = atoi(pos2 + 7);
6444
6445 pos2 = os_strstr(pos, " max_oper_chwidth=");
6446 if (pos2)
6447 chwidth = atoi(pos2 + 18);
6448
6449 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
6450 if (max_oper_chwidth < 0)
6451 return -1;
6452
6453 if (allow_6ghz && chwidth == 40)
6454 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
6455
6456 pos2 = os_strstr(pos, " ssid=");
6457 if (pos2) {
6458 char *end;
6459
6460 pos2 += 6;
6461 end = os_strchr(pos2, ' ');
6462 if (!end)
6463 group_ssid_len = os_strlen(pos2) / 2;
6464 else
6465 group_ssid_len = (end - pos2) / 2;
6466 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6467 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6468 return -1;
6469 group_ssid = _group_ssid;
6470 }
6471
6472 if (os_strncmp(pos, "pin", 3) == 0) {
6473 /* Request random PIN (to be displayed) and enable the PIN */
6474 wps_method = WPS_PIN_DISPLAY;
6475 } else if (os_strncmp(pos, "pbc", 3) == 0) {
6476 wps_method = WPS_PBC;
6477 } else if (os_strstr(pos, "p2ps") != NULL) {
6478 wps_method = WPS_P2PS;
6479 } else {
6480 pin = pos;
6481 pos = os_strchr(pin, ' ');
6482 wps_method = WPS_PIN_KEYPAD;
6483 if (pos) {
6484 *pos++ = '\0';
6485 if (os_strncmp(pos, "display", 7) == 0)
6486 wps_method = WPS_PIN_DISPLAY;
6487 }
6488 if (!wps_pin_str_valid(pin)) {
6489 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6490 return 17;
6491 }
6492 }
6493
6494 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
6495 persistent_group, automatic, join,
6496 auth, go_intent, freq, freq2, persistent_id,
6497 pd, ht40, vht, max_oper_chwidth, he, edmg,
6498 group_ssid, group_ssid_len, allow_6ghz);
6499 if (new_pin == -2) {
6500 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6501 return 25;
6502 }
6503 if (new_pin == -3) {
6504 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6505 return 25;
6506 }
6507 if (new_pin < 0)
6508 return -1;
6509 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6510 ret = os_snprintf(buf, buflen, "%08d", new_pin);
6511 if (os_snprintf_error(buflen, ret))
6512 return -1;
6513 return ret;
6514 }
6515
6516 os_memcpy(buf, "OK\n", 3);
6517 return 3;
6518 }
6519
6520
p2p_ctrl_listen(struct wpa_supplicant * wpa_s,char * cmd)6521 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6522 {
6523 unsigned int timeout = atoi(cmd);
6524 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6525 wpa_dbg(wpa_s, MSG_INFO,
6526 "Reject P2P_LISTEN since interface is disabled");
6527 return -1;
6528 }
6529 return wpas_p2p_listen(wpa_s, timeout);
6530 }
6531
6532
p2p_ctrl_prov_disc(struct wpa_supplicant * wpa_s,char * cmd)6533 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6534 {
6535 u8 addr[ETH_ALEN];
6536 char *pos;
6537 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
6538
6539 /* <addr> <config method> [join|auto] */
6540
6541 if (hwaddr_aton(cmd, addr))
6542 return -1;
6543
6544 pos = cmd + 17;
6545 if (*pos != ' ')
6546 return -1;
6547 pos++;
6548
6549 if (os_strstr(pos, " join") != NULL)
6550 use = WPAS_P2P_PD_FOR_JOIN;
6551 else if (os_strstr(pos, " auto") != NULL)
6552 use = WPAS_P2P_PD_AUTO;
6553
6554 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
6555 }
6556
6557
p2p_get_passphrase(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)6558 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6559 size_t buflen)
6560 {
6561 struct wpa_ssid *ssid = wpa_s->current_ssid;
6562
6563 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6564 ssid->passphrase == NULL)
6565 return -1;
6566
6567 os_strlcpy(buf, ssid->passphrase, buflen);
6568 return os_strlen(buf);
6569 }
6570
6571
p2p_ctrl_serv_disc_req(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6572 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6573 char *buf, size_t buflen)
6574 {
6575 u64 ref;
6576 int res;
6577 u8 dst_buf[ETH_ALEN], *dst;
6578 struct wpabuf *tlvs;
6579 char *pos;
6580 size_t len;
6581
6582 if (hwaddr_aton(cmd, dst_buf))
6583 return -1;
6584 dst = dst_buf;
6585 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6586 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6587 dst = NULL;
6588 pos = cmd + 17;
6589 if (*pos != ' ')
6590 return -1;
6591 pos++;
6592
6593 if (os_strncmp(pos, "upnp ", 5) == 0) {
6594 u8 version;
6595 pos += 5;
6596 if (hexstr2bin(pos, &version, 1) < 0)
6597 return -1;
6598 pos += 2;
6599 if (*pos != ' ')
6600 return -1;
6601 pos++;
6602 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
6603 #ifdef CONFIG_WIFI_DISPLAY
6604 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6605 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6606 #endif /* CONFIG_WIFI_DISPLAY */
6607 } else if (os_strncmp(pos, "asp ", 4) == 0) {
6608 char *svc_str;
6609 char *svc_info = NULL;
6610 u32 id;
6611
6612 pos += 4;
6613 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6614 return -1;
6615
6616 pos = os_strchr(pos, ' ');
6617 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6618 return -1;
6619
6620 svc_str = pos + 1;
6621
6622 pos = os_strchr(svc_str, ' ');
6623
6624 if (pos)
6625 *pos++ = '\0';
6626
6627 /* All remaining data is the svc_info string */
6628 if (pos && pos[0] && pos[0] != ' ') {
6629 len = os_strlen(pos);
6630
6631 /* Unescape in place */
6632 len = utf8_unescape(pos, len, pos, len);
6633 if (len > 0xff)
6634 return -1;
6635
6636 svc_info = pos;
6637 }
6638
6639 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6640 svc_str, svc_info);
6641 } else {
6642 len = os_strlen(pos);
6643 if (len & 1)
6644 return -1;
6645 len /= 2;
6646 tlvs = wpabuf_alloc(len);
6647 if (tlvs == NULL)
6648 return -1;
6649 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6650 wpabuf_free(tlvs);
6651 return -1;
6652 }
6653
6654 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
6655 wpabuf_free(tlvs);
6656 }
6657 if (ref == 0)
6658 return -1;
6659 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
6660 if (os_snprintf_error(buflen, res))
6661 return -1;
6662 return res;
6663 }
6664
6665
p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant * wpa_s,char * cmd)6666 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6667 char *cmd)
6668 {
6669 long long unsigned val;
6670 u64 req;
6671 if (sscanf(cmd, "%llx", &val) != 1)
6672 return -1;
6673 req = val;
6674 return wpas_p2p_sd_cancel_request(wpa_s, req);
6675 }
6676
6677
p2p_ctrl_serv_disc_resp(struct wpa_supplicant * wpa_s,char * cmd)6678 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6679 {
6680 int freq;
6681 u8 dst[ETH_ALEN];
6682 u8 dialog_token;
6683 struct wpabuf *resp_tlvs;
6684 char *pos, *pos2;
6685 size_t len;
6686
6687 pos = os_strchr(cmd, ' ');
6688 if (pos == NULL)
6689 return -1;
6690 *pos++ = '\0';
6691 freq = atoi(cmd);
6692 if (freq == 0)
6693 return -1;
6694
6695 if (hwaddr_aton(pos, dst))
6696 return -1;
6697 pos += 17;
6698 if (*pos != ' ')
6699 return -1;
6700 pos++;
6701
6702 pos2 = os_strchr(pos, ' ');
6703 if (pos2 == NULL)
6704 return -1;
6705 *pos2++ = '\0';
6706 dialog_token = atoi(pos);
6707
6708 len = os_strlen(pos2);
6709 if (len & 1)
6710 return -1;
6711 len /= 2;
6712 resp_tlvs = wpabuf_alloc(len);
6713 if (resp_tlvs == NULL)
6714 return -1;
6715 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6716 wpabuf_free(resp_tlvs);
6717 return -1;
6718 }
6719
6720 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6721 wpabuf_free(resp_tlvs);
6722 return 0;
6723 }
6724
6725
p2p_ctrl_serv_disc_external(struct wpa_supplicant * wpa_s,char * cmd)6726 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6727 char *cmd)
6728 {
6729 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6730 return -1;
6731 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6732 return 0;
6733 }
6734
6735
p2p_ctrl_service_add_bonjour(struct wpa_supplicant * wpa_s,char * cmd)6736 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6737 char *cmd)
6738 {
6739 char *pos;
6740 size_t len;
6741 struct wpabuf *query, *resp;
6742 int ret;
6743
6744 pos = os_strchr(cmd, ' ');
6745 if (pos == NULL)
6746 return -1;
6747 *pos++ = '\0';
6748
6749 len = os_strlen(cmd);
6750 if (len & 1)
6751 return -1;
6752 len /= 2;
6753 query = wpabuf_alloc(len);
6754 if (query == NULL)
6755 return -1;
6756 ret = hexstr2bin(cmd, wpabuf_put(query, len), len);
6757 if (ret < 0)
6758 goto err_query;
6759 ret = -1;
6760 len = os_strlen(pos);
6761 if (len & 1)
6762 goto err_query;
6763 len /= 2;
6764 resp = wpabuf_alloc(len);
6765 if (!resp)
6766 goto err_query;
6767 ret = hexstr2bin(pos, wpabuf_put(resp, len), len);
6768 if (ret < 0)
6769 goto err_resp;
6770
6771 ret = wpas_p2p_service_add_bonjour(wpa_s, query, resp);
6772
6773 err_resp:
6774 wpabuf_free(resp);
6775 err_query:
6776 wpabuf_free(query);
6777 return ret;
6778 }
6779
6780
p2p_ctrl_service_add_upnp(struct wpa_supplicant * wpa_s,char * cmd)6781 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6782 {
6783 char *pos;
6784 u8 version;
6785
6786 pos = os_strchr(cmd, ' ');
6787 if (pos == NULL)
6788 return -1;
6789 *pos++ = '\0';
6790
6791 if (hexstr2bin(cmd, &version, 1) < 0)
6792 return -1;
6793
6794 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6795 }
6796
6797
p2p_ctrl_service_add_asp(struct wpa_supplicant * wpa_s,u8 replace,char * cmd)6798 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6799 u8 replace, char *cmd)
6800 {
6801 char *pos;
6802 char *adv_str;
6803 u32 auto_accept, adv_id, svc_state, config_methods;
6804 char *svc_info = NULL;
6805 char *cpt_prio_str;
6806 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
6807
6808 pos = os_strchr(cmd, ' ');
6809 if (pos == NULL)
6810 return -1;
6811 *pos++ = '\0';
6812
6813 /* Auto-Accept value is mandatory, and must be one of the
6814 * single values (0, 1, 2, 4) */
6815 auto_accept = atoi(cmd);
6816 switch (auto_accept) {
6817 case P2PS_SETUP_NONE: /* No auto-accept */
6818 case P2PS_SETUP_NEW:
6819 case P2PS_SETUP_CLIENT:
6820 case P2PS_SETUP_GROUP_OWNER:
6821 break;
6822 default:
6823 return -1;
6824 }
6825
6826 /* Advertisement ID is mandatory */
6827 cmd = pos;
6828 pos = os_strchr(cmd, ' ');
6829 if (pos == NULL)
6830 return -1;
6831 *pos++ = '\0';
6832
6833 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6834 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6835 return -1;
6836
6837 /* Only allow replacements if exist, and adds if not */
6838 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6839 if (!replace)
6840 return -1;
6841 } else {
6842 if (replace)
6843 return -1;
6844 }
6845
6846 /* svc_state between 0 - 0xff is mandatory */
6847 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6848 return -1;
6849
6850 pos = os_strchr(pos, ' ');
6851 if (pos == NULL)
6852 return -1;
6853
6854 /* config_methods is mandatory */
6855 pos++;
6856 if (sscanf(pos, "%x", &config_methods) != 1)
6857 return -1;
6858
6859 if (!(config_methods &
6860 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6861 return -1;
6862
6863 pos = os_strchr(pos, ' ');
6864 if (pos == NULL)
6865 return -1;
6866
6867 pos++;
6868 adv_str = pos;
6869
6870 /* Advertisement string is mandatory */
6871 if (!pos[0] || pos[0] == ' ')
6872 return -1;
6873
6874 /* Terminate svc string */
6875 pos = os_strchr(pos, ' ');
6876 if (pos != NULL)
6877 *pos++ = '\0';
6878
6879 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6880 if (cpt_prio_str) {
6881 pos = os_strchr(pos, ' ');
6882 if (pos != NULL)
6883 *pos++ = '\0';
6884
6885 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6886 return -1;
6887 } else {
6888 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6889 cpt_prio[1] = 0;
6890 }
6891
6892 /* Service and Response Information are optional */
6893 if (pos && pos[0]) {
6894 size_t len;
6895
6896 /* Note the bare ' included, which cannot exist legally
6897 * in unescaped string. */
6898 svc_info = os_strstr(pos, "svc_info='");
6899
6900 if (svc_info) {
6901 svc_info += 9;
6902 len = os_strlen(svc_info);
6903 utf8_unescape(svc_info, len, svc_info, len);
6904 }
6905 }
6906
6907 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6908 (u8) svc_state, (u16) config_methods,
6909 svc_info, cpt_prio);
6910 }
6911
6912
p2p_ctrl_service_add(struct wpa_supplicant * wpa_s,char * cmd)6913 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6914 {
6915 char *pos;
6916
6917 pos = os_strchr(cmd, ' ');
6918 if (pos == NULL)
6919 return -1;
6920 *pos++ = '\0';
6921
6922 if (os_strcmp(cmd, "bonjour") == 0)
6923 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6924 if (os_strcmp(cmd, "upnp") == 0)
6925 return p2p_ctrl_service_add_upnp(wpa_s, pos);
6926 if (os_strcmp(cmd, "asp") == 0)
6927 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
6928 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6929 return -1;
6930 }
6931
6932
p2p_ctrl_service_del_bonjour(struct wpa_supplicant * wpa_s,char * cmd)6933 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6934 char *cmd)
6935 {
6936 size_t len;
6937 struct wpabuf *query;
6938 int ret;
6939
6940 len = os_strlen(cmd);
6941 if (len & 1)
6942 return -1;
6943 len /= 2;
6944 query = wpabuf_alloc(len);
6945 if (query == NULL)
6946 return -1;
6947 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6948 wpabuf_free(query);
6949 return -1;
6950 }
6951
6952 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6953 wpabuf_free(query);
6954 return ret;
6955 }
6956
6957
p2p_ctrl_service_del_upnp(struct wpa_supplicant * wpa_s,char * cmd)6958 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6959 {
6960 char *pos;
6961 u8 version;
6962
6963 pos = os_strchr(cmd, ' ');
6964 if (pos == NULL)
6965 return -1;
6966 *pos++ = '\0';
6967
6968 if (hexstr2bin(cmd, &version, 1) < 0)
6969 return -1;
6970
6971 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6972 }
6973
6974
p2p_ctrl_service_del_asp(struct wpa_supplicant * wpa_s,char * cmd)6975 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6976 {
6977 u32 adv_id;
6978
6979 if (os_strcmp(cmd, "all") == 0) {
6980 wpas_p2p_service_flush_asp(wpa_s);
6981 return 0;
6982 }
6983
6984 if (sscanf(cmd, "%x", &adv_id) != 1)
6985 return -1;
6986
6987 return wpas_p2p_service_del_asp(wpa_s, adv_id);
6988 }
6989
6990
p2p_ctrl_service_del(struct wpa_supplicant * wpa_s,char * cmd)6991 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6992 {
6993 char *pos;
6994
6995 pos = os_strchr(cmd, ' ');
6996 if (pos == NULL)
6997 return -1;
6998 *pos++ = '\0';
6999
7000 if (os_strcmp(cmd, "bonjour") == 0)
7001 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
7002 if (os_strcmp(cmd, "upnp") == 0)
7003 return p2p_ctrl_service_del_upnp(wpa_s, pos);
7004 if (os_strcmp(cmd, "asp") == 0)
7005 return p2p_ctrl_service_del_asp(wpa_s, pos);
7006 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7007 return -1;
7008 }
7009
7010
p2p_ctrl_service_replace(struct wpa_supplicant * wpa_s,char * cmd)7011 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
7012 {
7013 char *pos;
7014
7015 pos = os_strchr(cmd, ' ');
7016 if (pos == NULL)
7017 return -1;
7018 *pos++ = '\0';
7019
7020 if (os_strcmp(cmd, "asp") == 0)
7021 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
7022
7023 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7024 return -1;
7025 }
7026
7027
p2p_ctrl_reject(struct wpa_supplicant * wpa_s,char * cmd)7028 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
7029 {
7030 u8 addr[ETH_ALEN];
7031
7032 /* <addr> */
7033
7034 if (hwaddr_aton(cmd, addr))
7035 return -1;
7036
7037 return wpas_p2p_reject(wpa_s, addr);
7038 }
7039
7040
p2p_ctrl_invite_persistent(struct wpa_supplicant * wpa_s,char * cmd)7041 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
7042 {
7043 char *pos;
7044 int id;
7045 struct wpa_ssid *ssid;
7046 u8 *_peer = NULL, peer[ETH_ALEN];
7047 int freq = 0, pref_freq = 0;
7048 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
7049 int edmg;
7050 bool allow_6ghz;
7051
7052 id = atoi(cmd);
7053 pos = os_strstr(cmd, " peer=");
7054 if (pos) {
7055 pos += 6;
7056 if (hwaddr_aton(pos, peer))
7057 return -1;
7058 _peer = peer;
7059 }
7060 ssid = wpa_config_get_network(wpa_s->conf, id);
7061 if (ssid == NULL || ssid->disabled != 2) {
7062 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7063 "for persistent P2P group",
7064 id);
7065 return -1;
7066 }
7067
7068 pos = os_strstr(cmd, " freq=");
7069 if (pos) {
7070 pos += 6;
7071 freq = atoi(pos);
7072 if (freq <= 0)
7073 return -1;
7074 }
7075
7076 pos = os_strstr(cmd, " pref=");
7077 if (pos) {
7078 pos += 6;
7079 pref_freq = atoi(pos);
7080 if (pref_freq <= 0)
7081 return -1;
7082 }
7083
7084 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
7085 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
7086 vht;
7087 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
7088 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
7089
7090 pos = os_strstr(cmd, "freq2=");
7091 if (pos)
7092 freq2 = atoi(pos + 6);
7093
7094 pos = os_strstr(cmd, " max_oper_chwidth=");
7095 if (pos)
7096 chwidth = atoi(pos + 18);
7097
7098 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
7099 if (max_oper_chwidth < 0)
7100 return -1;
7101
7102 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
7103
7104 if (allow_6ghz && chwidth == 40)
7105 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
7106
7107 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
7108 max_oper_chwidth, pref_freq, he, edmg,
7109 allow_6ghz);
7110 }
7111
7112
p2p_ctrl_invite_group(struct wpa_supplicant * wpa_s,char * cmd)7113 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
7114 {
7115 char *pos;
7116 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
7117 bool allow_6ghz;
7118
7119 pos = os_strstr(cmd, " peer=");
7120 if (!pos)
7121 return -1;
7122
7123 *pos = '\0';
7124 pos += 6;
7125 if (hwaddr_aton(pos, peer)) {
7126 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
7127 return -1;
7128 }
7129
7130 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
7131
7132 pos = os_strstr(pos, " go_dev_addr=");
7133 if (pos) {
7134 pos += 13;
7135 if (hwaddr_aton(pos, go_dev_addr)) {
7136 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
7137 pos);
7138 return -1;
7139 }
7140 go_dev = go_dev_addr;
7141 }
7142
7143 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
7144 }
7145
7146
p2p_ctrl_invite(struct wpa_supplicant * wpa_s,char * cmd)7147 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
7148 {
7149 if (os_strncmp(cmd, "persistent=", 11) == 0)
7150 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
7151 if (os_strncmp(cmd, "group=", 6) == 0)
7152 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
7153
7154 return -1;
7155 }
7156
7157
p2p_ctrl_group_add_persistent(struct wpa_supplicant * wpa_s,int id,int freq,int vht_center_freq2,int ht40,int vht,int vht_chwidth,int he,int edmg,bool allow_6ghz,const u8 * go_bssid)7158 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
7159 int id, int freq, int vht_center_freq2,
7160 int ht40, int vht, int vht_chwidth,
7161 int he, int edmg, bool allow_6ghz,
7162 const u8 *go_bssid)
7163 {
7164 struct wpa_ssid *ssid;
7165
7166 ssid = wpa_config_get_network(wpa_s->conf, id);
7167 if (ssid == NULL || ssid->disabled != 2) {
7168 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7169 "for persistent P2P group",
7170 id);
7171 return -1;
7172 }
7173
7174 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
7175 vht_center_freq2, ht40, vht,
7176 vht_chwidth, he, edmg,
7177 NULL, 0, 0, allow_6ghz, 0,
7178 go_bssid);
7179 }
7180
7181
p2p_ctrl_group_add(struct wpa_supplicant * wpa_s,char * cmd)7182 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
7183 {
7184 int freq = 0, persistent = 0, group_id = -1;
7185 bool allow_6ghz = false;
7186 int vht = wpa_s->conf->p2p_go_vht;
7187 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
7188 int he = wpa_s->conf->p2p_go_he;
7189 int edmg = wpa_s->conf->p2p_go_edmg;
7190 int max_oper_chwidth, chwidth = 0, freq2 = 0;
7191 char *token, *context = NULL;
7192 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
7193 #ifdef CONFIG_ACS
7194 int acs = 0;
7195 #endif /* CONFIG_ACS */
7196
7197 while ((token = str_token(cmd, " ", &context))) {
7198 if (sscanf(token, "freq2=%d", &freq2) == 1 ||
7199 sscanf(token, "persistent=%d", &group_id) == 1 ||
7200 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
7201 continue;
7202 #ifdef CONFIG_ACS
7203 } else if (os_strcmp(token, "freq=acs") == 0) {
7204 acs = 1;
7205 #endif /* CONFIG_ACS */
7206 } else if (sscanf(token, "freq=%d", &freq) == 1) {
7207 continue;
7208 } else if (os_strcmp(token, "ht40") == 0) {
7209 ht40 = 1;
7210 } else if (os_strcmp(token, "vht") == 0) {
7211 vht = 1;
7212 ht40 = 1;
7213 } else if (os_strcmp(token, "he") == 0) {
7214 he = 1;
7215 } else if (os_strcmp(token, "edmg") == 0) {
7216 edmg = 1;
7217 } else if (os_strcmp(token, "persistent") == 0) {
7218 persistent = 1;
7219 } else if (os_strcmp(token, "allow_6ghz") == 0) {
7220 allow_6ghz = true;
7221 } else if (os_strncmp(token, "go_bssid=", 9) == 0) {
7222 if (hwaddr_aton(token + 9, go_bssid_buf))
7223 return -1;
7224 go_bssid = go_bssid_buf;
7225 } else {
7226 wpa_printf(MSG_DEBUG,
7227 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
7228 token);
7229 return -1;
7230 }
7231 }
7232
7233 #ifdef CONFIG_ACS
7234 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
7235 (acs || freq == 2 || freq == 5)) {
7236 if (freq == 2 && wpa_s->best_24_freq <= 0) {
7237 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
7238 wpa_s->p2p_go_do_acs = 1;
7239 freq = 0;
7240 } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
7241 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
7242 wpa_s->p2p_go_do_acs = 1;
7243 freq = 0;
7244 } else {
7245 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
7246 wpa_s->p2p_go_do_acs = 1;
7247 }
7248 } else {
7249 wpa_s->p2p_go_do_acs = 0;
7250 }
7251 #endif /* CONFIG_ACS */
7252
7253 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
7254 if (max_oper_chwidth < 0)
7255 return -1;
7256
7257 if (allow_6ghz && chwidth == 40)
7258 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
7259
7260 /* Allow DFS to be used for Autonomous GO */
7261 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
7262 WPA_DRIVER_FLAGS_DFS_OFFLOAD);
7263
7264 if (group_id >= 0)
7265 return p2p_ctrl_group_add_persistent(wpa_s, group_id,
7266 freq, freq2, ht40, vht,
7267 max_oper_chwidth, he,
7268 edmg, allow_6ghz,
7269 go_bssid);
7270
7271 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
7272 max_oper_chwidth, he, edmg, allow_6ghz);
7273 }
7274
7275
p2p_ctrl_group_member(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)7276 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
7277 char *buf, size_t buflen)
7278 {
7279 u8 dev_addr[ETH_ALEN];
7280 struct wpa_ssid *ssid;
7281 int res;
7282 const u8 *iaddr;
7283
7284 ssid = wpa_s->current_ssid;
7285 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
7286 hwaddr_aton(cmd, dev_addr))
7287 return -1;
7288
7289 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
7290 if (!iaddr)
7291 return -1;
7292 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
7293 if (os_snprintf_error(buflen, res))
7294 return -1;
7295 return res;
7296 }
7297
7298
wpas_find_p2p_dev_addr_bss(struct wpa_global * global,const u8 * p2p_dev_addr)7299 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
7300 const u8 *p2p_dev_addr)
7301 {
7302 struct wpa_supplicant *wpa_s;
7303
7304 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7305 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
7306 return 1;
7307 }
7308
7309 return 0;
7310 }
7311
7312
p2p_ctrl_peer(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)7313 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7314 char *buf, size_t buflen)
7315 {
7316 u8 addr[ETH_ALEN], *addr_ptr, group_capab;
7317 int next, res;
7318 const struct p2p_peer_info *info;
7319 char *pos, *end;
7320 char devtype[WPS_DEV_TYPE_BUFSIZE];
7321 struct wpa_ssid *ssid;
7322 size_t i;
7323
7324 if (!wpa_s->global->p2p)
7325 return -1;
7326
7327 if (os_strcmp(cmd, "FIRST") == 0) {
7328 addr_ptr = NULL;
7329 next = 0;
7330 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
7331 if (hwaddr_aton(cmd + 5, addr) < 0)
7332 return -1;
7333 addr_ptr = addr;
7334 next = 1;
7335 } else {
7336 if (hwaddr_aton(cmd, addr) < 0)
7337 return -1;
7338 addr_ptr = addr;
7339 next = 0;
7340 }
7341
7342 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7343 if (info == NULL)
7344 return -1;
7345 group_capab = info->group_capab;
7346
7347 if (group_capab &&
7348 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
7349 wpa_printf(MSG_DEBUG,
7350 "P2P: Could not find any BSS with p2p_dev_addr "
7351 MACSTR ", hence override group_capab from 0x%x to 0",
7352 MAC2STR(info->p2p_device_addr), group_capab);
7353 group_capab = 0;
7354 }
7355
7356 pos = buf;
7357 end = buf + buflen;
7358
7359 res = os_snprintf(pos, end - pos, MACSTR "\n"
7360 "pri_dev_type=%s\n"
7361 "device_name=%s\n"
7362 "manufacturer=%s\n"
7363 "model_name=%s\n"
7364 "model_number=%s\n"
7365 "serial_number=%s\n"
7366 "config_methods=0x%x\n"
7367 "dev_capab=0x%x\n"
7368 "group_capab=0x%x\n"
7369 "level=%d\n",
7370 MAC2STR(info->p2p_device_addr),
7371 wps_dev_type_bin2str(info->pri_dev_type,
7372 devtype, sizeof(devtype)),
7373 info->device_name,
7374 info->manufacturer,
7375 info->model_name,
7376 info->model_number,
7377 info->serial_number,
7378 info->config_methods,
7379 info->dev_capab,
7380 group_capab,
7381 info->level);
7382 if (os_snprintf_error(end - pos, res))
7383 return pos - buf;
7384 pos += res;
7385
7386 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7387 {
7388 const u8 *t;
7389 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7390 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7391 wps_dev_type_bin2str(t, devtype,
7392 sizeof(devtype)));
7393 if (os_snprintf_error(end - pos, res))
7394 return pos - buf;
7395 pos += res;
7396 }
7397
7398 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
7399 if (ssid) {
7400 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
7401 if (os_snprintf_error(end - pos, res))
7402 return pos - buf;
7403 pos += res;
7404 }
7405
7406 res = p2p_get_peer_info_txt(info, pos, end - pos);
7407 if (res < 0)
7408 return pos - buf;
7409 pos += res;
7410
7411 if (info->vendor_elems) {
7412 res = os_snprintf(pos, end - pos, "vendor_elems=");
7413 if (os_snprintf_error(end - pos, res))
7414 return pos - buf;
7415 pos += res;
7416
7417 pos += wpa_snprintf_hex(pos, end - pos,
7418 wpabuf_head(info->vendor_elems),
7419 wpabuf_len(info->vendor_elems));
7420
7421 res = os_snprintf(pos, end - pos, "\n");
7422 if (os_snprintf_error(end - pos, res))
7423 return pos - buf;
7424 pos += res;
7425 }
7426
7427 return pos - buf;
7428 }
7429
7430
p2p_ctrl_disallow_freq(struct wpa_supplicant * wpa_s,const char * param)7431 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7432 const char *param)
7433 {
7434 unsigned int i;
7435
7436 if (wpa_s->global->p2p == NULL)
7437 return -1;
7438
7439 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7440 return -1;
7441
7442 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7443 struct wpa_freq_range *freq;
7444 freq = &wpa_s->global->p2p_disallow_freq.range[i];
7445 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
7446 freq->min, freq->max);
7447 }
7448
7449 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
7450 return 0;
7451 }
7452
7453
p2p_ctrl_set(struct wpa_supplicant * wpa_s,char * cmd)7454 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7455 {
7456 char *param;
7457
7458 if (wpa_s->global->p2p == NULL)
7459 return -1;
7460
7461 param = os_strchr(cmd, ' ');
7462 if (param == NULL)
7463 return -1;
7464 *param++ = '\0';
7465
7466 if (os_strcmp(cmd, "discoverability") == 0) {
7467 p2p_set_client_discoverability(wpa_s->global->p2p,
7468 atoi(param));
7469 return 0;
7470 }
7471
7472 if (os_strcmp(cmd, "managed") == 0) {
7473 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7474 return 0;
7475 }
7476
7477 if (os_strcmp(cmd, "listen_channel") == 0) {
7478 char *pos;
7479 u8 channel, op_class;
7480
7481 channel = atoi(param);
7482 pos = os_strchr(param, ' ');
7483 op_class = pos ? atoi(pos) : 81;
7484
7485 return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7486 channel, 1);
7487 }
7488
7489 if (os_strcmp(cmd, "ssid_postfix") == 0) {
7490 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7491 os_strlen(param));
7492 }
7493
7494 if (os_strcmp(cmd, "noa") == 0) {
7495 char *pos;
7496 int count, start, duration;
7497 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
7498 count = atoi(param);
7499 pos = os_strchr(param, ',');
7500 if (pos == NULL)
7501 return -1;
7502 pos++;
7503 start = atoi(pos);
7504 pos = os_strchr(pos, ',');
7505 if (pos == NULL)
7506 return -1;
7507 pos++;
7508 duration = atoi(pos);
7509 if (count < 0 || count > 255 || start < 0 || duration < 0)
7510 return -1;
7511 if (count == 0 && duration > 0)
7512 return -1;
7513 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7514 "start=%d duration=%d", count, start, duration);
7515 return wpas_p2p_set_noa(wpa_s, count, start, duration);
7516 }
7517
7518 if (os_strcmp(cmd, "ps") == 0)
7519 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7520
7521 if (os_strcmp(cmd, "oppps") == 0)
7522 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7523
7524 if (os_strcmp(cmd, "ctwindow") == 0)
7525 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7526
7527 if (os_strcmp(cmd, "disabled") == 0) {
7528 wpa_s->global->p2p_disabled = atoi(param);
7529 wpa_printf(MSG_DEBUG, "P2P functionality %s",
7530 wpa_s->global->p2p_disabled ?
7531 "disabled" : "enabled");
7532 if (wpa_s->global->p2p_disabled) {
7533 wpas_p2p_stop_find(wpa_s);
7534 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7535 p2p_flush(wpa_s->global->p2p);
7536 }
7537 return 0;
7538 }
7539
7540 if (os_strcmp(cmd, "conc_pref") == 0) {
7541 if (os_strcmp(param, "sta") == 0)
7542 wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7543 else if (os_strcmp(param, "p2p") == 0)
7544 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
7545 else {
7546 wpa_printf(MSG_INFO, "Invalid conc_pref value");
7547 return -1;
7548 }
7549 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
7550 "%s", param);
7551 return 0;
7552 }
7553
7554 if (os_strcmp(cmd, "force_long_sd") == 0) {
7555 wpa_s->force_long_sd = atoi(param);
7556 return 0;
7557 }
7558
7559 if (os_strcmp(cmd, "peer_filter") == 0) {
7560 u8 addr[ETH_ALEN];
7561 if (hwaddr_aton(param, addr))
7562 return -1;
7563 p2p_set_peer_filter(wpa_s->global->p2p, addr);
7564 return 0;
7565 }
7566
7567 if (os_strcmp(cmd, "cross_connect") == 0)
7568 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7569
7570 if (os_strcmp(cmd, "go_apsd") == 0) {
7571 if (os_strcmp(param, "disable") == 0)
7572 wpa_s->set_ap_uapsd = 0;
7573 else {
7574 wpa_s->set_ap_uapsd = 1;
7575 wpa_s->ap_uapsd = atoi(param);
7576 }
7577 return 0;
7578 }
7579
7580 if (os_strcmp(cmd, "client_apsd") == 0) {
7581 if (os_strcmp(param, "disable") == 0)
7582 wpa_s->set_sta_uapsd = 0;
7583 else {
7584 int be, bk, vi, vo;
7585 char *pos;
7586 /* format: BE,BK,VI,VO;max SP Length */
7587 be = atoi(param);
7588 pos = os_strchr(param, ',');
7589 if (pos == NULL)
7590 return -1;
7591 pos++;
7592 bk = atoi(pos);
7593 pos = os_strchr(pos, ',');
7594 if (pos == NULL)
7595 return -1;
7596 pos++;
7597 vi = atoi(pos);
7598 pos = os_strchr(pos, ',');
7599 if (pos == NULL)
7600 return -1;
7601 pos++;
7602 vo = atoi(pos);
7603 /* ignore max SP Length for now */
7604
7605 wpa_s->set_sta_uapsd = 1;
7606 wpa_s->sta_uapsd = 0;
7607 if (be)
7608 wpa_s->sta_uapsd |= BIT(0);
7609 if (bk)
7610 wpa_s->sta_uapsd |= BIT(1);
7611 if (vi)
7612 wpa_s->sta_uapsd |= BIT(2);
7613 if (vo)
7614 wpa_s->sta_uapsd |= BIT(3);
7615 }
7616 return 0;
7617 }
7618
7619 if (os_strcmp(cmd, "disallow_freq") == 0)
7620 return p2p_ctrl_disallow_freq(wpa_s, param);
7621
7622 if (os_strcmp(cmd, "disc_int") == 0) {
7623 int min_disc_int, max_disc_int, max_disc_tu;
7624 char *pos;
7625
7626 pos = param;
7627
7628 min_disc_int = atoi(pos);
7629 pos = os_strchr(pos, ' ');
7630 if (pos == NULL)
7631 return -1;
7632 *pos++ = '\0';
7633
7634 max_disc_int = atoi(pos);
7635 pos = os_strchr(pos, ' ');
7636 if (pos == NULL)
7637 return -1;
7638 *pos++ = '\0';
7639
7640 max_disc_tu = atoi(pos);
7641
7642 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7643 max_disc_int, max_disc_tu);
7644 }
7645
7646 if (os_strcmp(cmd, "per_sta_psk") == 0) {
7647 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7648 return 0;
7649 }
7650
7651 #ifdef CONFIG_WPS_NFC
7652 if (os_strcmp(cmd, "nfc_tag") == 0)
7653 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7654 #endif /* CONFIG_WPS_NFC */
7655
7656 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7657 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7658 return 0;
7659 }
7660
7661 if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7662 int op_class, chan;
7663
7664 op_class = atoi(param);
7665 param = os_strchr(param, ':');
7666 if (!param)
7667 return -1;
7668 param++;
7669 chan = atoi(param);
7670 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7671 chan);
7672 return 0;
7673 }
7674
7675 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7676 cmd);
7677
7678 return -1;
7679 }
7680
7681
p2p_ctrl_flush(struct wpa_supplicant * wpa_s)7682 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7683 {
7684 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7685 wpa_s->force_long_sd = 0;
7686
7687 #ifdef CONFIG_TESTING_OPTIONS
7688 os_free(wpa_s->get_pref_freq_list_override);
7689 wpa_s->get_pref_freq_list_override = NULL;
7690 #endif /* CONFIG_TESTING_OPTIONS */
7691
7692 wpas_p2p_stop_find(wpa_s);
7693 wpa_s->parent->p2ps_method_config_any = 0;
7694 if (wpa_s->global->p2p)
7695 p2p_flush(wpa_s->global->p2p);
7696 }
7697
7698
p2p_ctrl_presence_req(struct wpa_supplicant * wpa_s,char * cmd)7699 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7700 {
7701 char *pos, *pos2;
7702 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7703
7704 if (cmd[0]) {
7705 pos = os_strchr(cmd, ' ');
7706 if (pos == NULL)
7707 return -1;
7708 *pos++ = '\0';
7709 dur1 = atoi(cmd);
7710
7711 pos2 = os_strchr(pos, ' ');
7712 if (pos2)
7713 *pos2++ = '\0';
7714 int1 = atoi(pos);
7715 } else
7716 pos2 = NULL;
7717
7718 if (pos2) {
7719 pos = os_strchr(pos2, ' ');
7720 if (pos == NULL)
7721 return -1;
7722 *pos++ = '\0';
7723 dur2 = atoi(pos2);
7724 int2 = atoi(pos);
7725 }
7726
7727 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7728 }
7729
7730
p2p_ctrl_ext_listen(struct wpa_supplicant * wpa_s,char * cmd)7731 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7732 {
7733 char *pos;
7734 unsigned int period = 0, interval = 0;
7735
7736 if (cmd[0]) {
7737 pos = os_strchr(cmd, ' ');
7738 if (pos == NULL)
7739 return -1;
7740 *pos++ = '\0';
7741 period = atoi(cmd);
7742 interval = atoi(pos);
7743 }
7744
7745 return wpas_p2p_ext_listen(wpa_s, period, interval);
7746 }
7747
7748
p2p_ctrl_remove_client(struct wpa_supplicant * wpa_s,const char * cmd)7749 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7750 {
7751 const char *pos;
7752 u8 peer[ETH_ALEN];
7753 int iface_addr = 0;
7754
7755 pos = cmd;
7756 if (os_strncmp(pos, "iface=", 6) == 0) {
7757 iface_addr = 1;
7758 pos += 6;
7759 }
7760 if (hwaddr_aton(pos, peer))
7761 return -1;
7762
7763 wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7764 return 0;
7765 }
7766
7767
p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant * wpa_s,char * cmd)7768 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7769 {
7770 int freq = 0, period = 0, interval = 0, count = 0;
7771
7772 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7773 {
7774 wpa_printf(MSG_DEBUG,
7775 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7776 return -1;
7777 }
7778
7779 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7780 }
7781
7782 #endif /* CONFIG_P2P */
7783
7784
freq_range_to_channel_list(struct wpa_supplicant * wpa_s,char * val)7785 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7786 {
7787 struct wpa_freq_range_list ranges;
7788 int *freqs = NULL;
7789 struct hostapd_hw_modes *mode;
7790 u16 i;
7791
7792 if (wpa_s->hw.modes == NULL)
7793 return NULL;
7794
7795 os_memset(&ranges, 0, sizeof(ranges));
7796 if (freq_range_list_parse(&ranges, val) < 0)
7797 return NULL;
7798
7799 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7800 int j;
7801
7802 mode = &wpa_s->hw.modes[i];
7803 for (j = 0; j < mode->num_channels; j++) {
7804 unsigned int freq;
7805
7806 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7807 continue;
7808
7809 freq = mode->channels[j].freq;
7810 if (!freq_range_list_includes(&ranges, freq))
7811 continue;
7812
7813 int_array_add_unique(&freqs, freq);
7814 }
7815 }
7816
7817 os_free(ranges.range);
7818 return freqs;
7819 }
7820
7821
7822 #ifdef CONFIG_INTERWORKING
7823
ctrl_interworking_select(struct wpa_supplicant * wpa_s,char * param)7824 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7825 {
7826 int auto_sel = 0;
7827 int *freqs = NULL;
7828
7829 if (param) {
7830 char *pos;
7831
7832 auto_sel = os_strstr(param, "auto") != NULL;
7833
7834 pos = os_strstr(param, "freq=");
7835 if (pos) {
7836 freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7837 if (freqs == NULL)
7838 return -1;
7839 }
7840
7841 }
7842
7843 return interworking_select(wpa_s, auto_sel, freqs);
7844 }
7845
7846
ctrl_interworking_connect(struct wpa_supplicant * wpa_s,char * dst,int only_add)7847 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7848 int only_add)
7849 {
7850 u8 bssid[ETH_ALEN];
7851 struct wpa_bss *bss;
7852
7853 if (hwaddr_aton(dst, bssid)) {
7854 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7855 return -1;
7856 }
7857
7858 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
7859 if (bss == NULL) {
7860 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7861 MAC2STR(bssid));
7862 return -1;
7863 }
7864
7865 if (bss->ssid_len == 0) {
7866 int found = 0;
7867
7868 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7869 " does not have SSID information", MAC2STR(bssid));
7870
7871 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7872 list) {
7873 if (ether_addr_equal(bss->bssid, bssid) &&
7874 bss->ssid_len > 0) {
7875 found = 1;
7876 break;
7877 }
7878 }
7879
7880 if (!found)
7881 return -1;
7882 wpa_printf(MSG_DEBUG,
7883 "Found another matching BSS entry with SSID");
7884 }
7885
7886 return interworking_connect(wpa_s, bss, only_add);
7887 }
7888
7889
get_anqp(struct wpa_supplicant * wpa_s,char * dst)7890 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7891 {
7892 u8 dst_addr[ETH_ALEN];
7893 int used, freq = 0;
7894 char *pos;
7895 #define MAX_ANQP_INFO_ID 100
7896 u16 id[MAX_ANQP_INFO_ID];
7897 size_t num_id = 0;
7898 u32 subtypes = 0;
7899 u32 mbo_subtypes = 0;
7900
7901 used = hwaddr_aton2(dst, dst_addr);
7902 if (used < 0)
7903 return -1;
7904 pos = dst + used;
7905 if (*pos == ' ')
7906 pos++;
7907
7908 if (os_strncmp(pos, "freq=", 5) == 0) {
7909 freq = atoi(pos + 5);
7910 pos = os_strchr(pos, ' ');
7911 if (!pos)
7912 return -1;
7913 pos++;
7914 }
7915
7916 while (num_id < MAX_ANQP_INFO_ID) {
7917 if (os_strncmp(pos, "hs20:", 5) == 0) {
7918 #ifdef CONFIG_HS20
7919 int num = atoi(pos + 5);
7920 if (num <= 0 || num > 31)
7921 return -1;
7922 subtypes |= BIT(num);
7923 #else /* CONFIG_HS20 */
7924 return -1;
7925 #endif /* CONFIG_HS20 */
7926 } else if (os_strncmp(pos, "mbo:", 4) == 0) {
7927 #ifdef CONFIG_MBO
7928 int num = atoi(pos + 4);
7929
7930 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
7931 return -1;
7932 mbo_subtypes |= BIT(num);
7933 #else /* CONFIG_MBO */
7934 return -1;
7935 #endif /* CONFIG_MBO */
7936 } else {
7937 id[num_id] = atoi(pos);
7938 if (id[num_id])
7939 num_id++;
7940 }
7941 pos = os_strchr(pos + 1, ',');
7942 if (pos == NULL)
7943 break;
7944 pos++;
7945 }
7946
7947 if (num_id == 0 && !subtypes && !mbo_subtypes)
7948 return -1;
7949
7950 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
7951 mbo_subtypes);
7952 }
7953
7954
gas_request(struct wpa_supplicant * wpa_s,char * cmd)7955 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
7956 {
7957 u8 dst_addr[ETH_ALEN];
7958 struct wpabuf *advproto, *query = NULL;
7959 int used, ret = -1;
7960 char *pos, *end;
7961 size_t len;
7962
7963 used = hwaddr_aton2(cmd, dst_addr);
7964 if (used < 0)
7965 return -1;
7966
7967 pos = cmd + used;
7968 while (*pos == ' ')
7969 pos++;
7970
7971 /* Advertisement Protocol ID */
7972 end = os_strchr(pos, ' ');
7973 if (end)
7974 len = end - pos;
7975 else
7976 len = os_strlen(pos);
7977 if (len & 0x01)
7978 return -1;
7979 len /= 2;
7980 if (len == 0)
7981 return -1;
7982 advproto = wpabuf_alloc(len);
7983 if (advproto == NULL)
7984 return -1;
7985 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
7986 goto fail;
7987
7988 if (end) {
7989 /* Optional Query Request */
7990 pos = end + 1;
7991 while (*pos == ' ')
7992 pos++;
7993
7994 len = os_strlen(pos);
7995 if (len) {
7996 if (len & 0x01)
7997 goto fail;
7998 len /= 2;
7999 if (len == 0)
8000 goto fail;
8001 query = wpabuf_alloc(len);
8002 if (query == NULL)
8003 goto fail;
8004 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
8005 goto fail;
8006 }
8007 }
8008
8009 ret = gas_send_request(wpa_s, dst_addr, advproto, query);
8010
8011 fail:
8012 wpabuf_free(advproto);
8013 wpabuf_free(query);
8014
8015 return ret;
8016 }
8017
8018
gas_response_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8019 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
8020 size_t buflen)
8021 {
8022 u8 addr[ETH_ALEN];
8023 int dialog_token;
8024 int used;
8025 char *pos;
8026 size_t resp_len, start, requested_len;
8027 struct wpabuf *resp;
8028 int ret;
8029
8030 used = hwaddr_aton2(cmd, addr);
8031 if (used < 0)
8032 return -1;
8033
8034 pos = cmd + used;
8035 while (*pos == ' ')
8036 pos++;
8037 dialog_token = atoi(pos);
8038
8039 if (wpa_s->last_gas_resp &&
8040 ether_addr_equal(addr, wpa_s->last_gas_addr) &&
8041 dialog_token == wpa_s->last_gas_dialog_token)
8042 resp = wpa_s->last_gas_resp;
8043 else if (wpa_s->prev_gas_resp &&
8044 ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
8045 dialog_token == wpa_s->prev_gas_dialog_token)
8046 resp = wpa_s->prev_gas_resp;
8047 else
8048 return -1;
8049
8050 resp_len = wpabuf_len(resp);
8051 start = 0;
8052 requested_len = resp_len;
8053
8054 pos = os_strchr(pos, ' ');
8055 if (pos) {
8056 start = atoi(pos);
8057 if (start > resp_len)
8058 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8059 pos = os_strchr(pos, ',');
8060 if (pos == NULL)
8061 return -1;
8062 pos++;
8063 requested_len = atoi(pos);
8064 if (start + requested_len > resp_len)
8065 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8066 }
8067
8068 if (requested_len * 2 + 1 > buflen)
8069 return os_snprintf(buf, buflen, "FAIL-Too long response");
8070
8071 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
8072 requested_len);
8073
8074 if (start + requested_len == resp_len) {
8075 /*
8076 * Free memory by dropping the response after it has been
8077 * fetched.
8078 */
8079 if (resp == wpa_s->prev_gas_resp) {
8080 wpabuf_free(wpa_s->prev_gas_resp);
8081 wpa_s->prev_gas_resp = NULL;
8082 } else {
8083 wpabuf_free(wpa_s->last_gas_resp);
8084 wpa_s->last_gas_resp = NULL;
8085 }
8086 }
8087
8088 return ret;
8089 }
8090 #endif /* CONFIG_INTERWORKING */
8091
8092
8093 #ifdef CONFIG_HS20
8094
get_hs20_anqp(struct wpa_supplicant * wpa_s,char * dst)8095 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
8096 {
8097 u8 dst_addr[ETH_ALEN];
8098 int used;
8099 char *pos;
8100 u32 subtypes = 0;
8101
8102 used = hwaddr_aton2(dst, dst_addr);
8103 if (used < 0)
8104 return -1;
8105 pos = dst + used;
8106 if (*pos == ' ')
8107 pos++;
8108 for (;;) {
8109 int num = atoi(pos);
8110 if (num <= 0 || num > 31)
8111 return -1;
8112 subtypes |= BIT(num);
8113 pos = os_strchr(pos + 1, ',');
8114 if (pos == NULL)
8115 break;
8116 pos++;
8117 }
8118
8119 if (subtypes == 0)
8120 return -1;
8121
8122 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
8123 }
8124
8125
hs20_nai_home_realm_list(struct wpa_supplicant * wpa_s,const u8 * addr,const char * realm)8126 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8127 const u8 *addr, const char *realm)
8128 {
8129 u8 *buf;
8130 size_t rlen, len;
8131 int ret;
8132
8133 rlen = os_strlen(realm);
8134 len = 3 + rlen;
8135 buf = os_malloc(len);
8136 if (buf == NULL)
8137 return -1;
8138 buf[0] = 1; /* NAI Home Realm Count */
8139 buf[1] = 0; /* Formatted in accordance with RFC 4282 */
8140 buf[2] = rlen;
8141 os_memcpy(buf + 3, realm, rlen);
8142
8143 ret = hs20_anqp_send_req(wpa_s, addr,
8144 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8145 buf, len, 0);
8146
8147 os_free(buf);
8148
8149 return ret;
8150 }
8151
8152
hs20_get_nai_home_realm_list(struct wpa_supplicant * wpa_s,char * dst)8153 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8154 char *dst)
8155 {
8156 struct wpa_cred *cred = wpa_s->conf->cred;
8157 u8 dst_addr[ETH_ALEN];
8158 int used;
8159 u8 *buf;
8160 size_t len;
8161 int ret;
8162
8163 used = hwaddr_aton2(dst, dst_addr);
8164 if (used < 0)
8165 return -1;
8166
8167 while (dst[used] == ' ')
8168 used++;
8169 if (os_strncmp(dst + used, "realm=", 6) == 0)
8170 return hs20_nai_home_realm_list(wpa_s, dst_addr,
8171 dst + used + 6);
8172
8173 len = os_strlen(dst + used);
8174
8175 if (len == 0 && cred && cred->realm)
8176 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
8177
8178 if (len & 1)
8179 return -1;
8180 len /= 2;
8181 buf = os_malloc(len);
8182 if (buf == NULL)
8183 return -1;
8184 if (hexstr2bin(dst + used, buf, len) < 0) {
8185 os_free(buf);
8186 return -1;
8187 }
8188
8189 ret = hs20_anqp_send_req(wpa_s, dst_addr,
8190 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
8191 buf, len, 0);
8192 os_free(buf);
8193
8194 return ret;
8195 }
8196
8197
get_hs20_icon(struct wpa_supplicant * wpa_s,char * cmd,char * reply,int buflen)8198 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
8199 int buflen)
8200 {
8201 u8 dst_addr[ETH_ALEN];
8202 int used;
8203 char *ctx = NULL, *icon, *poffset, *psize;
8204
8205 used = hwaddr_aton2(cmd, dst_addr);
8206 if (used < 0)
8207 return -1;
8208 cmd += used;
8209
8210 icon = str_token(cmd, " ", &ctx);
8211 poffset = str_token(cmd, " ", &ctx);
8212 psize = str_token(cmd, " ", &ctx);
8213 if (!icon || !poffset || !psize)
8214 return -1;
8215
8216 wpa_s->fetch_osu_icon_in_progress = 0;
8217 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
8218 reply, buflen);
8219 }
8220
8221
del_hs20_icon(struct wpa_supplicant * wpa_s,char * cmd)8222 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
8223 {
8224 u8 dst_addr[ETH_ALEN];
8225 int used;
8226 char *icon;
8227
8228 if (!cmd[0])
8229 return hs20_del_icon(wpa_s, NULL, NULL);
8230
8231 used = hwaddr_aton2(cmd, dst_addr);
8232 if (used < 0)
8233 return -1;
8234
8235 while (cmd[used] == ' ')
8236 used++;
8237 icon = cmd[used] ? &cmd[used] : NULL;
8238
8239 return hs20_del_icon(wpa_s, dst_addr, icon);
8240 }
8241
8242
hs20_icon_request(struct wpa_supplicant * wpa_s,char * cmd,int inmem)8243 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
8244 {
8245 u8 dst_addr[ETH_ALEN];
8246 int used;
8247 char *icon;
8248
8249 used = hwaddr_aton2(cmd, dst_addr);
8250 if (used < 0)
8251 return -1;
8252
8253 while (cmd[used] == ' ')
8254 used++;
8255 icon = &cmd[used];
8256
8257 wpa_s->fetch_osu_icon_in_progress = 0;
8258 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
8259 (u8 *) icon, os_strlen(icon), inmem);
8260 }
8261
8262 #endif /* CONFIG_HS20 */
8263
8264
8265 #ifdef CONFIG_AUTOSCAN
8266
wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant * wpa_s,char * cmd)8267 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
8268 char *cmd)
8269 {
8270 enum wpa_states state = wpa_s->wpa_state;
8271 char *new_params = NULL;
8272
8273 if (os_strlen(cmd) > 0) {
8274 new_params = os_strdup(cmd);
8275 if (new_params == NULL)
8276 return -1;
8277 }
8278
8279 os_free(wpa_s->conf->autoscan);
8280 wpa_s->conf->autoscan = new_params;
8281
8282 if (wpa_s->conf->autoscan == NULL)
8283 autoscan_deinit(wpa_s);
8284 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
8285 autoscan_init(wpa_s, 1);
8286 else if (state == WPA_SCANNING)
8287 wpa_supplicant_reinit_autoscan(wpa_s);
8288 else
8289 wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
8290 wpa_supplicant_state_txt(state));
8291
8292 return 0;
8293 }
8294
8295 #endif /* CONFIG_AUTOSCAN */
8296
8297
8298 #ifdef CONFIG_WNM
8299
wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant * wpa_s,char * cmd)8300 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
8301 {
8302 int enter;
8303 int intval = 0;
8304 char *pos;
8305 int ret;
8306 struct wpabuf *tfs_req = NULL;
8307
8308 if (os_strncmp(cmd, "enter", 5) == 0)
8309 enter = 1;
8310 else if (os_strncmp(cmd, "exit", 4) == 0)
8311 enter = 0;
8312 else
8313 return -1;
8314
8315 pos = os_strstr(cmd, " interval=");
8316 if (pos)
8317 intval = atoi(pos + 10);
8318
8319 pos = os_strstr(cmd, " tfs_req=");
8320 if (pos) {
8321 char *end;
8322 size_t len;
8323 pos += 9;
8324 end = os_strchr(pos, ' ');
8325 if (end)
8326 len = end - pos;
8327 else
8328 len = os_strlen(pos);
8329 if (len & 1)
8330 return -1;
8331 len /= 2;
8332 tfs_req = wpabuf_alloc(len);
8333 if (tfs_req == NULL)
8334 return -1;
8335 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
8336 wpabuf_free(tfs_req);
8337 return -1;
8338 }
8339 }
8340
8341 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
8342 WNM_SLEEP_MODE_EXIT, intval,
8343 tfs_req);
8344 wpabuf_free(tfs_req);
8345
8346 return ret;
8347 }
8348
8349
wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant * wpa_s,char * cmd)8350 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
8351 {
8352 int query_reason, list = 0;
8353 char *btm_candidates = NULL;
8354
8355 query_reason = atoi(cmd);
8356
8357 cmd = os_strchr(cmd, ' ');
8358 if (cmd) {
8359 if (os_strncmp(cmd, " list", 5) == 0)
8360 list = 1;
8361 else
8362 btm_candidates = cmd;
8363 }
8364
8365 wpa_printf(MSG_DEBUG,
8366 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8367 query_reason, list ? " candidate list" : "");
8368
8369 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8370 btm_candidates,
8371 list);
8372 }
8373
wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant * wpa_s,char * cmd)8374 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8375 char *cmd)
8376 {
8377 struct wpabuf *elems;
8378 int ret;
8379
8380 elems = wpabuf_parse_bin(cmd);
8381 if (!elems)
8382 return -1;
8383
8384 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8385 wpabuf_free(elems);
8386 return ret;
8387 }
8388
8389 #endif /* CONFIG_WNM */
8390
8391
wpa_supplicant_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8392 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8393 size_t buflen)
8394 {
8395 struct wpa_signal_info si;
8396 int ret;
8397 char *pos, *end;
8398
8399 ret = wpa_drv_signal_poll(wpa_s, &si);
8400 if (ret)
8401 return -1;
8402
8403 pos = buf;
8404 end = buf + buflen;
8405
8406 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n"
8407 "NOISE=%d\nFREQUENCY=%u\n",
8408 si.data.signal, si.data.current_tx_rate / 1000,
8409 si.current_noise, si.frequency);
8410 if (os_snprintf_error(end - pos, ret))
8411 return -1;
8412 pos += ret;
8413
8414 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8415 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
8416 channel_width_to_string(si.chanwidth));
8417 if (os_snprintf_error(end - pos, ret))
8418 return -1;
8419 pos += ret;
8420 }
8421
8422 if (si.center_frq1 > 0) {
8423 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8424 si.center_frq1);
8425 if (os_snprintf_error(end - pos, ret))
8426 return -1;
8427 pos += ret;
8428 }
8429
8430 if (si.center_frq2 > 0) {
8431 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8432 si.center_frq2);
8433 if (os_snprintf_error(end - pos, ret))
8434 return -1;
8435 pos += ret;
8436 }
8437
8438 if (si.data.avg_signal) {
8439 ret = os_snprintf(pos, end - pos,
8440 "AVG_RSSI=%d\n", si.data.avg_signal);
8441 if (os_snprintf_error(end - pos, ret))
8442 return -1;
8443 pos += ret;
8444 }
8445
8446 if (si.data.avg_beacon_signal) {
8447 ret = os_snprintf(pos, end - pos,
8448 "AVG_BEACON_RSSI=%d\n",
8449 si.data.avg_beacon_signal);
8450 if (os_snprintf_error(end - pos, ret))
8451 return -1;
8452 pos += ret;
8453 }
8454
8455 return pos - buf;
8456 }
8457
8458
wpas_ctrl_iface_signal_monitor(struct wpa_supplicant * wpa_s,const char * cmd)8459 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8460 const char *cmd)
8461 {
8462 const char *pos;
8463 int threshold = 0;
8464 int hysteresis = 0;
8465
8466 if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8467 wpa_printf(MSG_DEBUG,
8468 "Reject SIGNAL_MONITOR command - bgscan is active");
8469 return -1;
8470 }
8471 pos = os_strstr(cmd, "THRESHOLD=");
8472 if (pos)
8473 threshold = atoi(pos + 10);
8474 pos = os_strstr(cmd, "HYSTERESIS=");
8475 if (pos)
8476 hysteresis = atoi(pos + 11);
8477 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8478 }
8479
8480
8481 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant * wpa_s,enum wpa_driver_if_type if_type,unsigned int * num,struct weighted_pcl * freq_list)8482 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8483 enum wpa_driver_if_type if_type,
8484 unsigned int *num,
8485 struct weighted_pcl *freq_list)
8486 {
8487 char *pos = wpa_s->get_pref_freq_list_override;
8488 char *end;
8489 unsigned int count = 0;
8490
8491 /* Override string format:
8492 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8493
8494 while (pos) {
8495 if (atoi(pos) == (int) if_type)
8496 break;
8497 pos = os_strchr(pos, ' ');
8498 if (pos)
8499 pos++;
8500 }
8501 if (!pos)
8502 return -1;
8503 pos = os_strchr(pos, ':');
8504 if (!pos)
8505 return -1;
8506 pos++;
8507 end = os_strchr(pos, ' ');
8508 while (pos && (!end || pos < end) && count < *num) {
8509 freq_list[count].freq = atoi(pos);
8510 freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
8511 pos = os_strchr(pos, ',');
8512 if (pos)
8513 pos++;
8514 }
8515
8516 *num = count;
8517 return 0;
8518 }
8519 #endif /* CONFIG_TESTING_OPTIONS */
8520
8521
wpas_ctrl_iface_get_pref_freq_list(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8522 static int wpas_ctrl_iface_get_pref_freq_list(
8523 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8524 {
8525 unsigned int num = 100, i;
8526 int ret;
8527 enum wpa_driver_if_type iface_type;
8528 char *pos, *end;
8529 struct weighted_pcl freq_list[100];
8530
8531 pos = buf;
8532 end = buf + buflen;
8533
8534 /* buf: "<interface_type>" */
8535 if (os_strcmp(cmd, "STATION") == 0)
8536 iface_type = WPA_IF_STATION;
8537 else if (os_strcmp(cmd, "AP") == 0)
8538 iface_type = WPA_IF_AP_BSS;
8539 else if (os_strcmp(cmd, "P2P_GO") == 0)
8540 iface_type = WPA_IF_P2P_GO;
8541 else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8542 iface_type = WPA_IF_P2P_CLIENT;
8543 else if (os_strcmp(cmd, "IBSS") == 0)
8544 iface_type = WPA_IF_IBSS;
8545 else if (os_strcmp(cmd, "TDLS") == 0)
8546 iface_type = WPA_IF_TDLS;
8547 else
8548 return -1;
8549
8550 wpa_printf(MSG_DEBUG,
8551 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
8552 iface_type, cmd);
8553
8554 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8555 if (ret)
8556 return -1;
8557
8558 for (i = 0; i < num; i++) {
8559 ret = os_snprintf(pos, end - pos, "%s%u",
8560 i > 0 ? "," : "", freq_list[i].freq);
8561 if (os_snprintf_error(end - pos, ret))
8562 return -1;
8563 pos += ret;
8564 }
8565
8566 return pos - buf;
8567 }
8568
8569
wpas_ctrl_iface_driver_flags(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8570 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8571 char *buf, size_t buflen)
8572 {
8573 int ret, i;
8574 char *pos, *end;
8575
8576 ret = os_snprintf(buf, buflen, "%016llX:\n",
8577 (long long unsigned) wpa_s->drv_flags);
8578 if (os_snprintf_error(buflen, ret))
8579 return -1;
8580
8581 pos = buf + ret;
8582 end = buf + buflen;
8583
8584 for (i = 0; i < 64; i++) {
8585 if (wpa_s->drv_flags & (1LLU << i)) {
8586 ret = os_snprintf(pos, end - pos, "%s\n",
8587 driver_flag_to_string(1LLU << i));
8588 if (os_snprintf_error(end - pos, ret))
8589 return -1;
8590 pos += ret;
8591 }
8592 }
8593
8594 return pos - buf;
8595 }
8596
8597
wpas_ctrl_iface_driver_flags2(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8598 static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8599 char *buf, size_t buflen)
8600 {
8601 int ret, i;
8602 char *pos, *end;
8603
8604 ret = os_snprintf(buf, buflen, "%016llX:\n",
8605 (long long unsigned) wpa_s->drv_flags2);
8606 if (os_snprintf_error(buflen, ret))
8607 return -1;
8608
8609 pos = buf + ret;
8610 end = buf + buflen;
8611
8612 for (i = 0; i < 64; i++) {
8613 if (wpa_s->drv_flags2 & (1LLU << i)) {
8614 ret = os_snprintf(pos, end - pos, "%s\n",
8615 driver_flag2_to_string(1LLU << i));
8616 if (os_snprintf_error(end - pos, ret))
8617 return -1;
8618 pos += ret;
8619 }
8620 }
8621
8622 return pos - buf;
8623 }
8624
8625
wpa_supplicant_pktcnt_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8626 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8627 size_t buflen)
8628 {
8629 struct hostap_sta_driver_data sta;
8630 int ret;
8631
8632 ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8633 if (ret)
8634 return -1;
8635
8636 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
8637 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
8638 if (os_snprintf_error(buflen, ret))
8639 return -1;
8640 return ret;
8641 }
8642
8643
8644 #ifdef ANDROID
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8645 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8646 char *buf, size_t buflen)
8647 {
8648 int ret;
8649
8650 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
8651 if (ret == 0) {
8652 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8653 struct p2p_data *p2p = wpa_s->global->p2p;
8654 if (p2p) {
8655 char country[3];
8656 country[0] = cmd[8];
8657 country[1] = cmd[9];
8658 country[2] = 0x04;
8659 p2p_set_country(p2p, country);
8660 }
8661 }
8662 ret = os_snprintf(buf, buflen, "%s\n", "OK");
8663 if (os_snprintf_error(buflen, ret))
8664 ret = -1;
8665 }
8666 return ret;
8667 }
8668 #endif /* ANDROID */
8669
8670
wpa_supplicant_vendor_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8671 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8672 char *buf, size_t buflen)
8673 {
8674 int ret;
8675 char *pos, *temp = NULL;
8676 u8 *data = NULL;
8677 unsigned int vendor_id, subcmd;
8678 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
8679 struct wpabuf *reply;
8680 size_t data_len = 0;
8681
8682 /**
8683 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8684 * [nested=<0|1>]
8685 */
8686 vendor_id = strtoul(cmd, &pos, 16);
8687 if (!isblank((unsigned char) *pos))
8688 return -EINVAL;
8689
8690 subcmd = strtoul(pos, &pos, 10);
8691
8692 if (*pos != '\0') {
8693 if (!isblank((unsigned char) *pos++))
8694 return -EINVAL;
8695
8696 temp = os_strchr(pos, ' ');
8697 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
8698 }
8699
8700 if (data_len) {
8701 data_len /= 2;
8702 data = os_malloc(data_len);
8703 if (!data)
8704 return -1;
8705
8706 if (hexstr2bin(pos, data, data_len)) {
8707 wpa_printf(MSG_DEBUG,
8708 "Vendor command: wrong parameter format");
8709 os_free(data);
8710 return -EINVAL;
8711 }
8712 }
8713
8714 pos = os_strstr(cmd, "nested=");
8715 if (pos)
8716 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8717 NESTED_ATTR_NOT_USED;
8718
8719 reply = wpabuf_alloc((buflen - 1) / 2);
8720 if (!reply) {
8721 os_free(data);
8722 return -1;
8723 }
8724
8725 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
8726 nested_attr_flag, reply);
8727
8728 if (ret == 0)
8729 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8730 wpabuf_len(reply));
8731
8732 wpabuf_free(reply);
8733 os_free(data);
8734
8735 return ret;
8736 }
8737
8738
wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant * wpa_s)8739 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8740 {
8741 #ifdef CONFIG_P2P
8742 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8743 wpa_s->global->p2p_init_wpa_s : wpa_s;
8744 #endif /* CONFIG_P2P */
8745
8746 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8747
8748 if (wpas_abort_ongoing_scan(wpa_s) == 0)
8749 wpa_s->ignore_post_flush_scan_res = 1;
8750
8751 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8752 /*
8753 * Avoid possible auto connect re-connection on getting
8754 * disconnected due to state flush.
8755 */
8756 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8757 }
8758
8759 #ifdef CONFIG_P2P
8760 wpas_p2p_group_remove(p2p_wpa_s, "*");
8761 wpas_p2p_cancel(p2p_wpa_s);
8762 p2p_ctrl_flush(p2p_wpa_s);
8763 wpas_p2p_service_flush(p2p_wpa_s);
8764 p2p_wpa_s->global->p2p_disabled = 0;
8765 p2p_wpa_s->global->p2p_per_sta_psk = 0;
8766 p2p_wpa_s->conf->num_sec_device_types = 0;
8767 p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8768 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8769 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
8770 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
8771 p2p_wpa_s->global->pending_p2ps_group = 0;
8772 p2p_wpa_s->global->pending_p2ps_group_freq = 0;
8773 #endif /* CONFIG_P2P */
8774
8775 #ifdef CONFIG_WPS_TESTING
8776 wps_version_number = 0x20;
8777 wps_testing_stub_cred = 0;
8778 wps_corrupt_pkhash = 0;
8779 wps_force_auth_types_in_use = 0;
8780 wps_force_encr_types_in_use = 0;
8781 #endif /* CONFIG_WPS_TESTING */
8782 #ifdef CONFIG_WPS
8783 wpa_s->wps_fragment_size = 0;
8784 wpas_wps_cancel(wpa_s);
8785 wps_registrar_flush(wpa_s->wps->registrar);
8786 #endif /* CONFIG_WPS */
8787 wpa_s->after_wps = 0;
8788 wpa_s->known_wps_freq = 0;
8789
8790 #ifdef CONFIG_DPP
8791 wpas_dpp_deinit(wpa_s);
8792 wpa_s->dpp_init_max_tries = 0;
8793 wpa_s->dpp_init_retry_time = 0;
8794 wpa_s->dpp_resp_wait_time = 0;
8795 wpa_s->dpp_resp_max_tries = 0;
8796 wpa_s->dpp_resp_retry_time = 0;
8797 #ifdef CONFIG_DPP2
8798 wpas_dpp_chirp_stop(wpa_s);
8799 wpa_s->dpp_pfs_fallback = 0;
8800 #endif /* CONFIG_DPP2 */
8801 #ifdef CONFIG_DPP3
8802 {
8803 int i;
8804
8805 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
8806 struct dpp_pb_info *info;
8807
8808 info = &wpa_s->dpp_pb[i];
8809 info->rx_time.sec = 0;
8810 info->rx_time.usec = 0;
8811 }
8812 }
8813 #endif /* CONFIG_DPP3 */
8814 #ifdef CONFIG_TESTING_OPTIONS
8815 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8816 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8817 dpp_pkex_ephemeral_key_override_len = 0;
8818 dpp_protocol_key_override_len = 0;
8819 dpp_nonce_override_len = 0;
8820 #ifdef CONFIG_DPP3
8821 dpp_version_override = 3;
8822 #elif defined(CONFIG_DPP2)
8823 dpp_version_override = 2;
8824 #else /* CONFIG_DPP2 */
8825 dpp_version_override = 1;
8826 #endif /* CONFIG_DPP2 */
8827 #endif /* CONFIG_TESTING_OPTIONS */
8828 #endif /* CONFIG_DPP */
8829
8830 #ifdef CONFIG_TDLS
8831 #ifdef CONFIG_TDLS_TESTING
8832 tdls_testing = 0;
8833 #endif /* CONFIG_TDLS_TESTING */
8834 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8835 wpa_tdls_enable(wpa_s->wpa, 1);
8836 #endif /* CONFIG_TDLS */
8837
8838 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8839 wpa_supplicant_stop_countermeasures(wpa_s, NULL);
8840 wpa_s->last_michael_mic_error.sec = 0;
8841
8842 wpa_s->no_keep_alive = 0;
8843 wpa_s->own_disconnect_req = 0;
8844 wpa_s->own_reconnect_req = 0;
8845 wpa_s->deny_ptk0_rekey = 0;
8846
8847 os_free(wpa_s->disallow_aps_bssid);
8848 wpa_s->disallow_aps_bssid = NULL;
8849 wpa_s->disallow_aps_bssid_count = 0;
8850 os_free(wpa_s->disallow_aps_ssid);
8851 wpa_s->disallow_aps_ssid = NULL;
8852 wpa_s->disallow_aps_ssid_count = 0;
8853
8854 wpa_s->set_sta_uapsd = 0;
8855 wpa_s->sta_uapsd = 0;
8856
8857 wpa_s->consecutive_conn_failures = 0;
8858
8859 wpa_drv_radio_disable(wpa_s, 0);
8860 wpa_bssid_ignore_clear(wpa_s);
8861 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8862 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
8863 wpa_config_flush_blobs(wpa_s->conf);
8864 wpa_s->conf->auto_interworking = 0;
8865 wpa_s->conf->okc = 0;
8866
8867 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
8868 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8869 rsn_preauth_deinit(wpa_s->wpa);
8870
8871 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8872 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8873 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
8874 eapol_sm_notify_logoff(wpa_s->eapol, false);
8875
8876 radio_remove_works(wpa_s, NULL, 1);
8877 wpa_s->ext_work_in_progress = 0;
8878
8879 wpa_s->next_ssid = NULL;
8880
8881 wnm_btm_reset(wpa_s);
8882
8883 #ifdef CONFIG_INTERWORKING
8884 #ifdef CONFIG_HS20
8885 hs20_cancel_fetch_osu(wpa_s);
8886 hs20_del_icon(wpa_s, NULL, NULL);
8887 #endif /* CONFIG_HS20 */
8888 #endif /* CONFIG_INTERWORKING */
8889
8890 wpa_s->ext_mgmt_frame_handling = 0;
8891 wpa_s->ext_eapol_frame_io = 0;
8892 #ifdef CONFIG_TESTING_OPTIONS
8893 wpa_s->extra_roc_dur = 0;
8894 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
8895 wpa_s->p2p_go_csa_on_inv = 0;
8896 wpa_s->ignore_auth_resp = 0;
8897 wpa_s->ignore_assoc_disallow = 0;
8898 wpa_s->disable_sa_query = 0;
8899 wpa_s->testing_resend_assoc = 0;
8900 wpa_s->ignore_sae_h2e_only = 0;
8901 wpa_s->ft_rsnxe_used = 0;
8902 wpa_s->reject_btm_req_reason = 0;
8903 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
8904 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
8905 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
8906 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
8907 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
8908 os_free(wpa_s->get_pref_freq_list_override);
8909 wpa_s->get_pref_freq_list_override = NULL;
8910 wpabuf_free(wpa_s->sae_commit_override);
8911 wpa_s->sae_commit_override = NULL;
8912 os_free(wpa_s->extra_sae_rejected_groups);
8913 wpa_s->extra_sae_rejected_groups = NULL;
8914 wpabuf_free(wpa_s->rsne_override_eapol);
8915 wpa_s->rsne_override_eapol = NULL;
8916 wpabuf_free(wpa_s->rsnxe_override_assoc);
8917 wpa_s->rsnxe_override_assoc = NULL;
8918 wpabuf_free(wpa_s->rsnxe_override_eapol);
8919 wpa_s->rsnxe_override_eapol = NULL;
8920 wpas_clear_driver_signal_override(wpa_s);
8921 #ifndef CONFIG_NO_ROBUST_AV
8922 wpa_s->disable_scs_support = 0;
8923 wpa_s->disable_mscs_support = 0;
8924 wpa_s->enable_dscp_policy_capa = 0;
8925 #endif /* CONFIG_NO_ROBUST_AV */
8926 wpa_s->oci_freq_override_eapol = 0;
8927 wpa_s->oci_freq_override_saquery_req = 0;
8928 wpa_s->oci_freq_override_saquery_resp = 0;
8929 wpa_s->oci_freq_override_eapol_g2 = 0;
8930 wpa_s->oci_freq_override_ft_assoc = 0;
8931 wpa_s->oci_freq_override_fils_assoc = 0;
8932 wpa_s->oci_freq_override_wnm_sleep = 0;
8933 wpa_s->disable_eapol_g2_tx = 0;
8934 wpa_s->test_assoc_comeback_type = -1;
8935 #ifdef CONFIG_DPP
8936 os_free(wpa_s->dpp_config_obj_override);
8937 wpa_s->dpp_config_obj_override = NULL;
8938 os_free(wpa_s->dpp_discovery_override);
8939 wpa_s->dpp_discovery_override = NULL;
8940 os_free(wpa_s->dpp_groups_override);
8941 wpa_s->dpp_groups_override = NULL;
8942 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
8943 wpa_s->dpp_discard_public_action = 0;
8944 dpp_test = DPP_TEST_DISABLED;
8945 #endif /* CONFIG_DPP */
8946 #endif /* CONFIG_TESTING_OPTIONS */
8947
8948 wpa_s->disconnected = 0;
8949 os_free(wpa_s->next_scan_freqs);
8950 wpa_s->next_scan_freqs = NULL;
8951 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
8952 wpa_s->next_scan_bssid_wildcard_ssid = 0;
8953 os_free(wpa_s->select_network_scan_freqs);
8954 wpa_s->select_network_scan_freqs = NULL;
8955 #ifndef CONFIG_NO_ROBUST_AV
8956 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
8957 #endif /* CONFIG_NO_ROBUST_AV */
8958
8959 wpa_bss_flush(wpa_s);
8960 if (!dl_list_empty(&wpa_s->bss)) {
8961 wpa_printf(MSG_DEBUG,
8962 "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8963 MACSTR " pending_bssid=" MACSTR,
8964 dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8965 MAC2STR(wpa_s->bssid),
8966 MAC2STR(wpa_s->pending_bssid));
8967 }
8968
8969 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
8970 wpa_s->wnmsleep_used = 0;
8971
8972 #ifdef CONFIG_SME
8973 wpa_s->sme.last_unprot_disconnect.sec = 0;
8974 wpa_s->sme.auth_alg = 0;
8975 #endif /* CONFIG_SME */
8976
8977 wpabuf_free(wpa_s->ric_ies);
8978 wpa_s->ric_ies = NULL;
8979
8980 wpa_supplicant_update_channel_list(wpa_s, NULL);
8981
8982 free_bss_tmp_disallowed(wpa_s);
8983
8984 #ifndef CONFIG_NO_ROBUST_AV
8985 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
8986 #endif /* CONFIG_NO_ROBUST_AV */
8987
8988 #ifdef CONFIG_PASN
8989 wpas_pasn_auth_stop(wpa_s);
8990 #endif /* CONFIG_PASN */
8991
8992 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
8993 wpas_restore_permanent_mac_addr(wpa_s);
8994
8995 wpa_s->conf->ignore_old_scan_res = 0;
8996
8997 #ifdef CONFIG_NAN_USD
8998 wpas_nan_usd_flush(wpa_s);
8999 #endif /* CONFIG_NAN_USD */
9000 }
9001
9002
wpas_ctrl_radio_work_show(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)9003 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
9004 char *buf, size_t buflen)
9005 {
9006 struct wpa_radio_work *work;
9007 char *pos, *end;
9008 struct os_reltime now, diff;
9009
9010 pos = buf;
9011 end = buf + buflen;
9012
9013 os_get_reltime(&now);
9014
9015 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9016 {
9017 int ret;
9018
9019 os_reltime_sub(&now, &work->time, &diff);
9020 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
9021 work->type, work->wpa_s->ifname, work->freq,
9022 work->started, diff.sec, diff.usec);
9023 if (os_snprintf_error(end - pos, ret))
9024 break;
9025 pos += ret;
9026 }
9027
9028 return pos - buf;
9029 }
9030
9031
wpas_ctrl_radio_work_timeout(void * eloop_ctx,void * timeout_ctx)9032 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
9033 {
9034 struct wpa_radio_work *work = eloop_ctx;
9035 struct wpa_external_work *ework = work->ctx;
9036
9037 wpa_dbg(work->wpa_s, MSG_DEBUG,
9038 "Timing out external radio work %u (%s)",
9039 ework->id, work->type);
9040 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
9041 work->wpa_s->ext_work_in_progress = 0;
9042 radio_work_done(work);
9043 os_free(ework);
9044 }
9045
9046
wpas_ctrl_radio_work_cb(struct wpa_radio_work * work,int deinit)9047 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
9048 {
9049 struct wpa_external_work *ework = work->ctx;
9050
9051 if (deinit) {
9052 if (work->started)
9053 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9054 work, NULL);
9055
9056 /*
9057 * work->type points to a buffer in ework, so need to replace
9058 * that here with a fixed string to avoid use of freed memory
9059 * in debug prints.
9060 */
9061 work->type = "freed-ext-work";
9062 work->ctx = NULL;
9063 os_free(ework);
9064 return;
9065 }
9066
9067 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
9068 ework->id, ework->type);
9069 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
9070 work->wpa_s->ext_work_in_progress = 1;
9071 if (!ework->timeout)
9072 ework->timeout = 10;
9073 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
9074 work, NULL);
9075 }
9076
9077
wpas_ctrl_radio_work_add(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)9078 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
9079 char *buf, size_t buflen)
9080 {
9081 struct wpa_external_work *ework;
9082 char *pos, *pos2;
9083 size_t type_len;
9084 int ret;
9085 unsigned int freq = 0;
9086
9087 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
9088
9089 ework = os_zalloc(sizeof(*ework));
9090 if (ework == NULL)
9091 return -1;
9092
9093 pos = os_strchr(cmd, ' ');
9094 if (pos) {
9095 type_len = pos - cmd;
9096 pos++;
9097
9098 pos2 = os_strstr(pos, "freq=");
9099 if (pos2)
9100 freq = atoi(pos2 + 5);
9101
9102 pos2 = os_strstr(pos, "timeout=");
9103 if (pos2)
9104 ework->timeout = atoi(pos2 + 8);
9105 } else {
9106 type_len = os_strlen(cmd);
9107 }
9108 if (4 + type_len >= sizeof(ework->type))
9109 type_len = sizeof(ework->type) - 4 - 1;
9110 os_strlcpy(ework->type, "ext:", sizeof(ework->type));
9111 os_memcpy(ework->type + 4, cmd, type_len);
9112 ework->type[4 + type_len] = '\0';
9113
9114 wpa_s->ext_work_id++;
9115 if (wpa_s->ext_work_id == 0)
9116 wpa_s->ext_work_id++;
9117 ework->id = wpa_s->ext_work_id;
9118
9119 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
9120 ework) < 0) {
9121 os_free(ework);
9122 return -1;
9123 }
9124
9125 ret = os_snprintf(buf, buflen, "%u", ework->id);
9126 if (os_snprintf_error(buflen, ret))
9127 return -1;
9128 return ret;
9129 }
9130
9131
wpas_ctrl_radio_work_done(struct wpa_supplicant * wpa_s,char * cmd)9132 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
9133 {
9134 struct wpa_radio_work *work;
9135 unsigned int id = atoi(cmd);
9136
9137 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9138 {
9139 struct wpa_external_work *ework;
9140
9141 if (os_strncmp(work->type, "ext:", 4) != 0)
9142 continue;
9143 ework = work->ctx;
9144 if (id && ework->id != id)
9145 continue;
9146 wpa_dbg(wpa_s, MSG_DEBUG,
9147 "Completed external radio work %u (%s)",
9148 ework->id, ework->type);
9149 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
9150 wpa_s->ext_work_in_progress = 0;
9151 radio_work_done(work);
9152 os_free(ework);
9153 return 3; /* "OK\n" */
9154 }
9155
9156 return -1;
9157 }
9158
9159
wpas_ctrl_radio_work(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)9160 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
9161 char *buf, size_t buflen)
9162 {
9163 if (os_strcmp(cmd, "show") == 0)
9164 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
9165 if (os_strncmp(cmd, "add ", 4) == 0)
9166 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
9167 if (os_strncmp(cmd, "done ", 5) == 0)
9168 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
9169 return -1;
9170 }
9171
9172
wpas_ctrl_radio_work_flush(struct wpa_supplicant * wpa_s)9173 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
9174 {
9175 struct wpa_radio_work *work, *tmp;
9176
9177 if (!wpa_s || !wpa_s->radio)
9178 return;
9179
9180 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
9181 struct wpa_radio_work, list) {
9182 struct wpa_external_work *ework;
9183
9184 if (os_strncmp(work->type, "ext:", 4) != 0)
9185 continue;
9186 ework = work->ctx;
9187 wpa_dbg(wpa_s, MSG_DEBUG,
9188 "Flushing%s external radio work %u (%s)",
9189 work->started ? " started" : "", ework->id,
9190 ework->type);
9191 if (work->started)
9192 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9193 work, NULL);
9194 radio_work_done(work);
9195 os_free(ework);
9196 }
9197 }
9198
9199
wpas_ctrl_eapol_response(void * eloop_ctx,void * timeout_ctx)9200 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
9201 {
9202 struct wpa_supplicant *wpa_s = eloop_ctx;
9203 eapol_sm_notify_ctrl_response(wpa_s->eapol);
9204 }
9205
9206
scan_id_list_parse(struct wpa_supplicant * wpa_s,const char * value,unsigned int * scan_id_count,int scan_id[])9207 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
9208 unsigned int *scan_id_count, int scan_id[])
9209 {
9210 const char *pos = value;
9211
9212 while (pos) {
9213 if (*pos == ' ' || *pos == '\0')
9214 break;
9215 if (*scan_id_count == MAX_SCAN_ID)
9216 return -1;
9217 scan_id[(*scan_id_count)++] = atoi(pos);
9218 pos = os_strchr(pos, ',');
9219 if (pos)
9220 pos++;
9221 }
9222
9223 return 0;
9224 }
9225
9226
wpas_ctrl_scan(struct wpa_supplicant * wpa_s,char * params,char * reply,int reply_size,int * reply_len)9227 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9228 char *reply, int reply_size, int *reply_len)
9229 {
9230 char *pos;
9231 unsigned int manual_scan_passive = 0;
9232 unsigned int manual_scan_use_id = 0;
9233 unsigned int manual_scan_only_new = 0;
9234 unsigned int scan_only = 0;
9235 unsigned int scan_id_count = 0;
9236 unsigned int manual_non_coloc_6ghz = 0;
9237 int scan_id[MAX_SCAN_ID];
9238 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
9239 struct wpa_scan_results *scan_res);
9240 int *manual_scan_freqs = NULL;
9241 struct wpa_ssid_value *ssid = NULL, *ns;
9242 unsigned int ssid_count = 0;
9243
9244 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
9245 *reply_len = -1;
9246 return;
9247 }
9248
9249 if (radio_work_pending(wpa_s, "scan")) {
9250 wpa_printf(MSG_DEBUG,
9251 "Pending scan scheduled - reject new request");
9252 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9253 return;
9254 }
9255
9256 #ifdef CONFIG_INTERWORKING
9257 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
9258 wpa_printf(MSG_DEBUG,
9259 "Interworking select in progress - reject new scan");
9260 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9261 return;
9262 }
9263 #endif /* CONFIG_INTERWORKING */
9264
9265 if (params) {
9266 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
9267 scan_only = 1;
9268
9269 pos = os_strstr(params, "freq=");
9270 if (pos) {
9271 manual_scan_freqs = freq_range_to_channel_list(wpa_s,
9272 pos + 5);
9273 if (manual_scan_freqs == NULL) {
9274 *reply_len = -1;
9275 goto done;
9276 }
9277 }
9278
9279 pos = os_strstr(params, "passive=");
9280 if (pos)
9281 manual_scan_passive = !!atoi(pos + 8);
9282
9283 pos = os_strstr(params, "use_id=");
9284 if (pos)
9285 manual_scan_use_id = atoi(pos + 7);
9286
9287 pos = os_strstr(params, "only_new=1");
9288 if (pos)
9289 manual_scan_only_new = 1;
9290
9291 pos = os_strstr(params, "scan_id=");
9292 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
9293 scan_id) < 0) {
9294 *reply_len = -1;
9295 goto done;
9296 }
9297
9298 pos = os_strstr(params, "bssid=");
9299 if (pos) {
9300 u8 bssid[ETH_ALEN];
9301
9302 pos += 6;
9303 if (hwaddr_aton(pos, bssid)) {
9304 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
9305 *reply_len = -1;
9306 goto done;
9307 }
9308 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
9309
9310 wpa_s->next_scan_bssid_wildcard_ssid =
9311 os_strstr(params, "wildcard_ssid=1") != NULL;
9312 }
9313
9314 pos = os_strstr(params, "non_coloc_6ghz=");
9315 if (pos)
9316 manual_non_coloc_6ghz = !!atoi(pos + 15);
9317
9318 pos = params;
9319 while (pos && *pos != '\0') {
9320 if (os_strncmp(pos, "ssid ", 5) == 0) {
9321 char *end;
9322
9323 pos += 5;
9324 end = pos;
9325 while (*end) {
9326 if (*end == '\0' || *end == ' ')
9327 break;
9328 end++;
9329 }
9330
9331 ns = os_realloc_array(
9332 ssid, ssid_count + 1,
9333 sizeof(struct wpa_ssid_value));
9334 if (ns == NULL) {
9335 *reply_len = -1;
9336 goto done;
9337 }
9338 ssid = ns;
9339
9340 if ((end - pos) & 0x01 ||
9341 end - pos > 2 * SSID_MAX_LEN ||
9342 hexstr2bin(pos, ssid[ssid_count].ssid,
9343 (end - pos) / 2) < 0) {
9344 wpa_printf(MSG_DEBUG,
9345 "Invalid SSID value '%s'",
9346 pos);
9347 *reply_len = -1;
9348 goto done;
9349 }
9350 ssid[ssid_count].ssid_len = (end - pos) / 2;
9351 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
9352 ssid[ssid_count].ssid,
9353 ssid[ssid_count].ssid_len);
9354 ssid_count++;
9355 pos = end;
9356 }
9357
9358 pos = os_strchr(pos, ' ');
9359 if (pos)
9360 pos++;
9361 }
9362 }
9363
9364 wpa_s->num_ssids_from_scan_req = ssid_count;
9365 os_free(wpa_s->ssids_from_scan_req);
9366 if (ssid_count) {
9367 wpa_s->ssids_from_scan_req = ssid;
9368 ssid = NULL;
9369 } else {
9370 wpa_s->ssids_from_scan_req = NULL;
9371 }
9372
9373 if (scan_only)
9374 scan_res_handler = scan_only_handler;
9375 else if (wpa_s->scan_res_handler == scan_only_handler)
9376 scan_res_handler = NULL;
9377 else
9378 scan_res_handler = wpa_s->scan_res_handler;
9379
9380 if (!wpa_s->sched_scanning && !wpa_s->scanning &&
9381 ((wpa_s->wpa_state <= WPA_SCANNING) ||
9382 (wpa_s->wpa_state == WPA_COMPLETED))) {
9383 wpa_s->manual_scan_passive = manual_scan_passive;
9384 wpa_s->manual_scan_use_id = manual_scan_use_id;
9385 wpa_s->manual_scan_only_new = manual_scan_only_new;
9386 wpa_s->scan_id_count = scan_id_count;
9387 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
9388 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9389 wpa_s->scan_res_handler = scan_res_handler;
9390 os_free(wpa_s->manual_scan_freqs);
9391 wpa_s->manual_scan_freqs = manual_scan_freqs;
9392 manual_scan_freqs = NULL;
9393
9394 wpa_s->normal_scans = 0;
9395 wpa_s->scan_req = MANUAL_SCAN_REQ;
9396 wpa_s->after_wps = 0;
9397 wpa_s->known_wps_freq = 0;
9398 wpa_supplicant_req_scan(wpa_s, 0, 0);
9399 if (wpa_s->manual_scan_use_id) {
9400 wpa_s->manual_scan_id++;
9401 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9402 wpa_s->manual_scan_id);
9403 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9404 wpa_s->manual_scan_id);
9405 }
9406 } else if (wpa_s->sched_scanning) {
9407 wpa_s->manual_scan_passive = manual_scan_passive;
9408 wpa_s->manual_scan_use_id = manual_scan_use_id;
9409 wpa_s->manual_scan_only_new = manual_scan_only_new;
9410 wpa_s->scan_id_count = scan_id_count;
9411 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
9412 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9413 wpa_s->scan_res_handler = scan_res_handler;
9414 os_free(wpa_s->manual_scan_freqs);
9415 wpa_s->manual_scan_freqs = manual_scan_freqs;
9416 manual_scan_freqs = NULL;
9417
9418 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9419 wpa_supplicant_cancel_sched_scan(wpa_s);
9420 wpa_s->scan_req = MANUAL_SCAN_REQ;
9421 wpa_supplicant_req_scan(wpa_s, 0, 0);
9422 if (wpa_s->manual_scan_use_id) {
9423 wpa_s->manual_scan_id++;
9424 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9425 wpa_s->manual_scan_id);
9426 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9427 wpa_s->manual_scan_id);
9428 }
9429 } else {
9430 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9431 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9432 }
9433
9434 done:
9435 os_free(manual_scan_freqs);
9436 os_free(ssid);
9437 }
9438
9439
9440 #ifdef CONFIG_TESTING_OPTIONS
9441
wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant * wpa_s,unsigned int freq,const u8 * dst,const u8 * src,const u8 * bssid,const u8 * data,size_t data_len,enum offchannel_send_action_result result)9442 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9443 unsigned int freq, const u8 *dst,
9444 const u8 *src, const u8 *bssid,
9445 const u8 *data, size_t data_len,
9446 enum offchannel_send_action_result
9447 result)
9448 {
9449 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9450 " src=" MACSTR " bssid=" MACSTR " result=%s",
9451 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9452 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9453 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9454 "NO_ACK" : "FAILED"));
9455 }
9456
9457
wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant * wpa_s,char * cmd)9458 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9459 {
9460 char *pos, *param;
9461 size_t len;
9462 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9463 int res, used;
9464 int freq = 0, no_cck = 0, wait_time = 0;
9465
9466 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9467 * <action=Action frame payload> */
9468
9469 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9470
9471 pos = cmd;
9472 used = hwaddr_aton2(pos, da);
9473 if (used < 0)
9474 return -1;
9475 pos += used;
9476 while (*pos == ' ')
9477 pos++;
9478 used = hwaddr_aton2(pos, bssid);
9479 if (used < 0)
9480 return -1;
9481 pos += used;
9482
9483 param = os_strstr(pos, " freq=");
9484 if (param) {
9485 param += 6;
9486 freq = atoi(param);
9487 }
9488
9489 param = os_strstr(pos, " no_cck=");
9490 if (param) {
9491 param += 8;
9492 no_cck = atoi(param);
9493 }
9494
9495 param = os_strstr(pos, " wait_time=");
9496 if (param) {
9497 param += 11;
9498 wait_time = atoi(param);
9499 }
9500
9501 param = os_strstr(pos, " action=");
9502 if (param == NULL)
9503 return -1;
9504 param += 8;
9505
9506 len = os_strlen(param);
9507 if (len & 1)
9508 return -1;
9509 len /= 2;
9510
9511 buf = os_malloc(len);
9512 if (buf == NULL)
9513 return -1;
9514
9515 if (hexstr2bin(param, buf, len) < 0) {
9516 os_free(buf);
9517 return -1;
9518 }
9519
9520 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9521 buf, len, wait_time,
9522 wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9523 os_free(buf);
9524 return res;
9525 }
9526
9527
wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant * wpa_s)9528 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9529 {
9530 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9531 offchannel_send_action_done(wpa_s);
9532 }
9533
9534
wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant * wpa_s,char * cmd)9535 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9536 char *cmd)
9537 {
9538 char *pos, *param;
9539 size_t len;
9540 u8 *buf;
9541 int freq = 0, datarate = 0, ssi_signal = 0;
9542 union wpa_event_data event;
9543
9544 if (!wpa_s->ext_mgmt_frame_handling)
9545 return -1;
9546
9547 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9548
9549 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9550
9551 pos = cmd;
9552 param = os_strstr(pos, "freq=");
9553 if (param) {
9554 param += 5;
9555 freq = atoi(param);
9556 }
9557
9558 param = os_strstr(pos, " datarate=");
9559 if (param) {
9560 param += 10;
9561 datarate = atoi(param);
9562 }
9563
9564 param = os_strstr(pos, " ssi_signal=");
9565 if (param) {
9566 param += 12;
9567 ssi_signal = atoi(param);
9568 }
9569
9570 param = os_strstr(pos, " frame=");
9571 if (param == NULL)
9572 return -1;
9573 param += 7;
9574
9575 len = os_strlen(param);
9576 if (len & 1)
9577 return -1;
9578 len /= 2;
9579
9580 buf = os_malloc(len);
9581 if (buf == NULL)
9582 return -1;
9583
9584 if (hexstr2bin(param, buf, len) < 0) {
9585 os_free(buf);
9586 return -1;
9587 }
9588
9589 os_memset(&event, 0, sizeof(event));
9590 event.rx_mgmt.freq = freq;
9591 event.rx_mgmt.frame = buf;
9592 event.rx_mgmt.frame_len = len;
9593 event.rx_mgmt.ssi_signal = ssi_signal;
9594 event.rx_mgmt.datarate = datarate;
9595 wpa_s->ext_mgmt_frame_handling = 0;
9596 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9597 wpa_s->ext_mgmt_frame_handling = 1;
9598
9599 os_free(buf);
9600
9601 return 0;
9602 }
9603
9604
wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant * wpa_s,char * param)9605 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9606 char *param)
9607 {
9608 struct wpa_scan_res *res;
9609 struct os_reltime now;
9610 char *pos, *end;
9611 int ret = -1;
9612
9613 if (!param)
9614 return -1;
9615
9616 if (os_strcmp(param, "START") == 0) {
9617 wpa_bss_update_start(wpa_s);
9618 return 0;
9619 }
9620
9621 if (os_strcmp(param, "END") == 0) {
9622 wpa_bss_update_end(wpa_s, NULL, 1);
9623 return 0;
9624 }
9625
9626 if (os_strncmp(param, "BSS ", 4) != 0)
9627 return -1;
9628 param += 3;
9629
9630 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9631 if (!res)
9632 return -1;
9633
9634 pos = os_strstr(param, " flags=");
9635 if (pos)
9636 res->flags = strtol(pos + 7, NULL, 16);
9637
9638 pos = os_strstr(param, " bssid=");
9639 if (pos && hwaddr_aton(pos + 7, res->bssid))
9640 goto fail;
9641
9642 pos = os_strstr(param, " freq=");
9643 if (pos)
9644 res->freq = atoi(pos + 6);
9645
9646 pos = os_strstr(param, " beacon_int=");
9647 if (pos)
9648 res->beacon_int = atoi(pos + 12);
9649
9650 pos = os_strstr(param, " caps=");
9651 if (pos)
9652 res->caps = strtol(pos + 6, NULL, 16);
9653
9654 pos = os_strstr(param, " qual=");
9655 if (pos)
9656 res->qual = atoi(pos + 6);
9657
9658 pos = os_strstr(param, " noise=");
9659 if (pos)
9660 res->noise = atoi(pos + 7);
9661
9662 pos = os_strstr(param, " level=");
9663 if (pos)
9664 res->level = atoi(pos + 7);
9665
9666 pos = os_strstr(param, " tsf=");
9667 if (pos)
9668 res->tsf = strtoll(pos + 5, NULL, 16);
9669
9670 pos = os_strstr(param, " age=");
9671 if (pos)
9672 res->age = atoi(pos + 5);
9673
9674 pos = os_strstr(param, " est_throughput=");
9675 if (pos)
9676 res->est_throughput = atoi(pos + 16);
9677
9678 pos = os_strstr(param, " snr=");
9679 if (pos)
9680 res->snr = atoi(pos + 5);
9681
9682 pos = os_strstr(param, " parent_tsf=");
9683 if (pos)
9684 res->parent_tsf = strtoll(pos + 7, NULL, 16);
9685
9686 pos = os_strstr(param, " tsf_bssid=");
9687 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9688 goto fail;
9689
9690 pos = os_strstr(param, " ie=");
9691 if (pos) {
9692 pos += 4;
9693 end = os_strchr(pos, ' ');
9694 if (!end)
9695 end = pos + os_strlen(pos);
9696 res->ie_len = (end - pos) / 2;
9697 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9698 goto fail;
9699 }
9700
9701 pos = os_strstr(param, " beacon_ie=");
9702 if (pos) {
9703 pos += 11;
9704 end = os_strchr(pos, ' ');
9705 if (!end)
9706 end = pos + os_strlen(pos);
9707 res->beacon_ie_len = (end - pos) / 2;
9708 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9709 res->beacon_ie_len))
9710 goto fail;
9711 }
9712
9713 os_get_reltime(&now);
9714 wpa_bss_update_scan_res(wpa_s, res, &now);
9715 ret = 0;
9716 fail:
9717 os_free(res);
9718
9719 return ret;
9720 }
9721
9722
wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant * wpa_s,char * param)9723 static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9724 char *param)
9725 {
9726 union wpa_event_data event;
9727 struct assoc_info *ai;
9728 char *ctx = NULL;
9729 int ret = -1;
9730 struct wpabuf *req_ies = NULL;
9731 struct wpabuf *resp_ies = NULL;
9732 struct wpabuf *resp_frame = NULL;
9733 struct wpabuf *beacon_ies = NULL;
9734 struct wpabuf *key_replay_ctr = NULL;
9735 struct wpabuf *ptk_kck = NULL;
9736 struct wpabuf *ptk_kek = NULL;
9737 struct wpabuf *fils_pmk = NULL;
9738 char *str, *pos;
9739 u8 addr[ETH_ALEN];
9740 u8 fils_pmkid[PMKID_LEN];
9741
9742 os_memset(&event, 0, sizeof(event));
9743 ai = &event.assoc_info;
9744
9745 while ((str = str_token(param, " ", &ctx))) {
9746 pos = os_strchr(str, '=');
9747 if (!pos)
9748 goto fail;
9749 *pos++ = '\0';
9750
9751 if (os_strcmp(str, "reassoc") == 0) {
9752 ai->reassoc = atoi(pos);
9753 } else if (os_strcmp(str, "req_ies") == 0) {
9754 wpabuf_free(req_ies);
9755 req_ies = wpabuf_parse_bin(pos);
9756 if (!req_ies)
9757 goto fail;
9758 ai->req_ies = wpabuf_head(req_ies);
9759 ai->req_ies_len = wpabuf_len(req_ies);
9760 } else if (os_strcmp(str, "resp_ies") == 0) {
9761 wpabuf_free(resp_ies);
9762 resp_ies = wpabuf_parse_bin(pos);
9763 if (!resp_ies)
9764 goto fail;
9765 ai->resp_ies = wpabuf_head(resp_ies);
9766 ai->resp_ies_len = wpabuf_len(resp_ies);
9767 } else if (os_strcmp(str, "resp_frame") == 0) {
9768 wpabuf_free(resp_frame);
9769 resp_frame = wpabuf_parse_bin(pos);
9770 if (!resp_frame)
9771 goto fail;
9772 ai->resp_frame = wpabuf_head(resp_frame);
9773 ai->resp_frame_len = wpabuf_len(resp_frame);
9774 } else if (os_strcmp(str, "beacon_ies") == 0) {
9775 wpabuf_free(beacon_ies);
9776 beacon_ies = wpabuf_parse_bin(pos);
9777 if (!beacon_ies)
9778 goto fail;
9779 ai->beacon_ies = wpabuf_head(beacon_ies);
9780 ai->beacon_ies_len = wpabuf_len(beacon_ies);
9781 } else if (os_strcmp(str, "freq") == 0) {
9782 ai->freq = atoi(pos);
9783 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9784 ai->wmm_params.info_bitmap = atoi(pos);
9785 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9786 ai->wmm_params.uapsd_queues = atoi(pos);
9787 } else if (os_strcmp(str, "addr") == 0) {
9788 if (hwaddr_aton(pos, addr))
9789 goto fail;
9790 ai->addr = addr;
9791 } else if (os_strcmp(str, "authorized") == 0) {
9792 ai->authorized = atoi(pos);
9793 } else if (os_strcmp(str, "key_replay_ctr") == 0) {
9794 wpabuf_free(key_replay_ctr);
9795 key_replay_ctr = wpabuf_parse_bin(pos);
9796 if (!key_replay_ctr)
9797 goto fail;
9798 ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9799 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9800 } else if (os_strcmp(str, "ptk_kck") == 0) {
9801 wpabuf_free(ptk_kck);
9802 ptk_kck = wpabuf_parse_bin(pos);
9803 if (!ptk_kck)
9804 goto fail;
9805 ai->ptk_kck = wpabuf_head(ptk_kck);
9806 ai->ptk_kck_len = wpabuf_len(ptk_kck);
9807 } else if (os_strcmp(str, "ptk_kek") == 0) {
9808 wpabuf_free(ptk_kek);
9809 ptk_kek = wpabuf_parse_bin(pos);
9810 if (!ptk_kek)
9811 goto fail;
9812 ai->ptk_kek = wpabuf_head(ptk_kek);
9813 ai->ptk_kek_len = wpabuf_len(ptk_kek);
9814 } else if (os_strcmp(str, "subnet_status") == 0) {
9815 ai->subnet_status = atoi(pos);
9816 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9817 ai->fils_erp_next_seq_num = atoi(pos);
9818 } else if (os_strcmp(str, "fils_pmk") == 0) {
9819 wpabuf_free(fils_pmk);
9820 fils_pmk = wpabuf_parse_bin(pos);
9821 if (!fils_pmk)
9822 goto fail;
9823 ai->fils_pmk = wpabuf_head(fils_pmk);
9824 ai->fils_pmk_len = wpabuf_len(fils_pmk);
9825 } else if (os_strcmp(str, "fils_pmkid") == 0) {
9826 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9827 goto fail;
9828 ai->fils_pmkid = fils_pmkid;
9829 } else {
9830 goto fail;
9831 }
9832 }
9833
9834 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9835 ret = 0;
9836 fail:
9837 wpabuf_free(req_ies);
9838 wpabuf_free(resp_ies);
9839 wpabuf_free(resp_frame);
9840 wpabuf_free(beacon_ies);
9841 wpabuf_free(key_replay_ctr);
9842 wpabuf_free(ptk_kck);
9843 wpabuf_free(ptk_kek);
9844 wpabuf_free(fils_pmk);
9845 return ret;
9846 }
9847
9848
wpas_ctrl_iface_driver_event(struct wpa_supplicant * wpa_s,char * cmd)9849 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9850 {
9851 char *pos, *param;
9852 union wpa_event_data event;
9853 enum wpa_event_type ev;
9854
9855 /* <event name> [parameters..] */
9856
9857 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9858
9859 pos = cmd;
9860 param = os_strchr(pos, ' ');
9861 if (param)
9862 *param++ = '\0';
9863
9864 os_memset(&event, 0, sizeof(event));
9865
9866 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9867 ev = EVENT_INTERFACE_ENABLED;
9868 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9869 ev = EVENT_INTERFACE_DISABLED;
9870 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9871 ev = EVENT_AVOID_FREQUENCIES;
9872 if (param == NULL)
9873 param = "";
9874 if (freq_range_list_parse(&event.freq_range, param) < 0)
9875 return -1;
9876 wpa_supplicant_event(wpa_s, ev, &event);
9877 os_free(event.freq_range.range);
9878 return 0;
9879 } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
9880 return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
9881 } else if (os_strcmp(cmd, "ASSOC") == 0) {
9882 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
9883 } else {
9884 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
9885 cmd);
9886 return -1;
9887 }
9888
9889 wpa_supplicant_event(wpa_s, ev, &event);
9890
9891 return 0;
9892 }
9893
9894
wpas_ctrl_iface_eapol_rx(struct wpa_supplicant * wpa_s,char * cmd)9895 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
9896 {
9897 char *pos;
9898 u8 src[ETH_ALEN], *buf;
9899 int used;
9900 size_t len;
9901
9902 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
9903
9904 pos = cmd;
9905 used = hwaddr_aton2(pos, src);
9906 if (used < 0)
9907 return -1;
9908 pos += used;
9909 while (*pos == ' ')
9910 pos++;
9911
9912 len = os_strlen(pos);
9913 if (len & 1)
9914 return -1;
9915 len /= 2;
9916
9917 buf = os_malloc(len);
9918 if (buf == NULL)
9919 return -1;
9920
9921 if (hexstr2bin(pos, buf, len) < 0) {
9922 os_free(buf);
9923 return -1;
9924 }
9925
9926 wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
9927 os_free(buf);
9928
9929 return 0;
9930 }
9931
9932
wpas_ctrl_iface_eapol_tx(struct wpa_supplicant * wpa_s,char * cmd)9933 static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
9934 {
9935 char *pos;
9936 u8 dst[ETH_ALEN], *buf;
9937 int used, ret;
9938 size_t len;
9939 unsigned int prev;
9940
9941 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
9942
9943 pos = cmd;
9944 used = hwaddr_aton2(pos, dst);
9945 if (used < 0)
9946 return -1;
9947 pos += used;
9948 while (*pos == ' ')
9949 pos++;
9950
9951 len = os_strlen(pos);
9952 if (len & 1)
9953 return -1;
9954 len /= 2;
9955
9956 buf = os_malloc(len);
9957 if (!buf || hexstr2bin(pos, buf, len) < 0) {
9958 os_free(buf);
9959 return -1;
9960 }
9961
9962 prev = wpa_s->ext_eapol_frame_io;
9963 wpa_s->ext_eapol_frame_io = 0;
9964 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
9965 wpa_s->ext_eapol_frame_io = prev;
9966 os_free(buf);
9967
9968 return ret;
9969 }
9970
9971
ipv4_hdr_checksum(const void * buf,size_t len)9972 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
9973 {
9974 size_t i;
9975 u32 sum = 0;
9976 const u16 *pos = buf;
9977
9978 for (i = 0; i < len / 2; i++)
9979 sum += *pos++;
9980
9981 while (sum >> 16)
9982 sum = (sum & 0xffff) + (sum >> 16);
9983
9984 return sum ^ 0xffff;
9985 }
9986
9987
9988 #define HWSIM_PACKETLEN 1500
9989 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
9990
wpas_data_test_rx(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)9991 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
9992 size_t len)
9993 {
9994 struct wpa_supplicant *wpa_s = ctx;
9995 const struct ether_header *eth;
9996 struct ip ip;
9997 const u8 *pos;
9998 unsigned int i;
9999 char extra[30];
10000
10001 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
10002 wpa_printf(MSG_DEBUG,
10003 "test data: RX - ignore unexpected length %d",
10004 (int) len);
10005 return;
10006 }
10007
10008 eth = (const struct ether_header *) buf;
10009 os_memcpy(&ip, eth + 1, sizeof(ip));
10010 pos = &buf[sizeof(*eth) + sizeof(ip)];
10011
10012 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
10013 wpa_printf(MSG_DEBUG,
10014 "test data: RX - ignore unexpected IP header");
10015 return;
10016 }
10017
10018 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
10019 if (*pos != (u8) i) {
10020 wpa_printf(MSG_DEBUG,
10021 "test data: RX - ignore mismatching payload");
10022 return;
10023 }
10024 pos++;
10025 }
10026 extra[0] = '\0';
10027 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
10028 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
10029 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
10030 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
10031 }
10032
10033
wpas_ctrl_iface_data_test_config(struct wpa_supplicant * wpa_s,char * cmd)10034 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
10035 char *cmd)
10036 {
10037 int enabled = atoi(cmd);
10038 char *pos;
10039 const char *ifname;
10040
10041 if (!enabled) {
10042 if (wpa_s->l2_test) {
10043 l2_packet_deinit(wpa_s->l2_test);
10044 wpa_s->l2_test = NULL;
10045 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
10046 }
10047 return 0;
10048 }
10049
10050 if (wpa_s->l2_test)
10051 return 0;
10052
10053 pos = os_strstr(cmd, " ifname=");
10054 if (pos)
10055 ifname = pos + 8;
10056 else
10057 ifname = wpa_s->ifname;
10058
10059 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
10060 ETHERTYPE_IP, wpas_data_test_rx,
10061 wpa_s, 1);
10062 if (wpa_s->l2_test == NULL)
10063 return -1;
10064
10065 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
10066
10067 return 0;
10068 }
10069
10070
wpas_ctrl_iface_data_test_tx(struct wpa_supplicant * wpa_s,char * cmd)10071 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
10072 {
10073 u8 dst[ETH_ALEN], src[ETH_ALEN];
10074 char *pos, *pos2;
10075 int used;
10076 long int val;
10077 u8 tos;
10078 u8 buf[2 + HWSIM_PACKETLEN];
10079 struct ether_header *eth;
10080 struct ip *ip;
10081 u8 *dpos;
10082 unsigned int i;
10083 size_t send_len = HWSIM_IP_LEN;
10084
10085 if (wpa_s->l2_test == NULL)
10086 return -1;
10087
10088 /* format: <dst> <src> <tos> [len=<length>] */
10089
10090 pos = cmd;
10091 used = hwaddr_aton2(pos, dst);
10092 if (used < 0)
10093 return -1;
10094 pos += used;
10095 while (*pos == ' ')
10096 pos++;
10097 used = hwaddr_aton2(pos, src);
10098 if (used < 0)
10099 return -1;
10100 pos += used;
10101
10102 val = strtol(pos, &pos2, 0);
10103 if (val < 0 || val > 0xff)
10104 return -1;
10105 tos = val;
10106
10107 pos = os_strstr(pos2, " len=");
10108 if (pos) {
10109 i = atoi(pos + 5);
10110 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
10111 return -1;
10112 send_len = i;
10113 }
10114
10115 eth = (struct ether_header *) &buf[2];
10116 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
10117 os_memcpy(eth->ether_shost, src, ETH_ALEN);
10118 eth->ether_type = htons(ETHERTYPE_IP);
10119 ip = (struct ip *) (eth + 1);
10120 os_memset(ip, 0, sizeof(*ip));
10121 ip->ip_hl = 5;
10122 ip->ip_v = 4;
10123 ip->ip_ttl = 64;
10124 ip->ip_tos = tos;
10125 ip->ip_len = htons(send_len);
10126 ip->ip_p = 1;
10127 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
10128 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
10129 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
10130 dpos = (u8 *) (ip + 1);
10131 for (i = 0; i < send_len - sizeof(*ip); i++)
10132 *dpos++ = i;
10133
10134 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
10135 sizeof(struct ether_header) + send_len) < 0)
10136 return -1;
10137
10138 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
10139 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
10140
10141 return 0;
10142 }
10143
10144
wpas_ctrl_iface_data_test_frame(struct wpa_supplicant * wpa_s,char * cmd)10145 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
10146 char *cmd)
10147 {
10148 u8 *buf;
10149 struct ether_header *eth;
10150 struct l2_packet_data *l2 = NULL;
10151 size_t len;
10152 u16 ethertype;
10153 int res = -1;
10154
10155 len = os_strlen(cmd);
10156 if (len & 1 || len < ETH_HLEN * 2)
10157 return -1;
10158 len /= 2;
10159
10160 buf = os_malloc(len);
10161 if (buf == NULL)
10162 return -1;
10163
10164 if (hexstr2bin(cmd, buf, len) < 0)
10165 goto done;
10166
10167 eth = (struct ether_header *) buf;
10168 ethertype = ntohs(eth->ether_type);
10169
10170 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
10171 wpas_data_test_rx, wpa_s, 1);
10172 if (l2 == NULL)
10173 goto done;
10174
10175 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
10176 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
10177 done:
10178 if (l2)
10179 l2_packet_deinit(l2);
10180 os_free(buf);
10181
10182 return res < 0 ? -1 : 0;
10183 }
10184
10185
wpas_ctrl_event_test_cb(void * eloop_ctx,void * timeout_ctx)10186 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
10187 {
10188 struct wpa_supplicant *wpa_s = eloop_ctx;
10189 int i, count = (intptr_t) timeout_ctx;
10190
10191 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
10192 count);
10193 for (i = 0; i < count; i++) {
10194 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
10195 i + 1, count);
10196 }
10197 }
10198
10199
wpas_ctrl_event_test(struct wpa_supplicant * wpa_s,const char * cmd)10200 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
10201 {
10202 int count;
10203
10204 count = atoi(cmd);
10205 if (count <= 0)
10206 return -1;
10207
10208 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
10209 (void *) (intptr_t) count);
10210 }
10211
10212
wpas_get_hex_buf(const char * val,struct wpabuf ** ret)10213 static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
10214 {
10215 struct wpabuf *buf;
10216 size_t len;
10217
10218 len = os_strlen(val);
10219 if (len & 1)
10220 return -1;
10221 len /= 2;
10222
10223 if (len == 0) {
10224 buf = NULL;
10225 } else {
10226 buf = wpabuf_alloc(len);
10227 if (!buf)
10228 return -1;
10229
10230 if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
10231 wpabuf_free(buf);
10232 return -1;
10233 }
10234 }
10235
10236 *ret = buf;
10237 return 0;
10238 }
10239
10240
wpas_ctrl_test_assoc_ie(struct wpa_supplicant * wpa_s,const char * cmd)10241 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
10242 const char *cmd)
10243 {
10244 struct wpabuf *buf;
10245
10246 if (wpas_get_hex_buf(cmd, &buf) < 0)
10247 return -1;
10248 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
10249 return 0;
10250 }
10251
10252
wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant * wpa_s,const char * cmd)10253 static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
10254 const char *cmd)
10255 {
10256 struct wpabuf *buf;
10257
10258 if (wpas_get_hex_buf(cmd, &buf) < 0)
10259 return -1;
10260 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
10261 return 0;
10262 }
10263
10264
wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant * wpa_s,const char * cmd)10265 static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
10266 const char *cmd)
10267 {
10268 struct wpabuf *buf;
10269
10270 if (wpas_get_hex_buf(cmd, &buf) < 0)
10271 return -1;
10272 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
10273 return 0;
10274 }
10275
10276
wpas_ctrl_reset_pn(struct wpa_supplicant * wpa_s)10277 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
10278 {
10279 u8 zero[WPA_TK_MAX_LEN];
10280
10281 if (wpa_s->last_tk_alg == WPA_ALG_NONE)
10282 return -1;
10283
10284 wpa_printf(MSG_INFO, "TESTING: Reset PN");
10285 os_memset(zero, 0, sizeof(zero));
10286
10287 /* First, use a zero key to avoid any possible duplicate key avoidance
10288 * in the driver. */
10289 if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
10290 wpa_s->last_tk_key_idx, 1, zero, 6,
10291 zero, wpa_s->last_tk_len,
10292 KEY_FLAG_PAIRWISE_RX_TX) < 0)
10293 return -1;
10294
10295 /* Set the previously configured key to reset its TSC/RSC */
10296 return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg,
10297 wpa_s->last_tk_addr,
10298 wpa_s->last_tk_key_idx, 1, zero, 6,
10299 wpa_s->last_tk, wpa_s->last_tk_len,
10300 KEY_FLAG_PAIRWISE_RX_TX);
10301 }
10302
10303
wpas_ctrl_key_request(struct wpa_supplicant * wpa_s,const char * cmd)10304 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
10305 {
10306 const char *pos = cmd;
10307 int error, pairwise;
10308
10309 error = atoi(pos);
10310 pos = os_strchr(pos, ' ');
10311 if (!pos)
10312 return -1;
10313 pairwise = atoi(pos);
10314 wpa_sm_key_request(wpa_s->wpa, error, pairwise);
10315 return 0;
10316 }
10317
10318
wpas_ctrl_resend_assoc(struct wpa_supplicant * wpa_s)10319 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
10320 {
10321 #ifdef CONFIG_SME
10322 struct wpa_driver_associate_params params;
10323 int ret;
10324
10325 os_memset(¶ms, 0, sizeof(params));
10326 params.bssid = wpa_s->bssid;
10327 params.ssid = wpa_s->sme.ssid;
10328 params.ssid_len = wpa_s->sme.ssid_len;
10329 params.freq.freq = wpa_s->sme.freq;
10330 if (wpa_s->last_assoc_req_wpa_ie) {
10331 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
10332 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
10333 }
10334 params.pairwise_suite = wpa_s->pairwise_cipher;
10335 params.group_suite = wpa_s->group_cipher;
10336 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
10337 params.key_mgmt_suite = wpa_s->key_mgmt;
10338 params.wpa_proto = wpa_s->wpa_proto;
10339 params.mgmt_frame_protection = wpa_s->sme.mfp;
10340 params.rrm_used = wpa_s->rrm.rrm_used;
10341 if (wpa_s->sme.prev_bssid_set)
10342 params.prev_bssid = wpa_s->sme.prev_bssid;
10343 wpa_printf(MSG_INFO, "TESTING: Resend association request");
10344 ret = wpa_drv_associate(wpa_s, ¶ms);
10345 wpa_s->testing_resend_assoc = 1;
10346 return ret;
10347 #else /* CONFIG_SME */
10348 return -1;
10349 #endif /* CONFIG_SME */
10350 }
10351
10352
wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant * wpa_s,const char * cmd)10353 static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
10354 const char *cmd)
10355 {
10356 u8 dtok = 1;
10357 int exponent = 10;
10358 int mantissa = 8192;
10359 u8 min_twt = 255;
10360 unsigned long long twt = 0;
10361 bool requestor = true;
10362 int setup_cmd = 0;
10363 bool trigger = true;
10364 bool implicit = true;
10365 bool flow_type = true;
10366 int flow_id = 0;
10367 bool protection = false;
10368 u8 twt_channel = 0;
10369 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021,
10370 * Figure 9-687 - Control field format):
10371 * B4 = TWT Information Frame Disabled */
10372 const char *tok_s;
10373
10374 tok_s = os_strstr(cmd, " dialog=");
10375 if (tok_s)
10376 dtok = atoi(tok_s + os_strlen(" dialog="));
10377
10378 tok_s = os_strstr(cmd, " exponent=");
10379 if (tok_s)
10380 exponent = atoi(tok_s + os_strlen(" exponent="));
10381
10382 tok_s = os_strstr(cmd, " mantissa=");
10383 if (tok_s)
10384 mantissa = atoi(tok_s + os_strlen(" mantissa="));
10385
10386 tok_s = os_strstr(cmd, " min_twt=");
10387 if (tok_s)
10388 min_twt = atoi(tok_s + os_strlen(" min_twt="));
10389
10390 tok_s = os_strstr(cmd, " setup_cmd=");
10391 if (tok_s)
10392 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10393
10394 tok_s = os_strstr(cmd, " twt=");
10395 if (tok_s &&
10396 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1)
10397 return -1;
10398
10399 tok_s = os_strstr(cmd, " requestor=");
10400 if (tok_s)
10401 requestor = atoi(tok_s + os_strlen(" requestor="));
10402
10403 tok_s = os_strstr(cmd, " trigger=");
10404 if (tok_s)
10405 trigger = atoi(tok_s + os_strlen(" trigger="));
10406
10407 tok_s = os_strstr(cmd, " implicit=");
10408 if (tok_s)
10409 implicit = atoi(tok_s + os_strlen(" implicit="));
10410
10411 tok_s = os_strstr(cmd, " flow_type=");
10412 if (tok_s)
10413 flow_type = atoi(tok_s + os_strlen(" flow_type="));
10414
10415 tok_s = os_strstr(cmd, " flow_id=");
10416 if (tok_s)
10417 flow_id = atoi(tok_s + os_strlen(" flow_id="));
10418
10419 tok_s = os_strstr(cmd, " protection=");
10420 if (tok_s)
10421 protection = atoi(tok_s + os_strlen(" protection="));
10422
10423 tok_s = os_strstr(cmd, " twt_channel=");
10424 if (tok_s)
10425 twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10426
10427 tok_s = os_strstr(cmd, " control=");
10428 if (tok_s)
10429 control = atoi(tok_s + os_strlen(" control="));
10430
10431 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10432 setup_cmd, twt, requestor, trigger, implicit,
10433 flow_type, flow_id, protection, twt_channel,
10434 control);
10435 }
10436
10437
wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant * wpa_s,const char * cmd)10438 static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10439 const char *cmd)
10440 {
10441 u8 flags = 0x1;
10442 const char *tok_s;
10443
10444 tok_s = os_strstr(cmd, " flags=");
10445 if (tok_s)
10446 flags = atoi(tok_s + os_strlen(" flags="));
10447
10448 return wpas_twt_send_teardown(wpa_s, flags);
10449 }
10450
10451 #endif /* CONFIG_TESTING_OPTIONS */
10452
10453
wpas_ctrl_vendor_elem_add(struct wpa_supplicant * wpa_s,char * cmd)10454 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10455 {
10456 char *pos = cmd;
10457 int frame;
10458 size_t len;
10459 struct wpabuf *buf;
10460 struct ieee802_11_elems elems;
10461
10462 frame = atoi(pos);
10463 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10464 return -1;
10465 wpa_s = wpas_vendor_elem(wpa_s, frame);
10466
10467 pos = os_strchr(pos, ' ');
10468 if (pos == NULL)
10469 return -1;
10470 pos++;
10471
10472 len = os_strlen(pos);
10473 if (len == 0)
10474 return 0;
10475 if (len & 1)
10476 return -1;
10477 len /= 2;
10478
10479 buf = wpabuf_alloc(len);
10480 if (buf == NULL)
10481 return -1;
10482
10483 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10484 wpabuf_free(buf);
10485 return -1;
10486 }
10487
10488 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10489 ParseFailed) {
10490 wpabuf_free(buf);
10491 return -1;
10492 }
10493
10494 if (wpa_s->vendor_elem[frame] == NULL) {
10495 wpa_s->vendor_elem[frame] = buf;
10496 goto update_ies;
10497 }
10498
10499 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10500 wpabuf_free(buf);
10501 return -1;
10502 }
10503
10504 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10505 wpabuf_free(buf);
10506
10507 update_ies:
10508 wpas_vendor_elem_update(wpa_s);
10509
10510 if (frame == VENDOR_ELEM_PROBE_REQ ||
10511 frame == VENDOR_ELEM_PROBE_REQ_P2P)
10512 wpa_supplicant_set_default_scan_ies(wpa_s);
10513
10514 return 0;
10515 }
10516
10517
wpas_ctrl_vendor_elem_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)10518 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10519 char *buf, size_t buflen)
10520 {
10521 int frame = atoi(cmd);
10522
10523 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10524 return -1;
10525 wpa_s = wpas_vendor_elem(wpa_s, frame);
10526
10527 if (wpa_s->vendor_elem[frame] == NULL)
10528 return 0;
10529
10530 return wpa_snprintf_hex(buf, buflen,
10531 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10532 wpabuf_len(wpa_s->vendor_elem[frame]));
10533 }
10534
10535
wpas_ctrl_vendor_elem_remove(struct wpa_supplicant * wpa_s,char * cmd)10536 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10537 {
10538 char *pos = cmd;
10539 int frame;
10540 size_t len;
10541 u8 *buf;
10542 struct ieee802_11_elems elems;
10543 int res;
10544
10545 frame = atoi(pos);
10546 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10547 return -1;
10548 wpa_s = wpas_vendor_elem(wpa_s, frame);
10549
10550 pos = os_strchr(pos, ' ');
10551 if (pos == NULL)
10552 return -1;
10553 pos++;
10554
10555 if (*pos == '*') {
10556 wpabuf_free(wpa_s->vendor_elem[frame]);
10557 wpa_s->vendor_elem[frame] = NULL;
10558 wpas_vendor_elem_update(wpa_s);
10559 return 0;
10560 }
10561
10562 if (wpa_s->vendor_elem[frame] == NULL)
10563 return -1;
10564
10565 len = os_strlen(pos);
10566 if (len == 0)
10567 return 0;
10568 if (len & 1)
10569 return -1;
10570 len /= 2;
10571
10572 buf = os_malloc(len);
10573 if (buf == NULL)
10574 return -1;
10575
10576 if (hexstr2bin(pos, buf, len) < 0) {
10577 os_free(buf);
10578 return -1;
10579 }
10580
10581 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10582 os_free(buf);
10583 return -1;
10584 }
10585
10586 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
10587 os_free(buf);
10588 return res;
10589 }
10590
10591
10592 #ifndef CONFIG_NO_RRM
10593
wpas_ctrl_neighbor_rep_cb(void * ctx,struct wpabuf * neighbor_rep)10594 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10595 {
10596 struct wpa_supplicant *wpa_s = ctx;
10597 size_t len;
10598 const u8 *data;
10599
10600 /*
10601 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10602 * BSSID[6]
10603 * BSSID Information[4]
10604 * Operating Class[1]
10605 * Channel Number[1]
10606 * PHY Type[1]
10607 * Optional Subelements[variable]
10608 */
10609 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10610
10611 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
10612 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
10613 goto out;
10614 }
10615
10616 data = wpabuf_head_u8(neighbor_rep);
10617 len = wpabuf_len(neighbor_rep);
10618
10619 while (len >= 2 + NR_IE_MIN_LEN) {
10620 const u8 *nr;
10621 char lci[256 * 2 + 1];
10622 char civic[256 * 2 + 1];
10623 u8 nr_len = data[1];
10624 const u8 *pos = data, *end;
10625
10626 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
10627 nr_len < NR_IE_MIN_LEN) {
10628 wpa_dbg(wpa_s, MSG_DEBUG,
10629 "CTRL: Invalid Neighbor Report element: id=%u len=%u",
10630 data[0], nr_len);
10631 goto out;
10632 }
10633
10634 if (2U + nr_len > len) {
10635 wpa_dbg(wpa_s, MSG_DEBUG,
10636 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
10637 data[0], len, nr_len);
10638 goto out;
10639 }
10640 pos += 2;
10641 end = pos + nr_len;
10642
10643 nr = pos;
10644 pos += NR_IE_MIN_LEN;
10645
10646 lci[0] = '\0';
10647 civic[0] = '\0';
10648 while (end - pos > 2) {
10649 u8 s_id, s_len;
10650
10651 s_id = *pos++;
10652 s_len = *pos++;
10653 if (s_len > end - pos)
10654 goto out;
10655 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
10656 /* Measurement Token[1] */
10657 /* Measurement Report Mode[1] */
10658 /* Measurement Type[1] */
10659 /* Measurement Report[variable] */
10660 switch (pos[2]) {
10661 case MEASURE_TYPE_LCI:
10662 if (lci[0])
10663 break;
10664 wpa_snprintf_hex(lci, sizeof(lci),
10665 pos, s_len);
10666 break;
10667 case MEASURE_TYPE_LOCATION_CIVIC:
10668 if (civic[0])
10669 break;
10670 wpa_snprintf_hex(civic, sizeof(civic),
10671 pos, s_len);
10672 break;
10673 }
10674 }
10675
10676 pos += s_len;
10677 }
10678
10679 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10680 "bssid=" MACSTR
10681 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10682 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10683 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10684 nr[ETH_ALEN + 6],
10685 lci[0] ? " lci=" : "", lci,
10686 civic[0] ? " civic=" : "", civic);
10687
10688 data = end;
10689 len -= 2 + nr_len;
10690 }
10691
10692 #ifdef __ZEPHYR__
10693 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
10694 NET_EVENT_WIFI_CMD_NEIGHBOR_REP_COMPLETE,
10695 (void *)wpa_s->current_ssid->ssid,
10696 wpa_s->current_ssid->ssid_len);
10697 #endif
10698
10699 out:
10700 wpabuf_free(neighbor_rep);
10701 }
10702
wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant * wpa_s,char * cmd)10703 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10704 char *cmd)
10705 {
10706 struct wpa_ssid_value ssid, *ssid_p = NULL;
10707 int ret, lci = 0, civic = 0;
10708 char *ssid_s;
10709
10710 ssid_s = os_strstr(cmd, "ssid=");
10711 if (ssid_s) {
10712 if (ssid_parse(ssid_s + 5, &ssid)) {
10713 wpa_msg(wpa_s, MSG_INFO,
10714 "CTRL: Send Neighbor Report: bad SSID");
10715 return -1;
10716 }
10717
10718 ssid_p = &ssid;
10719
10720 /*
10721 * Move cmd after the SSID text that may include "lci" or
10722 * "civic".
10723 */
10724 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10725 if (cmd)
10726 cmd++;
10727
10728 }
10729
10730 if (cmd && os_strstr(cmd, "lci"))
10731 lci = 1;
10732
10733 if (cmd && os_strstr(cmd, "civic"))
10734 civic = 1;
10735
10736 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
10737 wpas_ctrl_neighbor_rep_cb,
10738 wpa_s);
10739
10740 return ret;
10741 }
10742
10743 #endif /* CONFIG_NO_RRM */
10744
10745
wpas_ctrl_iface_erp_flush(struct wpa_supplicant * wpa_s)10746 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10747 {
10748 eapol_sm_erp_flush(wpa_s->eapol);
10749 return 0;
10750 }
10751
10752
wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant * wpa_s,char * cmd)10753 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10754 char *cmd)
10755 {
10756 char *token, *context = NULL;
10757 unsigned int enable = ~0, type = 0;
10758 u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10759 u8 *addr = NULL, *mask = NULL;
10760
10761 while ((token = str_token(cmd, " ", &context))) {
10762 if (os_strcasecmp(token, "scan") == 0) {
10763 type |= MAC_ADDR_RAND_SCAN;
10764 } else if (os_strcasecmp(token, "sched") == 0) {
10765 type |= MAC_ADDR_RAND_SCHED_SCAN;
10766 } else if (os_strcasecmp(token, "pno") == 0) {
10767 type |= MAC_ADDR_RAND_PNO;
10768 } else if (os_strcasecmp(token, "all") == 0) {
10769 type = wpa_s->mac_addr_rand_supported;
10770 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
10771 enable = atoi(token + 7);
10772 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
10773 addr = _addr;
10774 if (hwaddr_aton(token + 5, addr)) {
10775 wpa_printf(MSG_INFO,
10776 "CTRL: Invalid MAC address: %s",
10777 token);
10778 return -1;
10779 }
10780 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
10781 mask = _mask;
10782 if (hwaddr_aton(token + 5, mask)) {
10783 wpa_printf(MSG_INFO,
10784 "CTRL: Invalid MAC address mask: %s",
10785 token);
10786 return -1;
10787 }
10788 } else {
10789 wpa_printf(MSG_INFO,
10790 "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10791 token);
10792 return -1;
10793 }
10794 }
10795
10796 if (!type) {
10797 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10798 return -1;
10799 }
10800
10801 if (enable > 1) {
10802 wpa_printf(MSG_INFO,
10803 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10804 return -1;
10805 }
10806
10807 if (!enable)
10808 return wpas_disable_mac_addr_randomization(wpa_s, type);
10809
10810 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
10811 }
10812
10813
wpas_ctrl_iface_pmksa(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)10814 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10815 char *buf, size_t buflen)
10816 {
10817 size_t reply_len;
10818
10819 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10820 #ifdef CONFIG_AP
10821 if (reply_len != -1) {
10822 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10823 buflen - reply_len);
10824 }
10825 #endif /* CONFIG_AP */
10826 return reply_len;
10827 }
10828
10829
wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant * wpa_s)10830 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10831 {
10832 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
10833 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10834 #ifdef CONFIG_AP
10835 wpas_ap_pmksa_cache_flush(wpa_s);
10836 #endif /* CONFIG_AP */
10837 }
10838
10839
10840 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10841
wpas_ctrl_iface_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)10842 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
10843 const char *cmd, char *buf, size_t buflen)
10844 {
10845 struct rsn_pmksa_cache_entry *entry;
10846 struct wpa_ssid *ssid;
10847 char *pos, *pos2, *end;
10848 int ret;
10849 struct os_reltime now;
10850
10851 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10852 if (!ssid)
10853 return -1;
10854
10855 pos = buf;
10856 end = buf + buflen;
10857
10858 os_get_reltime(&now);
10859
10860 /*
10861 * Entry format:
10862 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10863 * <expiration in seconds> <akmp> <opportunistic>
10864 * [FILS Cache Identifier]
10865 */
10866
10867 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
10868 entry = entry->next) {
10869 if (entry->network_ctx != ssid)
10870 continue;
10871
10872 pos2 = pos;
10873 ret = os_snprintf(pos2, end - pos2, MACSTR " ",
10874 MAC2STR(entry->aa));
10875 if (os_snprintf_error(end - pos2, ret))
10876 break;
10877 pos2 += ret;
10878
10879 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
10880 PMKID_LEN);
10881
10882 ret = os_snprintf(pos2, end - pos2, " ");
10883 if (os_snprintf_error(end - pos2, ret))
10884 break;
10885 pos2 += ret;
10886
10887 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
10888 entry->pmk_len);
10889
10890 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
10891 (int) (entry->reauth_time - now.sec),
10892 (int) (entry->expiration - now.sec),
10893 entry->akmp,
10894 entry->opportunistic);
10895 if (os_snprintf_error(end - pos2, ret))
10896 break;
10897 pos2 += ret;
10898
10899 if (entry->fils_cache_id_set) {
10900 ret = os_snprintf(pos2, end - pos2, " %02x%02x",
10901 entry->fils_cache_id[0],
10902 entry->fils_cache_id[1]);
10903 if (os_snprintf_error(end - pos2, ret))
10904 break;
10905 pos2 += ret;
10906 }
10907
10908 ret = os_snprintf(pos2, end - pos2, "\n");
10909 if (os_snprintf_error(end - pos2, ret))
10910 break;
10911 pos2 += ret;
10912
10913 pos = pos2;
10914 }
10915
10916 return pos - buf;
10917 }
10918
10919
wpas_ctrl_iface_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)10920 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
10921 char *cmd)
10922 {
10923 struct rsn_pmksa_cache_entry *entry;
10924 struct wpa_ssid *ssid;
10925 char *pos, *pos2;
10926 int ret = -1;
10927 struct os_reltime now;
10928 int reauth_time = 0, expiration = 0, i;
10929
10930 /*
10931 * Entry format:
10932 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10933 * <expiration in seconds> <akmp> <opportunistic>
10934 * [FILS Cache Identifier]
10935 */
10936
10937 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10938 if (!ssid)
10939 return -1;
10940
10941 pos = os_strchr(cmd, ' ');
10942 if (!pos)
10943 return -1;
10944 pos++;
10945
10946 entry = os_zalloc(sizeof(*entry));
10947 if (!entry)
10948 return -1;
10949
10950 if (hwaddr_aton(pos, entry->aa))
10951 goto fail;
10952
10953 pos = os_strchr(pos, ' ');
10954 if (!pos)
10955 goto fail;
10956 pos++;
10957
10958 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
10959 goto fail;
10960
10961 pos = os_strchr(pos, ' ');
10962 if (!pos)
10963 goto fail;
10964 pos++;
10965
10966 pos2 = os_strchr(pos, ' ');
10967 if (!pos2)
10968 goto fail;
10969 entry->pmk_len = (pos2 - pos) / 2;
10970 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
10971 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
10972 goto fail;
10973
10974 pos = os_strchr(pos, ' ');
10975 if (!pos)
10976 goto fail;
10977 pos++;
10978
10979 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
10980 &entry->akmp, &entry->opportunistic) != 4)
10981 goto fail;
10982 if (reauth_time > expiration)
10983 goto fail;
10984 for (i = 0; i < 4; i++) {
10985 pos = os_strchr(pos, ' ');
10986 if (!pos) {
10987 if (i < 3)
10988 goto fail;
10989 break;
10990 }
10991 pos++;
10992 }
10993 if (pos) {
10994 if (hexstr2bin(pos, entry->fils_cache_id,
10995 FILS_CACHE_ID_LEN) < 0)
10996 goto fail;
10997 entry->fils_cache_id_set = 1;
10998 }
10999 os_get_reltime(&now);
11000 entry->expiration = now.sec + expiration;
11001 entry->reauth_time = now.sec + reauth_time;
11002
11003 entry->network_ctx = ssid;
11004 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
11005
11006 entry->external = true;
11007
11008 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
11009 entry = NULL;
11010 ret = 0;
11011 fail:
11012 os_free(entry);
11013 return ret;
11014 }
11015
11016
11017 #ifdef CONFIG_MESH
11018
wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)11019 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
11020 const char *cmd, char *buf,
11021 size_t buflen)
11022 {
11023 u8 spa[ETH_ALEN];
11024
11025 if (!wpa_s->ifmsh)
11026 return -1;
11027
11028 if (os_strcasecmp(cmd, "any") == 0)
11029 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
11030
11031 if (hwaddr_aton(cmd, spa))
11032 return -1;
11033
11034 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
11035 }
11036
11037
wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)11038 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
11039 char *cmd)
11040 {
11041 /*
11042 * We do not check mesh interface existence because PMKSA should be
11043 * stored before wpa_s->ifmsh creation to suppress commit message
11044 * creation.
11045 */
11046 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
11047 }
11048
11049 #endif /* CONFIG_MESH */
11050 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
11051
11052
11053 #ifdef CONFIG_FILS
wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant * wpa_s,const char * cmd)11054 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
11055 const char *cmd)
11056 {
11057 struct fils_hlp_req *req;
11058 const char *pos;
11059
11060 /* format: <dst> <packet starting from ethertype> */
11061
11062 req = os_zalloc(sizeof(*req));
11063 if (!req)
11064 return -1;
11065
11066 if (hwaddr_aton(cmd, req->dst))
11067 goto fail;
11068
11069 pos = os_strchr(cmd, ' ');
11070 if (!pos)
11071 goto fail;
11072 pos++;
11073 req->pkt = wpabuf_parse_bin(pos);
11074 if (!req->pkt)
11075 goto fail;
11076
11077 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
11078 return 0;
11079 fail:
11080 wpabuf_free(req->pkt);
11081 os_free(req);
11082 return -1;
11083 }
11084 #endif /* CONFIG_FILS */
11085
11086
wpas_ctrl_cmd_debug_level(const char * cmd)11087 int wpas_ctrl_cmd_debug_level(const char *cmd)
11088 {
11089 if (os_strcmp(cmd, "PING") == 0 ||
11090 os_strncmp(cmd, "BSS ", 4) == 0 ||
11091 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
11092 os_strncmp(cmd, "STATUS", 6) == 0 ||
11093 os_strncmp(cmd, "STA ", 4) == 0 ||
11094 os_strncmp(cmd, "STA-", 4) == 0)
11095 return MSG_EXCESSIVE;
11096 return MSG_DEBUG;
11097 }
11098
11099
11100 #ifndef CONFIG_NO_ROBUST_AV
wpas_ctrl_iface_configure_mscs(struct wpa_supplicant * wpa_s,const char * cmd)11101 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
11102 const char *cmd)
11103 {
11104 size_t frame_classifier_len;
11105 const char *pos, *end;
11106 struct robust_av_data *robust_av = &wpa_s->robust_av;
11107 int val;
11108
11109 /*
11110 * format:
11111 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
11112 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
11113 */
11114 os_memset(robust_av, 0, sizeof(struct robust_av_data));
11115 if (os_strncmp(cmd, "add ", 4) == 0) {
11116 robust_av->request_type = SCS_REQ_ADD;
11117 } else if (os_strcmp(cmd, "remove") == 0) {
11118 robust_av->request_type = SCS_REQ_REMOVE;
11119 robust_av->valid_config = false;
11120 return wpas_send_mscs_req(wpa_s);
11121 } else if (os_strncmp(cmd, "change ", 7) == 0) {
11122 robust_av->request_type = SCS_REQ_CHANGE;
11123 } else {
11124 return -1;
11125 }
11126
11127 pos = os_strstr(cmd, "up_bitmap=");
11128 if (!pos)
11129 return -1;
11130
11131 val = hex2byte(pos + 10);
11132 if (val < 0)
11133 return -1;
11134 robust_av->up_bitmap = val;
11135
11136 pos = os_strstr(cmd, "up_limit=");
11137 if (!pos)
11138 return -1;
11139
11140 robust_av->up_limit = atoi(pos + 9);
11141
11142 pos = os_strstr(cmd, "stream_timeout=");
11143 if (!pos)
11144 return -1;
11145
11146 robust_av->stream_timeout = atoi(pos + 15);
11147 if (robust_av->stream_timeout == 0)
11148 return -1;
11149
11150 pos = os_strstr(cmd, "frame_classifier=");
11151 if (!pos)
11152 return -1;
11153
11154 pos += 17;
11155 end = os_strchr(pos, ' ');
11156 if (!end)
11157 end = pos + os_strlen(pos);
11158
11159 frame_classifier_len = (end - pos) / 2;
11160 if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
11161 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
11162 return -1;
11163
11164 robust_av->frame_classifier_len = frame_classifier_len;
11165 robust_av->valid_config = true;
11166
11167 return wpas_send_mscs_req(wpa_s);
11168 }
11169 #endif /* CONFIG_NO_ROBUST_AV */
11170
11171 #ifdef CONFIG_PASN
wpas_ctrl_iface_pasn_start(struct wpa_supplicant * wpa_s,char * cmd)11172 static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
11173 {
11174 char *token, *context = NULL;
11175 u8 bssid[ETH_ALEN];
11176 int akmp = -1, cipher = -1, got_bssid = 0;
11177 u16 group = 0xFFFF;
11178 u8 *comeback = NULL;
11179 size_t comeback_len = 0;
11180 int id = 0, ret = -1;
11181
11182 /*
11183 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
11184 * [comeback=<hexdump>]
11185 */
11186 while ((token = str_token(cmd, " ", &context))) {
11187 if (os_strncmp(token, "bssid=", 6) == 0) {
11188 if (hwaddr_aton(token + 6, bssid))
11189 goto out;
11190 got_bssid = 1;
11191 } else if (os_strcmp(token, "akmp=PASN") == 0) {
11192 akmp = WPA_KEY_MGMT_PASN;
11193 #ifdef CONFIG_IEEE80211R
11194 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
11195 akmp = WPA_KEY_MGMT_FT_PSK;
11196 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
11197 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
11198 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
11199 akmp = WPA_KEY_MGMT_FT_IEEE8021X;
11200 #endif /* CONFIG_IEEE80211R */
11201 #ifdef CONFIG_SAE
11202 } else if (os_strcmp(token, "akmp=SAE") == 0) {
11203 akmp = WPA_KEY_MGMT_SAE;
11204 } else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) {
11205 akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
11206 #endif /* CONFIG_SAE */
11207 #ifdef CONFIG_FILS
11208 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
11209 akmp = WPA_KEY_MGMT_FILS_SHA256;
11210 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
11211 akmp = WPA_KEY_MGMT_FILS_SHA384;
11212 #endif /* CONFIG_FILS */
11213 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
11214 cipher = WPA_CIPHER_CCMP_256;
11215 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
11216 cipher = WPA_CIPHER_GCMP_256;
11217 } else if (os_strcmp(token, "cipher=CCMP") == 0) {
11218 cipher = WPA_CIPHER_CCMP;
11219 } else if (os_strcmp(token, "cipher=GCMP") == 0) {
11220 cipher = WPA_CIPHER_GCMP;
11221 } else if (os_strncmp(token, "group=", 6) == 0) {
11222 group = atoi(token + 6);
11223 } else if (os_strncmp(token, "nid=", 4) == 0) {
11224 id = atoi(token + 4);
11225 } else if (os_strncmp(token, "comeback=", 9) == 0) {
11226 comeback_len = os_strlen(token + 9);
11227 if (comeback || !comeback_len || comeback_len % 2)
11228 goto out;
11229
11230 comeback_len /= 2;
11231 comeback = os_malloc(comeback_len);
11232 if (!comeback ||
11233 hexstr2bin(token + 9, comeback, comeback_len))
11234 goto out;
11235 } else {
11236 wpa_printf(MSG_DEBUG,
11237 "CTRL: PASN Invalid parameter: '%s'",
11238 token);
11239 goto out;
11240 }
11241 }
11242
11243 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
11244 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
11245 goto out;
11246 }
11247
11248 ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher,
11249 group, id, comeback, comeback_len);
11250 out:
11251 os_free(comeback);
11252 return ret;
11253 }
11254
11255
wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant * wpa_s,const char * cmd)11256 static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
11257 const char *cmd)
11258 {
11259 u8 bssid[ETH_ALEN];
11260
11261 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
11262 wpa_printf(MSG_DEBUG,
11263 "CTRL: PASN_DEAUTH without valid BSSID");
11264 return -1;
11265 }
11266
11267 return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
11268 }
11269
11270
11271 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_pasn_driver(struct wpa_supplicant * wpa_s,const char * cmd)11272 static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
11273 const char *cmd)
11274 {
11275 union wpa_event_data event;
11276 const char *pos = cmd;
11277 u8 addr[ETH_ALEN];
11278
11279 os_memset(&event, 0, sizeof(event));
11280
11281 if (os_strncmp(pos, "auth ", 5) == 0)
11282 event.pasn_auth.action = PASN_ACTION_AUTH;
11283 else if (os_strncmp(pos, "del ", 4) == 0)
11284 event.pasn_auth.action =
11285 PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
11286 else
11287 return -1;
11288
11289 pos = os_strchr(pos, ' ');
11290 if (!pos)
11291 return -1;
11292 pos++;
11293 while (hwaddr_aton(pos, addr) == 0) {
11294 struct pasn_peer *peer;
11295
11296 if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
11297 return -1;
11298 peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
11299 os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
11300 os_memcpy(peer->peer_addr, addr, ETH_ALEN);
11301 event.pasn_auth.num_peers++;
11302
11303 pos = os_strchr(pos, ' ');
11304 if (!pos)
11305 break;
11306 pos++;
11307 }
11308
11309 wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
11310 return 0;
11311 }
11312 #endif /* CONFIG_TESTING_OPTIONS */
11313
11314 #endif /* CONFIG_PASN */
11315
11316
11317 #ifndef CONFIG_NO_ROBUST_AV
11318
set_type4_frame_classifier(const char * cmd,struct type4_params * param)11319 static int set_type4_frame_classifier(const char *cmd,
11320 struct type4_params *param)
11321 {
11322 const char *pos, *end;
11323 u8 classifier_mask = 0;
11324 int ret;
11325 char addr[INET6_ADDRSTRLEN];
11326 size_t alen;
11327
11328 if (os_strstr(cmd, "ip_version=ipv4")) {
11329 param->ip_version = IPV4;
11330 } else if (os_strstr(cmd, "ip_version=ipv6")) {
11331 param->ip_version = IPV6;
11332 } else {
11333 wpa_printf(MSG_ERROR, "IP version missing/invalid");
11334 return -1;
11335 }
11336
11337 classifier_mask |= BIT(0);
11338
11339 pos = os_strstr(cmd, "src_ip=");
11340 if (pos) {
11341 pos += 7;
11342 end = os_strchr(pos, ' ');
11343 if (!end)
11344 end = pos + os_strlen(pos);
11345
11346 alen = end - pos;
11347 if (alen >= INET6_ADDRSTRLEN)
11348 return -1;
11349 os_memcpy(addr, pos, alen);
11350 addr[alen] = '\0';
11351 if (param->ip_version == IPV4)
11352 ret = inet_pton(AF_INET, addr,
11353 ¶m->ip_params.v4.src_ip);
11354 else
11355 ret = inet_pton(AF_INET6, addr,
11356 ¶m->ip_params.v6.src_ip);
11357
11358 if (ret != 1) {
11359 wpa_printf(MSG_ERROR,
11360 "Error converting src IP address to binary ret=%d",
11361 ret);
11362 return -1;
11363 }
11364
11365 classifier_mask |= BIT(1);
11366 }
11367
11368 pos = os_strstr(cmd, "dst_ip=");
11369 if (pos) {
11370 pos += 7;
11371 end = os_strchr(pos, ' ');
11372 if (!end)
11373 end = pos + os_strlen(pos);
11374
11375 alen = end - pos;
11376 if (alen >= INET6_ADDRSTRLEN)
11377 return -1;
11378 os_memcpy(addr, pos, alen);
11379 addr[alen] = '\0';
11380 if (param->ip_version == IPV4)
11381 ret = inet_pton(AF_INET, addr,
11382 ¶m->ip_params.v4.dst_ip);
11383 else
11384 ret = inet_pton(AF_INET6, addr,
11385 ¶m->ip_params.v6.dst_ip);
11386
11387 if (ret != 1) {
11388 wpa_printf(MSG_ERROR,
11389 "Error converting dst IP address to binary ret=%d",
11390 ret);
11391 return -1;
11392 }
11393
11394 classifier_mask |= BIT(2);
11395 }
11396
11397 pos = os_strstr(cmd, "src_port=");
11398 if (pos && atoi(pos + 9) > 0) {
11399 if (param->ip_version == IPV4)
11400 param->ip_params.v4.src_port = atoi(pos + 9);
11401 else
11402 param->ip_params.v6.src_port = atoi(pos + 9);
11403 classifier_mask |= BIT(3);
11404 }
11405
11406 pos = os_strstr(cmd, "dst_port=");
11407 if (pos && atoi(pos + 9) > 0) {
11408 if (param->ip_version == IPV4)
11409 param->ip_params.v4.dst_port = atoi(pos + 9);
11410 else
11411 param->ip_params.v6.dst_port = atoi(pos + 9);
11412 classifier_mask |= BIT(4);
11413 }
11414
11415 pos = os_strstr(cmd, "dscp=");
11416 if (pos && atoi(pos + 5) > 0) {
11417 if (param->ip_version == IPV4)
11418 param->ip_params.v4.dscp = atoi(pos + 5);
11419 else
11420 param->ip_params.v6.dscp = atoi(pos + 5);
11421 classifier_mask |= BIT(5);
11422 }
11423
11424 if (param->ip_version == IPV4) {
11425 pos = os_strstr(cmd, "protocol=");
11426 if (pos) {
11427 if (os_strstr(pos, "udp")) {
11428 param->ip_params.v4.protocol = 17;
11429 } else if (os_strstr(pos, "tcp")) {
11430 param->ip_params.v4.protocol = 6;
11431 } else if (os_strstr(pos, "esp")) {
11432 param->ip_params.v4.protocol = 50;
11433 } else {
11434 wpa_printf(MSG_ERROR, "Invalid protocol");
11435 return -1;
11436 }
11437 classifier_mask |= BIT(6);
11438 }
11439 } else {
11440 pos = os_strstr(cmd, "next_header=");
11441 if (pos) {
11442 if (os_strstr(pos, "udp")) {
11443 param->ip_params.v6.next_header = 17;
11444 } else if (os_strstr(pos, "tcp")) {
11445 param->ip_params.v6.next_header = 6;
11446 } else if (os_strstr(pos, "esp")) {
11447 param->ip_params.v6.next_header = 50;
11448 } else {
11449 wpa_printf(MSG_ERROR, "Invalid next header");
11450 return -1;
11451 }
11452
11453 classifier_mask |= BIT(6);
11454 }
11455
11456 pos = os_strstr(cmd, "flow_label=");
11457 if (pos) {
11458 pos += 11;
11459 end = os_strchr(pos, ' ');
11460 if (!end)
11461 end = pos + os_strlen(pos);
11462
11463 if (end - pos != 6 ||
11464 hexstr2bin(pos, param->ip_params.v6.flow_label,
11465 3) ||
11466 param->ip_params.v6.flow_label[0] > 0x0F) {
11467 wpa_printf(MSG_ERROR, "Invalid flow label");
11468 return -1;
11469 }
11470
11471 classifier_mask |= BIT(7);
11472 }
11473 }
11474
11475 param->classifier_mask = classifier_mask;
11476 return 0;
11477 }
11478
11479
set_type10_frame_classifier(const char * cmd,struct type10_params * param)11480 static int set_type10_frame_classifier(const char *cmd,
11481 struct type10_params *param)
11482 {
11483 const char *pos, *end;
11484 size_t filter_len;
11485
11486 pos = os_strstr(cmd, "prot_instance=");
11487 if (!pos) {
11488 wpa_printf(MSG_ERROR, "Protocol instance missing");
11489 return -1;
11490 }
11491 param->prot_instance = atoi(pos + 14);
11492
11493 pos = os_strstr(cmd, "prot_number=");
11494 if (!pos) {
11495 wpa_printf(MSG_ERROR, "Protocol number missing");
11496 return -1;
11497 }
11498 if (os_strstr(pos, "udp")) {
11499 param->prot_number = 17;
11500 } else if (os_strstr(pos, "tcp")) {
11501 param->prot_number = 6;
11502 } else if (os_strstr(pos, "esp")) {
11503 param->prot_number = 50;
11504 } else {
11505 wpa_printf(MSG_ERROR, "Invalid protocol number");
11506 return -1;
11507 }
11508
11509 pos = os_strstr(cmd, "filter_value=");
11510 if (!pos) {
11511 wpa_printf(MSG_ERROR,
11512 "Classifier parameter filter_value missing");
11513 return -1;
11514 }
11515
11516 pos += 13;
11517 end = os_strchr(pos, ' ');
11518 if (!end)
11519 end = pos + os_strlen(pos);
11520
11521 filter_len = (end - pos) / 2;
11522 param->filter_value = os_malloc(filter_len);
11523 if (!param->filter_value)
11524 return -1;
11525
11526 if (hexstr2bin(pos, param->filter_value, filter_len)) {
11527 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11528 goto free;
11529 }
11530
11531 pos = os_strstr(cmd, "filter_mask=");
11532 if (!pos) {
11533 wpa_printf(MSG_ERROR,
11534 "Classifier parameter filter_mask missing");
11535 goto free;
11536 }
11537
11538 pos += 12;
11539 end = os_strchr(pos, ' ');
11540 if (!end)
11541 end = pos + os_strlen(pos);
11542
11543 if (filter_len != (size_t) (end - pos) / 2) {
11544 wpa_printf(MSG_ERROR,
11545 "Filter mask length mismatch expected=%zu received=%zu",
11546 filter_len, (size_t) (end - pos) / 2);
11547 goto free;
11548 }
11549
11550 param->filter_mask = os_malloc(filter_len);
11551 if (!param->filter_mask)
11552 goto free;
11553
11554 if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11555 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11556 os_free(param->filter_mask);
11557 param->filter_mask = NULL;
11558 goto free;
11559 }
11560
11561 param->filter_len = filter_len;
11562 return 0;
11563 free:
11564 os_free(param->filter_value);
11565 param->filter_value = NULL;
11566 return -1;
11567 }
11568
11569
scs_parse_type4(struct tclas_element * elem,const char * pos)11570 static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11571 {
11572 struct type4_params type4_param = { 0 };
11573
11574 if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11575 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11576 return -1;
11577 }
11578
11579 os_memcpy(&elem->frame_classifier.type4_param,
11580 &type4_param, sizeof(struct type4_params));
11581 return 0;
11582 }
11583
11584
scs_parse_type10(struct tclas_element * elem,const char * pos)11585 static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11586 {
11587 struct type10_params type10_param = { 0 };
11588
11589 if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11590 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11591 return -1;
11592 }
11593
11594 os_memcpy(&elem->frame_classifier.type10_param,
11595 &type10_param, sizeof(struct type10_params));
11596 return 0;
11597 }
11598
11599
wpas_ctrl_iface_configure_scs(struct wpa_supplicant * wpa_s,char * cmd)11600 static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11601 char *cmd)
11602 {
11603 char *pos1, *pos;
11604 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11605 struct scs_desc_elem desc_elem = { 0 };
11606 int val;
11607 unsigned int num_scs_desc = 0;
11608
11609 if (wpa_s->ongoing_scs_req) {
11610 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11611 __func__);
11612 return -1;
11613 }
11614
11615 /**
11616 * format:
11617 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11618 * [classifier_type=<4|10>]
11619 * [classifier params based on classifier type]
11620 * [tclas_processing=<0|1>]
11621 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>]
11622 * [max_si=<decimal number>] [min_data_rate=<decimal number>]
11623 * [delay_bound=<decimal number>] [max_msdu=<decimal number>]
11624 * [service_start_time=<decimal number>]
11625 * [service_start_time_link_id=<decimal number>]
11626 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>]
11627 * [msdu_lifetime=<decimal number>]
11628 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>]
11629 * [scs_id=<decimal number>] ...
11630 */
11631 pos1 = os_strstr(cmd, "scs_id=");
11632 if (!pos1) {
11633 wpa_printf(MSG_ERROR, "SCSID not present");
11634 return -1;
11635 }
11636
11637 free_up_scs_desc(scs_data);
11638
11639 while (pos1) {
11640 struct scs_desc_elem *n1;
11641 struct active_scs_elem *active_scs_desc;
11642 char *next_scs_desc, *pos2;
11643 unsigned int num_tclas_elem = 0;
11644 bool scsid_active = false, tclas_present = false;
11645 struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem;
11646
11647 desc_elem.scs_id = atoi(pos1 + 7);
11648 pos1 += 7;
11649
11650 next_scs_desc = os_strstr(pos1, "scs_id=");
11651 if (next_scs_desc) {
11652 char temp[20];
11653
11654 os_snprintf(temp, sizeof(temp), "scs_id=%d ",
11655 desc_elem.scs_id);
11656 if (os_strstr(next_scs_desc, temp)) {
11657 wpa_printf(MSG_ERROR,
11658 "Multiple SCS descriptors configured with same SCSID(=%d)",
11659 desc_elem.scs_id);
11660 goto free_scs_desc;
11661 }
11662 pos1[next_scs_desc - pos1 - 1] = '\0';
11663 }
11664
11665 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
11666 struct active_scs_elem, list) {
11667 if (desc_elem.scs_id == active_scs_desc->scs_id) {
11668 scsid_active = true;
11669 break;
11670 }
11671 }
11672
11673 if (os_strstr(pos1, "add ")) {
11674 desc_elem.request_type = SCS_REQ_ADD;
11675 if (scsid_active) {
11676 wpa_printf(MSG_ERROR, "SCSID %d already active",
11677 desc_elem.scs_id);
11678 return -1;
11679 }
11680 } else if (os_strstr(pos1, "remove")) {
11681 desc_elem.request_type = SCS_REQ_REMOVE;
11682 if (!scsid_active) {
11683 wpa_printf(MSG_ERROR, "SCSID %d not active",
11684 desc_elem.scs_id);
11685 return -1;
11686 }
11687 goto scs_desc_end;
11688 } else if (os_strstr(pos1, "change ")) {
11689 desc_elem.request_type = SCS_REQ_CHANGE;
11690 if (!scsid_active) {
11691 wpa_printf(MSG_ERROR, "SCSID %d not active",
11692 desc_elem.scs_id);
11693 return -1;
11694 }
11695 } else {
11696 wpa_printf(MSG_ERROR, "SCS Request type invalid");
11697 goto free_scs_desc;
11698 }
11699
11700 pos1 = os_strstr(pos1, "scs_up=");
11701 if (!pos1) {
11702 wpa_printf(MSG_ERROR,
11703 "Intra-Access user priority not present");
11704 goto free_scs_desc;
11705 }
11706
11707 val = atoi(pos1 + 7);
11708 if (val < 0 || val > 7) {
11709 wpa_printf(MSG_ERROR,
11710 "Intra-Access user priority invalid %d",
11711 val);
11712 goto free_scs_desc;
11713 }
11714
11715 desc_elem.intra_access_priority = val;
11716 desc_elem.scs_up_avail = true;
11717
11718 pos = os_strstr(pos1, "classifier_type=");
11719 if (!pos) {
11720 wpa_printf(MSG_ERROR, "classifier type empty");
11721 goto qos_characteristics;
11722 }
11723 tclas_present = true;
11724
11725 while (pos) {
11726 struct tclas_element elem = { 0 }, *n;
11727 char *next_tclas_elem;
11728
11729 val = atoi(pos + 16);
11730 if (val != 4 && val != 10) {
11731 wpa_printf(MSG_ERROR,
11732 "classifier type invalid %d", val);
11733 goto free_scs_desc;
11734 }
11735
11736 elem.classifier_type = val;
11737 pos += 16;
11738
11739 next_tclas_elem = os_strstr(pos, "classifier_type=");
11740 if (next_tclas_elem) {
11741 pos1 = next_tclas_elem;
11742 pos[next_tclas_elem - pos - 1] = '\0';
11743 }
11744
11745 switch (val) {
11746 case 4:
11747 if (scs_parse_type4(&elem, pos) < 0)
11748 goto free_scs_desc;
11749 break;
11750 case 10:
11751 if (scs_parse_type10(&elem, pos) < 0)
11752 goto free_scs_desc;
11753 break;
11754 }
11755
11756 n = os_realloc(desc_elem.tclas_elems,
11757 (num_tclas_elem + 1) * sizeof(elem));
11758 if (!n)
11759 goto free_scs_desc;
11760
11761 desc_elem.tclas_elems = n;
11762 os_memcpy((u8 *) desc_elem.tclas_elems +
11763 num_tclas_elem * sizeof(elem),
11764 &elem, sizeof(elem));
11765 num_tclas_elem++;
11766 desc_elem.num_tclas_elem = num_tclas_elem;
11767 pos = next_tclas_elem;
11768 }
11769
11770 if (desc_elem.num_tclas_elem > 1) {
11771 pos1 = os_strstr(pos1, "tclas_processing=");
11772 if (!pos1) {
11773 wpa_printf(MSG_ERROR, "tclas_processing empty");
11774 goto free_scs_desc;
11775 }
11776
11777 val = atoi(pos1 + 17);
11778 if (val != 0 && val != 1) {
11779 wpa_printf(MSG_ERROR,
11780 "tclas_processing invalid");
11781 goto free_scs_desc;
11782 }
11783
11784 desc_elem.tclas_processing = val;
11785 }
11786
11787 qos_characteristics:
11788 pos1 = os_strstr(pos1, "qos_characteristics");
11789 if (!pos1 && !tclas_present)
11790 goto free_scs_desc;
11791 if (!pos1)
11792 goto scs_desc_end;
11793
11794 qos_elem->available = true;
11795 if (os_strstr(pos1, "up ")) {
11796 qos_elem->direction = SCS_DIRECTION_UP;
11797 if (tclas_present) {
11798 wpa_printf(MSG_ERROR,
11799 "TCLAS with direction:UP not allowed");
11800 goto free_scs_desc;
11801 }
11802 } else if (os_strstr(pos1, "down ")) {
11803 qos_elem->direction = SCS_DIRECTION_DOWN;
11804 } else if (os_strstr(pos1, "direct ")) {
11805 qos_elem->direction = SCS_DIRECTION_DIRECT;
11806 }
11807
11808 pos1 = os_strstr(pos1, "min_si=");
11809 if (!pos1) {
11810 wpa_printf(MSG_ERROR, "Min SI is required");
11811 goto free_scs_desc;
11812 }
11813 qos_elem->min_si = atoi(pos1 + 7);
11814
11815 pos1 = os_strstr(pos1, "max_si=");
11816 if (!pos1) {
11817 wpa_printf(MSG_ERROR, "Max SI is required");
11818 goto free_scs_desc;
11819 }
11820 qos_elem->max_si = atoi(pos1 + 7);
11821
11822 if (qos_elem->min_si && qos_elem->max_si &&
11823 qos_elem->max_si < qos_elem->min_si) {
11824 wpa_printf(MSG_ERROR, "Invalid Max SI");
11825 goto free_scs_desc;
11826 }
11827
11828 pos1 = os_strstr(pos1, "min_data_rate=");
11829 if (!pos1) {
11830 wpa_printf(MSG_ERROR, "Min data rate is required");
11831 goto free_scs_desc;
11832 }
11833 qos_elem->min_data_rate = atoi(pos1 + 14);
11834
11835 pos1 = os_strstr(pos1, "delay_bound=");
11836 if (!pos1) {
11837 wpa_printf(MSG_ERROR, "Delay Bound is required");
11838 goto free_scs_desc;
11839 }
11840 qos_elem->delay_bound = atoi(pos1 + 12);
11841
11842 if (qos_elem->min_data_rate >= BIT(24) ||
11843 qos_elem->delay_bound >= BIT(24)) {
11844 wpa_printf(MSG_ERROR,
11845 "Invalid min_data_rate or delay_bound");
11846 goto free_scs_desc;
11847 }
11848
11849 pos2 = os_strstr(pos1, "max_msdu=");
11850 if (pos2) {
11851 qos_elem->max_msdu_size = atoi(pos2 + 9);
11852 qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE;
11853 }
11854
11855 pos2 = os_strstr(pos1, "service_start_time=");
11856 if (pos2) {
11857 qos_elem->service_start_time = atoi(pos2 + 19);
11858 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME;
11859 }
11860
11861 pos2 = os_strstr(pos1, "service_start_time_link_id=");
11862 if (pos2) {
11863 qos_elem->service_start_time_link_id = atoi(pos2 + 27);
11864 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
11865 }
11866
11867 pos2 = os_strstr(pos1, "mean_data_rate=");
11868 if (pos2) {
11869 qos_elem->mean_data_rate = atoi(pos2 + 15);
11870 qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE;
11871 }
11872
11873 pos2 = os_strstr(pos1, "burst_size=");
11874 if (pos2) {
11875 qos_elem->burst_size = atoi(pos2 + 11);
11876 qos_elem->mask |=
11877 SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE;
11878 }
11879
11880 pos2 = os_strstr(pos1, "msdu_lifetime=");
11881 if (pos2) {
11882 qos_elem->msdu_lifetime = atoi(pos2 + 14);
11883 qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME;
11884 }
11885
11886 pos2 = os_strstr(pos1, "msdu_delivery_info=");
11887 if (pos2) {
11888 qos_elem->msdu_delivery_info = atoi(pos2 + 19);
11889 qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO;
11890 }
11891
11892 pos2 = os_strstr(pos1, "medium_time=");
11893 if (pos2) {
11894 qos_elem->medium_time = atoi(pos2 + 12);
11895 qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME;
11896 }
11897
11898 scs_desc_end:
11899 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
11900 sizeof(struct scs_desc_elem));
11901 if (!n1)
11902 goto free_scs_desc;
11903
11904 scs_data->scs_desc_elems = n1;
11905 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
11906 sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
11907 num_scs_desc++;
11908 scs_data->num_scs_desc = num_scs_desc;
11909 pos1 = next_scs_desc;
11910 os_memset(&desc_elem, 0, sizeof(desc_elem));
11911 }
11912
11913 return wpas_send_scs_req(wpa_s);
11914
11915 free_scs_desc:
11916 free_up_tclas_elem(&desc_elem);
11917 free_up_scs_desc(scs_data);
11918 return -1;
11919 }
11920
11921
wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant * wpa_s,const char * cmd)11922 static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
11923 const char *cmd)
11924 {
11925 char *pos;
11926 struct dscp_policy_status *policy = NULL, *n;
11927 int num_policies = 0, ret = -1;
11928 struct dscp_resp_data resp_data;
11929
11930 /*
11931 * format:
11932 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
11933 */
11934
11935 os_memset(&resp_data, 0, sizeof(resp_data));
11936
11937 resp_data.more = os_strstr(cmd, "more") != NULL;
11938
11939 if (os_strstr(cmd, "reset")) {
11940 resp_data.reset = true;
11941 resp_data.solicited = false;
11942 goto send_resp;
11943 }
11944
11945 resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
11946
11947 pos = os_strstr(cmd, "policy_id=");
11948 while (pos) {
11949 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
11950 if (!n)
11951 goto fail;
11952
11953 policy = n;
11954 pos += 10;
11955 policy[num_policies].id = atoi(pos);
11956 if (policy[num_policies].id == 0) {
11957 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
11958 goto fail;
11959 }
11960
11961 pos = os_strstr(pos, "status=");
11962 if (!pos) {
11963 wpa_printf(MSG_ERROR,
11964 "DSCP: Status is not found for a policy");
11965 goto fail;
11966 }
11967
11968 pos += 7;
11969 policy[num_policies].status = atoi(pos);
11970 num_policies++;
11971
11972 pos = os_strstr(pos, "policy_id");
11973 }
11974
11975 resp_data.policy = policy;
11976 resp_data.num_policies = num_policies;
11977 send_resp:
11978 ret = wpas_send_dscp_response(wpa_s, &resp_data);
11979 if (ret)
11980 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
11981 fail:
11982 os_free(policy);
11983 return ret;
11984 }
11985
11986
wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant * wpa_s,const char * cmd)11987 static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
11988 const char *cmd)
11989 {
11990 char *pos;
11991
11992 /*
11993 * format:
11994 * Wildcard DSCP query
11995 * <wildcard>
11996 *
11997 * DSCP query with a domain name attribute:
11998 * [domain_name=<string>]
11999 */
12000
12001 if (os_strstr(cmd, "wildcard")) {
12002 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
12003 return wpas_send_dscp_query(wpa_s, NULL, 0);
12004 }
12005
12006 pos = os_strstr(cmd, "domain_name=");
12007 if (!pos || !os_strlen(pos + 12)) {
12008 wpa_printf(MSG_ERROR, "QM: Domain name not preset");
12009 return -1;
12010 }
12011
12012 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
12013 }
12014
12015 #endif /* CONFIG_NO_ROBUST_AV */
12016
wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)12017 static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
12018 char *buf, size_t buflen)
12019 {
12020 int ret, i;
12021 char *pos, *end;
12022 struct wpa_mlo_signal_info mlo_si;
12023
12024 if (!wpa_s->valid_links)
12025 return -1;
12026
12027 ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si);
12028 if (ret)
12029 return -1;
12030
12031 pos = buf;
12032 end = buf + buflen;
12033
12034 for_each_link(mlo_si.valid_links, i) {
12035 ret = os_snprintf(pos, end - pos,
12036 "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
12037 "NOISE=%d\nFREQUENCY=%u\n",
12038 i, mlo_si.links[i].data.signal,
12039 mlo_si.links[i].data.current_tx_rate / 1000,
12040 mlo_si.links[i].current_noise,
12041 mlo_si.links[i].frequency);
12042 if (os_snprintf_error(end - pos, ret))
12043 return -1;
12044 pos += ret;
12045
12046 if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) {
12047 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
12048 channel_width_to_string(
12049 mlo_si.links[i].chanwidth));
12050 if (os_snprintf_error(end - pos, ret))
12051 return -1;
12052 pos += ret;
12053 }
12054
12055 if (mlo_si.links[i].center_frq1 > 0) {
12056 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
12057 mlo_si.links[i].center_frq1);
12058 if (os_snprintf_error(end - pos, ret))
12059 return -1;
12060 pos += ret;
12061 }
12062
12063 if (mlo_si.links[i].center_frq2 > 0) {
12064 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
12065 mlo_si.links[i].center_frq2);
12066 if (os_snprintf_error(end - pos, ret))
12067 return -1;
12068 pos += ret;
12069 }
12070
12071 if (mlo_si.links[i].data.avg_signal) {
12072 ret = os_snprintf(pos, end - pos,
12073 "AVG_RSSI=%d\n",
12074 mlo_si.links[i].data.avg_signal);
12075 if (os_snprintf_error(end - pos, ret))
12076 return -1;
12077 pos += ret;
12078 }
12079
12080 if (mlo_si.links[i].data.avg_beacon_signal) {
12081 ret = os_snprintf(
12082 pos, end - pos, "AVG_BEACON_RSSI=%d\n",
12083 mlo_si.links[i].data.avg_beacon_signal);
12084 if (os_snprintf_error(end - pos, ret))
12085 return -1;
12086 pos += ret;
12087 }
12088 }
12089
12090 return pos - buf;
12091 }
12092
12093
wpas_ctrl_iface_mlo_status(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)12094 static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s,
12095 char *buf, size_t buflen)
12096 {
12097 int ret, i;
12098 char *pos, *end;
12099
12100 if (!wpa_s->valid_links)
12101 return -1;
12102
12103 pos = buf;
12104 end = buf + buflen;
12105
12106 for_each_link(wpa_s->valid_links, i) {
12107 ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n"
12108 "ap_link_addr=" MACSTR
12109 "\nsta_link_addr=" MACSTR "\n",
12110 i, wpa_s->links[i].freq,
12111 MAC2STR(wpa_s->links[i].bssid),
12112 MAC2STR(wpa_s->links[i].addr));
12113 if (os_snprintf_error(end - pos, ret))
12114 return pos - buf;
12115 pos += ret;
12116 }
12117
12118 return pos - buf;
12119 }
12120
12121
12122 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_ml_probe(struct wpa_supplicant * wpa_s,char * cmd)12123 static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd)
12124 {
12125 char *token, *context = NULL;
12126 u8 bssid[ETH_ALEN];
12127 int mld_id = -1, link_id = -1;
12128 struct wpa_bss *bss;
12129 int *freqs;
12130
12131 os_memset(bssid, 0, sizeof(bssid));
12132
12133 while ((token = str_token(cmd, " ", &context))) {
12134 if (os_strncmp(token, "bssid=", 6) == 0) {
12135 if (hwaddr_aton(token + 6, bssid))
12136 return -1;
12137 } else if (os_strncmp(token, "mld_id=", 7) == 0) {
12138 mld_id = atoi(token + 7);
12139 } else if (os_strncmp(token, "link_id=", 8) == 0) {
12140 link_id = atoi(token + 8);
12141 }
12142 }
12143
12144 if (is_zero_ether_addr(bssid)) {
12145 wpa_printf(MSG_DEBUG,
12146 "MLD: Failed parsing ML probe request arguments");
12147 return -1;
12148 }
12149
12150 bss = wpa_bss_get_bssid(wpa_s, bssid);
12151 if (!bss) {
12152 wpa_printf(MSG_DEBUG,
12153 "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid));
12154 return -1;
12155 }
12156
12157 if (wpa_s->sched_scanning || wpa_s->scanning ||
12158 (wpa_s->wpa_state > WPA_SCANNING &&
12159 wpa_s->wpa_state != WPA_COMPLETED)) {
12160 wpa_printf(MSG_DEBUG,
12161 "MLO: Ongoing scan: Reject ML probe request");
12162 return -1;
12163 }
12164
12165 freqs = os_malloc(sizeof(int) * 2);
12166 if (!freqs)
12167 return -1;
12168
12169 freqs[0] = bss->freq;
12170 freqs[1] = 0;
12171
12172 wpa_s->manual_scan_passive = 0;
12173 wpa_s->manual_scan_use_id = 0;
12174 wpa_s->manual_scan_only_new = 0;
12175 wpa_s->scan_id_count = 0;
12176 wpa_s->scan_res_handler = scan_only_handler;
12177 os_free(wpa_s->manual_scan_freqs);
12178 wpa_s->manual_scan_freqs = freqs;
12179
12180 os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN);
12181 wpa_s->ml_probe_mld_id = mld_id;
12182 if (link_id >= 0)
12183 wpa_s->ml_probe_links = BIT(link_id);
12184
12185 wpa_s->normal_scans = 0;
12186 wpa_s->scan_req = MANUAL_SCAN_REQ;
12187 wpa_s->after_wps = 0;
12188 wpa_s->known_wps_freq = 0;
12189 wpa_supplicant_req_scan(wpa_s, 0, 0);
12190
12191 return 0;
12192 }
12193 #endif /* CONFIG_TESTING_OPTIONS */
12194
12195
12196 #ifdef CONFIG_NAN_USD
12197
wpas_ctrl_nan_publish(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)12198 static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
12199 char *buf, size_t buflen)
12200 {
12201 char *token, *context = NULL;
12202 int publish_id;
12203 struct nan_publish_params params;
12204 const char *service_name = NULL;
12205 struct wpabuf *ssi = NULL;
12206 int ret = -1;
12207 enum nan_service_protocol_type srv_proto_type = 0;
12208 int *freq_list = NULL;
12209
12210 os_memset(¶ms, 0, sizeof(params));
12211 /* USD shall use both solicited and unsolicited transmissions */
12212 params.unsolicited = true;
12213 params.solicited = true;
12214 /* USD shall require FSD without GAS */
12215 params.fsd = true;
12216 params.freq = NAN_USD_DEFAULT_FREQ;
12217
12218 while ((token = str_token(cmd, " ", &context))) {
12219 if (os_strncmp(token, "service_name=", 13) == 0) {
12220 service_name = token + 13;
12221 continue;
12222 }
12223
12224 if (os_strncmp(token, "ttl=", 4) == 0) {
12225 params.ttl = atoi(token + 4);
12226 continue;
12227 }
12228
12229 if (os_strncmp(token, "freq=", 5) == 0) {
12230 params.freq = atoi(token + 5);
12231 continue;
12232 }
12233
12234 if (os_strncmp(token, "freq_list=", 10) == 0) {
12235 char *pos = token + 10;
12236
12237 if (os_strcmp(pos, "all") == 0) {
12238 os_free(freq_list);
12239 freq_list = wpas_nan_usd_all_freqs(wpa_s);
12240 params.freq_list = freq_list;
12241 continue;
12242 }
12243
12244 while (pos && pos[0]) {
12245 int_array_add_unique(&freq_list, atoi(pos));
12246 pos = os_strchr(pos, ',');
12247 if (pos)
12248 pos++;
12249 }
12250
12251 params.freq_list = freq_list;
12252 continue;
12253 }
12254
12255 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12256 srv_proto_type = atoi(token + 15);
12257 continue;
12258 }
12259
12260 if (os_strncmp(token, "ssi=", 4) == 0) {
12261 if (ssi)
12262 goto fail;
12263 ssi = wpabuf_parse_bin(token + 4);
12264 if (!ssi)
12265 goto fail;
12266 continue;
12267 }
12268
12269 if (os_strcmp(token, "solicited=0") == 0) {
12270 params.solicited = false;
12271 continue;
12272 }
12273
12274 if (os_strcmp(token, "unsolicited=0") == 0) {
12275 params.unsolicited = false;
12276 continue;
12277 }
12278
12279 if (os_strcmp(token, "fsd=0") == 0) {
12280 params.fsd = false;
12281 continue;
12282 }
12283
12284 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
12285 token);
12286 goto fail;
12287 }
12288
12289 publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
12290 ssi, ¶ms);
12291 if (publish_id > 0)
12292 ret = os_snprintf(buf, buflen, "%d", publish_id);
12293 fail:
12294 wpabuf_free(ssi);
12295 os_free(freq_list);
12296 return ret;
12297 }
12298
12299
wpas_ctrl_nan_cancel_publish(struct wpa_supplicant * wpa_s,char * cmd)12300 static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
12301 char *cmd)
12302 {
12303 char *token, *context = NULL;
12304 int publish_id = 0;
12305
12306 while ((token = str_token(cmd, " ", &context))) {
12307 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12308 continue;
12309 wpa_printf(MSG_INFO,
12310 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
12311 token);
12312 return -1;
12313 }
12314
12315 if (publish_id <= 0) {
12316 wpa_printf(MSG_INFO,
12317 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
12318 return -1;
12319 }
12320
12321 wpas_nan_usd_cancel_publish(wpa_s, publish_id);
12322 return 0;
12323 }
12324
12325
wpas_ctrl_nan_update_publish(struct wpa_supplicant * wpa_s,char * cmd)12326 static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
12327 char *cmd)
12328 {
12329 char *token, *context = NULL;
12330 int publish_id = 0;
12331 struct wpabuf *ssi = NULL;
12332 int ret = -1;
12333
12334 while ((token = str_token(cmd, " ", &context))) {
12335 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12336 continue;
12337 if (os_strncmp(token, "ssi=", 4) == 0) {
12338 if (ssi)
12339 goto fail;
12340 ssi = wpabuf_parse_bin(token + 4);
12341 if (!ssi)
12342 goto fail;
12343 continue;
12344 }
12345 wpa_printf(MSG_INFO,
12346 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
12347 token);
12348 goto fail;
12349 }
12350
12351 if (publish_id <= 0) {
12352 wpa_printf(MSG_INFO,
12353 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
12354 goto fail;
12355 }
12356
12357 ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
12358 fail:
12359 wpabuf_free(ssi);
12360 return ret;
12361 }
12362
12363
wpas_ctrl_nan_subscribe(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)12364 static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
12365 char *buf, size_t buflen)
12366 {
12367 char *token, *context = NULL;
12368 int subscribe_id;
12369 struct nan_subscribe_params params;
12370 const char *service_name = NULL;
12371 struct wpabuf *ssi = NULL;
12372 int ret = -1;
12373 enum nan_service_protocol_type srv_proto_type = 0;
12374
12375 os_memset(¶ms, 0, sizeof(params));
12376 params.freq = NAN_USD_DEFAULT_FREQ;
12377
12378 while ((token = str_token(cmd, " ", &context))) {
12379 if (os_strncmp(token, "service_name=", 13) == 0) {
12380 service_name = token + 13;
12381 continue;
12382 }
12383
12384 if (os_strcmp(token, "active=1") == 0) {
12385 params.active = true;
12386 continue;
12387 }
12388
12389 if (os_strncmp(token, "ttl=", 4) == 0) {
12390 params.ttl = atoi(token + 4);
12391 continue;
12392 }
12393
12394 if (os_strncmp(token, "freq=", 5) == 0) {
12395 params.freq = atoi(token + 5);
12396 continue;
12397 }
12398
12399 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12400 srv_proto_type = atoi(token + 15);
12401 continue;
12402 }
12403
12404 if (os_strncmp(token, "ssi=", 4) == 0) {
12405 if (ssi)
12406 goto fail;
12407 ssi = wpabuf_parse_bin(token + 4);
12408 if (!ssi)
12409 goto fail;
12410 continue;
12411 }
12412
12413 wpa_printf(MSG_INFO,
12414 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
12415 token);
12416 goto fail;
12417 }
12418
12419 subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
12420 srv_proto_type, ssi,
12421 ¶ms);
12422 if (subscribe_id > 0)
12423 ret = os_snprintf(buf, buflen, "%d", subscribe_id);
12424 fail:
12425 wpabuf_free(ssi);
12426 return ret;
12427 }
12428
12429
wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant * wpa_s,char * cmd)12430 static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
12431 char *cmd)
12432 {
12433 char *token, *context = NULL;
12434 int subscribe_id = 0;
12435
12436 while ((token = str_token(cmd, " ", &context))) {
12437 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
12438 continue;
12439 wpa_printf(MSG_INFO,
12440 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
12441 token);
12442 return -1;
12443 }
12444
12445 if (subscribe_id <= 0) {
12446 wpa_printf(MSG_INFO,
12447 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
12448 return -1;
12449 }
12450
12451 wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
12452 return 0;
12453 }
12454
12455
wpas_ctrl_nan_transmit(struct wpa_supplicant * wpa_s,char * cmd)12456 static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
12457 {
12458 char *token, *context = NULL;
12459 int handle = 0;
12460 int req_instance_id = 0;
12461 struct wpabuf *ssi = NULL;
12462 u8 peer_addr[ETH_ALEN];
12463 int ret = -1;
12464
12465 os_memset(peer_addr, 0, ETH_ALEN);
12466
12467 while ((token = str_token(cmd, " ", &context))) {
12468 if (sscanf(token, "handle=%i", &handle) == 1)
12469 continue;
12470
12471 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
12472 continue;
12473
12474 if (os_strncmp(token, "address=", 8) == 0) {
12475 if (hwaddr_aton(token + 8, peer_addr) < 0)
12476 return -1;
12477 continue;
12478 }
12479
12480 if (os_strncmp(token, "ssi=", 4) == 0) {
12481 if (ssi)
12482 goto fail;
12483 ssi = wpabuf_parse_bin(token + 4);
12484 if (!ssi)
12485 goto fail;
12486 continue;
12487 }
12488
12489 wpa_printf(MSG_INFO,
12490 "CTRL: Invalid NAN_TRANSMIT parameter: %s",
12491 token);
12492 goto fail;
12493 }
12494
12495 if (handle <= 0) {
12496 wpa_printf(MSG_INFO,
12497 "CTRL: Invalid or missing NAN_TRANSMIT handle");
12498 goto fail;
12499 }
12500
12501 if (is_zero_ether_addr(peer_addr)) {
12502 wpa_printf(MSG_INFO,
12503 "CTRL: Invalid or missing NAN_TRANSMIT address");
12504 goto fail;
12505 }
12506
12507 ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
12508 req_instance_id);
12509 fail:
12510 wpabuf_free(ssi);
12511 return ret;
12512 }
12513
12514 #endif /* CONFIG_NAN_USD */
12515
12516
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)12517 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
12518 char *buf, size_t *resp_len)
12519 {
12520 static char reply[1024];
12521 const int reply_size = sizeof(reply);
12522 int reply_len;
12523
12524 os_memset(reply, 0, reply_size);
12525
12526 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
12527 os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
12528 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
12529 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12530 if (wpa_debug_show_keys)
12531 wpa_dbg(wpa_s, MSG_DEBUG,
12532 "Control interface command '%s'", buf);
12533 else
12534 wpa_dbg(wpa_s, MSG_DEBUG,
12535 "Control interface command '%s [REMOVED]'",
12536 os_strncmp(buf, WPA_CTRL_RSP,
12537 os_strlen(WPA_CTRL_RSP)) == 0 ?
12538 WPA_CTRL_RSP :
12539 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
12540 "SET_NETWORK" : "key-add"));
12541 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
12542 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
12543 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
12544 (const u8 *) buf, os_strlen(buf));
12545 } else {
12546 wpa_dbg(wpa_s, wpas_ctrl_cmd_debug_level(buf), "Control interface command '%s'", buf);
12547 }
12548
12549 os_memcpy(reply, "OK\n", 3);
12550 reply_len = 3;
12551
12552 if (os_strcmp(buf, "PING") == 0) {
12553 os_memcpy(reply, "PONG\n", 5);
12554 reply_len = 5;
12555 } else if (os_strcmp(buf, "IFNAME") == 0) {
12556 reply_len = os_strlen(wpa_s->ifname);
12557 os_memcpy(reply, wpa_s->ifname, reply_len);
12558 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
12559 if (wpa_debug_reopen_file() < 0)
12560 reply_len = -1;
12561 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
12562 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
12563 } else if (os_strcmp(buf, "MIB") == 0) {
12564 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
12565 if (reply_len >= 0) {
12566 reply_len += eapol_sm_get_mib(wpa_s->eapol,
12567 reply + reply_len,
12568 reply_size - reply_len);
12569 #ifdef CONFIG_MACSEC
12570 reply_len += ieee802_1x_kay_get_mib(
12571 wpa_s->kay, reply + reply_len,
12572 reply_size - reply_len);
12573 #endif /* CONFIG_MACSEC */
12574 }
12575 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
12576 reply_len = wpa_supplicant_ctrl_iface_status(
12577 wpa_s, buf + 6, reply, reply_size);
12578 } else if (os_strcmp(buf, "PMKSA") == 0) {
12579 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
12580 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
12581 wpas_ctrl_iface_pmksa_flush(wpa_s);
12582 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
12583 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
12584 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
12585 reply, reply_size);
12586 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
12587 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
12588 reply_len = -1;
12589 #ifdef CONFIG_MESH
12590 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
12591 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
12592 reply, reply_size);
12593 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12594 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
12595 reply_len = -1;
12596 #endif /* CONFIG_MESH */
12597 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
12598 } else if (os_strncmp(buf, "SET ", 4) == 0) {
12599 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
12600 reply_len = -1;
12601 } else if (os_strncmp(buf, "DUMP", 4) == 0) {
12602 reply_len = wpa_config_dump_values(wpa_s->conf,
12603 reply, reply_size);
12604 } else if (os_strncmp(buf, "GET ", 4) == 0) {
12605 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
12606 reply, reply_size);
12607 } else if (os_strcmp(buf, "LOGON") == 0) {
12608 eapol_sm_notify_logoff(wpa_s->eapol, false);
12609 } else if (os_strcmp(buf, "LOGOFF") == 0) {
12610 eapol_sm_notify_logoff(wpa_s->eapol, true);
12611 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
12612 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12613 reply_len = -1;
12614 else
12615 wpas_request_connection(wpa_s);
12616 } else if (os_strcmp(buf, "REATTACH") == 0) {
12617 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
12618 !wpa_s->current_ssid)
12619 reply_len = -1;
12620 else {
12621 wpa_s->reattach = 1;
12622 wpas_request_connection(wpa_s);
12623 }
12624 } else if (os_strcmp(buf, "RECONNECT") == 0) {
12625 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12626 reply_len = -1;
12627 else if (wpa_s->disconnected)
12628 wpas_request_connection(wpa_s);
12629 #ifdef IEEE8021X_EAPOL
12630 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
12631 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
12632 reply_len = -1;
12633 #endif /* IEEE8021X_EAPOL */
12634 #ifdef CONFIG_IEEE80211R
12635 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
12636 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
12637 reply_len = -1;
12638 #endif /* CONFIG_IEEE80211R */
12639 #ifdef CONFIG_WPS
12640 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
12641 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
12642 if (res == -2) {
12643 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12644 reply_len = 17;
12645 } else if (res)
12646 reply_len = -1;
12647 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
12648 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
12649 if (res == -2) {
12650 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12651 reply_len = 17;
12652 } else if (res)
12653 reply_len = -1;
12654 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
12655 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
12656 reply,
12657 reply_size);
12658 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
12659 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
12660 wpa_s, buf + 14, reply, reply_size);
12661 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
12662 if (wpas_wps_cancel(wpa_s))
12663 reply_len = -1;
12664 #ifdef CONFIG_WPS_NFC
12665 } else if (os_strcmp(buf, "WPS_NFC") == 0) {
12666 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
12667 reply_len = -1;
12668 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
12669 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
12670 reply_len = -1;
12671 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
12672 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
12673 wpa_s, buf + 21, reply, reply_size);
12674 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
12675 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
12676 wpa_s, buf + 14, reply, reply_size);
12677 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
12678 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
12679 buf + 17))
12680 reply_len = -1;
12681 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
12682 reply_len = wpas_ctrl_nfc_get_handover_req(
12683 wpa_s, buf + 21, reply, reply_size);
12684 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
12685 reply_len = wpas_ctrl_nfc_get_handover_sel(
12686 wpa_s, buf + 21, reply, reply_size);
12687 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
12688 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
12689 reply_len = -1;
12690 #endif /* CONFIG_WPS_NFC */
12691 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
12692 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
12693 reply_len = -1;
12694 #ifdef CONFIG_AP
12695 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
12696 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
12697 wpa_s, buf + 11, reply, reply_size);
12698 #endif /* CONFIG_AP */
12699 #ifdef CONFIG_WPS_ER
12700 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
12701 if (wpas_wps_er_start(wpa_s, NULL))
12702 reply_len = -1;
12703 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
12704 if (wpas_wps_er_start(wpa_s, buf + 13))
12705 reply_len = -1;
12706 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
12707 wpas_wps_er_stop(wpa_s);
12708 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
12709 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
12710 reply_len = -1;
12711 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
12712 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
12713 if (ret == -2) {
12714 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12715 reply_len = 17;
12716 } else if (ret == -3) {
12717 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
12718 reply_len = 18;
12719 } else if (ret == -4) {
12720 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
12721 reply_len = 20;
12722 } else if (ret)
12723 reply_len = -1;
12724 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
12725 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
12726 reply_len = -1;
12727 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
12728 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
12729 buf + 18))
12730 reply_len = -1;
12731 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
12732 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
12733 reply_len = -1;
12734 #ifdef CONFIG_WPS_NFC
12735 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
12736 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
12737 wpa_s, buf + 24, reply, reply_size);
12738 #endif /* CONFIG_WPS_NFC */
12739 #endif /* CONFIG_WPS_ER */
12740 #endif /* CONFIG_WPS */
12741 #ifdef CONFIG_IBSS_RSN
12742 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
12743 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
12744 reply_len = -1;
12745 #endif /* CONFIG_IBSS_RSN */
12746 #ifdef CONFIG_MESH
12747 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
12748 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12749 wpa_s, buf + 19, reply, reply_size);
12750 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
12751 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12752 wpa_s, "", reply, reply_size);
12753 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
12754 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
12755 reply_len = -1;
12756 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
12757 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
12758 buf + 18))
12759 reply_len = -1;
12760 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
12761 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
12762 reply_len = -1;
12763 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
12764 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
12765 reply_len = -1;
12766 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
12767 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
12768 reply_len = -1;
12769 #endif /* CONFIG_MESH */
12770 #ifdef CONFIG_P2P
12771 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
12772 if (p2p_ctrl_find(wpa_s, buf + 8))
12773 reply_len = -1;
12774 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
12775 if (p2p_ctrl_find(wpa_s, ""))
12776 reply_len = -1;
12777 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
12778 wpas_p2p_stop_find(wpa_s);
12779 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
12780 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
12781 reply_len = -1;
12782 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
12783 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
12784 reply_len = -1;
12785 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
12786 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
12787 reply_size);
12788 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
12789 if (p2p_ctrl_listen(wpa_s, buf + 11))
12790 reply_len = -1;
12791 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
12792 if (p2p_ctrl_listen(wpa_s, ""))
12793 reply_len = -1;
12794 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
12795 if (wpas_p2p_group_remove(wpa_s, buf + 17))
12796 reply_len = -1;
12797 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
12798 if (p2p_ctrl_group_add(wpa_s, ""))
12799 reply_len = -1;
12800 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
12801 if (p2p_ctrl_group_add(wpa_s, buf + 14))
12802 reply_len = -1;
12803 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
12804 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
12805 reply_size);
12806 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
12807 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
12808 reply_len = -1;
12809 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
12810 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
12811 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
12812 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
12813 reply_size);
12814 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
12815 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
12816 reply_len = -1;
12817 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
12818 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
12819 reply_len = -1;
12820 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
12821 wpas_p2p_sd_service_update(wpa_s);
12822 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
12823 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
12824 reply_len = -1;
12825 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
12826 wpas_p2p_service_flush(wpa_s);
12827 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
12828 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
12829 reply_len = -1;
12830 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
12831 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
12832 reply_len = -1;
12833 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
12834 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
12835 reply_len = -1;
12836 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
12837 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
12838 reply_len = -1;
12839 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
12840 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
12841 reply_len = -1;
12842 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
12843 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
12844 reply_size);
12845 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
12846 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
12847 reply_len = -1;
12848 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
12849 p2p_ctrl_flush(wpa_s);
12850 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
12851 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
12852 reply_len = -1;
12853 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
12854 if (wpas_p2p_cancel(wpa_s))
12855 reply_len = -1;
12856 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
12857 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
12858 reply_len = -1;
12859 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
12860 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
12861 reply_len = -1;
12862 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
12863 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
12864 reply_len = -1;
12865 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
12866 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
12867 reply_len = -1;
12868 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
12869 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
12870 reply_len = -1;
12871 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
12872 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
12873 reply_len = -1;
12874 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
12875 if (wpas_p2p_lo_stop(wpa_s))
12876 reply_len = -1;
12877 #endif /* CONFIG_P2P */
12878 #ifdef CONFIG_WIFI_DISPLAY
12879 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
12880 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
12881 reply_len = -1;
12882 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
12883 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
12884 reply, reply_size);
12885 #endif /* CONFIG_WIFI_DISPLAY */
12886 #ifdef CONFIG_INTERWORKING
12887 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
12888 if (interworking_fetch_anqp(wpa_s) < 0)
12889 reply_len = -1;
12890 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
12891 interworking_stop_fetch_anqp(wpa_s);
12892 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
12893 if (ctrl_interworking_select(wpa_s, NULL) < 0)
12894 reply_len = -1;
12895 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
12896 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
12897 reply_len = -1;
12898 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
12899 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
12900 reply_len = -1;
12901 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
12902 int id;
12903
12904 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
12905 if (id < 0)
12906 reply_len = -1;
12907 else {
12908 reply_len = os_snprintf(reply, reply_size, "%d\n", id);
12909 if (os_snprintf_error(reply_size, reply_len))
12910 reply_len = -1;
12911 }
12912 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
12913 if (get_anqp(wpa_s, buf + 9) < 0)
12914 reply_len = -1;
12915 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
12916 if (gas_request(wpa_s, buf + 12) < 0)
12917 reply_len = -1;
12918 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
12919 reply_len = gas_response_get(wpa_s, buf + 17, reply,
12920 reply_size);
12921 #endif /* CONFIG_INTERWORKING */
12922 #ifdef CONFIG_HS20
12923 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
12924 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
12925 reply_len = -1;
12926 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
12927 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
12928 reply_len = -1;
12929 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
12930 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
12931 reply_len = -1;
12932 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
12933 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
12934 reply_len = -1;
12935 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
12936 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
12937 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
12938 if (del_hs20_icon(wpa_s, buf + 14) < 0)
12939 reply_len = -1;
12940 } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
12941 if (hs20_fetch_osu(wpa_s, 0) < 0)
12942 reply_len = -1;
12943 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
12944 if (hs20_fetch_osu(wpa_s, 1) < 0)
12945 reply_len = -1;
12946 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
12947 hs20_cancel_fetch_osu(wpa_s);
12948 #endif /* CONFIG_HS20 */
12949 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
12950 {
12951 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
12952 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
12953 reply_len = -1;
12954 else {
12955 /*
12956 * Notify response from timeout to allow the control
12957 * interface response to be sent first.
12958 */
12959 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
12960 wpa_s, NULL);
12961 }
12962 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
12963 if (wpa_supplicant_reload_configuration(wpa_s))
12964 reply_len = -1;
12965 } else if (os_strcmp(buf, "TERMINATE") == 0) {
12966 wpa_supplicant_terminate_proc(wpa_s->global);
12967 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
12968 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
12969 reply_len = -1;
12970 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
12971 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
12972 wpa_s, buf + 12, reply, reply_size);
12973 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
12974 /* deprecated backwards compatibility alias for BSSID_IGNORE */
12975 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
12976 wpa_s, buf + 9, reply, reply_size);
12977 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
12978 reply_len = wpa_supplicant_ctrl_iface_log_level(
12979 wpa_s, buf + 9, reply, reply_size);
12980 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
12981 reply_len = wpa_supplicant_ctrl_iface_list_networks(
12982 wpa_s, buf + 14, reply, reply_size);
12983 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
12984 reply_len = wpa_supplicant_ctrl_iface_list_networks(
12985 wpa_s, NULL, reply, reply_size);
12986 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
12987 wpas_request_disconnection(wpa_s);
12988 } else if (os_strcmp(buf, "SCAN") == 0) {
12989 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
12990 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
12991 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
12992 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
12993 reply_len = wpa_supplicant_ctrl_iface_scan_results(
12994 wpa_s, reply, reply_size);
12995 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
12996 if (wpas_abort_ongoing_scan(wpa_s) < 0)
12997 reply_len = -1;
12998 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
12999 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
13000 reply_len = -1;
13001 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
13002 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
13003 reply_len = -1;
13004 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
13005 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
13006 reply_len = -1;
13007 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
13008 reply_len = wpa_supplicant_ctrl_iface_add_network(
13009 wpa_s, reply, reply_size);
13010 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
13011 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
13012 reply_len = -1;
13013 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
13014 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
13015 reply_len = -1;
13016 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
13017 reply_len = wpa_supplicant_ctrl_iface_get_network(
13018 wpa_s, buf + 12, reply, reply_size);
13019 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
13020 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
13021 wpa_s))
13022 reply_len = -1;
13023 } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
13024 reply_len = wpa_supplicant_ctrl_iface_list_creds(
13025 wpa_s, reply, reply_size);
13026 } else if (os_strcmp(buf, "ADD_CRED") == 0) {
13027 reply_len = wpa_supplicant_ctrl_iface_add_cred(
13028 wpa_s, reply, reply_size);
13029 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
13030 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
13031 reply_len = -1;
13032 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
13033 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
13034 reply_len = -1;
13035 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
13036 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
13037 reply,
13038 reply_size);
13039 #ifndef CONFIG_NO_CONFIG_WRITE
13040 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
13041 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
13042 reply_len = -1;
13043 #endif /* CONFIG_NO_CONFIG_WRITE */
13044 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
13045 reply_len = wpa_supplicant_ctrl_iface_get_capability(
13046 wpa_s, buf + 15, reply, reply_size);
13047 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
13048 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
13049 reply_len = -1;
13050 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
13051 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
13052 reply_len = -1;
13053 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
13054 reply_len = wpa_supplicant_global_iface_list(
13055 wpa_s->global, reply, reply_size);
13056 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
13057 reply_len = wpa_supplicant_global_iface_interfaces(
13058 wpa_s->global, buf + 10, reply, reply_size);
13059 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
13060 reply_len = wpa_supplicant_ctrl_iface_bss(
13061 wpa_s, buf + 4, reply, reply_size);
13062 #ifdef CONFIG_AP
13063 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
13064 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13065 } else if (os_strncmp(buf, "STA ", 4) == 0) {
13066 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
13067 reply_size);
13068 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13069 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13070 reply_size);
13071 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13072 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13073 reply_len = -1;
13074 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13075 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13076 reply_len = -1;
13077 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13078 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13079 reply_len = -1;
13080 } else if (os_strcmp(buf, "STOP_AP") == 0) {
13081 if (wpas_ap_stop_ap(wpa_s))
13082 reply_len = -1;
13083 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
13084 if (wpas_ap_update_beacon(wpa_s))
13085 reply_len = -1;
13086 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
13087 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
13088 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13089 DENY_UNLESS_ACCEPTED,
13090 buf + 19) ||
13091 ap_ctrl_iface_set_acl(wpa_s))
13092 reply_len = -1;
13093 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
13094 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13095 DENY_UNLESS_ACCEPTED,
13096 buf + 19) ||
13097 ap_ctrl_iface_set_acl(wpa_s) ||
13098 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13099 reply_len = -1;
13100 } else if (os_strcmp(buf + 11, "SHOW") == 0) {
13101 reply_len = ap_ctrl_iface_acl_show_mac(
13102 wpa_s, DENY_UNLESS_ACCEPTED,
13103 reply, reply_size);
13104 } else if (os_strcmp(buf + 11, "CLEAR") == 0) {
13105 ap_ctrl_iface_acl_clear_list(wpa_s,
13106 DENY_UNLESS_ACCEPTED);
13107 if (ap_ctrl_iface_set_acl(wpa_s) ||
13108 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13109 reply_len = -1;
13110 } else {
13111 reply_len = -1;
13112 }
13113 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
13114 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
13115 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13116 ACCEPT_UNLESS_DENIED,
13117 buf + 17) ||
13118 ap_ctrl_iface_set_acl(wpa_s) ||
13119 ap_ctrl_iface_disassoc_deny_mac(wpa_s))
13120 reply_len = -1;
13121 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
13122 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13123 ACCEPT_UNLESS_DENIED,
13124 buf + 17) ||
13125 ap_ctrl_iface_set_acl(wpa_s))
13126 reply_len = -1;
13127 } else if (os_strcmp(buf + 9, "SHOW") == 0) {
13128 reply_len = ap_ctrl_iface_acl_show_mac(
13129 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size);
13130 } else if (os_strcmp(buf + 9, "CLEAR") == 0) {
13131 ap_ctrl_iface_acl_clear_list(wpa_s,
13132 ACCEPT_UNLESS_DENIED);
13133 if (ap_ctrl_iface_set_acl(wpa_s))
13134 reply_len = -1;
13135 } else {
13136 reply_len = -1;
13137 }
13138 #endif /* CONFIG_AP */
13139 } else if (os_strcmp(buf, "SUSPEND") == 0) {
13140 wpas_notify_suspend(wpa_s->global);
13141 } else if (os_strcmp(buf, "RESUME") == 0) {
13142 wpas_notify_resume(wpa_s->global);
13143 #ifdef CONFIG_TESTING_OPTIONS
13144 } else if (os_strcmp(buf, "DROP_SA") == 0) {
13145 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
13146 #endif /* CONFIG_TESTING_OPTIONS */
13147 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
13148 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
13149 reply_len = -1;
13150 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
13151 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
13152 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
13153 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
13154 reply_len = -1;
13155 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
13156 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
13157 buf + 17))
13158 reply_len = -1;
13159 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
13160 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
13161 #ifdef CONFIG_TDLS
13162 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
13163 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
13164 reply_len = -1;
13165 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
13166 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
13167 reply_len = -1;
13168 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
13169 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
13170 reply_len = -1;
13171 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
13172 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
13173 buf + 17))
13174 reply_len = -1;
13175 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
13176 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
13177 buf + 24))
13178 reply_len = -1;
13179 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
13180 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
13181 wpa_s, buf + 17, reply, reply_size);
13182 #endif /* CONFIG_TDLS */
13183 #ifndef CONFIG_NO_WMM_AC
13184 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
13185 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
13186 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
13187 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
13188 reply_len = -1;
13189 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
13190 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
13191 reply_len = -1;
13192 #endif /* CONFIG_NO_WMM_AC */
13193 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
13194 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
13195 reply_size);
13196 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
13197 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
13198 reply_len = -1;
13199 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
13200 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
13201 reply_size);
13202 #ifdef CONFIG_AUTOSCAN
13203 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
13204 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
13205 reply_len = -1;
13206 #endif /* CONFIG_AUTOSCAN */
13207 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
13208 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
13209 reply_size);
13210 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
13211 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
13212 reply_size);
13213 #ifdef ANDROID
13214 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
13215 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
13216 reply_size);
13217 #endif /* ANDROID */
13218 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
13219 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
13220 reply_size);
13221 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
13222 pmksa_cache_clear_current(wpa_s->wpa);
13223 eapol_sm_request_reauth(wpa_s->eapol);
13224 #ifdef CONFIG_WNM
13225 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
13226 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
13227 reply_len = -1;
13228 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
13229 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
13230 reply_len = -1;
13231 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
13232 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13233 reply_len = -1;
13234 #endif /* CONFIG_WNM */
13235 #ifdef CONFIG_WNM_AP
13236 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13237 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13238 reply_len = -1;
13239 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
13240 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13))
13241 reply_len = -1;
13242 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13243 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13244 reply_len = -1;
13245 #endif /* CONFIG_WNM_AP */
13246 } else if (os_strcmp(buf, "FLUSH") == 0) {
13247 wpa_supplicant_ctrl_iface_flush(wpa_s);
13248 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13249 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
13250 reply_size);
13251 #ifdef CONFIG_TESTING_OPTIONS
13252 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
13253 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
13254 reply_len = -1;
13255 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
13256 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
13257 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
13258 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
13259 reply_len = -1;
13260 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
13261 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
13262 reply_len = -1;
13263 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
13264 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
13265 reply_len = -1;
13266 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
13267 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
13268 reply_len = -1;
13269 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
13270 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
13271 reply_len = -1;
13272 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
13273 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
13274 reply_len = -1;
13275 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
13276 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
13277 reply_len = -1;
13278 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
13279 if (testing_set_fail_pattern(true, buf + 16) < 0)
13280 reply_len = -1;
13281 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
13282 reply_len = testing_get_fail_pattern(true, reply, reply_size);
13283 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
13284 if (testing_set_fail_pattern(false, buf + 10) < 0)
13285 reply_len = -1;
13286 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
13287 reply_len = testing_get_fail_pattern(false, reply, reply_size);
13288 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
13289 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
13290 reply_len = -1;
13291 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
13292 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
13293 reply_len = -1;
13294 } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
13295 if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
13296 reply_len = -1;
13297 } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
13298 if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
13299 reply_len = -1;
13300 } else if (os_strcmp(buf, "RESET_PN") == 0) {
13301 if (wpas_ctrl_reset_pn(wpa_s) < 0)
13302 reply_len = -1;
13303 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
13304 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
13305 reply_len = -1;
13306 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
13307 if (wpas_ctrl_resend_assoc(wpa_s) < 0)
13308 reply_len = -1;
13309 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
13310 sme_event_unprot_disconnect(
13311 wpa_s, wpa_s->bssid, NULL,
13312 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13313 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
13314 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
13315 reply_len = -1;
13316 } else if (os_strcmp(buf, "TWT_SETUP") == 0) {
13317 if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
13318 reply_len = -1;
13319 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
13320 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
13321 reply_len = -1;
13322 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
13323 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
13324 reply_len = -1;
13325 } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
13326 if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
13327 reply_len = -1;
13328 #endif /* CONFIG_TESTING_OPTIONS */
13329 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
13330 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
13331 reply_len = -1;
13332 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
13333 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
13334 reply_size);
13335 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
13336 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
13337 reply_len = -1;
13338 #ifndef CONFIG_NO_RRM
13339 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
13340 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
13341 reply_len = -1;
13342 #endif /* CONFIG_NO_RRM */
13343 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
13344 wpas_ctrl_iface_erp_flush(wpa_s);
13345 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
13346 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
13347 reply_len = -1;
13348 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
13349 reply_len = wpas_ctrl_iface_get_pref_freq_list(
13350 wpa_s, buf + 19, reply, reply_size);
13351 #ifdef CONFIG_FILS
13352 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
13353 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
13354 reply_len = -1;
13355 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
13356 wpas_flush_fils_hlp_req(wpa_s);
13357 #endif /* CONFIG_FILS */
13358 #ifdef CONFIG_DPP
13359 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
13360 int res;
13361
13362 res = wpas_dpp_qr_code(wpa_s, buf + 12);
13363 if (res < 0) {
13364 reply_len = -1;
13365 } else {
13366 reply_len = os_snprintf(reply, reply_size, "%d", res);
13367 if (os_snprintf_error(reply_size, reply_len))
13368 reply_len = -1;
13369 }
13370 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
13371 int res;
13372
13373 res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
13374 if (res < 0) {
13375 reply_len = -1;
13376 } else {
13377 reply_len = os_snprintf(reply, reply_size, "%d", res);
13378 if (os_snprintf_error(reply_size, reply_len))
13379 reply_len = -1;
13380 }
13381 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
13382 int res;
13383
13384 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
13385 if (res < 0) {
13386 reply_len = -1;
13387 } else {
13388 reply_len = os_snprintf(reply, reply_size, "%d", res);
13389 if (os_snprintf_error(reply_size, reply_len))
13390 reply_len = -1;
13391 }
13392 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
13393 int res;
13394
13395 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
13396 if (res < 0) {
13397 reply_len = -1;
13398 } else {
13399 reply_len = os_snprintf(reply, reply_size, "%d", res);
13400 if (os_snprintf_error(reply_size, reply_len))
13401 reply_len = -1;
13402 }
13403 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
13404 int res;
13405
13406 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
13407 if (res < 0) {
13408 reply_len = -1;
13409 } else {
13410 reply_len = os_snprintf(reply, reply_size, "%d", res);
13411 if (os_snprintf_error(reply_size, reply_len))
13412 reply_len = -1;
13413 }
13414 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
13415 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
13416 reply_len = -1;
13417 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
13418 const char *uri;
13419
13420 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
13421 if (!uri) {
13422 reply_len = -1;
13423 } else {
13424 reply_len = os_snprintf(reply, reply_size, "%s", uri);
13425 if (os_snprintf_error(reply_size, reply_len))
13426 reply_len = -1;
13427 }
13428 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
13429 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
13430 reply, reply_size);
13431 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
13432 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
13433 os_strchr(buf + 18, ' ')) < 0)
13434 reply_len = -1;
13435 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
13436 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
13437 reply_len = -1;
13438 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
13439 if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
13440 reply_len = -1;
13441 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
13442 wpas_dpp_stop(wpa_s);
13443 wpas_dpp_listen_stop(wpa_s);
13444 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
13445 int res;
13446
13447 res = dpp_configurator_add(wpa_s->dpp, buf + 20);
13448 if (res < 0) {
13449 reply_len = -1;
13450 } else {
13451 reply_len = os_snprintf(reply, reply_size, "%d", res);
13452 if (os_snprintf_error(reply_size, reply_len))
13453 reply_len = -1;
13454 }
13455 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
13456 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0)
13457 reply_len = -1;
13458 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
13459 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
13460 reply_len = -1;
13461 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
13462 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
13463 reply_len = -1;
13464 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
13465 reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
13466 atoi(buf + 25),
13467 reply, reply_size);
13468 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
13469 int res;
13470
13471 res = wpas_dpp_pkex_add(wpa_s, buf + 12);
13472 if (res < 0) {
13473 reply_len = -1;
13474 } else {
13475 reply_len = os_snprintf(reply, reply_size, "%d", res);
13476 if (os_snprintf_error(reply_size, reply_len))
13477 reply_len = -1;
13478 }
13479 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
13480 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
13481 reply_len = -1;
13482 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
13483 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
13484 reply_len = -1;
13485 #ifdef CONFIG_DPP2
13486 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
13487 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
13488 reply_len = -1;
13489 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
13490 if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
13491 reply_len = -1;
13492 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
13493 dpp_controller_stop(wpa_s->dpp);
13494 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
13495 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
13496 reply_len = -1;
13497 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
13498 wpas_dpp_chirp_stop(wpa_s);
13499 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
13500 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
13501 reply_len = -1;
13502 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
13503 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
13504 reply_len = -1;
13505 #endif /* CONFIG_DPP2 */
13506 #ifdef CONFIG_DPP3
13507 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
13508 if (wpas_dpp_push_button(wpa_s, NULL) < 0)
13509 reply_len = -1;
13510 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
13511 if (wpas_dpp_push_button(wpa_s, buf + 15) < 0)
13512 reply_len = -1;
13513 #endif /* CONFIG_DPP3 */
13514 #endif /* CONFIG_DPP */
13515 #ifdef CONFIG_NAN_USD
13516 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
13517 reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
13518 reply_size);
13519 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
13520 if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
13521 reply_len = -1;
13522 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
13523 if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
13524 reply_len = -1;
13525 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
13526 reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
13527 reply_size);
13528 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
13529 if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
13530 reply_len = -1;
13531 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
13532 if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
13533 reply_len = -1;
13534 #endif /* CONFIG_NAN_USD */
13535 #ifdef CONFIG_PASN
13536 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
13537 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
13538 reply_len = -1;
13539 } else if (os_strcmp(buf, "PASN_STOP") == 0) {
13540 wpas_pasn_auth_stop(wpa_s);
13541 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
13542 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
13543 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
13544 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
13545 reply_len = -1;
13546 #ifdef CONFIG_TESTING_OPTIONS
13547 } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
13548 if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
13549 reply_len = -1;
13550 #endif /* CONFIG_TESTING_OPTIONS */
13551 #endif /* CONFIG_PASN */
13552 #ifndef CONFIG_NO_ROBUST_AV
13553 } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
13554 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
13555 reply_len = -1;
13556 } else if (os_strncmp(buf, "SCS ", 4) == 0) {
13557 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
13558 reply_len = -1;
13559 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
13560 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
13561 reply_len = -1;
13562 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
13563 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
13564 reply_len = -1;
13565 #endif /* CONFIG_NO_ROBUST_AV */
13566 } else if (os_strcmp(buf, "MLO_STATUS") == 0) {
13567 reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
13568 reply_size);
13569 } else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) {
13570 reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply,
13571 reply_size);
13572 } else {
13573 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13574 reply_len = 16;
13575 }
13576
13577 if (reply_len < 0) {
13578 os_memcpy(reply, "FAIL\n", 5);
13579 reply_len = 5;
13580 }
13581
13582 *resp_len = reply_len;
13583 return reply;
13584 }
13585
13586
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)13587 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
13588 char *cmd)
13589 {
13590 struct wpa_interface iface;
13591 char *pos, *extra;
13592 struct wpa_supplicant *wpa_s;
13593 unsigned int create_iface = 0;
13594 u8 mac_addr[ETH_ALEN];
13595 enum wpa_driver_if_type type = WPA_IF_STATION;
13596
13597 /*
13598 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
13599 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
13600 */
13601 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
13602
13603 os_memset(&iface, 0, sizeof(iface));
13604
13605 do {
13606 iface.ifname = pos = cmd;
13607 pos = os_strchr(pos, '\t');
13608 if (pos)
13609 *pos++ = '\0';
13610 if (iface.ifname[0] == '\0')
13611 return -1;
13612 if (pos == NULL)
13613 break;
13614
13615 iface.confname = pos;
13616 pos = os_strchr(pos, '\t');
13617 if (pos)
13618 *pos++ = '\0';
13619 if (iface.confname[0] == '\0')
13620 iface.confname = NULL;
13621 if (pos == NULL)
13622 break;
13623
13624 iface.driver = pos;
13625 pos = os_strchr(pos, '\t');
13626 if (pos)
13627 *pos++ = '\0';
13628 if (iface.driver[0] == '\0')
13629 iface.driver = NULL;
13630 if (pos == NULL)
13631 break;
13632
13633 iface.ctrl_interface = pos;
13634 pos = os_strchr(pos, '\t');
13635 if (pos)
13636 *pos++ = '\0';
13637 if (iface.ctrl_interface[0] == '\0')
13638 iface.ctrl_interface = NULL;
13639 if (pos == NULL)
13640 break;
13641
13642 iface.driver_param = pos;
13643 pos = os_strchr(pos, '\t');
13644 if (pos)
13645 *pos++ = '\0';
13646 if (iface.driver_param[0] == '\0')
13647 iface.driver_param = NULL;
13648 if (pos == NULL)
13649 break;
13650
13651 iface.bridge_ifname = pos;
13652 pos = os_strchr(pos, '\t');
13653 if (pos)
13654 *pos++ = '\0';
13655 if (iface.bridge_ifname[0] == '\0')
13656 iface.bridge_ifname = NULL;
13657 if (pos == NULL)
13658 break;
13659
13660 extra = pos;
13661 pos = os_strchr(pos, '\t');
13662 if (pos)
13663 *pos++ = '\0';
13664 if (!extra[0])
13665 break;
13666
13667 if (os_strcmp(extra, "create") == 0) {
13668 create_iface = 1;
13669 if (!pos)
13670 break;
13671
13672 if (os_strcmp(pos, "sta") == 0) {
13673 type = WPA_IF_STATION;
13674 } else if (os_strcmp(pos, "ap") == 0) {
13675 type = WPA_IF_AP_BSS;
13676 } else {
13677 wpa_printf(MSG_DEBUG,
13678 "INTERFACE_ADD unsupported interface type: '%s'",
13679 pos);
13680 return -1;
13681 }
13682 } else {
13683 wpa_printf(MSG_DEBUG,
13684 "INTERFACE_ADD unsupported extra parameter: '%s'",
13685 extra);
13686 return -1;
13687 }
13688 } while (0);
13689
13690 if (create_iface) {
13691 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
13692 iface.ifname);
13693 if (!global->ifaces)
13694 return -1;
13695 if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
13696 NULL, NULL, NULL, mac_addr, NULL) < 0) {
13697 wpa_printf(MSG_ERROR,
13698 "CTRL_IFACE interface creation failed");
13699 return -1;
13700 }
13701
13702 wpa_printf(MSG_DEBUG,
13703 "CTRL_IFACE interface '%s' created with MAC addr: "
13704 MACSTR, iface.ifname, MAC2STR(mac_addr));
13705 }
13706
13707 if (wpa_supplicant_get_iface(global, iface.ifname))
13708 goto fail;
13709
13710 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
13711 if (!wpa_s)
13712 goto fail;
13713 wpa_s->added_vif = create_iface;
13714 return 0;
13715
13716 fail:
13717 if (create_iface) {
13718 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13719 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
13720 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
13721 }
13722 return -1;
13723 }
13724
13725
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)13726 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
13727 char *cmd)
13728 {
13729 struct wpa_supplicant *wpa_s;
13730 int ret;
13731 unsigned int delete_iface;
13732
13733 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
13734
13735 wpa_s = wpa_supplicant_get_iface(global, cmd);
13736 if (wpa_s == NULL)
13737 return -1;
13738 delete_iface = wpa_s->added_vif;
13739 ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
13740 if (!ret && delete_iface) {
13741 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
13742 cmd);
13743 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13744 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
13745 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
13746 }
13747 return ret;
13748 }
13749
13750
wpa_free_iface_info(struct wpa_interface_info * iface)13751 static void wpa_free_iface_info(struct wpa_interface_info *iface)
13752 {
13753 struct wpa_interface_info *prev;
13754
13755 while (iface) {
13756 prev = iface;
13757 iface = iface->next;
13758
13759 os_free(prev->ifname);
13760 os_free(prev->desc);
13761 os_free(prev);
13762 }
13763 }
13764
13765
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)13766 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
13767 char *buf, int len)
13768 {
13769 int i, res;
13770 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
13771 char *pos, *end;
13772
13773 for (i = 0; wpa_drivers[i]; i++) {
13774 const struct wpa_driver_ops *drv = wpa_drivers[i];
13775 if (drv->get_interfaces == NULL)
13776 continue;
13777 tmp = drv->get_interfaces(global->drv_priv[i]);
13778 if (tmp == NULL)
13779 continue;
13780
13781 if (last == NULL)
13782 iface = last = tmp;
13783 else
13784 last->next = tmp;
13785 while (last->next)
13786 last = last->next;
13787 }
13788
13789 pos = buf;
13790 end = buf + len;
13791 for (tmp = iface; tmp; tmp = tmp->next) {
13792 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
13793 tmp->drv_name, tmp->ifname,
13794 tmp->desc ? tmp->desc : "");
13795 if (os_snprintf_error(end - pos, res)) {
13796 *pos = '\0';
13797 break;
13798 }
13799 pos += res;
13800 }
13801
13802 wpa_free_iface_info(iface);
13803
13804 return pos - buf;
13805 }
13806
13807
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,const char * input,char * buf,int len)13808 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
13809 const char *input,
13810 char *buf, int len)
13811 {
13812 int res;
13813 char *pos, *end;
13814 struct wpa_supplicant *wpa_s;
13815 int show_ctrl = 0;
13816
13817 if (input)
13818 show_ctrl = !!os_strstr(input, "ctrl");
13819
13820 wpa_s = global->ifaces;
13821 pos = buf;
13822 end = buf + len;
13823
13824 while (wpa_s) {
13825 if (show_ctrl)
13826 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
13827 wpa_s->ifname,
13828 wpa_s->conf->ctrl_interface ?
13829 wpa_s->conf->ctrl_interface : "N/A");
13830 else
13831 res = os_snprintf(pos, end - pos, "%s\n",
13832 wpa_s->ifname);
13833
13834 if (os_snprintf_error(end - pos, res)) {
13835 *pos = '\0';
13836 break;
13837 }
13838 pos += res;
13839 wpa_s = wpa_s->next;
13840 }
13841 return pos - buf;
13842 }
13843
13844
wpas_global_ctrl_iface_ifname(struct wpa_global * global,const char * ifname,char * cmd,size_t * resp_len)13845 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
13846 const char *ifname,
13847 char *cmd, size_t *resp_len)
13848 {
13849 struct wpa_supplicant *wpa_s;
13850
13851 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13852 if (os_strcmp(ifname, wpa_s->ifname) == 0)
13853 break;
13854 }
13855
13856 if (wpa_s == NULL) {
13857 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
13858 if (resp)
13859 *resp_len = os_strlen(resp);
13860 else
13861 *resp_len = 1;
13862 return resp;
13863 }
13864
13865 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
13866 }
13867
13868
wpas_global_ctrl_iface_redir_p2p(struct wpa_global * global,char * buf,size_t * resp_len)13869 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
13870 char *buf, size_t *resp_len)
13871 {
13872 #ifdef CONFIG_P2P
13873 static const char * cmd[] = {
13874 "LIST_NETWORKS",
13875 "P2P_FIND",
13876 "P2P_STOP_FIND",
13877 "P2P_LISTEN",
13878 "P2P_GROUP_ADD",
13879 "P2P_GET_PASSPHRASE",
13880 "P2P_SERVICE_UPDATE",
13881 "P2P_SERVICE_FLUSH",
13882 "P2P_FLUSH",
13883 "P2P_CANCEL",
13884 "P2P_PRESENCE_REQ",
13885 "P2P_EXT_LISTEN",
13886 #ifdef CONFIG_AP
13887 "STA-FIRST",
13888 #endif /* CONFIG_AP */
13889 NULL
13890 };
13891 static const char * prefix[] = {
13892 #ifdef ANDROID
13893 "DRIVER ",
13894 #endif /* ANDROID */
13895 "GET_CAPABILITY ",
13896 "GET_NETWORK ",
13897 "REMOVE_NETWORK ",
13898 "P2P_FIND ",
13899 "P2P_CONNECT ",
13900 "P2P_LISTEN ",
13901 "P2P_GROUP_REMOVE ",
13902 "P2P_GROUP_ADD ",
13903 "P2P_GROUP_MEMBER ",
13904 "P2P_PROV_DISC ",
13905 "P2P_SERV_DISC_REQ ",
13906 "P2P_SERV_DISC_CANCEL_REQ ",
13907 "P2P_SERV_DISC_RESP ",
13908 "P2P_SERV_DISC_EXTERNAL ",
13909 "P2P_SERVICE_ADD ",
13910 "P2P_SERVICE_DEL ",
13911 "P2P_SERVICE_REP ",
13912 "P2P_REJECT ",
13913 "P2P_INVITE ",
13914 "P2P_PEER ",
13915 "P2P_SET ",
13916 "P2P_UNAUTHORIZE ",
13917 "P2P_PRESENCE_REQ ",
13918 "P2P_EXT_LISTEN ",
13919 "P2P_REMOVE_CLIENT ",
13920 "WPS_NFC_TOKEN ",
13921 "WPS_NFC_TAG_READ ",
13922 "NFC_GET_HANDOVER_SEL ",
13923 "NFC_GET_HANDOVER_REQ ",
13924 "NFC_REPORT_HANDOVER ",
13925 "P2P_ASP_PROVISION ",
13926 "P2P_ASP_PROVISION_RESP ",
13927 #ifdef CONFIG_AP
13928 "STA ",
13929 "STA-NEXT ",
13930 #endif /* CONFIG_AP */
13931 NULL
13932 };
13933 int found = 0;
13934 int i;
13935
13936 if (global->p2p_init_wpa_s == NULL)
13937 return NULL;
13938
13939 for (i = 0; !found && cmd[i]; i++) {
13940 if (os_strcmp(buf, cmd[i]) == 0)
13941 found = 1;
13942 }
13943
13944 for (i = 0; !found && prefix[i]; i++) {
13945 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
13946 found = 1;
13947 }
13948
13949 if (found)
13950 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13951 buf, resp_len);
13952 #endif /* CONFIG_P2P */
13953 return NULL;
13954 }
13955
13956
wpas_global_ctrl_iface_redir_wfd(struct wpa_global * global,char * buf,size_t * resp_len)13957 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
13958 char *buf, size_t *resp_len)
13959 {
13960 #ifdef CONFIG_WIFI_DISPLAY
13961 if (global->p2p_init_wpa_s == NULL)
13962 return NULL;
13963 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
13964 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
13965 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13966 buf, resp_len);
13967 #endif /* CONFIG_WIFI_DISPLAY */
13968 return NULL;
13969 }
13970
13971
wpas_global_ctrl_iface_redir(struct wpa_global * global,char * buf,size_t * resp_len)13972 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
13973 char *buf, size_t *resp_len)
13974 {
13975 char *ret;
13976
13977 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
13978 if (ret)
13979 return ret;
13980
13981 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
13982 if (ret)
13983 return ret;
13984
13985 return NULL;
13986 }
13987
13988
wpas_global_ctrl_iface_set(struct wpa_global * global,char * cmd)13989 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
13990 {
13991 char *value;
13992
13993 value = os_strchr(cmd, ' ');
13994 if (value == NULL)
13995 return -1;
13996 *value++ = '\0';
13997
13998 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
13999
14000 #ifdef CONFIG_WIFI_DISPLAY
14001 if (os_strcasecmp(cmd, "wifi_display") == 0) {
14002 wifi_display_enable(global, !!atoi(value));
14003 return 0;
14004 }
14005 #endif /* CONFIG_WIFI_DISPLAY */
14006
14007 /* Restore cmd to its original value to allow redirection */
14008 value[-1] = ' ';
14009
14010 return -1;
14011 }
14012
14013
wpas_global_ctrl_iface_dup_network(struct wpa_global * global,char * cmd)14014 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
14015 char *cmd)
14016 {
14017 struct wpa_supplicant *wpa_s[2]; /* src, dst */
14018 char *p;
14019 unsigned int i;
14020
14021 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
14022 * <variable name> */
14023
14024 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
14025 p = os_strchr(cmd, ' ');
14026 if (p == NULL)
14027 return -1;
14028 *p = '\0';
14029
14030 wpa_s[i] = global->ifaces;
14031 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
14032 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
14033 break;
14034 }
14035
14036 if (!wpa_s[i]) {
14037 wpa_printf(MSG_DEBUG,
14038 "CTRL_IFACE: Could not find iface=%s", cmd);
14039 return -1;
14040 }
14041
14042 cmd = p + 1;
14043 }
14044
14045 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
14046 }
14047
14048
14049 #ifndef CONFIG_NO_CONFIG_WRITE
wpas_global_ctrl_iface_save_config(struct wpa_global * global)14050 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
14051 {
14052 int ret = 0, saved = 0;
14053 struct wpa_supplicant *wpa_s;
14054
14055 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14056 if (!wpa_s->conf->update_config) {
14057 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
14058 continue;
14059 }
14060
14061 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
14062 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
14063 ret = 1;
14064 } else {
14065 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
14066 saved++;
14067 }
14068 }
14069
14070 if (!saved && !ret) {
14071 wpa_dbg(wpa_s, MSG_DEBUG,
14072 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
14073 ret = 1;
14074 }
14075
14076 return ret;
14077 }
14078 #endif /* CONFIG_NO_CONFIG_WRITE */
14079
14080
wpas_global_ctrl_iface_status(struct wpa_global * global,char * buf,size_t buflen)14081 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
14082 char *buf, size_t buflen)
14083 {
14084 char *pos, *end;
14085 int ret;
14086 struct wpa_supplicant *wpa_s;
14087
14088 pos = buf;
14089 end = buf + buflen;
14090
14091 #ifdef CONFIG_P2P
14092 if (global->p2p && !global->p2p_disabled) {
14093 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
14094 "\n"
14095 "p2p_state=%s\n",
14096 MAC2STR(global->p2p_dev_addr),
14097 p2p_get_state_txt(global->p2p));
14098 if (os_snprintf_error(end - pos, ret))
14099 return pos - buf;
14100 pos += ret;
14101 } else if (global->p2p) {
14102 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
14103 if (os_snprintf_error(end - pos, ret))
14104 return pos - buf;
14105 pos += ret;
14106 }
14107 #endif /* CONFIG_P2P */
14108
14109 #ifdef CONFIG_WIFI_DISPLAY
14110 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
14111 !!global->wifi_display);
14112 if (os_snprintf_error(end - pos, ret))
14113 return pos - buf;
14114 pos += ret;
14115 #endif /* CONFIG_WIFI_DISPLAY */
14116
14117 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14118 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
14119 "address=" MACSTR "\n",
14120 wpa_s->ifname, MAC2STR(wpa_s->own_addr));
14121 if (os_snprintf_error(end - pos, ret))
14122 return pos - buf;
14123 pos += ret;
14124 }
14125
14126 return pos - buf;
14127 }
14128
14129
14130 #ifdef CONFIG_FST
14131
wpas_global_ctrl_iface_fst_attach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)14132 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
14133 char *cmd, char *buf,
14134 size_t reply_size)
14135 {
14136 char ifname[IFNAMSIZ + 1];
14137 struct fst_iface_cfg cfg;
14138 struct wpa_supplicant *wpa_s;
14139 struct fst_wpa_obj iface_obj;
14140
14141 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
14142 wpa_s = wpa_supplicant_get_iface(global, ifname);
14143 if (wpa_s) {
14144 if (wpa_s->fst) {
14145 wpa_printf(MSG_INFO, "FST: Already attached");
14146 return -1;
14147 }
14148 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
14149 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
14150 &iface_obj, &cfg);
14151 if (wpa_s->fst)
14152 return os_snprintf(buf, reply_size, "OK\n");
14153 }
14154 }
14155
14156 return -1;
14157 }
14158
14159
wpas_global_ctrl_iface_fst_detach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)14160 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
14161 char *cmd, char *buf,
14162 size_t reply_size)
14163 {
14164 char ifname[IFNAMSIZ + 1];
14165 struct wpa_supplicant *wpa_s;
14166
14167 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
14168 wpa_s = wpa_supplicant_get_iface(global, ifname);
14169 if (wpa_s) {
14170 if (!fst_iface_detach(ifname)) {
14171 wpa_s->fst = NULL;
14172 return os_snprintf(buf, reply_size, "OK\n");
14173 }
14174 }
14175 }
14176
14177 return -1;
14178 }
14179
14180 #endif /* CONFIG_FST */
14181
14182
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)14183 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
14184 char *buf, size_t *resp_len)
14185 {
14186 static char reply[1024];
14187 const int reply_size = sizeof(reply);
14188 int reply_len;
14189 int level = MSG_DEBUG;
14190 char *reply_redir;
14191
14192 os_memset(reply, 0, reply_size);
14193
14194 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
14195 char *pos = os_strchr(buf + 7, ' ');
14196 if (pos) {
14197 *pos++ = '\0';
14198 return wpas_global_ctrl_iface_ifname(global,
14199 buf + 7, pos,
14200 resp_len);
14201 }
14202 }
14203
14204 reply_redir = wpas_global_ctrl_iface_redir(global, buf, resp_len);
14205 if (reply_redir)
14206 return reply_redir;
14207
14208 if (os_strcmp(buf, "PING") == 0)
14209 level = MSG_EXCESSIVE;
14210 wpa_hexdump_ascii(level, "RX global ctrl_iface",
14211 (const u8 *) buf, os_strlen(buf));
14212
14213 os_memcpy(reply, "OK\n", 3);
14214 reply_len = 3;
14215
14216 if (os_strcmp(buf, "PING") == 0) {
14217 os_memcpy(reply, "PONG\n", 5);
14218 reply_len = 5;
14219 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
14220 if (wpa_supplicant_global_iface_add(global, buf + 14))
14221 reply_len = -1;
14222 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
14223 if (wpa_supplicant_global_iface_remove(global, buf + 17))
14224 reply_len = -1;
14225 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
14226 reply_len = wpa_supplicant_global_iface_list(
14227 global, reply, reply_size);
14228 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
14229 reply_len = wpa_supplicant_global_iface_interfaces(
14230 global, buf + 10, reply, reply_size);
14231 #ifdef CONFIG_FST
14232 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
14233 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
14234 reply,
14235 reply_size);
14236 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
14237 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
14238 reply,
14239 reply_size);
14240 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
14241 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
14242 #endif /* CONFIG_FST */
14243 } else if (os_strcmp(buf, "TERMINATE") == 0) {
14244 wpa_supplicant_terminate_proc(global);
14245 } else if (os_strcmp(buf, "SUSPEND") == 0) {
14246 wpas_notify_suspend(global);
14247 } else if (os_strcmp(buf, "RESUME") == 0) {
14248 wpas_notify_resume(global);
14249 } else if (os_strncmp(buf, "SET ", 4) == 0) {
14250 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
14251 #ifdef CONFIG_P2P
14252 if (global->p2p_init_wpa_s) {
14253 os_free(reply);
14254 /* Check if P2P redirection would work for this
14255 * command. */
14256 return wpa_supplicant_ctrl_iface_process(
14257 global->p2p_init_wpa_s,
14258 buf, resp_len);
14259 }
14260 #endif /* CONFIG_P2P */
14261 reply_len = -1;
14262 }
14263 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
14264 if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
14265 reply_len = -1;
14266 #ifndef CONFIG_NO_CONFIG_WRITE
14267 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
14268 if (wpas_global_ctrl_iface_save_config(global))
14269 reply_len = -1;
14270 #endif /* CONFIG_NO_CONFIG_WRITE */
14271 } else if (os_strcmp(buf, "STATUS") == 0) {
14272 reply_len = wpas_global_ctrl_iface_status(global, reply,
14273 reply_size);
14274 #ifdef CONFIG_MODULE_TESTS
14275 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
14276 if (wpas_module_tests() < 0)
14277 reply_len = -1;
14278 #endif /* CONFIG_MODULE_TESTS */
14279 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
14280 if (wpa_debug_reopen_file() < 0)
14281 reply_len = -1;
14282 } else {
14283 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
14284 reply_len = 16;
14285 }
14286
14287 if (reply_len < 0) {
14288 os_memcpy(reply, "FAIL\n", 5);
14289 reply_len = 5;
14290 }
14291
14292 *resp_len = reply_len;
14293 return reply;
14294 }
14295