1 /*
2 * WPA Supplicant / Control interface (shared code for all backends)
3 * Copyright (c) 2004-2020, 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/ptksa_cache.h"
26 #include "crypto/tls.h"
27 #include "ap/hostapd.h"
28 #include "eap_peer/eap.h"
29 #include "eapol_supp/eapol_supp_sm.h"
30 #include "rsn_supp/wpa.h"
31 #include "rsn_supp/preauth.h"
32 #include "rsn_supp/pmksa_cache.h"
33 #include "l2_packet/l2_packet.h"
34 #include "wps/wps.h"
35 #include "fst/fst.h"
36 #include "fst/fst_ctrl_iface.h"
37 #include "config.h"
38 #include "wpa_supplicant_i.h"
39 #include "driver_i.h"
40 #include "wps_supplicant.h"
41 #include "ibss_rsn.h"
42 #include "ap.h"
43 #include "p2p_supplicant.h"
44 #include "p2p/p2p.h"
45 #include "hs20_supplicant.h"
46 #include "wifi_display.h"
47 #include "notify.h"
48 #include "bss.h"
49 #include "scan.h"
50 #include "ctrl_iface.h"
51 #include "interworking.h"
52 #include "bssid_ignore.h"
53 #include "autoscan.h"
54 #include "wnm_sta.h"
55 #include "offchannel.h"
56 #include "drivers/driver.h"
57 #include "mesh.h"
58 #include "dpp_supplicant.h"
59 #include "sme.h"
60
61 #ifdef __NetBSD__
62 #include <net/if_ether.h>
63 #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS)
64 #include <net/ethernet.h>
65 #endif
66
67 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
68 char *buf, int len);
69 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
70 const char *input,
71 char *buf, int len);
72 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
73 char *val);
74
75
set_bssid_filter(struct wpa_supplicant * wpa_s,char * val)76 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
77 {
78 char *pos;
79 u8 addr[ETH_ALEN], *filter = NULL, *n;
80 size_t count = 0;
81
82 pos = val;
83 while (pos) {
84 if (*pos == '\0')
85 break;
86 if (hwaddr_aton(pos, addr)) {
87 os_free(filter);
88 return -1;
89 }
90 n = os_realloc_array(filter, count + 1, ETH_ALEN);
91 if (n == NULL) {
92 os_free(filter);
93 return -1;
94 }
95 filter = n;
96 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
97 count++;
98
99 pos = os_strchr(pos, ' ');
100 if (pos)
101 pos++;
102 }
103
104 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
105 os_free(wpa_s->bssid_filter);
106 wpa_s->bssid_filter = filter;
107 wpa_s->bssid_filter_count = count;
108
109 return 0;
110 }
111
112
set_disallow_aps(struct wpa_supplicant * wpa_s,char * val)113 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
114 {
115 char *pos;
116 u8 addr[ETH_ALEN], *bssid = NULL, *n;
117 struct wpa_ssid_value *ssid = NULL, *ns;
118 size_t count = 0, ssid_count = 0;
119 struct wpa_ssid *c;
120
121 /*
122 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
123 * SSID_SPEC ::= ssid <SSID_HEX>
124 * BSSID_SPEC ::= bssid <BSSID_HEX>
125 */
126
127 pos = val;
128 while (pos) {
129 if (*pos == '\0')
130 break;
131 if (os_strncmp(pos, "bssid ", 6) == 0) {
132 int res;
133 pos += 6;
134 res = hwaddr_aton2(pos, addr);
135 if (res < 0) {
136 os_free(ssid);
137 os_free(bssid);
138 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
139 "BSSID value '%s'", pos);
140 return -1;
141 }
142 pos += res;
143 n = os_realloc_array(bssid, count + 1, ETH_ALEN);
144 if (n == NULL) {
145 os_free(ssid);
146 os_free(bssid);
147 return -1;
148 }
149 bssid = n;
150 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
151 count++;
152 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
153 char *end;
154 pos += 5;
155
156 end = pos;
157 while (*end) {
158 if (*end == '\0' || *end == ' ')
159 break;
160 end++;
161 }
162
163 ns = os_realloc_array(ssid, ssid_count + 1,
164 sizeof(struct wpa_ssid_value));
165 if (ns == NULL) {
166 os_free(ssid);
167 os_free(bssid);
168 return -1;
169 }
170 ssid = ns;
171
172 if ((end - pos) & 0x01 ||
173 end - pos > 2 * SSID_MAX_LEN ||
174 hexstr2bin(pos, ssid[ssid_count].ssid,
175 (end - pos) / 2) < 0) {
176 os_free(ssid);
177 os_free(bssid);
178 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
179 "SSID value '%s'", pos);
180 return -1;
181 }
182 ssid[ssid_count].ssid_len = (end - pos) / 2;
183 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
184 ssid[ssid_count].ssid,
185 ssid[ssid_count].ssid_len);
186 ssid_count++;
187 pos = end;
188 } else {
189 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
190 "'%s'", pos);
191 os_free(ssid);
192 os_free(bssid);
193 return -1;
194 }
195
196 pos = os_strchr(pos, ' ');
197 if (pos)
198 pos++;
199 }
200
201 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
202 os_free(wpa_s->disallow_aps_bssid);
203 wpa_s->disallow_aps_bssid = bssid;
204 wpa_s->disallow_aps_bssid_count = count;
205
206 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
207 os_free(wpa_s->disallow_aps_ssid);
208 wpa_s->disallow_aps_ssid = ssid;
209 wpa_s->disallow_aps_ssid_count = ssid_count;
210
211 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
212 return 0;
213
214 c = wpa_s->current_ssid;
215 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
216 return 0;
217
218 if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
219 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
220 return 0;
221
222 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
223 "because current AP was marked disallowed");
224
225 #ifdef CONFIG_SME
226 wpa_s->sme.prev_bssid_set = 0;
227 #endif /* CONFIG_SME */
228 wpa_s->reassociate = 1;
229 wpa_s->own_disconnect_req = 1;
230 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
231 wpa_supplicant_req_scan(wpa_s, 0, 0);
232
233 return 0;
234 }
235
236
237 #ifndef CONFIG_NO_CONFIG_BLOBS
wpas_ctrl_set_blob(struct wpa_supplicant * wpa_s,char * pos)238 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
239 {
240 char *name = pos;
241 struct wpa_config_blob *blob;
242 size_t len;
243
244 pos = os_strchr(pos, ' ');
245 if (pos == NULL)
246 return -1;
247 *pos++ = '\0';
248 len = os_strlen(pos);
249 if (len & 1)
250 return -1;
251
252 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
253 blob = os_zalloc(sizeof(*blob));
254 if (blob == NULL)
255 return -1;
256 blob->name = os_strdup(name);
257 blob->data = os_malloc(len / 2);
258 if (blob->name == NULL || blob->data == NULL) {
259 wpa_config_free_blob(blob);
260 return -1;
261 }
262
263 if (hexstr2bin(pos, blob->data, len / 2) < 0) {
264 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
265 wpa_config_free_blob(blob);
266 return -1;
267 }
268 blob->len = len / 2;
269
270 wpa_config_set_blob(wpa_s->conf, blob);
271
272 return 0;
273 }
274 #endif /* CONFIG_NO_CONFIG_BLOBS */
275
276
wpas_ctrl_pno(struct wpa_supplicant * wpa_s,char * cmd)277 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
278 {
279 char *params;
280 char *pos;
281 int *freqs = NULL;
282 int ret;
283
284 if (atoi(cmd)) {
285 params = os_strchr(cmd, ' ');
286 os_free(wpa_s->manual_sched_scan_freqs);
287 if (params) {
288 params++;
289 pos = os_strstr(params, "freq=");
290 if (pos)
291 freqs = freq_range_to_channel_list(wpa_s,
292 pos + 5);
293 }
294 wpa_s->manual_sched_scan_freqs = freqs;
295 ret = wpas_start_pno(wpa_s);
296 } else {
297 ret = wpas_stop_pno(wpa_s);
298 }
299 return ret;
300 }
301
302
wpas_ctrl_set_band(struct wpa_supplicant * wpa_s,char * bands)303 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
304 {
305 union wpa_event_data event;
306 u32 setband_mask = WPA_SETBAND_AUTO;
307
308 /*
309 * For example:
310 * SET setband 2G,6G
311 * SET setband 5G
312 * SET setband AUTO
313 */
314 if (!os_strstr(bands, "AUTO")) {
315 if (os_strstr(bands, "5G"))
316 setband_mask |= WPA_SETBAND_5G;
317 if (os_strstr(bands, "6G"))
318 setband_mask |= WPA_SETBAND_6G;
319 if (os_strstr(bands, "2G"))
320 setband_mask |= WPA_SETBAND_2G;
321 if (setband_mask == WPA_SETBAND_AUTO)
322 return -1;
323 }
324
325 wpa_s->setband_mask = setband_mask;
326 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
327 os_memset(&event, 0, sizeof(event));
328 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
329 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
330 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
331 }
332
333 return 0;
334 }
335
336
wpas_ctrl_iface_set_lci(struct wpa_supplicant * wpa_s,const char * cmd)337 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
338 const char *cmd)
339 {
340 struct wpabuf *lci;
341
342 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
343 wpabuf_free(wpa_s->lci);
344 wpa_s->lci = NULL;
345 return 0;
346 }
347
348 lci = wpabuf_parse_bin(cmd);
349 if (!lci)
350 return -1;
351
352 if (os_get_reltime(&wpa_s->lci_time)) {
353 wpabuf_free(lci);
354 return -1;
355 }
356
357 wpabuf_free(wpa_s->lci);
358 wpa_s->lci = lci;
359
360 return 0;
361 }
362
363
364 static int
wpas_ctrl_set_relative_rssi(struct wpa_supplicant * wpa_s,const char * cmd)365 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
366 {
367 int relative_rssi;
368
369 if (os_strcmp(cmd, "disable") == 0) {
370 wpa_s->srp.relative_rssi_set = 0;
371 return 0;
372 }
373
374 relative_rssi = atoi(cmd);
375 if (relative_rssi < 0 || relative_rssi > 100)
376 return -1;
377 wpa_s->srp.relative_rssi = relative_rssi;
378 wpa_s->srp.relative_rssi_set = 1;
379 return 0;
380 }
381
382
wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant * wpa_s,const char * cmd)383 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
384 const char *cmd)
385 {
386 char *pos;
387 int adjust_rssi;
388
389 /* <band>:adjust_value */
390 pos = os_strchr(cmd, ':');
391 if (!pos)
392 return -1;
393 pos++;
394 adjust_rssi = atoi(pos);
395 if (adjust_rssi < -100 || adjust_rssi > 100)
396 return -1;
397
398 if (os_strncmp(cmd, "2G", 2) == 0)
399 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
400 else if (os_strncmp(cmd, "5G", 2) == 0)
401 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
402 else
403 return -1;
404
405 wpa_s->srp.relative_adjust_rssi = adjust_rssi;
406
407 return 0;
408 }
409
410
wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant * wpa_s,const char * cmd)411 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
412 const char *cmd)
413 {
414 struct wpabuf *ric_ies;
415
416 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
417 wpabuf_free(wpa_s->ric_ies);
418 wpa_s->ric_ies = NULL;
419 return 0;
420 }
421
422 ric_ies = wpabuf_parse_bin(cmd);
423 if (!ric_ies)
424 return -1;
425
426 wpabuf_free(wpa_s->ric_ies);
427 wpa_s->ric_ies = ric_ies;
428
429 return 0;
430 }
431
432
433 #ifdef CONFIG_TESTING_OPTIONS
wpas_ctrl_iface_set_dso(struct wpa_supplicant * wpa_s,const char * val)434 static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
435 const char *val)
436 {
437 u8 bssid[ETH_ALEN];
438 const char *pos = val;
439 struct driver_signal_override *dso = NULL, *tmp, parsed;
440
441 if (hwaddr_aton(pos, bssid))
442 return -1;
443 pos = os_strchr(pos, ' ');
444
445 dl_list_for_each(tmp, &wpa_s->drv_signal_override,
446 struct driver_signal_override, list) {
447 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
448 dso = tmp;
449 break;
450 }
451 }
452
453 if (!pos) {
454 /* Remove existing entry */
455 if (dso) {
456 dl_list_del(&dso->list);
457 os_free(dso);
458 }
459 return 0;
460 }
461 pos++;
462
463 /* Update an existing entry or add a new one */
464 os_memset(&parsed, 0, sizeof(parsed));
465 if (sscanf(pos, "%d %d %d %d %d",
466 &parsed.si_current_signal,
467 &parsed.si_avg_signal,
468 &parsed.si_avg_beacon_signal,
469 &parsed.si_current_noise,
470 &parsed.scan_level) != 5)
471 return -1;
472
473 if (!dso) {
474 dso = os_zalloc(sizeof(*dso));
475 if (!dso)
476 return -1;
477 os_memcpy(dso->bssid, bssid, ETH_ALEN);
478 dl_list_add(&wpa_s->drv_signal_override, &dso->list);
479 }
480 dso->si_current_signal = parsed.si_current_signal;
481 dso->si_avg_signal = parsed.si_avg_signal;
482 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
483 dso->si_current_noise = parsed.si_current_noise;
484 dso->scan_level = parsed.scan_level;
485
486 return 0;
487 }
488 #endif /* CONFIG_TESTING_OPTIONS */
489
490
wpa_supplicant_ctrl_iface_set(struct wpa_supplicant * wpa_s,char * cmd)491 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
492 char *cmd)
493 {
494 char *value;
495 int ret = 0;
496
497 value = os_strchr(cmd, ' ');
498 if (value == NULL)
499 return -1;
500 *value++ = '\0';
501
502 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
503 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
504 eapol_sm_configure(wpa_s->eapol,
505 atoi(value), -1, -1, -1);
506 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
507 eapol_sm_configure(wpa_s->eapol,
508 -1, atoi(value), -1, -1);
509 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
510 eapol_sm_configure(wpa_s->eapol,
511 -1, -1, atoi(value), -1);
512 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
513 eapol_sm_configure(wpa_s->eapol,
514 -1, -1, -1, atoi(value));
515 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
516 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
517 atoi(value))) {
518 ret = -1;
519 } else {
520 value[-1] = '=';
521 wpa_config_process_global(wpa_s->conf, cmd, -1);
522 }
523 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
524 0) {
525 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
526 atoi(value))) {
527 ret = -1;
528 } else {
529 value[-1] = '=';
530 wpa_config_process_global(wpa_s->conf, cmd, -1);
531 }
532 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
533 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
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, "wps_fragment_size") == 0) {
541 wpa_s->wps_fragment_size = atoi(value);
542 #ifdef CONFIG_WPS_TESTING
543 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
544 long int val;
545 val = strtol(value, NULL, 0);
546 if (val < 0 || val > 0xff) {
547 ret = -1;
548 wpa_printf(MSG_DEBUG, "WPS: Invalid "
549 "wps_version_number %ld", val);
550 } else {
551 wps_version_number = val;
552 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
553 "version %u.%u",
554 (wps_version_number & 0xf0) >> 4,
555 wps_version_number & 0x0f);
556 }
557 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
558 wps_testing_dummy_cred = atoi(value);
559 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
560 wps_testing_dummy_cred);
561 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
562 wps_corrupt_pkhash = atoi(value);
563 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
564 wps_corrupt_pkhash);
565 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
566 if (value[0] == '\0') {
567 wps_force_auth_types_in_use = 0;
568 } else {
569 wps_force_auth_types = strtol(value, NULL, 0);
570 wps_force_auth_types_in_use = 1;
571 }
572 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
573 if (value[0] == '\0') {
574 wps_force_encr_types_in_use = 0;
575 } else {
576 wps_force_encr_types = strtol(value, NULL, 0);
577 wps_force_encr_types_in_use = 1;
578 }
579 #endif /* CONFIG_WPS_TESTING */
580 } else if (os_strcasecmp(cmd, "ampdu") == 0) {
581 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
582 ret = -1;
583 #ifdef CONFIG_TDLS
584 #ifdef CONFIG_TDLS_TESTING
585 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
586 tdls_testing = strtol(value, NULL, 0);
587 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
588 #endif /* CONFIG_TDLS_TESTING */
589 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
590 int disabled = atoi(value);
591 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
592 if (disabled) {
593 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
594 ret = -1;
595 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
596 ret = -1;
597 wpa_tdls_enable(wpa_s->wpa, !disabled);
598 #endif /* CONFIG_TDLS */
599 } else if (os_strcasecmp(cmd, "pno") == 0) {
600 ret = wpas_ctrl_pno(wpa_s, value);
601 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
602 int disabled = atoi(value);
603 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
604 ret = -1;
605 else if (disabled)
606 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
607 } else if (os_strcasecmp(cmd, "uapsd") == 0) {
608 if (os_strcmp(value, "disable") == 0)
609 wpa_s->set_sta_uapsd = 0;
610 else {
611 int be, bk, vi, vo;
612 char *pos;
613 /* format: BE,BK,VI,VO;max SP Length */
614 be = atoi(value);
615 pos = os_strchr(value, ',');
616 if (pos == NULL)
617 return -1;
618 pos++;
619 bk = atoi(pos);
620 pos = os_strchr(pos, ',');
621 if (pos == NULL)
622 return -1;
623 pos++;
624 vi = atoi(pos);
625 pos = os_strchr(pos, ',');
626 if (pos == NULL)
627 return -1;
628 pos++;
629 vo = atoi(pos);
630 /* ignore max SP Length for now */
631
632 wpa_s->set_sta_uapsd = 1;
633 wpa_s->sta_uapsd = 0;
634 if (be)
635 wpa_s->sta_uapsd |= BIT(0);
636 if (bk)
637 wpa_s->sta_uapsd |= BIT(1);
638 if (vi)
639 wpa_s->sta_uapsd |= BIT(2);
640 if (vo)
641 wpa_s->sta_uapsd |= BIT(3);
642 }
643 } else if (os_strcasecmp(cmd, "ps") == 0) {
644 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
645 #ifdef CONFIG_WIFI_DISPLAY
646 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
647 int enabled = !!atoi(value);
648 if (enabled && !wpa_s->global->p2p)
649 ret = -1;
650 else
651 wifi_display_enable(wpa_s->global, enabled);
652 #endif /* CONFIG_WIFI_DISPLAY */
653 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
654 ret = set_bssid_filter(wpa_s, value);
655 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
656 ret = set_disallow_aps(wpa_s, value);
657 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
658 wpa_s->no_keep_alive = !!atoi(value);
659 #ifdef CONFIG_DPP
660 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
661 os_free(wpa_s->dpp_configurator_params);
662 wpa_s->dpp_configurator_params = os_strdup(value);
663 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
664 wpa_s->dpp_init_max_tries = atoi(value);
665 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
666 wpa_s->dpp_init_retry_time = atoi(value);
667 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
668 wpa_s->dpp_resp_wait_time = atoi(value);
669 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
670 wpa_s->dpp_resp_max_tries = atoi(value);
671 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
672 wpa_s->dpp_resp_retry_time = atoi(value);
673 #ifdef CONFIG_TESTING_OPTIONS
674 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
675 if (hwaddr_aton(value, dpp_pkex_own_mac_override))
676 ret = -1;
677 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
678 if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
679 ret = -1;
680 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
681 size_t hex_len = os_strlen(value);
682
683 if (hex_len >
684 2 * sizeof(dpp_pkex_ephemeral_key_override))
685 ret = -1;
686 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
687 hex_len / 2))
688 ret = -1;
689 else
690 dpp_pkex_ephemeral_key_override_len = hex_len / 2;
691 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
692 size_t hex_len = os_strlen(value);
693
694 if (hex_len > 2 * sizeof(dpp_protocol_key_override))
695 ret = -1;
696 else if (hexstr2bin(value, dpp_protocol_key_override,
697 hex_len / 2))
698 ret = -1;
699 else
700 dpp_protocol_key_override_len = hex_len / 2;
701 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
702 size_t hex_len = os_strlen(value);
703
704 if (hex_len > 2 * sizeof(dpp_nonce_override))
705 ret = -1;
706 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
707 ret = -1;
708 else
709 dpp_nonce_override_len = hex_len / 2;
710 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
711 dpp_version_override = atoi(value);
712 #endif /* CONFIG_TESTING_OPTIONS */
713 #endif /* CONFIG_DPP */
714 #ifdef CONFIG_TESTING_OPTIONS
715 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
716 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
717 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
718 wpa_s->ext_eapol_frame_io = !!atoi(value);
719 #ifdef CONFIG_AP
720 if (wpa_s->ap_iface) {
721 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
722 wpa_s->ext_eapol_frame_io;
723 }
724 #endif /* CONFIG_AP */
725 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
726 wpa_s->extra_roc_dur = atoi(value);
727 } else if (os_strcasecmp(cmd, "test_failure") == 0) {
728 wpa_s->test_failure = atoi(value);
729 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
730 wpa_s->p2p_go_csa_on_inv = !!atoi(value);
731 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
732 wpa_s->ignore_auth_resp = !!atoi(value);
733 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
734 wpa_s->ignore_assoc_disallow = !!atoi(value);
735 wpa_drv_ignore_assoc_disallow(wpa_s,
736 wpa_s->ignore_assoc_disallow);
737 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
738 wpa_s->disable_sa_query = !!atoi(value);
739 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
740 wpa_s->ignore_sae_h2e_only = !!atoi(value);
741 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
742 char *pos;
743
744 os_free(wpa_s->extra_sae_rejected_groups);
745 wpa_s->extra_sae_rejected_groups = NULL;
746 pos = value;
747 while (pos && pos[0]) {
748 int group;
749
750 group = atoi(pos);
751 wpa_printf(MSG_DEBUG,
752 "TESTING: Extra rejection of SAE group %d",
753 group);
754 if (group)
755 int_array_add_unique(
756 &wpa_s->extra_sae_rejected_groups,
757 group);
758 pos = os_strchr(pos, ' ');
759 if (!pos)
760 break;
761 pos++;
762 }
763 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
764 wpa_s->ft_rsnxe_used = atoi(value);
765 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
766 wpa_s->oci_freq_override_eapol = atoi(value);
767 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
768 wpa_s->oci_freq_override_saquery_req = atoi(value);
769 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
770 wpa_s->oci_freq_override_saquery_resp = atoi(value);
771 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
772 wpa_s->oci_freq_override_eapol_g2 = atoi(value);
773 /* Populate value to wpa_sm if already associated. */
774 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
775 wpa_s->oci_freq_override_eapol_g2);
776 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
777 wpa_s->oci_freq_override_ft_assoc = atoi(value);
778 /* Populate value to wpa_sm if already associated. */
779 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
780 wpa_s->oci_freq_override_ft_assoc);
781 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
782 wpa_s->oci_freq_override_fils_assoc = atoi(value);
783 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
784 wpa_s->oci_freq_override_wnm_sleep = atoi(value);
785 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
786 wpabuf_free(wpa_s->rsne_override_eapol);
787 if (os_strcmp(value, "NULL") == 0)
788 wpa_s->rsne_override_eapol = NULL;
789 else
790 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
791 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
792 wpabuf_free(wpa_s->rsnxe_override_assoc);
793 if (os_strcmp(value, "NULL") == 0)
794 wpa_s->rsnxe_override_assoc = NULL;
795 else
796 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
797 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
798 wpabuf_free(wpa_s->rsnxe_override_eapol);
799 if (os_strcmp(value, "NULL") == 0)
800 wpa_s->rsnxe_override_eapol = NULL;
801 else
802 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
803 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
804 wpa_s->reject_btm_req_reason = atoi(value);
805 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
806 os_free(wpa_s->get_pref_freq_list_override);
807 if (!value[0])
808 wpa_s->get_pref_freq_list_override = NULL;
809 else
810 wpa_s->get_pref_freq_list_override = os_strdup(value);
811 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
812 wpabuf_free(wpa_s->sae_commit_override);
813 if (value[0] == '\0')
814 wpa_s->sae_commit_override = NULL;
815 else
816 wpa_s->sae_commit_override = wpabuf_parse_bin(value);
817 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
818 ret = wpas_ctrl_iface_set_dso(wpa_s, value);
819 } else if (os_strcasecmp(cmd, "force_hunting_and_pecking_pwe") == 0) {
820 wpa_s->force_hunting_and_pecking_pwe = (atoi(value) != 0) ? 1 : 0;
821 #ifdef CONFIG_DPP
822 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
823 os_free(wpa_s->dpp_config_obj_override);
824 if (value[0] == '\0')
825 wpa_s->dpp_config_obj_override = NULL;
826 else
827 wpa_s->dpp_config_obj_override = os_strdup(value);
828 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
829 os_free(wpa_s->dpp_discovery_override);
830 if (value[0] == '\0')
831 wpa_s->dpp_discovery_override = NULL;
832 else
833 wpa_s->dpp_discovery_override = os_strdup(value);
834 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
835 os_free(wpa_s->dpp_groups_override);
836 if (value[0] == '\0')
837 wpa_s->dpp_groups_override = NULL;
838 else
839 wpa_s->dpp_groups_override = os_strdup(value);
840 } else if (os_strcasecmp(cmd,
841 "dpp_ignore_netaccesskey_mismatch") == 0) {
842 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
843 } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
844 dpp_test = atoi(value);
845 #endif /* CONFIG_DPP */
846 #endif /* CONFIG_TESTING_OPTIONS */
847 #ifdef CONFIG_FILS
848 } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
849 wpa_s->disable_fils = !!atoi(value);
850 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
851 wpa_supplicant_set_default_scan_ies(wpa_s);
852 #endif /* CONFIG_FILS */
853 #ifndef CONFIG_NO_CONFIG_BLOBS
854 } else if (os_strcmp(cmd, "blob") == 0) {
855 ret = wpas_ctrl_set_blob(wpa_s, value);
856 #endif /* CONFIG_NO_CONFIG_BLOBS */
857 } else if (os_strcasecmp(cmd, "setband") == 0) {
858 ret = wpas_ctrl_set_band(wpa_s, value);
859 #ifdef CONFIG_MBO
860 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
861 ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
862 if (ret == 0) {
863 value[-1] = '=';
864 wpa_config_process_global(wpa_s->conf, cmd, -1);
865 }
866 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
867 wpas_mbo_update_cell_capa(wpa_s, atoi(value));
868 } else if (os_strcasecmp(cmd, "oce") == 0) {
869 wpa_s->conf->oce = atoi(value);
870 if (wpa_s->conf->oce) {
871 if ((wpa_s->conf->oce & OCE_STA) &&
872 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
873 wpa_s->enable_oce = OCE_STA;
874
875 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
876 (wpa_s->drv_flags &
877 WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
878 /* TODO: Need to add STA-CFON support */
879 wpa_printf(MSG_ERROR,
880 "OCE STA-CFON feature is not yet supported");
881 return -1;
882 }
883 } else {
884 wpa_s->enable_oce = 0;
885 }
886 wpa_supplicant_set_default_scan_ies(wpa_s);
887 #endif /* CONFIG_MBO */
888 } else if (os_strcasecmp(cmd, "lci") == 0) {
889 ret = wpas_ctrl_iface_set_lci(wpa_s, value);
890 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
891 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
892 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
893 ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
894 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
895 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
896 } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
897 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
898 } else if (os_strcasecmp(cmd, "roaming") == 0) {
899 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
900 #ifdef CONFIG_WNM
901 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
902 struct wpabuf *elems;
903
904 elems = wpabuf_parse_bin(value);
905 if (!elems)
906 return -1;
907 wnm_set_coloc_intf_elems(wpa_s, elems);
908 #endif /* CONFIG_WNM */
909 } else {
910 value[-1] = '=';
911 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
912 if (ret == 0)
913 wpa_supplicant_update_config(wpa_s);
914 else if (ret == 1)
915 ret = 0;
916 }
917
918 return ret;
919 }
920
921
wpa_supplicant_ctrl_iface_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)922 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
923 char *cmd, char *buf, size_t buflen)
924 {
925 int res = -1;
926
927 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
928
929 if (os_strcmp(cmd, "version") == 0) {
930 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
931 } else if (os_strcasecmp(cmd, "max_command_len") == 0) {
932 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
933 } else if (os_strcasecmp(cmd, "country") == 0) {
934 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
935 res = os_snprintf(buf, buflen, "%c%c",
936 wpa_s->conf->country[0],
937 wpa_s->conf->country[1]);
938 #ifdef CONFIG_WIFI_DISPLAY
939 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
940 int enabled;
941 if (wpa_s->global->p2p == NULL ||
942 wpa_s->global->p2p_disabled)
943 enabled = 0;
944 else
945 enabled = wpa_s->global->wifi_display;
946 res = os_snprintf(buf, buflen, "%d", enabled);
947 #endif /* CONFIG_WIFI_DISPLAY */
948 #ifdef CONFIG_TESTING_GET_GTK
949 } else if (os_strcmp(cmd, "gtk") == 0) {
950 if (wpa_s->last_gtk_len == 0)
951 return -1;
952 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
953 wpa_s->last_gtk_len);
954 return res;
955 #endif /* CONFIG_TESTING_GET_GTK */
956 } else if (os_strcmp(cmd, "tls_library") == 0) {
957 res = tls_get_library_version(buf, buflen);
958 #ifdef CONFIG_TESTING_OPTIONS
959 } else if (os_strcmp(cmd, "anonce") == 0) {
960 return wpa_snprintf_hex(buf, buflen,
961 wpa_sm_get_anonce(wpa_s->wpa),
962 WPA_NONCE_LEN);
963 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
964 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
965 #endif /* CONFIG_TESTING_OPTIONS */
966 } else {
967 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
968 }
969
970 if (os_snprintf_error(buflen, res))
971 return -1;
972 return res;
973 }
974
975
976 #ifdef IEEE8021X_EAPOL
wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant * wpa_s,char * addr)977 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
978 char *addr)
979 {
980 u8 bssid[ETH_ALEN];
981 struct wpa_ssid *ssid = wpa_s->current_ssid;
982
983 if (hwaddr_aton(addr, bssid)) {
984 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
985 "'%s'", addr);
986 return -1;
987 }
988
989 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
990 rsn_preauth_deinit(wpa_s->wpa);
991 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
992 return -1;
993
994 return 0;
995 }
996 #endif /* IEEE8021X_EAPOL */
997
998
999 #ifdef CONFIG_TDLS
1000
wpa_supplicant_ctrl_iface_tdls_discover(struct wpa_supplicant * wpa_s,char * addr)1001 static int wpa_supplicant_ctrl_iface_tdls_discover(
1002 struct wpa_supplicant *wpa_s, char *addr)
1003 {
1004 u8 peer[ETH_ALEN];
1005 int ret;
1006
1007 if (hwaddr_aton(addr, peer)) {
1008 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1009 "address '%s'", addr);
1010 return -1;
1011 }
1012
1013 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1014 MAC2STR(peer));
1015
1016 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1017 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1018 else
1019 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1020
1021 return ret;
1022 }
1023
1024
wpa_supplicant_ctrl_iface_tdls_setup(struct wpa_supplicant * wpa_s,char * addr)1025 static int wpa_supplicant_ctrl_iface_tdls_setup(
1026 struct wpa_supplicant *wpa_s, char *addr)
1027 {
1028 u8 peer[ETH_ALEN];
1029 int ret;
1030
1031 if (hwaddr_aton(addr, peer)) {
1032 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1033 "address '%s'", addr);
1034 return -1;
1035 }
1036
1037 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1038 MAC2STR(peer));
1039
1040 if ((wpa_s->conf->tdls_external_control) &&
1041 wpa_tdls_is_external_setup(wpa_s->wpa))
1042 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1043
1044 wpa_tdls_remove(wpa_s->wpa, peer);
1045
1046 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1047 ret = wpa_tdls_start(wpa_s->wpa, peer);
1048 else
1049 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1050
1051 return ret;
1052 }
1053
1054
wpa_supplicant_ctrl_iface_tdls_teardown(struct wpa_supplicant * wpa_s,char * addr)1055 static int wpa_supplicant_ctrl_iface_tdls_teardown(
1056 struct wpa_supplicant *wpa_s, char *addr)
1057 {
1058 u8 peer[ETH_ALEN];
1059 int ret;
1060
1061 if (os_strcmp(addr, "*") == 0) {
1062 /* remove everyone */
1063 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1064 wpa_tdls_teardown_peers(wpa_s->wpa);
1065 return 0;
1066 }
1067
1068 if (hwaddr_aton(addr, peer)) {
1069 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1070 "address '%s'", addr);
1071 return -1;
1072 }
1073
1074 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1075 MAC2STR(peer));
1076
1077 if ((wpa_s->conf->tdls_external_control) &&
1078 wpa_tdls_is_external_setup(wpa_s->wpa))
1079 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1080
1081 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1082 ret = wpa_tdls_teardown_link(
1083 wpa_s->wpa, peer,
1084 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1085 else
1086 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1087
1088 return ret;
1089 }
1090
1091
ctrl_iface_get_capability_tdls(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)1092 static int ctrl_iface_get_capability_tdls(
1093 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1094 {
1095 int ret;
1096
1097 ret = os_snprintf(buf, buflen, "%s\n",
1098 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1099 (wpa_s->drv_flags &
1100 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1101 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
1102 if (os_snprintf_error(buflen, ret))
1103 return -1;
1104 return ret;
1105 }
1106
1107
wpa_supplicant_ctrl_iface_tdls_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1108 static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1109 struct wpa_supplicant *wpa_s, char *cmd)
1110 {
1111 u8 peer[ETH_ALEN];
1112 struct hostapd_freq_params freq_params;
1113 u8 oper_class;
1114 char *pos, *end;
1115
1116 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1117 wpa_printf(MSG_INFO,
1118 "tdls_chanswitch: Only supported with external setup");
1119 return -1;
1120 }
1121
1122 os_memset(&freq_params, 0, sizeof(freq_params));
1123
1124 pos = os_strchr(cmd, ' ');
1125 if (pos == NULL)
1126 return -1;
1127 *pos++ = '\0';
1128
1129 oper_class = strtol(pos, &end, 10);
1130 if (pos == end) {
1131 wpa_printf(MSG_INFO,
1132 "tdls_chanswitch: Invalid op class provided");
1133 return -1;
1134 }
1135
1136 pos = end;
1137 freq_params.freq = atoi(pos);
1138 if (freq_params.freq == 0) {
1139 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1140 return -1;
1141 }
1142
1143 #define SET_FREQ_SETTING(str) \
1144 do { \
1145 const char *pos2 = os_strstr(pos, " " #str "="); \
1146 if (pos2) { \
1147 pos2 += sizeof(" " #str "=") - 1; \
1148 freq_params.str = atoi(pos2); \
1149 } \
1150 } while (0)
1151
1152 SET_FREQ_SETTING(center_freq1);
1153 SET_FREQ_SETTING(center_freq2);
1154 SET_FREQ_SETTING(bandwidth);
1155 SET_FREQ_SETTING(sec_channel_offset);
1156 #undef SET_FREQ_SETTING
1157
1158 freq_params.ht_enabled = !!os_strstr(pos, " ht");
1159 freq_params.vht_enabled = !!os_strstr(pos, " vht");
1160
1161 if (hwaddr_aton(cmd, peer)) {
1162 wpa_printf(MSG_DEBUG,
1163 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1164 cmd);
1165 return -1;
1166 }
1167
1168 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1169 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1170 MAC2STR(peer), oper_class, freq_params.freq,
1171 freq_params.center_freq1, freq_params.center_freq2,
1172 freq_params.bandwidth, freq_params.sec_channel_offset,
1173 freq_params.ht_enabled ? " HT" : "",
1174 freq_params.vht_enabled ? " VHT" : "");
1175
1176 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1177 &freq_params);
1178 }
1179
1180
wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(struct wpa_supplicant * wpa_s,char * cmd)1181 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1182 struct wpa_supplicant *wpa_s, char *cmd)
1183 {
1184 u8 peer[ETH_ALEN];
1185
1186 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1187 wpa_printf(MSG_INFO,
1188 "tdls_chanswitch: Only supported with external setup");
1189 return -1;
1190 }
1191
1192 if (hwaddr_aton(cmd, peer)) {
1193 wpa_printf(MSG_DEBUG,
1194 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1195 cmd);
1196 return -1;
1197 }
1198
1199 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1200 MAC2STR(peer));
1201
1202 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1203 }
1204
1205
wpa_supplicant_ctrl_iface_tdls_link_status(struct wpa_supplicant * wpa_s,const char * addr,char * buf,size_t buflen)1206 static int wpa_supplicant_ctrl_iface_tdls_link_status(
1207 struct wpa_supplicant *wpa_s, const char *addr,
1208 char *buf, size_t buflen)
1209 {
1210 u8 peer[ETH_ALEN];
1211 const char *tdls_status;
1212 int ret;
1213
1214 if (hwaddr_aton(addr, peer)) {
1215 wpa_printf(MSG_DEBUG,
1216 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1217 addr);
1218 return -1;
1219 }
1220 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1221 MAC2STR(peer));
1222
1223 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1224 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1225 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1226 if (os_snprintf_error(buflen, ret))
1227 return -1;
1228
1229 return ret;
1230 }
1231
1232 #endif /* CONFIG_TDLS */
1233
1234
wmm_ac_ctrl_addts(struct wpa_supplicant * wpa_s,char * cmd)1235 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1236 {
1237 char *token, *context = NULL;
1238 struct wmm_ac_ts_setup_params params = {
1239 .tsid = 0xff,
1240 .direction = 0xff,
1241 };
1242
1243 while ((token = str_token(cmd, " ", &context))) {
1244 if (sscanf(token, "tsid=%i", ¶ms.tsid) == 1 ||
1245 sscanf(token, "up=%i", ¶ms.user_priority) == 1 ||
1246 sscanf(token, "nominal_msdu_size=%i",
1247 ¶ms.nominal_msdu_size) == 1 ||
1248 sscanf(token, "mean_data_rate=%i",
1249 ¶ms.mean_data_rate) == 1 ||
1250 sscanf(token, "min_phy_rate=%i",
1251 ¶ms.minimum_phy_rate) == 1 ||
1252 sscanf(token, "sba=%i",
1253 ¶ms.surplus_bandwidth_allowance) == 1)
1254 continue;
1255
1256 if (os_strcasecmp(token, "downlink") == 0) {
1257 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1258 } else if (os_strcasecmp(token, "uplink") == 0) {
1259 params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1260 } else if (os_strcasecmp(token, "bidi") == 0) {
1261 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1262 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1263 params.fixed_nominal_msdu = 1;
1264 } else {
1265 wpa_printf(MSG_DEBUG,
1266 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1267 token);
1268 return -1;
1269 }
1270
1271 }
1272
1273 return wpas_wmm_ac_addts(wpa_s, ¶ms);
1274 }
1275
1276
wmm_ac_ctrl_delts(struct wpa_supplicant * wpa_s,char * cmd)1277 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1278 {
1279 u8 tsid = atoi(cmd);
1280
1281 return wpas_wmm_ac_delts(wpa_s, tsid);
1282 }
1283
1284
1285 #ifdef CONFIG_IEEE80211R
wpa_supplicant_ctrl_iface_ft_ds(struct wpa_supplicant * wpa_s,char * addr)1286 static int wpa_supplicant_ctrl_iface_ft_ds(
1287 struct wpa_supplicant *wpa_s, char *addr)
1288 {
1289 u8 target_ap[ETH_ALEN];
1290 struct wpa_bss *bss;
1291 const u8 *mdie;
1292
1293 if (hwaddr_aton(addr, target_ap)) {
1294 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1295 "address '%s'", addr);
1296 return -1;
1297 }
1298
1299 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1300
1301 bss = wpa_bss_get_bssid(wpa_s, target_ap);
1302 if (bss)
1303 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1304 else
1305 mdie = NULL;
1306
1307 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
1308 }
1309 #endif /* CONFIG_IEEE80211R */
1310
1311
1312 #ifdef CONFIG_WPS
wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant * wpa_s,char * cmd)1313 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1314 char *cmd)
1315 {
1316 u8 bssid[ETH_ALEN], *_bssid = bssid;
1317 #ifdef CONFIG_P2P
1318 u8 p2p_dev_addr[ETH_ALEN];
1319 #endif /* CONFIG_P2P */
1320 #ifdef CONFIG_AP
1321 u8 *_p2p_dev_addr = NULL;
1322 #endif /* CONFIG_AP */
1323 char *pos;
1324 int multi_ap = 0;
1325
1326 if (!cmd || os_strcmp(cmd, "any") == 0 ||
1327 os_strncmp(cmd, "any ", 4) == 0) {
1328 _bssid = NULL;
1329 #ifdef CONFIG_P2P
1330 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1331 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1332 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1333 "P2P Device Address '%s'",
1334 cmd + 13);
1335 return -1;
1336 }
1337 _p2p_dev_addr = p2p_dev_addr;
1338 #endif /* CONFIG_P2P */
1339 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1340 _bssid = NULL;
1341 multi_ap = atoi(cmd + 9);
1342 } else if (hwaddr_aton(cmd, bssid)) {
1343 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1344 cmd);
1345 return -1;
1346 }
1347
1348 if (cmd) {
1349 pos = os_strstr(cmd, " multi_ap=");
1350 if (pos) {
1351 pos += 10;
1352 multi_ap = atoi(pos);
1353 }
1354 }
1355
1356 #ifdef CONFIG_AP
1357 if (wpa_s->ap_iface)
1358 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1359 #endif /* CONFIG_AP */
1360
1361 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
1362 }
1363
1364
wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1365 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1366 char *cmd, char *buf,
1367 size_t buflen)
1368 {
1369 u8 bssid[ETH_ALEN], *_bssid = bssid;
1370 char *pin;
1371 int ret;
1372
1373 pin = os_strchr(cmd, ' ');
1374 if (pin)
1375 *pin++ = '\0';
1376
1377 if (os_strcmp(cmd, "any") == 0)
1378 _bssid = NULL;
1379 else if (os_strcmp(cmd, "get") == 0) {
1380 if (wps_generate_pin((unsigned int *) &ret) < 0)
1381 return -1;
1382 goto done;
1383 } else if (hwaddr_aton(cmd, bssid)) {
1384 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1385 cmd);
1386 return -1;
1387 }
1388
1389 #ifdef CONFIG_AP
1390 if (wpa_s->ap_iface) {
1391 int timeout = 0;
1392 char *pos;
1393
1394 if (pin) {
1395 pos = os_strchr(pin, ' ');
1396 if (pos) {
1397 *pos++ = '\0';
1398 timeout = atoi(pos);
1399 }
1400 }
1401
1402 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
1403 buf, buflen, timeout);
1404 }
1405 #endif /* CONFIG_AP */
1406
1407 if (pin) {
1408 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1409 DEV_PW_DEFAULT);
1410 if (ret < 0)
1411 return -1;
1412 ret = os_snprintf(buf, buflen, "%s", pin);
1413 if (os_snprintf_error(buflen, ret))
1414 return -1;
1415 return ret;
1416 }
1417
1418 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1419 if (ret < 0)
1420 return -1;
1421
1422 done:
1423 /* Return the generated PIN */
1424 ret = os_snprintf(buf, buflen, "%08d", ret);
1425 if (os_snprintf_error(buflen, ret))
1426 return -1;
1427 return ret;
1428 }
1429
1430
wpa_supplicant_ctrl_iface_wps_check_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1431 static int wpa_supplicant_ctrl_iface_wps_check_pin(
1432 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1433 {
1434 char pin[9];
1435 size_t len;
1436 char *pos;
1437 int ret;
1438
1439 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1440 (u8 *) cmd, os_strlen(cmd));
1441 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1442 if (*pos < '0' || *pos > '9')
1443 continue;
1444 pin[len++] = *pos;
1445 if (len == 9) {
1446 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1447 return -1;
1448 }
1449 }
1450 if (len != 4 && len != 8) {
1451 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1452 return -1;
1453 }
1454 pin[len] = '\0';
1455
1456 if (len == 8) {
1457 unsigned int pin_val;
1458 pin_val = atoi(pin);
1459 if (!wps_pin_valid(pin_val)) {
1460 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1461 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
1462 if (os_snprintf_error(buflen, ret))
1463 return -1;
1464 return ret;
1465 }
1466 }
1467
1468 ret = os_snprintf(buf, buflen, "%s", pin);
1469 if (os_snprintf_error(buflen, ret))
1470 return -1;
1471
1472 return ret;
1473 }
1474
1475
1476 #ifdef CONFIG_WPS_NFC
1477
wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant * wpa_s,char * cmd)1478 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1479 char *cmd)
1480 {
1481 u8 bssid[ETH_ALEN], *_bssid = bssid;
1482
1483 if (cmd == NULL || cmd[0] == '\0')
1484 _bssid = NULL;
1485 else if (hwaddr_aton(cmd, bssid))
1486 return -1;
1487
1488 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1489 0, 0);
1490 }
1491
1492
wpa_supplicant_ctrl_iface_wps_nfc_config_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1493 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1494 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1495 {
1496 int ndef;
1497 struct wpabuf *buf;
1498 int res;
1499 char *pos;
1500
1501 pos = os_strchr(cmd, ' ');
1502 if (pos)
1503 *pos++ = '\0';
1504 if (os_strcmp(cmd, "WPS") == 0)
1505 ndef = 0;
1506 else if (os_strcmp(cmd, "NDEF") == 0)
1507 ndef = 1;
1508 else
1509 return -1;
1510
1511 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1512 if (buf == NULL)
1513 return -1;
1514
1515 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1516 wpabuf_len(buf));
1517 reply[res++] = '\n';
1518 reply[res] = '\0';
1519
1520 wpabuf_free(buf);
1521
1522 return res;
1523 }
1524
1525
wpa_supplicant_ctrl_iface_wps_nfc_token(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1526 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1527 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1528 {
1529 int ndef;
1530 struct wpabuf *buf;
1531 int res;
1532
1533 if (os_strcmp(cmd, "WPS") == 0)
1534 ndef = 0;
1535 else if (os_strcmp(cmd, "NDEF") == 0)
1536 ndef = 1;
1537 else
1538 return -1;
1539
1540 buf = wpas_wps_nfc_token(wpa_s, ndef);
1541 if (buf == NULL)
1542 return -1;
1543
1544 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1545 wpabuf_len(buf));
1546 reply[res++] = '\n';
1547 reply[res] = '\0';
1548
1549 wpabuf_free(buf);
1550
1551 return res;
1552 }
1553
1554
wpa_supplicant_ctrl_iface_wps_nfc_tag_read(struct wpa_supplicant * wpa_s,char * pos)1555 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1556 struct wpa_supplicant *wpa_s, char *pos)
1557 {
1558 size_t len;
1559 struct wpabuf *buf;
1560 int ret;
1561 char *freq;
1562 int forced_freq = 0;
1563
1564 freq = strstr(pos, " freq=");
1565 if (freq) {
1566 *freq = '\0';
1567 freq += 6;
1568 forced_freq = atoi(freq);
1569 }
1570
1571 len = os_strlen(pos);
1572 if (len & 0x01)
1573 return -1;
1574 len /= 2;
1575
1576 buf = wpabuf_alloc(len);
1577 if (buf == NULL)
1578 return -1;
1579 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1580 wpabuf_free(buf);
1581 return -1;
1582 }
1583
1584 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1585 wpabuf_free(buf);
1586
1587 return ret;
1588 }
1589
1590
wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1591 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1592 char *reply, size_t max_len,
1593 int ndef)
1594 {
1595 struct wpabuf *buf;
1596 int res;
1597
1598 buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1599 if (buf == NULL)
1600 return -1;
1601
1602 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1603 wpabuf_len(buf));
1604 reply[res++] = '\n';
1605 reply[res] = '\0';
1606
1607 wpabuf_free(buf);
1608
1609 return res;
1610 }
1611
1612
1613 #ifdef CONFIG_P2P
wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef)1614 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1615 char *reply, size_t max_len,
1616 int ndef)
1617 {
1618 struct wpabuf *buf;
1619 int res;
1620
1621 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1622 if (buf == NULL) {
1623 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1624 return -1;
1625 }
1626
1627 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1628 wpabuf_len(buf));
1629 reply[res++] = '\n';
1630 reply[res] = '\0';
1631
1632 wpabuf_free(buf);
1633
1634 return res;
1635 }
1636 #endif /* CONFIG_P2P */
1637
1638
wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1639 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1640 char *cmd, char *reply,
1641 size_t max_len)
1642 {
1643 char *pos;
1644 int ndef;
1645
1646 pos = os_strchr(cmd, ' ');
1647 if (pos == NULL)
1648 return -1;
1649 *pos++ = '\0';
1650
1651 if (os_strcmp(cmd, "WPS") == 0)
1652 ndef = 0;
1653 else if (os_strcmp(cmd, "NDEF") == 0)
1654 ndef = 1;
1655 else
1656 return -1;
1657
1658 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1659 if (!ndef)
1660 return -1;
1661 return wpas_ctrl_nfc_get_handover_req_wps(
1662 wpa_s, reply, max_len, ndef);
1663 }
1664
1665 #ifdef CONFIG_P2P
1666 if (os_strcmp(pos, "P2P-CR") == 0) {
1667 return wpas_ctrl_nfc_get_handover_req_p2p(
1668 wpa_s, reply, max_len, ndef);
1669 }
1670 #endif /* CONFIG_P2P */
1671
1672 return -1;
1673 }
1674
1675
wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant * wpa_s,char * reply,size_t max_len,int ndef,int cr,char * uuid)1676 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1677 char *reply, size_t max_len,
1678 int ndef, int cr, char *uuid)
1679 {
1680 struct wpabuf *buf;
1681 int res;
1682
1683 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1684 if (buf == NULL)
1685 return -1;
1686
1687 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1688 wpabuf_len(buf));
1689 reply[res++] = '\n';
1690 reply[res] = '\0';
1691
1692 wpabuf_free(buf);
1693
1694 return res;
1695 }
1696
1697
1698 #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)1699 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1700 char *reply, size_t max_len,
1701 int ndef, int tag)
1702 {
1703 struct wpabuf *buf;
1704 int res;
1705
1706 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1707 if (buf == NULL)
1708 return -1;
1709
1710 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1711 wpabuf_len(buf));
1712 reply[res++] = '\n';
1713 reply[res] = '\0';
1714
1715 wpabuf_free(buf);
1716
1717 return res;
1718 }
1719 #endif /* CONFIG_P2P */
1720
1721
wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)1722 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1723 char *cmd, char *reply,
1724 size_t max_len)
1725 {
1726 char *pos, *pos2;
1727 int ndef;
1728
1729 pos = os_strchr(cmd, ' ');
1730 if (pos == NULL)
1731 return -1;
1732 *pos++ = '\0';
1733
1734 if (os_strcmp(cmd, "WPS") == 0)
1735 ndef = 0;
1736 else if (os_strcmp(cmd, "NDEF") == 0)
1737 ndef = 1;
1738 else
1739 return -1;
1740
1741 pos2 = os_strchr(pos, ' ');
1742 if (pos2)
1743 *pos2++ = '\0';
1744 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1745 if (!ndef)
1746 return -1;
1747 return wpas_ctrl_nfc_get_handover_sel_wps(
1748 wpa_s, reply, max_len, ndef,
1749 os_strcmp(pos, "WPS-CR") == 0, pos2);
1750 }
1751
1752 #ifdef CONFIG_P2P
1753 if (os_strcmp(pos, "P2P-CR") == 0) {
1754 return wpas_ctrl_nfc_get_handover_sel_p2p(
1755 wpa_s, reply, max_len, ndef, 0);
1756 }
1757
1758 if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1759 return wpas_ctrl_nfc_get_handover_sel_p2p(
1760 wpa_s, reply, max_len, ndef, 1);
1761 }
1762 #endif /* CONFIG_P2P */
1763
1764 return -1;
1765 }
1766
1767
wpas_ctrl_nfc_report_handover(struct wpa_supplicant * wpa_s,char * cmd)1768 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1769 char *cmd)
1770 {
1771 size_t len;
1772 struct wpabuf *req, *sel;
1773 int ret;
1774 char *pos, *role, *type, *pos2;
1775 #ifdef CONFIG_P2P
1776 char *freq;
1777 int forced_freq = 0;
1778
1779 freq = strstr(cmd, " freq=");
1780 if (freq) {
1781 *freq = '\0';
1782 freq += 6;
1783 forced_freq = atoi(freq);
1784 }
1785 #endif /* CONFIG_P2P */
1786
1787 role = cmd;
1788 pos = os_strchr(role, ' ');
1789 if (pos == NULL) {
1790 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1791 return -1;
1792 }
1793 *pos++ = '\0';
1794
1795 type = pos;
1796 pos = os_strchr(type, ' ');
1797 if (pos == NULL) {
1798 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1799 return -1;
1800 }
1801 *pos++ = '\0';
1802
1803 pos2 = os_strchr(pos, ' ');
1804 if (pos2 == NULL) {
1805 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1806 return -1;
1807 }
1808 *pos2++ = '\0';
1809
1810 len = os_strlen(pos);
1811 if (len & 0x01) {
1812 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1813 return -1;
1814 }
1815 len /= 2;
1816
1817 req = wpabuf_alloc(len);
1818 if (req == NULL) {
1819 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1820 return -1;
1821 }
1822 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1823 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1824 wpabuf_free(req);
1825 return -1;
1826 }
1827
1828 len = os_strlen(pos2);
1829 if (len & 0x01) {
1830 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1831 wpabuf_free(req);
1832 return -1;
1833 }
1834 len /= 2;
1835
1836 sel = wpabuf_alloc(len);
1837 if (sel == NULL) {
1838 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1839 wpabuf_free(req);
1840 return -1;
1841 }
1842 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1843 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1844 wpabuf_free(req);
1845 wpabuf_free(sel);
1846 return -1;
1847 }
1848
1849 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1850 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1851
1852 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1853 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1854 #ifdef CONFIG_AP
1855 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1856 {
1857 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1858 if (ret < 0)
1859 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1860 #endif /* CONFIG_AP */
1861 #ifdef CONFIG_P2P
1862 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1863 {
1864 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1865 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1866 {
1867 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1868 forced_freq);
1869 #endif /* CONFIG_P2P */
1870 } else {
1871 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1872 "reported: role=%s type=%s", role, type);
1873 ret = -1;
1874 }
1875 wpabuf_free(req);
1876 wpabuf_free(sel);
1877
1878 if (ret)
1879 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1880
1881 return ret;
1882 }
1883
1884 #endif /* CONFIG_WPS_NFC */
1885
1886
wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant * wpa_s,char * cmd)1887 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1888 char *cmd)
1889 {
1890 u8 bssid[ETH_ALEN];
1891 char *pin;
1892 char *new_ssid;
1893 char *new_auth;
1894 char *new_encr;
1895 char *new_key;
1896 struct wps_new_ap_settings ap;
1897
1898 pin = os_strchr(cmd, ' ');
1899 if (pin == NULL)
1900 return -1;
1901 *pin++ = '\0';
1902
1903 if (hwaddr_aton(cmd, bssid)) {
1904 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1905 cmd);
1906 return -1;
1907 }
1908
1909 new_ssid = os_strchr(pin, ' ');
1910 if (new_ssid == NULL)
1911 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1912 *new_ssid++ = '\0';
1913
1914 new_auth = os_strchr(new_ssid, ' ');
1915 if (new_auth == NULL)
1916 return -1;
1917 *new_auth++ = '\0';
1918
1919 new_encr = os_strchr(new_auth, ' ');
1920 if (new_encr == NULL)
1921 return -1;
1922 *new_encr++ = '\0';
1923
1924 new_key = os_strchr(new_encr, ' ');
1925 if (new_key == NULL)
1926 return -1;
1927 *new_key++ = '\0';
1928
1929 os_memset(&ap, 0, sizeof(ap));
1930 ap.ssid_hex = new_ssid;
1931 ap.auth = new_auth;
1932 ap.encr = new_encr;
1933 ap.key_hex = new_key;
1934 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1935 }
1936
1937
1938 #ifdef CONFIG_AP
wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)1939 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1940 char *cmd, char *buf,
1941 size_t buflen)
1942 {
1943 int timeout = 300;
1944 char *pos;
1945 const char *pin_txt;
1946
1947 if (!wpa_s->ap_iface)
1948 return -1;
1949
1950 pos = os_strchr(cmd, ' ');
1951 if (pos)
1952 *pos++ = '\0';
1953
1954 if (os_strcmp(cmd, "disable") == 0) {
1955 wpas_wps_ap_pin_disable(wpa_s);
1956 return os_snprintf(buf, buflen, "OK\n");
1957 }
1958
1959 if (os_strcmp(cmd, "random") == 0) {
1960 if (pos)
1961 timeout = atoi(pos);
1962 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1963 if (pin_txt == NULL)
1964 return -1;
1965 return os_snprintf(buf, buflen, "%s", pin_txt);
1966 }
1967
1968 if (os_strcmp(cmd, "get") == 0) {
1969 pin_txt = wpas_wps_ap_pin_get(wpa_s);
1970 if (pin_txt == NULL)
1971 return -1;
1972 return os_snprintf(buf, buflen, "%s", pin_txt);
1973 }
1974
1975 if (os_strcmp(cmd, "set") == 0) {
1976 char *pin;
1977 if (pos == NULL)
1978 return -1;
1979 pin = pos;
1980 pos = os_strchr(pos, ' ');
1981 if (pos) {
1982 *pos++ = '\0';
1983 timeout = atoi(pos);
1984 }
1985 if (os_strlen(pin) > buflen)
1986 return -1;
1987 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1988 return -1;
1989 return os_snprintf(buf, buflen, "%s", pin);
1990 }
1991
1992 return -1;
1993 }
1994 #endif /* CONFIG_AP */
1995
1996
1997 #ifdef CONFIG_WPS_ER
wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant * wpa_s,char * cmd)1998 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1999 char *cmd)
2000 {
2001 char *uuid = cmd, *pin, *pos;
2002 u8 addr_buf[ETH_ALEN], *addr = NULL;
2003 pin = os_strchr(uuid, ' ');
2004 if (pin == NULL)
2005 return -1;
2006 *pin++ = '\0';
2007 pos = os_strchr(pin, ' ');
2008 if (pos) {
2009 *pos++ = '\0';
2010 if (hwaddr_aton(pos, addr_buf) == 0)
2011 addr = addr_buf;
2012 }
2013 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2014 }
2015
2016
wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant * wpa_s,char * cmd)2017 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2018 char *cmd)
2019 {
2020 char *uuid = cmd, *pin;
2021 pin = os_strchr(uuid, ' ');
2022 if (pin == NULL)
2023 return -1;
2024 *pin++ = '\0';
2025 return wpas_wps_er_learn(wpa_s, uuid, pin);
2026 }
2027
2028
wpa_supplicant_ctrl_iface_wps_er_set_config(struct wpa_supplicant * wpa_s,char * cmd)2029 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2030 struct wpa_supplicant *wpa_s, char *cmd)
2031 {
2032 char *uuid = cmd, *id;
2033 id = os_strchr(uuid, ' ');
2034 if (id == NULL)
2035 return -1;
2036 *id++ = '\0';
2037 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2038 }
2039
2040
wpa_supplicant_ctrl_iface_wps_er_config(struct wpa_supplicant * wpa_s,char * cmd)2041 static int wpa_supplicant_ctrl_iface_wps_er_config(
2042 struct wpa_supplicant *wpa_s, char *cmd)
2043 {
2044 char *pin;
2045 char *new_ssid;
2046 char *new_auth;
2047 char *new_encr;
2048 char *new_key;
2049 struct wps_new_ap_settings ap;
2050
2051 pin = os_strchr(cmd, ' ');
2052 if (pin == NULL)
2053 return -1;
2054 *pin++ = '\0';
2055
2056 new_ssid = os_strchr(pin, ' ');
2057 if (new_ssid == NULL)
2058 return -1;
2059 *new_ssid++ = '\0';
2060
2061 new_auth = os_strchr(new_ssid, ' ');
2062 if (new_auth == NULL)
2063 return -1;
2064 *new_auth++ = '\0';
2065
2066 new_encr = os_strchr(new_auth, ' ');
2067 if (new_encr == NULL)
2068 return -1;
2069 *new_encr++ = '\0';
2070
2071 new_key = os_strchr(new_encr, ' ');
2072 if (new_key == NULL)
2073 return -1;
2074 *new_key++ = '\0';
2075
2076 os_memset(&ap, 0, sizeof(ap));
2077 ap.ssid_hex = new_ssid;
2078 ap.auth = new_auth;
2079 ap.encr = new_encr;
2080 ap.key_hex = new_key;
2081 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2082 }
2083
2084
2085 #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)2086 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2087 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2088 {
2089 int ndef;
2090 struct wpabuf *buf;
2091 int res;
2092 char *uuid;
2093
2094 uuid = os_strchr(cmd, ' ');
2095 if (uuid == NULL)
2096 return -1;
2097 *uuid++ = '\0';
2098
2099 if (os_strcmp(cmd, "WPS") == 0)
2100 ndef = 0;
2101 else if (os_strcmp(cmd, "NDEF") == 0)
2102 ndef = 1;
2103 else
2104 return -1;
2105
2106 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2107 if (buf == NULL)
2108 return -1;
2109
2110 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2111 wpabuf_len(buf));
2112 reply[res++] = '\n';
2113 reply[res] = '\0';
2114
2115 wpabuf_free(buf);
2116
2117 return res;
2118 }
2119 #endif /* CONFIG_WPS_NFC */
2120 #endif /* CONFIG_WPS_ER */
2121
2122 #endif /* CONFIG_WPS */
2123
2124
2125 #ifdef CONFIG_IBSS_RSN
wpa_supplicant_ctrl_iface_ibss_rsn(struct wpa_supplicant * wpa_s,char * addr)2126 static int wpa_supplicant_ctrl_iface_ibss_rsn(
2127 struct wpa_supplicant *wpa_s, char *addr)
2128 {
2129 u8 peer[ETH_ALEN];
2130
2131 if (hwaddr_aton(addr, peer)) {
2132 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2133 "address '%s'", addr);
2134 return -1;
2135 }
2136
2137 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2138 MAC2STR(peer));
2139
2140 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2141 }
2142 #endif /* CONFIG_IBSS_RSN */
2143
2144
wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant * wpa_s,char * rsp)2145 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2146 char *rsp)
2147 {
2148 #ifdef IEEE8021X_EAPOL
2149 char *pos, *id_pos;
2150 int id;
2151 struct wpa_ssid *ssid;
2152
2153 pos = os_strchr(rsp, '-');
2154 if (pos == NULL)
2155 return -1;
2156 *pos++ = '\0';
2157 id_pos = pos;
2158 pos = os_strchr(pos, ':');
2159 if (pos == NULL)
2160 return -1;
2161 *pos++ = '\0';
2162 id = atoi(id_pos);
2163 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2164 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2165 (u8 *) pos, os_strlen(pos));
2166
2167 ssid = wpa_config_get_network(wpa_s->conf, id);
2168 if (ssid == NULL) {
2169 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2170 "to update", id);
2171 return -1;
2172 }
2173
2174 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2175 pos);
2176 #else /* IEEE8021X_EAPOL */
2177 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2178 return -1;
2179 #endif /* IEEE8021X_EAPOL */
2180 }
2181
2182
wpa_supplicant_ctrl_iface_status(struct wpa_supplicant * wpa_s,const char * params,char * buf,size_t buflen)2183 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2184 const char *params,
2185 char *buf, size_t buflen)
2186 {
2187 char *pos, *end, tmp[30];
2188 int res, verbose, wps, ret;
2189 #ifdef CONFIG_HS20
2190 const u8 *hs20;
2191 #endif /* CONFIG_HS20 */
2192 const u8 *sess_id;
2193 size_t sess_id_len;
2194
2195 if (os_strcmp(params, "-DRIVER") == 0)
2196 return wpa_drv_status(wpa_s, buf, buflen);
2197 verbose = os_strcmp(params, "-VERBOSE") == 0;
2198 wps = os_strcmp(params, "-WPS") == 0;
2199 pos = buf;
2200 end = buf + buflen;
2201 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2202 struct wpa_ssid *ssid = wpa_s->current_ssid;
2203 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2204 MAC2STR(wpa_s->bssid));
2205 if (os_snprintf_error(end - pos, ret))
2206 return pos - buf;
2207 pos += ret;
2208 ret = os_snprintf(pos, end - pos, "freq=%u\n",
2209 wpa_s->assoc_freq);
2210 if (os_snprintf_error(end - pos, ret))
2211 return pos - buf;
2212 pos += ret;
2213 if (ssid) {
2214 u8 *_ssid = ssid->ssid;
2215 size_t ssid_len = ssid->ssid_len;
2216 u8 ssid_buf[SSID_MAX_LEN];
2217 if (ssid_len == 0) {
2218 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2219 if (_res < 0)
2220 ssid_len = 0;
2221 else
2222 ssid_len = _res;
2223 _ssid = ssid_buf;
2224 }
2225 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2226 wpa_ssid_txt(_ssid, ssid_len),
2227 ssid->id);
2228 if (os_snprintf_error(end - pos, ret))
2229 return pos - buf;
2230 pos += ret;
2231
2232 if (wps && ssid->passphrase &&
2233 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2234 (ssid->mode == WPAS_MODE_AP ||
2235 ssid->mode == WPAS_MODE_P2P_GO)) {
2236 ret = os_snprintf(pos, end - pos,
2237 "passphrase=%s\n",
2238 ssid->passphrase);
2239 if (os_snprintf_error(end - pos, ret))
2240 return pos - buf;
2241 pos += ret;
2242 }
2243 if (ssid->id_str) {
2244 ret = os_snprintf(pos, end - pos,
2245 "id_str=%s\n",
2246 ssid->id_str);
2247 if (os_snprintf_error(end - pos, ret))
2248 return pos - buf;
2249 pos += ret;
2250 }
2251
2252 switch (ssid->mode) {
2253 case WPAS_MODE_INFRA:
2254 ret = os_snprintf(pos, end - pos,
2255 "mode=station\n");
2256 break;
2257 case WPAS_MODE_IBSS:
2258 ret = os_snprintf(pos, end - pos,
2259 "mode=IBSS\n");
2260 break;
2261 case WPAS_MODE_AP:
2262 ret = os_snprintf(pos, end - pos,
2263 "mode=AP\n");
2264 break;
2265 case WPAS_MODE_P2P_GO:
2266 ret = os_snprintf(pos, end - pos,
2267 "mode=P2P GO\n");
2268 break;
2269 case WPAS_MODE_P2P_GROUP_FORMATION:
2270 ret = os_snprintf(pos, end - pos,
2271 "mode=P2P GO - group "
2272 "formation\n");
2273 break;
2274 case WPAS_MODE_MESH:
2275 ret = os_snprintf(pos, end - pos,
2276 "mode=mesh\n");
2277 break;
2278 default:
2279 ret = 0;
2280 break;
2281 }
2282 if (os_snprintf_error(end - pos, ret))
2283 return pos - buf;
2284 pos += ret;
2285 }
2286
2287 if (wpa_s->connection_set &&
2288 (wpa_s->connection_ht || wpa_s->connection_vht ||
2289 wpa_s->connection_he)) {
2290 ret = os_snprintf(pos, end - pos,
2291 "wifi_generation=%u\n",
2292 wpa_s->connection_he ? 6 :
2293 (wpa_s->connection_vht ? 5 : 4));
2294 if (os_snprintf_error(end - pos, ret))
2295 return pos - buf;
2296 pos += ret;
2297 }
2298
2299 #ifdef CONFIG_AP
2300 if (wpa_s->ap_iface) {
2301 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2302 end - pos,
2303 verbose);
2304 } else
2305 #endif /* CONFIG_AP */
2306 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2307 }
2308 #ifdef CONFIG_SME
2309 #ifdef CONFIG_SAE
2310 if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
2311 #ifdef CONFIG_AP
2312 !wpa_s->ap_iface &&
2313 #endif /* CONFIG_AP */
2314 wpa_s->sme.sae.state == SAE_ACCEPTED) {
2315 ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2316 "sae_h2e=%d\n"
2317 "sae_pk=%d\n",
2318 wpa_s->sme.sae.group,
2319 wpa_s->sme.sae.h2e,
2320 wpa_s->sme.sae.pk);
2321 if (os_snprintf_error(end - pos, ret))
2322 return pos - buf;
2323 pos += ret;
2324 }
2325 #endif /* CONFIG_SAE */
2326 #endif /* CONFIG_SME */
2327 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2328 wpa_supplicant_state_txt(wpa_s->wpa_state));
2329 if (os_snprintf_error(end - pos, ret))
2330 return pos - buf;
2331 pos += ret;
2332
2333 if (wpa_s->l2 &&
2334 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2335 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
2336 if (os_snprintf_error(end - pos, ret))
2337 return pos - buf;
2338 pos += ret;
2339 }
2340
2341 #ifdef CONFIG_P2P
2342 if (wpa_s->global->p2p) {
2343 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2344 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
2345 if (os_snprintf_error(end - pos, ret))
2346 return pos - buf;
2347 pos += ret;
2348 }
2349 #endif /* CONFIG_P2P */
2350
2351 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2352 MAC2STR(wpa_s->own_addr));
2353 if (os_snprintf_error(end - pos, ret))
2354 return pos - buf;
2355 pos += ret;
2356
2357 #ifdef CONFIG_HS20
2358 if (wpa_s->current_bss &&
2359 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2360 HS20_IE_VENDOR_TYPE)) &&
2361 wpa_s->wpa_proto == WPA_PROTO_RSN &&
2362 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2363 int release = 1;
2364 if (hs20[1] >= 5) {
2365 u8 rel_num = (hs20[6] & 0xf0) >> 4;
2366 release = rel_num + 1;
2367 }
2368 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
2369 if (os_snprintf_error(end - pos, ret))
2370 return pos - buf;
2371 pos += ret;
2372 }
2373
2374 if (wpa_s->current_ssid) {
2375 struct wpa_cred *cred;
2376 char *type;
2377
2378 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2379 size_t i;
2380
2381 if (wpa_s->current_ssid->parent_cred != cred)
2382 continue;
2383
2384 if (cred->provisioning_sp) {
2385 ret = os_snprintf(pos, end - pos,
2386 "provisioning_sp=%s\n",
2387 cred->provisioning_sp);
2388 if (os_snprintf_error(end - pos, ret))
2389 return pos - buf;
2390 pos += ret;
2391 }
2392
2393 if (!cred->domain)
2394 goto no_domain;
2395
2396 i = 0;
2397 if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2398 struct wpabuf *names =
2399 wpa_s->current_bss->anqp->domain_name;
2400 for (i = 0; names && i < cred->num_domain; i++)
2401 {
2402 if (domain_name_list_contains(
2403 names, cred->domain[i], 1))
2404 break;
2405 }
2406 if (i == cred->num_domain)
2407 i = 0; /* show first entry by default */
2408 }
2409 ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2410 cred->domain[i]);
2411 if (os_snprintf_error(end - pos, ret))
2412 return pos - buf;
2413 pos += ret;
2414
2415 no_domain:
2416 if (wpa_s->current_bss == NULL ||
2417 wpa_s->current_bss->anqp == NULL)
2418 res = -1;
2419 else
2420 res = interworking_home_sp_cred(
2421 wpa_s, cred,
2422 wpa_s->current_bss->anqp->domain_name);
2423 if (res > 0)
2424 type = "home";
2425 else if (res == 0)
2426 type = "roaming";
2427 else
2428 type = "unknown";
2429
2430 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
2431 if (os_snprintf_error(end - pos, ret))
2432 return pos - buf;
2433 pos += ret;
2434
2435 break;
2436 }
2437 }
2438 #endif /* CONFIG_HS20 */
2439
2440 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2441 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2442 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2443 verbose);
2444 if (res >= 0)
2445 pos += res;
2446 }
2447
2448 #ifdef CONFIG_MACSEC
2449 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2450 if (res > 0)
2451 pos += res;
2452 #endif /* CONFIG_MACSEC */
2453
2454 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2455 if (sess_id) {
2456 char *start = pos;
2457
2458 ret = os_snprintf(pos, end - pos, "eap_session_id=");
2459 if (os_snprintf_error(end - pos, ret))
2460 return start - buf;
2461 pos += ret;
2462 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2463 if (ret <= 0)
2464 return start - buf;
2465 pos += ret;
2466 ret = os_snprintf(pos, end - pos, "\n");
2467 if (os_snprintf_error(end - pos, ret))
2468 return start - buf;
2469 pos += ret;
2470 }
2471
2472 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2473 if (res >= 0)
2474 pos += res;
2475
2476 #ifdef CONFIG_WPS
2477 {
2478 char uuid_str[100];
2479 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2480 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
2481 if (os_snprintf_error(end - pos, ret))
2482 return pos - buf;
2483 pos += ret;
2484 }
2485 #endif /* CONFIG_WPS */
2486
2487 if (wpa_s->ieee80211ac) {
2488 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2489 if (os_snprintf_error(end - pos, ret))
2490 return pos - buf;
2491 pos += ret;
2492 }
2493
2494 #ifdef ANDROID
2495 /*
2496 * Allow using the STATUS command with default behavior, say for debug,
2497 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2498 * events with STATUS-NO_EVENTS.
2499 */
2500 if (os_strcmp(params, "-NO_EVENTS")) {
2501 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2502 "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2503 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2504 wpa_s->wpa_state,
2505 MAC2STR(wpa_s->bssid),
2506 wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2507 wpa_ssid_txt(wpa_s->current_ssid->ssid,
2508 wpa_s->current_ssid->ssid_len) : "");
2509 if (wpa_s->wpa_state == WPA_COMPLETED) {
2510 struct wpa_ssid *ssid = wpa_s->current_ssid;
2511 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2512 "- connection to " MACSTR
2513 " completed %s [id=%d id_str=%s]",
2514 MAC2STR(wpa_s->bssid), "(auth)",
2515 ssid ? ssid->id : -1,
2516 ssid && ssid->id_str ? ssid->id_str : "");
2517 }
2518 }
2519 #endif /* ANDROID */
2520
2521 return pos - buf;
2522 }
2523
2524
wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant * wpa_s,char * cmd)2525 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2526 char *cmd)
2527 {
2528 char *pos;
2529 int id;
2530 struct wpa_ssid *ssid;
2531 u8 bssid[ETH_ALEN];
2532
2533 /* cmd: "<network id> <BSSID>" */
2534 pos = os_strchr(cmd, ' ');
2535 if (pos == NULL)
2536 return -1;
2537 *pos++ = '\0';
2538 id = atoi(cmd);
2539 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2540 if (hwaddr_aton(pos, bssid)) {
2541 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2542 return -1;
2543 }
2544
2545 ssid = wpa_config_get_network(wpa_s->conf, id);
2546 if (ssid == NULL) {
2547 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2548 "to update", id);
2549 return -1;
2550 }
2551
2552 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2553 ssid->bssid_set = !is_zero_ether_addr(bssid);
2554
2555 return 0;
2556 }
2557
2558
wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2559 static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2560 char *cmd, char *buf,
2561 size_t buflen)
2562 {
2563 u8 bssid[ETH_ALEN];
2564 struct wpa_bssid_ignore *e;
2565 char *pos, *end;
2566 int ret;
2567
2568 /* cmd: "BSSID_IGNORE [<BSSID>]" */
2569 if (*cmd == '\0') {
2570 pos = buf;
2571 end = buf + buflen;
2572 e = wpa_s->bssid_ignore;
2573 while (e) {
2574 ret = os_snprintf(pos, end - pos, MACSTR "\n",
2575 MAC2STR(e->bssid));
2576 if (os_snprintf_error(end - pos, ret))
2577 return pos - buf;
2578 pos += ret;
2579 e = e->next;
2580 }
2581 return pos - buf;
2582 }
2583
2584 cmd++;
2585 if (os_strncmp(cmd, "clear", 5) == 0) {
2586 wpa_bssid_ignore_clear(wpa_s);
2587 os_memcpy(buf, "OK\n", 3);
2588 return 3;
2589 }
2590
2591 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
2592 if (hwaddr_aton(cmd, bssid)) {
2593 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2594 return -1;
2595 }
2596
2597 /*
2598 * Add the BSSID twice, so its count will be 2, causing it to be
2599 * skipped when processing scan results.
2600 */
2601 ret = wpa_bssid_ignore_add(wpa_s, bssid);
2602 if (ret < 0)
2603 return -1;
2604 ret = wpa_bssid_ignore_add(wpa_s, bssid);
2605 if (ret < 0)
2606 return -1;
2607 os_memcpy(buf, "OK\n", 3);
2608 return 3;
2609 }
2610
2611
wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2612 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2613 char *cmd, char *buf,
2614 size_t buflen)
2615 {
2616 char *pos, *end, *stamp;
2617 int ret;
2618
2619 /* cmd: "LOG_LEVEL [<level>]" */
2620 if (*cmd == '\0') {
2621 pos = buf;
2622 end = buf + buflen;
2623 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2624 "Timestamp: %d\n",
2625 debug_level_str(wpa_debug_level),
2626 wpa_debug_timestamp);
2627 if (os_snprintf_error(end - pos, ret))
2628 ret = 0;
2629
2630 return ret;
2631 }
2632
2633 while (*cmd == ' ')
2634 cmd++;
2635
2636 stamp = os_strchr(cmd, ' ');
2637 if (stamp) {
2638 *stamp++ = '\0';
2639 while (*stamp == ' ') {
2640 stamp++;
2641 }
2642 }
2643
2644 if (os_strlen(cmd)) {
2645 int level = str_to_debug_level(cmd);
2646 if (level < 0)
2647 return -1;
2648 wpa_debug_level = level;
2649 }
2650
2651 if (stamp && os_strlen(stamp))
2652 wpa_debug_timestamp = atoi(stamp);
2653
2654 os_memcpy(buf, "OK\n", 3);
2655 return 3;
2656 }
2657
2658
wpa_supplicant_ctrl_iface_list_networks(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)2659 static int wpa_supplicant_ctrl_iface_list_networks(
2660 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2661 {
2662 char *pos, *end, *prev;
2663 struct wpa_ssid *ssid;
2664 int ret;
2665
2666 pos = buf;
2667 end = buf + buflen;
2668 ret = os_snprintf(pos, end - pos,
2669 "network id / ssid / bssid / flags\n");
2670 if (os_snprintf_error(end - pos, ret))
2671 return pos - buf;
2672 pos += ret;
2673
2674 ssid = wpa_s->conf->ssid;
2675
2676 /* skip over ssids until we find next one */
2677 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2678 int last_id = atoi(cmd + 8);
2679 if (last_id != -1) {
2680 while (ssid != NULL && ssid->id <= last_id) {
2681 ssid = ssid->next;
2682 }
2683 }
2684 }
2685
2686 while (ssid) {
2687 prev = pos;
2688 ret = os_snprintf(pos, end - pos, "%d\t%s",
2689 ssid->id,
2690 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2691 if (os_snprintf_error(end - pos, ret))
2692 return prev - buf;
2693 pos += ret;
2694 if (ssid->bssid_set) {
2695 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2696 MAC2STR(ssid->bssid));
2697 } else {
2698 ret = os_snprintf(pos, end - pos, "\tany");
2699 }
2700 if (os_snprintf_error(end - pos, ret))
2701 return prev - buf;
2702 pos += ret;
2703 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2704 ssid == wpa_s->current_ssid ?
2705 "[CURRENT]" : "",
2706 ssid->disabled ? "[DISABLED]" : "",
2707 ssid->disabled_until.sec ?
2708 "[TEMP-DISABLED]" : "",
2709 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2710 "");
2711 if (os_snprintf_error(end - pos, ret))
2712 return prev - buf;
2713 pos += ret;
2714 ret = os_snprintf(pos, end - pos, "\n");
2715 if (os_snprintf_error(end - pos, ret))
2716 return prev - buf;
2717 pos += ret;
2718
2719 ssid = ssid->next;
2720 }
2721
2722 return pos - buf;
2723 }
2724
2725
wpa_supplicant_cipher_txt(char * pos,char * end,int cipher)2726 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2727 {
2728 int ret;
2729 ret = os_snprintf(pos, end - pos, "-");
2730 if (os_snprintf_error(end - pos, ret))
2731 return pos;
2732 pos += ret;
2733 ret = wpa_write_ciphers(pos, end, cipher, "+");
2734 if (ret < 0)
2735 return pos;
2736 pos += ret;
2737 return pos;
2738 }
2739
2740
wpa_supplicant_ie_txt(char * pos,char * end,const char * proto,const u8 * ie,size_t ie_len)2741 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2742 const u8 *ie, size_t ie_len)
2743 {
2744 struct wpa_ie_data data;
2745 char *start;
2746 int ret;
2747
2748 ret = os_snprintf(pos, end - pos, "[%s-", proto);
2749 if (os_snprintf_error(end - pos, ret))
2750 return pos;
2751 pos += ret;
2752
2753 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2754 ret = os_snprintf(pos, end - pos, "?]");
2755 if (os_snprintf_error(end - pos, ret))
2756 return pos;
2757 pos += ret;
2758 return pos;
2759 }
2760
2761 start = pos;
2762 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2763 ret = os_snprintf(pos, end - pos, "%sEAP",
2764 pos == start ? "" : "+");
2765 if (os_snprintf_error(end - pos, ret))
2766 return pos;
2767 pos += ret;
2768 }
2769 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2770 ret = os_snprintf(pos, end - pos, "%sPSK",
2771 pos == start ? "" : "+");
2772 if (os_snprintf_error(end - pos, ret))
2773 return pos;
2774 pos += ret;
2775 }
2776 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2777 ret = os_snprintf(pos, end - pos, "%sNone",
2778 pos == start ? "" : "+");
2779 if (os_snprintf_error(end - pos, ret))
2780 return pos;
2781 pos += ret;
2782 }
2783 if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2784 ret = os_snprintf(pos, end - pos, "%sSAE",
2785 pos == start ? "" : "+");
2786 if (os_snprintf_error(end - pos, ret))
2787 return pos;
2788 pos += ret;
2789 }
2790 #ifdef CONFIG_IEEE80211R
2791 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2792 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2793 pos == start ? "" : "+");
2794 if (os_snprintf_error(end - pos, ret))
2795 return pos;
2796 pos += ret;
2797 }
2798 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2799 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2800 pos == start ? "" : "+");
2801 if (os_snprintf_error(end - pos, ret))
2802 return pos;
2803 pos += ret;
2804 }
2805 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2806 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2807 pos == start ? "" : "+");
2808 if (os_snprintf_error(end - pos, ret))
2809 return pos;
2810 pos += ret;
2811 }
2812 #endif /* CONFIG_IEEE80211R */
2813 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2814 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2815 pos == start ? "" : "+");
2816 if (os_snprintf_error(end - pos, ret))
2817 return pos;
2818 pos += ret;
2819 }
2820 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2821 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2822 pos == start ? "" : "+");
2823 if (os_snprintf_error(end - pos, ret))
2824 return pos;
2825 pos += ret;
2826 }
2827
2828 #ifdef CONFIG_SUITEB
2829 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2830 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2831 pos == start ? "" : "+");
2832 if (os_snprintf_error(end - pos, ret))
2833 return pos;
2834 pos += ret;
2835 }
2836 #endif /* CONFIG_SUITEB */
2837
2838 #ifdef CONFIG_SUITEB192
2839 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2840 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2841 pos == start ? "" : "+");
2842 if (os_snprintf_error(end - pos, ret))
2843 return pos;
2844 pos += ret;
2845 }
2846 #endif /* CONFIG_SUITEB192 */
2847
2848 #ifdef CONFIG_FILS
2849 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2850 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2851 pos == start ? "" : "+");
2852 if (os_snprintf_error(end - pos, ret))
2853 return pos;
2854 pos += ret;
2855 }
2856 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2857 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2858 pos == start ? "" : "+");
2859 if (os_snprintf_error(end - pos, ret))
2860 return pos;
2861 pos += ret;
2862 }
2863 #ifdef CONFIG_IEEE80211R
2864 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2865 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2866 pos == start ? "" : "+");
2867 if (os_snprintf_error(end - pos, ret))
2868 return pos;
2869 pos += ret;
2870 }
2871 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2872 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2873 pos == start ? "" : "+");
2874 if (os_snprintf_error(end - pos, ret))
2875 return pos;
2876 pos += ret;
2877 }
2878 #endif /* CONFIG_IEEE80211R */
2879 #endif /* CONFIG_FILS */
2880
2881 #ifdef CONFIG_OWE
2882 if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2883 ret = os_snprintf(pos, end - pos, "%sOWE",
2884 pos == start ? "" : "+");
2885 if (os_snprintf_error(end - pos, ret))
2886 return pos;
2887 pos += ret;
2888 }
2889 #endif /* CONFIG_OWE */
2890
2891 #ifdef CONFIG_DPP
2892 if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
2893 ret = os_snprintf(pos, end - pos, "%sDPP",
2894 pos == start ? "" : "+");
2895 if (os_snprintf_error(end - pos, ret))
2896 return pos;
2897 pos += ret;
2898 }
2899 #endif /* CONFIG_DPP */
2900
2901 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
2902 ret = os_snprintf(pos, end - pos, "%sOSEN",
2903 pos == start ? "" : "+");
2904 if (os_snprintf_error(end - pos, ret))
2905 return pos;
2906 pos += ret;
2907 }
2908
2909 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2910
2911 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2912 ret = os_snprintf(pos, end - pos, "-preauth");
2913 if (os_snprintf_error(end - pos, ret))
2914 return pos;
2915 pos += ret;
2916 }
2917
2918 ret = os_snprintf(pos, end - pos, "]");
2919 if (os_snprintf_error(end - pos, ret))
2920 return pos;
2921 pos += ret;
2922
2923 return pos;
2924 }
2925
2926
2927 #ifdef CONFIG_WPS
wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant * wpa_s,char * pos,char * end,struct wpabuf * wps_ie)2928 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2929 char *pos, char *end,
2930 struct wpabuf *wps_ie)
2931 {
2932 int ret;
2933 const char *txt;
2934
2935 if (wps_ie == NULL)
2936 return pos;
2937 if (wps_is_selected_pbc_registrar(wps_ie))
2938 txt = "[WPS-PBC]";
2939 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2940 txt = "[WPS-AUTH]";
2941 else if (wps_is_selected_pin_registrar(wps_ie))
2942 txt = "[WPS-PIN]";
2943 else
2944 txt = "[WPS]";
2945
2946 ret = os_snprintf(pos, end - pos, "%s", txt);
2947 if (!os_snprintf_error(end - pos, ret))
2948 pos += ret;
2949 wpabuf_free(wps_ie);
2950 return pos;
2951 }
2952 #endif /* CONFIG_WPS */
2953
2954
wpa_supplicant_wps_ie_txt(struct wpa_supplicant * wpa_s,char * pos,char * end,const struct wpa_bss * bss)2955 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2956 char *pos, char *end,
2957 const struct wpa_bss *bss)
2958 {
2959 #ifdef CONFIG_WPS
2960 struct wpabuf *wps_ie;
2961 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2962 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2963 #else /* CONFIG_WPS */
2964 return pos;
2965 #endif /* CONFIG_WPS */
2966 }
2967
2968
2969 /* 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)2970 static int wpa_supplicant_ctrl_iface_scan_result(
2971 struct wpa_supplicant *wpa_s,
2972 const struct wpa_bss *bss, char *buf, size_t buflen)
2973 {
2974 char *pos, *end;
2975 int ret;
2976 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
2977
2978 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
2979 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2980 if (!p2p)
2981 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2982 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2983 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2984 0)
2985 return 0; /* Do not show P2P listen discovery results here */
2986
2987 pos = buf;
2988 end = buf + buflen;
2989
2990 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2991 MAC2STR(bss->bssid), bss->freq, bss->level);
2992 if (os_snprintf_error(end - pos, ret))
2993 return -1;
2994 pos += ret;
2995 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2996 if (ie)
2997 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2998 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2999 if (ie2) {
3000 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3001 ie2, 2 + ie2[1]);
3002 }
3003 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
3004 if (rsnxe && rsnxe[1] >= 1) {
3005 if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
3006 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3007 if (os_snprintf_error(end - pos, ret))
3008 return -1;
3009 pos += ret;
3010 }
3011 if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
3012 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3013 if (os_snprintf_error(end - pos, ret))
3014 return -1;
3015 pos += ret;
3016 }
3017 }
3018 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3019 if (osen_ie)
3020 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3021 osen_ie, 2 + osen_ie[1]);
3022 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3023 if (owe) {
3024 ret = os_snprintf(pos, end - pos,
3025 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3026 if (os_snprintf_error(end - pos, ret))
3027 return -1;
3028 pos += ret;
3029 }
3030 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3031 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
3032 ret = os_snprintf(pos, end - pos, "[WEP]");
3033 if (os_snprintf_error(end - pos, ret))
3034 return -1;
3035 pos += ret;
3036 }
3037 if (mesh) {
3038 ret = os_snprintf(pos, end - pos, "[MESH]");
3039 if (os_snprintf_error(end - pos, ret))
3040 return -1;
3041 pos += ret;
3042 }
3043 if (bss_is_dmg(bss)) {
3044 const char *s;
3045
3046 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
3047 ret = os_snprintf(pos, end - pos, "[EDMG]");
3048 if (os_snprintf_error(end - pos, ret))
3049 return -1;
3050 pos += ret;
3051 }
3052
3053 ret = os_snprintf(pos, end - pos, "[DMG]");
3054 if (os_snprintf_error(end - pos, ret))
3055 return -1;
3056 pos += ret;
3057 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3058 case IEEE80211_CAP_DMG_IBSS:
3059 s = "[IBSS]";
3060 break;
3061 case IEEE80211_CAP_DMG_AP:
3062 s = "[ESS]";
3063 break;
3064 case IEEE80211_CAP_DMG_PBSS:
3065 s = "[PBSS]";
3066 break;
3067 default:
3068 s = "";
3069 break;
3070 }
3071 ret = os_snprintf(pos, end - pos, "%s", s);
3072 if (os_snprintf_error(end - pos, ret))
3073 return -1;
3074 pos += ret;
3075 } else {
3076 if (bss->caps & IEEE80211_CAP_IBSS) {
3077 ret = os_snprintf(pos, end - pos, "[IBSS]");
3078 if (os_snprintf_error(end - pos, ret))
3079 return -1;
3080 pos += ret;
3081 }
3082 if (bss->caps & IEEE80211_CAP_ESS) {
3083 ret = os_snprintf(pos, end - pos, "[ESS]");
3084 if (os_snprintf_error(end - pos, ret))
3085 return -1;
3086 pos += ret;
3087 }
3088 }
3089 if (p2p) {
3090 ret = os_snprintf(pos, end - pos, "[P2P]");
3091 if (os_snprintf_error(end - pos, ret))
3092 return -1;
3093 pos += ret;
3094 }
3095 #ifdef CONFIG_HS20
3096 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
3097 ret = os_snprintf(pos, end - pos, "[HS20]");
3098 if (os_snprintf_error(end - pos, ret))
3099 return -1;
3100 pos += ret;
3101 }
3102 #endif /* CONFIG_HS20 */
3103 #ifdef CONFIG_FILS
3104 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3105 ret = os_snprintf(pos, end - pos, "[FILS]");
3106 if (os_snprintf_error(end - pos, ret))
3107 return -1;
3108 pos += ret;
3109 }
3110 #endif /* CONFIG_FILS */
3111 #ifdef CONFIG_FST
3112 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3113 ret = os_snprintf(pos, end - pos, "[FST]");
3114 if (os_snprintf_error(end - pos, ret))
3115 return -1;
3116 pos += ret;
3117 }
3118 #endif /* CONFIG_FST */
3119 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3120 ret = os_snprintf(pos, end - pos, "[UTF-8]");
3121 if (os_snprintf_error(end - pos, ret))
3122 return -1;
3123 pos += ret;
3124 }
3125
3126 ret = os_snprintf(pos, end - pos, "\t%s",
3127 wpa_ssid_txt(bss->ssid, bss->ssid_len));
3128 if (os_snprintf_error(end - pos, ret))
3129 return -1;
3130 pos += ret;
3131
3132 ret = os_snprintf(pos, end - pos, "\n");
3133 if (os_snprintf_error(end - pos, ret))
3134 return -1;
3135 pos += ret;
3136
3137 return pos - buf;
3138 }
3139
3140
wpa_supplicant_ctrl_iface_scan_results(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3141 static int wpa_supplicant_ctrl_iface_scan_results(
3142 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3143 {
3144 char *pos, *end;
3145 struct wpa_bss *bss;
3146 int ret;
3147
3148 pos = buf;
3149 end = buf + buflen;
3150 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3151 "flags / ssid\n");
3152 if (os_snprintf_error(end - pos, ret))
3153 return pos - buf;
3154 pos += ret;
3155
3156 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3157 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3158 end - pos);
3159 if (ret < 0 || ret >= end - pos)
3160 return pos - buf;
3161 pos += ret;
3162 }
3163
3164 return pos - buf;
3165 }
3166
3167
3168 #ifdef CONFIG_MESH
3169
wpa_supplicant_ctrl_iface_mesh_interface_add(struct wpa_supplicant * wpa_s,char * cmd,char * reply,size_t max_len)3170 static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3171 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3172 {
3173 char *pos, ifname[IFNAMSIZ + 1];
3174
3175 ifname[0] = '\0';
3176
3177 pos = os_strstr(cmd, "ifname=");
3178 if (pos) {
3179 pos += 7;
3180 os_strlcpy(ifname, pos, sizeof(ifname));
3181 }
3182
3183 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3184 return -1;
3185
3186 os_strlcpy(reply, ifname, max_len);
3187 return os_strlen(ifname);
3188 }
3189
3190
wpa_supplicant_ctrl_iface_mesh_group_add(struct wpa_supplicant * wpa_s,char * cmd)3191 static int wpa_supplicant_ctrl_iface_mesh_group_add(
3192 struct wpa_supplicant *wpa_s, char *cmd)
3193 {
3194 int id;
3195 struct wpa_ssid *ssid;
3196
3197 id = atoi(cmd);
3198 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3199
3200 ssid = wpa_config_get_network(wpa_s->conf, id);
3201 if (ssid == NULL) {
3202 wpa_printf(MSG_DEBUG,
3203 "CTRL_IFACE: Could not find network id=%d", id);
3204 return -1;
3205 }
3206 if (ssid->mode != WPAS_MODE_MESH) {
3207 wpa_printf(MSG_DEBUG,
3208 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3209 return -1;
3210 }
3211 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3212 ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
3213 wpa_printf(MSG_ERROR,
3214 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3215 return -1;
3216 }
3217
3218 /*
3219 * TODO: If necessary write our own group_add function,
3220 * for now we can reuse select_network
3221 */
3222 wpa_supplicant_select_network(wpa_s, ssid);
3223
3224 return 0;
3225 }
3226
3227
wpa_supplicant_ctrl_iface_mesh_group_remove(struct wpa_supplicant * wpa_s,char * cmd)3228 static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3229 struct wpa_supplicant *wpa_s, char *cmd)
3230 {
3231 struct wpa_supplicant *orig;
3232 struct wpa_global *global;
3233 int found = 0;
3234
3235 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3236
3237 global = wpa_s->global;
3238 orig = wpa_s;
3239
3240 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3241 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3242 found = 1;
3243 break;
3244 }
3245 }
3246 if (!found) {
3247 wpa_printf(MSG_ERROR,
3248 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3249 cmd);
3250 return -1;
3251 }
3252 if (wpa_s->mesh_if_created && wpa_s == orig) {
3253 wpa_printf(MSG_ERROR,
3254 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3255 return -1;
3256 }
3257
3258 wpa_s->reassociate = 0;
3259 wpa_s->disconnected = 1;
3260 wpa_supplicant_cancel_sched_scan(wpa_s);
3261 wpa_supplicant_cancel_scan(wpa_s);
3262
3263 /*
3264 * TODO: If necessary write our own group_remove function,
3265 * for now we can reuse deauthenticate
3266 */
3267 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3268
3269 if (wpa_s->mesh_if_created)
3270 wpa_supplicant_remove_iface(global, wpa_s, 0);
3271
3272 return 0;
3273 }
3274
3275
wpa_supplicant_ctrl_iface_mesh_peer_remove(struct wpa_supplicant * wpa_s,char * cmd)3276 static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3277 struct wpa_supplicant *wpa_s, char *cmd)
3278 {
3279 u8 addr[ETH_ALEN];
3280
3281 if (hwaddr_aton(cmd, addr) < 0)
3282 return -1;
3283
3284 return wpas_mesh_peer_remove(wpa_s, addr);
3285 }
3286
3287
wpa_supplicant_ctrl_iface_mesh_peer_add(struct wpa_supplicant * wpa_s,char * cmd)3288 static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3289 struct wpa_supplicant *wpa_s, char *cmd)
3290 {
3291 u8 addr[ETH_ALEN];
3292 int duration;
3293 char *pos;
3294
3295 pos = os_strstr(cmd, " duration=");
3296 if (pos) {
3297 *pos = '\0';
3298 duration = atoi(pos + 10);
3299 } else {
3300 duration = -1;
3301 }
3302
3303 if (hwaddr_aton(cmd, addr))
3304 return -1;
3305
3306 return wpas_mesh_peer_add(wpa_s, addr, duration);
3307 }
3308
3309
wpa_supplicant_ctrl_iface_mesh_link_probe(struct wpa_supplicant * wpa_s,char * cmd)3310 static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3311 struct wpa_supplicant *wpa_s, char *cmd)
3312 {
3313 struct ether_header *eth;
3314 u8 addr[ETH_ALEN];
3315 u8 *buf;
3316 char *pos;
3317 size_t payload_len = 0, len;
3318 int ret = -1;
3319
3320 if (hwaddr_aton(cmd, addr))
3321 return -1;
3322
3323 pos = os_strstr(cmd, " payload=");
3324 if (pos) {
3325 pos = pos + 9;
3326 payload_len = os_strlen(pos);
3327 if (payload_len & 1)
3328 return -1;
3329
3330 payload_len /= 2;
3331 }
3332
3333 len = ETH_HLEN + payload_len;
3334 buf = os_malloc(len);
3335 if (!buf)
3336 return -1;
3337
3338 eth = (struct ether_header *) buf;
3339 os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3340 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3341 eth->ether_type = htons(ETH_P_802_3);
3342
3343 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3344 goto fail;
3345
3346 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3347 fail:
3348 os_free(buf);
3349 return -ret;
3350 }
3351
3352 #endif /* CONFIG_MESH */
3353
3354
wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant * wpa_s,char * cmd)3355 static int wpa_supplicant_ctrl_iface_select_network(
3356 struct wpa_supplicant *wpa_s, char *cmd)
3357 {
3358 int id;
3359 struct wpa_ssid *ssid;
3360 char *pos;
3361
3362 /* cmd: "<network id>" or "any" */
3363 if (os_strncmp(cmd, "any", 3) == 0) {
3364 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3365 ssid = NULL;
3366 } else {
3367 id = atoi(cmd);
3368 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3369
3370 ssid = wpa_config_get_network(wpa_s->conf, id);
3371 if (ssid == NULL) {
3372 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3373 "network id=%d", id);
3374 return -1;
3375 }
3376 if (ssid->disabled == 2) {
3377 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3378 "SELECT_NETWORK with persistent P2P group");
3379 return -1;
3380 }
3381 }
3382
3383 pos = os_strstr(cmd, " freq=");
3384 if (pos) {
3385 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3386 if (freqs) {
3387 os_free(wpa_s->select_network_scan_freqs);
3388 wpa_s->select_network_scan_freqs = freqs;
3389 }
3390 }
3391
3392 wpa_s->scan_min_time.sec = 0;
3393 wpa_s->scan_min_time.usec = 0;
3394 wpa_supplicant_select_network(wpa_s, ssid);
3395
3396 return 0;
3397 }
3398
3399
wpa_supplicant_ctrl_iface_enable_network(struct wpa_supplicant * wpa_s,char * cmd)3400 static int wpa_supplicant_ctrl_iface_enable_network(
3401 struct wpa_supplicant *wpa_s, char *cmd)
3402 {
3403 int id;
3404 struct wpa_ssid *ssid;
3405
3406 /* cmd: "<network id>" or "all" */
3407 if (os_strcmp(cmd, "all") == 0) {
3408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3409 ssid = NULL;
3410 } else {
3411 id = atoi(cmd);
3412 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3413
3414 ssid = wpa_config_get_network(wpa_s->conf, id);
3415 if (ssid == NULL) {
3416 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3417 "network id=%d", id);
3418 return -1;
3419 }
3420 if (ssid->disabled == 2) {
3421 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3422 "ENABLE_NETWORK with persistent P2P group");
3423 return -1;
3424 }
3425
3426 if (os_strstr(cmd, " no-connect")) {
3427 ssid->disabled = 0;
3428 return 0;
3429 }
3430 }
3431 wpa_s->scan_min_time.sec = 0;
3432 wpa_s->scan_min_time.usec = 0;
3433 wpa_supplicant_enable_network(wpa_s, ssid);
3434
3435 return 0;
3436 }
3437
3438
wpa_supplicant_ctrl_iface_disable_network(struct wpa_supplicant * wpa_s,char * cmd)3439 static int wpa_supplicant_ctrl_iface_disable_network(
3440 struct wpa_supplicant *wpa_s, char *cmd)
3441 {
3442 int id;
3443 struct wpa_ssid *ssid;
3444
3445 /* cmd: "<network id>" or "all" */
3446 if (os_strcmp(cmd, "all") == 0) {
3447 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3448 ssid = NULL;
3449 } else {
3450 id = atoi(cmd);
3451 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3452
3453 ssid = wpa_config_get_network(wpa_s->conf, id);
3454 if (ssid == NULL) {
3455 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3456 "network id=%d", id);
3457 return -1;
3458 }
3459 if (ssid->disabled == 2) {
3460 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3461 "DISABLE_NETWORK with persistent P2P "
3462 "group");
3463 return -1;
3464 }
3465 }
3466 wpa_supplicant_disable_network(wpa_s, ssid);
3467
3468 return 0;
3469 }
3470
3471
wpa_supplicant_ctrl_iface_add_network(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3472 static int wpa_supplicant_ctrl_iface_add_network(
3473 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3474 {
3475 struct wpa_ssid *ssid;
3476 int ret;
3477
3478 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3479
3480 ssid = wpa_supplicant_add_network(wpa_s);
3481 if (ssid == NULL)
3482 return -1;
3483
3484 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
3485 if (os_snprintf_error(buflen, ret))
3486 return -1;
3487 return ret;
3488 }
3489
3490
wpa_supplicant_ctrl_iface_remove_network(struct wpa_supplicant * wpa_s,char * cmd)3491 static int wpa_supplicant_ctrl_iface_remove_network(
3492 struct wpa_supplicant *wpa_s, char *cmd)
3493 {
3494 int id;
3495 int result;
3496
3497 /* cmd: "<network id>" or "all" */
3498 if (os_strcmp(cmd, "all") == 0) {
3499 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
3500 return wpa_supplicant_remove_all_networks(wpa_s);
3501 }
3502
3503 id = atoi(cmd);
3504 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3505
3506 result = wpa_supplicant_remove_network(wpa_s, id);
3507 if (result == -1) {
3508 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3509 "id=%d", id);
3510 return -1;
3511 }
3512 if (result == -2) {
3513 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3514 "network id=%d", id);
3515 return -1;
3516 }
3517 return 0;
3518 }
3519
3520
wpa_supplicant_ctrl_iface_update_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,char * name,char * value)3521 static int wpa_supplicant_ctrl_iface_update_network(
3522 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3523 char *name, char *value)
3524 {
3525 int ret;
3526
3527 ret = wpa_config_set(ssid, name, value, 0);
3528 if (ret < 0) {
3529 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3530 "variable '%s'", name);
3531 return -1;
3532 }
3533 if (ret == 1)
3534 return 0; /* No change to the previously configured value */
3535
3536 #ifdef CONFIG_BGSCAN
3537 if (os_strcmp(name, "bgscan") == 0) {
3538 /*
3539 * Reset the bgscan parameters for the current network and
3540 * return. There's no need to flush caches for bgscan parameter
3541 * changes.
3542 */
3543 if (wpa_s->current_ssid == ssid &&
3544 wpa_s->wpa_state == WPA_COMPLETED)
3545 wpa_supplicant_reset_bgscan(wpa_s);
3546 return 0;
3547 }
3548 #endif /* CONFIG_BGSCAN */
3549
3550 if (os_strcmp(name, "bssid") != 0 &&
3551 os_strcmp(name, "bssid_hint") != 0 &&
3552 os_strcmp(name, "priority") != 0) {
3553 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3554
3555 if (wpa_s->current_ssid == ssid ||
3556 wpa_s->current_ssid == NULL) {
3557 /*
3558 * Invalidate the EAP session cache if anything in the
3559 * current or previously used configuration changes.
3560 */
3561 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3562 }
3563 }
3564
3565 if ((os_strcmp(name, "psk") == 0 &&
3566 value[0] == '"' && ssid->ssid_len) ||
3567 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3568 wpa_config_update_psk(ssid);
3569 else if (os_strcmp(name, "priority") == 0)
3570 wpa_config_update_prio_list(wpa_s->conf);
3571
3572 return 0;
3573 }
3574
3575
wpa_supplicant_ctrl_iface_set_network(struct wpa_supplicant * wpa_s,char * cmd)3576 static int wpa_supplicant_ctrl_iface_set_network(
3577 struct wpa_supplicant *wpa_s, char *cmd)
3578 {
3579 int id, ret, prev_bssid_set, prev_disabled;
3580 struct wpa_ssid *ssid;
3581 char *name, *value;
3582 u8 prev_bssid[ETH_ALEN];
3583
3584 /* cmd: "<network id> <variable name> <value>" */
3585 name = os_strchr(cmd, ' ');
3586 if (name == NULL)
3587 return -1;
3588 *name++ = '\0';
3589
3590 value = os_strchr(name, ' ');
3591 if (value == NULL)
3592 return -1;
3593 *value++ = '\0';
3594
3595 id = atoi(cmd);
3596 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3597 id, name);
3598 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3599 (u8 *) value, os_strlen(value));
3600
3601 ssid = wpa_config_get_network(wpa_s->conf, id);
3602 if (ssid == NULL) {
3603 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3604 "id=%d", id);
3605 return -1;
3606 }
3607
3608 prev_bssid_set = ssid->bssid_set;
3609 prev_disabled = ssid->disabled;
3610 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3611 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3612 value);
3613 if (ret == 0 &&
3614 (ssid->bssid_set != prev_bssid_set ||
3615 os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
3616 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
3617
3618 if (prev_disabled != ssid->disabled &&
3619 (prev_disabled == 2 || ssid->disabled == 2))
3620 wpas_notify_network_type_changed(wpa_s, ssid);
3621
3622 return ret;
3623 }
3624
3625
wpa_supplicant_ctrl_iface_get_network(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3626 static int wpa_supplicant_ctrl_iface_get_network(
3627 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3628 {
3629 int id;
3630 size_t res;
3631 struct wpa_ssid *ssid;
3632 char *name, *value;
3633
3634 /* cmd: "<network id> <variable name>" */
3635 name = os_strchr(cmd, ' ');
3636 if (name == NULL || buflen == 0)
3637 return -1;
3638 *name++ = '\0';
3639
3640 id = atoi(cmd);
3641 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3642 id, name);
3643
3644 ssid = wpa_config_get_network(wpa_s->conf, id);
3645 if (ssid == NULL) {
3646 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
3647 "id=%d", id);
3648 return -1;
3649 }
3650
3651 value = wpa_config_get_no_key(ssid, name);
3652 if (value == NULL) {
3653 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
3654 "variable '%s'", name);
3655 return -1;
3656 }
3657
3658 res = os_strlcpy(buf, value, buflen);
3659 if (res >= buflen) {
3660 os_free(value);
3661 return -1;
3662 }
3663
3664 os_free(value);
3665
3666 return res;
3667 }
3668
3669
wpa_supplicant_ctrl_iface_dup_network(struct wpa_supplicant * wpa_s,char * cmd,struct wpa_supplicant * dst_wpa_s)3670 static int wpa_supplicant_ctrl_iface_dup_network(
3671 struct wpa_supplicant *wpa_s, char *cmd,
3672 struct wpa_supplicant *dst_wpa_s)
3673 {
3674 struct wpa_ssid *ssid_s, *ssid_d;
3675 char *name, *id, *value;
3676 int id_s, id_d, ret;
3677
3678 /* cmd: "<src network id> <dst network id> <variable name>" */
3679 id = os_strchr(cmd, ' ');
3680 if (id == NULL)
3681 return -1;
3682 *id++ = '\0';
3683
3684 name = os_strchr(id, ' ');
3685 if (name == NULL)
3686 return -1;
3687 *name++ = '\0';
3688
3689 id_s = atoi(cmd);
3690 id_d = atoi(id);
3691
3692 wpa_printf(MSG_DEBUG,
3693 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3694 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
3695
3696 ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3697 if (ssid_s == NULL) {
3698 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3699 "network id=%d", id_s);
3700 return -1;
3701 }
3702
3703 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
3704 if (ssid_d == NULL) {
3705 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3706 "network id=%d", id_d);
3707 return -1;
3708 }
3709
3710 value = wpa_config_get(ssid_s, name);
3711 if (value == NULL) {
3712 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3713 "variable '%s'", name);
3714 return -1;
3715 }
3716
3717 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
3718 value);
3719
3720 os_free(value);
3721
3722 return ret;
3723 }
3724
3725
wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3726 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3727 char *buf, size_t buflen)
3728 {
3729 char *pos, *end;
3730 struct wpa_cred *cred;
3731 int ret;
3732
3733 pos = buf;
3734 end = buf + buflen;
3735 ret = os_snprintf(pos, end - pos,
3736 "cred id / realm / username / domain / imsi\n");
3737 if (os_snprintf_error(end - pos, ret))
3738 return pos - buf;
3739 pos += ret;
3740
3741 cred = wpa_s->conf->cred;
3742 while (cred) {
3743 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3744 cred->id, cred->realm ? cred->realm : "",
3745 cred->username ? cred->username : "",
3746 cred->domain ? cred->domain[0] : "",
3747 cred->imsi ? cred->imsi : "");
3748 if (os_snprintf_error(end - pos, ret))
3749 return pos - buf;
3750 pos += ret;
3751
3752 cred = cred->next;
3753 }
3754
3755 return pos - buf;
3756 }
3757
3758
wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)3759 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3760 char *buf, size_t buflen)
3761 {
3762 struct wpa_cred *cred;
3763 int ret;
3764
3765 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3766
3767 cred = wpa_config_add_cred(wpa_s->conf);
3768 if (cred == NULL)
3769 return -1;
3770
3771 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3772
3773 ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3774 if (os_snprintf_error(buflen, ret))
3775 return -1;
3776 return ret;
3777 }
3778
3779
wpas_ctrl_remove_cred(struct wpa_supplicant * wpa_s,struct wpa_cred * cred)3780 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
3781 struct wpa_cred *cred)
3782 {
3783 struct wpa_ssid *ssid;
3784 char str[20];
3785 int id;
3786
3787 if (cred == NULL) {
3788 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3789 return -1;
3790 }
3791
3792 id = cred->id;
3793 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
3794 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3795 return -1;
3796 }
3797
3798 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
3799
3800 /* Remove any network entry created based on the removed credential */
3801 ssid = wpa_s->conf->ssid;
3802 while (ssid) {
3803 if (ssid->parent_cred == cred) {
3804 int res;
3805
3806 wpa_printf(MSG_DEBUG, "Remove network id %d since it "
3807 "used the removed credential", ssid->id);
3808 res = os_snprintf(str, sizeof(str), "%d", ssid->id);
3809 if (os_snprintf_error(sizeof(str), res))
3810 str[sizeof(str) - 1] = '\0';
3811 ssid = ssid->next;
3812 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
3813 } else
3814 ssid = ssid->next;
3815 }
3816
3817 return 0;
3818 }
3819
3820
wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant * wpa_s,char * cmd)3821 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3822 char *cmd)
3823 {
3824 int id;
3825 struct wpa_cred *cred, *prev;
3826
3827 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3828 * "provisioning_sp=<FQDN> */
3829 if (os_strcmp(cmd, "all") == 0) {
3830 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3831 cred = wpa_s->conf->cred;
3832 while (cred) {
3833 prev = cred;
3834 cred = cred->next;
3835 wpas_ctrl_remove_cred(wpa_s, prev);
3836 }
3837 return 0;
3838 }
3839
3840 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3841 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3842 cmd + 8);
3843 cred = wpa_s->conf->cred;
3844 while (cred) {
3845 prev = cred;
3846 cred = cred->next;
3847 if (prev->domain) {
3848 size_t i;
3849 for (i = 0; i < prev->num_domain; i++) {
3850 if (os_strcmp(prev->domain[i], cmd + 8)
3851 != 0)
3852 continue;
3853 wpas_ctrl_remove_cred(wpa_s, prev);
3854 break;
3855 }
3856 }
3857 }
3858 return 0;
3859 }
3860
3861 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3862 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3863 cmd + 16);
3864 cred = wpa_s->conf->cred;
3865 while (cred) {
3866 prev = cred;
3867 cred = cred->next;
3868 if (prev->provisioning_sp &&
3869 os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3870 wpas_ctrl_remove_cred(wpa_s, prev);
3871 }
3872 return 0;
3873 }
3874
3875 id = atoi(cmd);
3876 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3877
3878 cred = wpa_config_get_cred(wpa_s->conf, id);
3879 return wpas_ctrl_remove_cred(wpa_s, cred);
3880 }
3881
3882
wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant * wpa_s,char * cmd)3883 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3884 char *cmd)
3885 {
3886 int id;
3887 struct wpa_cred *cred;
3888 char *name, *value;
3889
3890 /* cmd: "<cred id> <variable name> <value>" */
3891 name = os_strchr(cmd, ' ');
3892 if (name == NULL)
3893 return -1;
3894 *name++ = '\0';
3895
3896 value = os_strchr(name, ' ');
3897 if (value == NULL)
3898 return -1;
3899 *value++ = '\0';
3900
3901 id = atoi(cmd);
3902 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3903 id, name);
3904 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3905 (u8 *) value, os_strlen(value));
3906
3907 cred = wpa_config_get_cred(wpa_s->conf, id);
3908 if (cred == NULL) {
3909 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3910 id);
3911 return -1;
3912 }
3913
3914 if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3915 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3916 "variable '%s'", name);
3917 return -1;
3918 }
3919
3920 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3921
3922 return 0;
3923 }
3924
3925
wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)3926 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3927 char *cmd, char *buf,
3928 size_t buflen)
3929 {
3930 int id;
3931 size_t res;
3932 struct wpa_cred *cred;
3933 char *name, *value;
3934
3935 /* cmd: "<cred id> <variable name>" */
3936 name = os_strchr(cmd, ' ');
3937 if (name == NULL)
3938 return -1;
3939 *name++ = '\0';
3940
3941 id = atoi(cmd);
3942 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3943 id, name);
3944
3945 cred = wpa_config_get_cred(wpa_s->conf, id);
3946 if (cred == NULL) {
3947 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3948 id);
3949 return -1;
3950 }
3951
3952 value = wpa_config_get_cred_no_key(cred, name);
3953 if (value == NULL) {
3954 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
3955 name);
3956 return -1;
3957 }
3958
3959 res = os_strlcpy(buf, value, buflen);
3960 if (res >= buflen) {
3961 os_free(value);
3962 return -1;
3963 }
3964
3965 os_free(value);
3966
3967 return res;
3968 }
3969
3970
3971 #ifndef CONFIG_NO_CONFIG_WRITE
wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant * wpa_s)3972 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
3973 {
3974 int ret;
3975
3976 if (!wpa_s->conf->update_config) {
3977 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
3978 "to update configuration (update_config=0)");
3979 return -1;
3980 }
3981
3982 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
3983 if (ret) {
3984 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
3985 "update configuration");
3986 } else {
3987 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
3988 " updated");
3989 }
3990
3991 return ret;
3992 }
3993 #endif /* CONFIG_NO_CONFIG_WRITE */
3994
3995
3996 struct cipher_info {
3997 unsigned int capa;
3998 const char *name;
3999 int group_only;
4000 };
4001
4002 static const struct cipher_info ciphers[] = {
4003 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4004 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4005 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4006 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
4007 #ifndef CONFIG_NO_TKIP
4008 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
4009 #endif /* CONFIG_NO_TKIP */
4010 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
4011 #ifdef CONFIG_WEP
4012 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4013 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
4014 #endif /* CONFIG_WEP */
4015 };
4016
4017 static const struct cipher_info ciphers_group_mgmt[] = {
4018 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4019 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4020 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4021 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4022 };
4023
4024
ctrl_iface_get_capability_pairwise(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4025 static int ctrl_iface_get_capability_pairwise(int res, bool strict,
4026 struct wpa_driver_capa *capa,
4027 char *buf, size_t buflen)
4028 {
4029 int ret;
4030 char *pos, *end;
4031 size_t len;
4032 unsigned int i;
4033
4034 pos = buf;
4035 end = pos + buflen;
4036
4037 if (res < 0) {
4038 if (strict)
4039 return 0;
4040 #ifdef CONFIG_NO_TKIP
4041 len = os_strlcpy(buf, "CCMP NONE", buflen);
4042 #else /* CONFIG_NO_TKIP */
4043 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
4044 #endif /* CONFIG_NO_TKIP */
4045 if (len >= buflen)
4046 return -1;
4047 return len;
4048 }
4049
4050 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4051 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4052 ret = os_snprintf(pos, end - pos, "%s%s",
4053 pos == buf ? "" : " ",
4054 ciphers[i].name);
4055 if (os_snprintf_error(end - pos, ret))
4056 return pos - buf;
4057 pos += ret;
4058 }
4059 }
4060
4061 return pos - buf;
4062 }
4063
4064
ctrl_iface_get_capability_group(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4065 static int ctrl_iface_get_capability_group(int res, bool strict,
4066 struct wpa_driver_capa *capa,
4067 char *buf, size_t buflen)
4068 {
4069 int ret;
4070 char *pos, *end;
4071 size_t len;
4072 unsigned int i;
4073
4074 pos = buf;
4075 end = pos + buflen;
4076
4077 if (res < 0) {
4078 if (strict)
4079 return 0;
4080 #ifdef CONFIG_WEP
4081 #ifdef CONFIG_NO_TKIP
4082 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4083 #else /* CONFIG_NO_TKIP */
4084 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
4085 #endif /* CONFIG_NO_TKIP */
4086 #else /* CONFIG_WEP */
4087 #ifdef CONFIG_NO_TKIP
4088 len = os_strlcpy(buf, "CCMP", buflen);
4089 #else /* CONFIG_NO_TKIP */
4090 len = os_strlcpy(buf, "CCMP TKIP", buflen);
4091 #endif /* CONFIG_NO_TKIP */
4092 #endif /* CONFIG_WEP */
4093 if (len >= buflen)
4094 return -1;
4095 return len;
4096 }
4097
4098 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4099 if (capa->enc & ciphers[i].capa) {
4100 ret = os_snprintf(pos, end - pos, "%s%s",
4101 pos == buf ? "" : " ",
4102 ciphers[i].name);
4103 if (os_snprintf_error(end - pos, ret))
4104 return pos - buf;
4105 pos += ret;
4106 }
4107 }
4108
4109 return pos - buf;
4110 }
4111
4112
ctrl_iface_get_capability_group_mgmt(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4113 static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
4114 struct wpa_driver_capa *capa,
4115 char *buf, size_t buflen)
4116 {
4117 int ret;
4118 char *pos, *end;
4119 unsigned int i;
4120
4121 pos = buf;
4122 end = pos + buflen;
4123
4124 if (res < 0)
4125 return 0;
4126
4127 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4128 if (capa->enc & ciphers_group_mgmt[i].capa) {
4129 ret = os_snprintf(pos, end - pos, "%s%s",
4130 pos == buf ? "" : " ",
4131 ciphers_group_mgmt[i].name);
4132 if (os_snprintf_error(end - pos, ret))
4133 return pos - buf;
4134 pos += ret;
4135 }
4136 }
4137
4138 return pos - buf;
4139 }
4140
4141
iftype_str_to_index(const char * iftype_str)4142 static int iftype_str_to_index(const char *iftype_str)
4143 {
4144 if (!iftype_str)
4145 return WPA_IF_MAX;
4146
4147 if (os_strcmp(iftype_str, "STATION") == 0)
4148 return WPA_IF_STATION;
4149
4150 if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4151 return WPA_IF_AP_VLAN;
4152
4153 if (os_strcmp(iftype_str, "AP") == 0)
4154 return WPA_IF_AP_BSS;
4155
4156 if (os_strcmp(iftype_str, "P2P_GO") == 0)
4157 return WPA_IF_P2P_GO;
4158
4159 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4160 return WPA_IF_P2P_CLIENT;
4161
4162 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4163 return WPA_IF_P2P_DEVICE;
4164
4165 if (os_strcmp(iftype_str, "MESH") == 0)
4166 return WPA_IF_MESH;
4167
4168 if (os_strcmp(iftype_str, "IBSS") == 0)
4169 return WPA_IF_IBSS;
4170
4171 if (os_strcmp(iftype_str, "NAN") == 0)
4172 return WPA_IF_NAN;
4173
4174 return WPA_IF_MAX;
4175 }
4176
4177
ctrl_iface_get_capability_key_mgmt(int res,bool strict,struct wpa_driver_capa * capa,const char * iftype_str,char * buf,size_t buflen)4178 static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
4179 struct wpa_driver_capa *capa,
4180 const char *iftype_str,
4181 char *buf, size_t buflen)
4182 {
4183 int ret;
4184 unsigned int key_mgmt;
4185 char *pos, *end;
4186 size_t len;
4187
4188 pos = buf;
4189 end = pos + buflen;
4190
4191 if (res < 0) {
4192 if (strict)
4193 return 0;
4194 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4195 "NONE", buflen);
4196 if (len >= buflen)
4197 return -1;
4198 return len;
4199 }
4200
4201 if (iftype_str) {
4202 enum wpa_driver_if_type iftype;
4203
4204 iftype = iftype_str_to_index(iftype_str);
4205 if (iftype == WPA_IF_MAX)
4206 return -1;
4207 key_mgmt = capa->key_mgmt_iftype[iftype];
4208 } else {
4209 key_mgmt = capa->key_mgmt;
4210 }
4211
4212 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
4213 if (os_snprintf_error(end - pos, ret))
4214 return pos - buf;
4215 pos += ret;
4216
4217 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4218 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
4219 ret = os_snprintf(pos, end - pos, " WPA-EAP");
4220 if (os_snprintf_error(end - pos, ret))
4221 return pos - buf;
4222 pos += ret;
4223 }
4224
4225 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4226 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4227 ret = os_snprintf(pos, end - pos, " WPA-PSK");
4228 if (os_snprintf_error(end - pos, ret))
4229 return pos - buf;
4230 pos += ret;
4231 }
4232
4233 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
4234 ret = os_snprintf(pos, end - pos, " WPA-NONE");
4235 if (os_snprintf_error(end - pos, ret))
4236 return pos - buf;
4237 pos += ret;
4238 }
4239
4240 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4241 ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4242 if (os_snprintf_error(end - pos, ret))
4243 return pos - buf;
4244 pos += ret;
4245 }
4246
4247 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4248 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4249 if (os_snprintf_error(end - pos, ret))
4250 return pos - buf;
4251 pos += ret;
4252 }
4253
4254 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4255 ret = os_snprintf(pos, end - pos, " CCKM");
4256 if (os_snprintf_error(end - pos, ret))
4257 return pos - buf;
4258 pos += ret;
4259 }
4260
4261 #ifdef CONFIG_SUITEB
4262 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
4263 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4264 if (os_snprintf_error(end - pos, ret))
4265 return pos - buf;
4266 pos += ret;
4267 }
4268 #endif /* CONFIG_SUITEB */
4269 #ifdef CONFIG_SUITEB192
4270 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
4271 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4272 if (os_snprintf_error(end - pos, ret))
4273 return pos - buf;
4274 pos += ret;
4275 }
4276 #endif /* CONFIG_SUITEB192 */
4277 #ifdef CONFIG_OWE
4278 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
4279 ret = os_snprintf(pos, end - pos, " OWE");
4280 if (os_snprintf_error(end - pos, ret))
4281 return pos - buf;
4282 pos += ret;
4283 }
4284 #endif /* CONFIG_OWE */
4285 #ifdef CONFIG_DPP
4286 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
4287 ret = os_snprintf(pos, end - pos, " DPP");
4288 if (os_snprintf_error(end - pos, ret))
4289 return pos - buf;
4290 pos += ret;
4291 }
4292 #endif /* CONFIG_DPP */
4293 #ifdef CONFIG_FILS
4294 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
4295 ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4296 if (os_snprintf_error(end - pos, ret))
4297 return pos - buf;
4298 pos += ret;
4299 }
4300 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
4301 ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4302 if (os_snprintf_error(end - pos, ret))
4303 return pos - buf;
4304 pos += ret;
4305 }
4306 #ifdef CONFIG_IEEE80211R
4307 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
4308 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4309 if (os_snprintf_error(end - pos, ret))
4310 return pos - buf;
4311 pos += ret;
4312 }
4313 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
4314 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4315 if (os_snprintf_error(end - pos, ret))
4316 return pos - buf;
4317 pos += ret;
4318 }
4319 #endif /* CONFIG_IEEE80211R */
4320 #endif /* CONFIG_FILS */
4321 #ifdef CONFIG_IEEE80211R
4322 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
4323 ret = os_snprintf(pos, end - pos, " FT-PSK");
4324 if (os_snprintf_error(end - pos, ret))
4325 return pos - buf;
4326 pos += ret;
4327 }
4328 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4329 ret = os_snprintf(pos, end - pos, " FT-EAP");
4330 if (os_snprintf_error(end - pos, ret))
4331 return pos - buf;
4332 pos += ret;
4333 }
4334 #ifdef CONFIG_SAE
4335 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4336 ret = os_snprintf(pos, end - pos, " FT-SAE");
4337 if (os_snprintf_error(end - pos, ret))
4338 return pos - buf;
4339 pos += ret;
4340 }
4341 #endif /* CONFIG_SAE */
4342 #ifdef CONFIG_SHA384
4343 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4344 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4345 if (os_snprintf_error(end - pos, ret))
4346 return pos - buf;
4347 pos += ret;
4348 }
4349 #endif /* CONFIG_SHA384 */
4350 #endif /* CONFIG_IEEE80211R */
4351 #ifdef CONFIG_SAE
4352 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
4353 ret = os_snprintf(pos, end - pos, " SAE");
4354 if (os_snprintf_error(end - pos, ret))
4355 return pos - buf;
4356 pos += ret;
4357 }
4358 #endif /* CONFIG_SAE */
4359 #ifdef CONFIG_SHA256
4360 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4361 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4362 if (os_snprintf_error(end - pos, ret))
4363 return pos - buf;
4364 pos += ret;
4365 }
4366
4367 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4368 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4369 if (os_snprintf_error(end - pos, ret))
4370 return pos - buf;
4371 pos += ret;
4372 }
4373 #endif /* CONFIG_SHA256 */
4374 #ifdef CONFIG_HS20
4375 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4376 ret = os_snprintf(pos, end - pos, " OSEN");
4377 if (os_snprintf_error(end - pos, ret))
4378 return pos - buf;
4379 pos += ret;
4380 }
4381 #endif /* CONFIG_HS20 */
4382
4383 return pos - buf;
4384 }
4385
4386
ctrl_iface_get_capability_proto(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4387 static int ctrl_iface_get_capability_proto(int res, bool strict,
4388 struct wpa_driver_capa *capa,
4389 char *buf, size_t buflen)
4390 {
4391 int ret;
4392 char *pos, *end;
4393 size_t len;
4394
4395 pos = buf;
4396 end = pos + buflen;
4397
4398 if (res < 0) {
4399 if (strict)
4400 return 0;
4401 len = os_strlcpy(buf, "RSN WPA", buflen);
4402 if (len >= buflen)
4403 return -1;
4404 return len;
4405 }
4406
4407 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4408 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
4409 ret = os_snprintf(pos, end - pos, "%sRSN",
4410 pos == buf ? "" : " ");
4411 if (os_snprintf_error(end - pos, ret))
4412 return pos - buf;
4413 pos += ret;
4414 }
4415
4416 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4417 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
4418 ret = os_snprintf(pos, end - pos, "%sWPA",
4419 pos == buf ? "" : " ");
4420 if (os_snprintf_error(end - pos, ret))
4421 return pos - buf;
4422 pos += ret;
4423 }
4424
4425 return pos - buf;
4426 }
4427
4428
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)4429 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
4430 int res, bool strict,
4431 struct wpa_driver_capa *capa,
4432 char *buf, size_t buflen)
4433 {
4434 int ret;
4435 char *pos, *end;
4436 size_t len;
4437
4438 pos = buf;
4439 end = pos + buflen;
4440
4441 if (res < 0) {
4442 if (strict)
4443 return 0;
4444 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4445 if (len >= buflen)
4446 return -1;
4447 return len;
4448 }
4449
4450 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
4451 ret = os_snprintf(pos, end - pos, "%sOPEN",
4452 pos == buf ? "" : " ");
4453 if (os_snprintf_error(end - pos, ret))
4454 return pos - buf;
4455 pos += ret;
4456 }
4457
4458 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4459 ret = os_snprintf(pos, end - pos, "%sSHARED",
4460 pos == buf ? "" : " ");
4461 if (os_snprintf_error(end - pos, ret))
4462 return pos - buf;
4463 pos += ret;
4464 }
4465
4466 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
4467 ret = os_snprintf(pos, end - pos, "%sLEAP",
4468 pos == buf ? "" : " ");
4469 if (os_snprintf_error(end - pos, ret))
4470 return pos - buf;
4471 pos += ret;
4472 }
4473
4474 #ifdef CONFIG_SAE
4475 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4476 ret = os_snprintf(pos, end - pos, "%sSAE",
4477 pos == buf ? "" : " ");
4478 if (os_snprintf_error(end - pos, ret))
4479 return pos - buf;
4480 pos += ret;
4481 }
4482 #endif /* CONFIG_SAE */
4483
4484 #ifdef CONFIG_FILS
4485 if (wpa_is_fils_supported(wpa_s)) {
4486 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4487 pos == buf ? "" : " ");
4488 if (os_snprintf_error(end - pos, ret))
4489 return pos - buf;
4490 pos += ret;
4491 }
4492
4493 #ifdef CONFIG_FILS_SK_PFS
4494 if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4495 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4496 pos == buf ? "" : " ");
4497 if (os_snprintf_error(end - pos, ret))
4498 return pos - buf;
4499 pos += ret;
4500 }
4501 #endif /* CONFIG_FILS_SK_PFS */
4502 #endif /* CONFIG_FILS */
4503
4504 #ifdef CONFIG_PASN
4505 ret = os_snprintf(pos, end - pos, "%sPASN",
4506 pos == buf ? "" : " ");
4507 if (os_snprintf_error(end - pos, ret))
4508 return pos - buf;
4509 pos += ret;
4510
4511 #endif /* CONFIG_PASN */
4512
4513 return pos - buf;
4514 }
4515
4516
ctrl_iface_get_capability_modes(int res,bool strict,struct wpa_driver_capa * capa,char * buf,size_t buflen)4517 static int ctrl_iface_get_capability_modes(int res, bool strict,
4518 struct wpa_driver_capa *capa,
4519 char *buf, size_t buflen)
4520 {
4521 int ret;
4522 char *pos, *end;
4523 size_t len;
4524
4525 pos = buf;
4526 end = pos + buflen;
4527
4528 if (res < 0) {
4529 if (strict)
4530 return 0;
4531 len = os_strlcpy(buf, "IBSS AP", buflen);
4532 if (len >= buflen)
4533 return -1;
4534 return len;
4535 }
4536
4537 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
4538 ret = os_snprintf(pos, end - pos, "%sIBSS",
4539 pos == buf ? "" : " ");
4540 if (os_snprintf_error(end - pos, ret))
4541 return pos - buf;
4542 pos += ret;
4543 }
4544
4545 if (capa->flags & WPA_DRIVER_FLAGS_AP) {
4546 ret = os_snprintf(pos, end - pos, "%sAP",
4547 pos == buf ? "" : " ");
4548 if (os_snprintf_error(end - pos, ret))
4549 return pos - buf;
4550 pos += ret;
4551 }
4552
4553 #ifdef CONFIG_MESH
4554 if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4555 ret = os_snprintf(pos, end - pos, "%sMESH",
4556 pos == buf ? "" : " ");
4557 if (os_snprintf_error(end - pos, ret))
4558 return pos - buf;
4559 pos += ret;
4560 }
4561 #endif /* CONFIG_MESH */
4562
4563 return pos - buf;
4564 }
4565
4566
ctrl_iface_get_capability_channels(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4567 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4568 char *buf, size_t buflen)
4569 {
4570 struct hostapd_channel_data *chnl;
4571 int ret, i, j;
4572 char *pos, *end, *hmode;
4573
4574 pos = buf;
4575 end = pos + buflen;
4576
4577 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4578 switch (wpa_s->hw.modes[j].mode) {
4579 case HOSTAPD_MODE_IEEE80211B:
4580 hmode = "B";
4581 break;
4582 case HOSTAPD_MODE_IEEE80211G:
4583 hmode = "G";
4584 break;
4585 case HOSTAPD_MODE_IEEE80211A:
4586 hmode = "A";
4587 break;
4588 case HOSTAPD_MODE_IEEE80211AD:
4589 hmode = "AD";
4590 break;
4591 default:
4592 continue;
4593 }
4594 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
4595 if (os_snprintf_error(end - pos, ret))
4596 return pos - buf;
4597 pos += ret;
4598 chnl = wpa_s->hw.modes[j].channels;
4599 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4600 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4601 continue;
4602 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
4603 if (os_snprintf_error(end - pos, ret))
4604 return pos - buf;
4605 pos += ret;
4606 }
4607 ret = os_snprintf(pos, end - pos, "\n");
4608 if (os_snprintf_error(end - pos, ret))
4609 return pos - buf;
4610 pos += ret;
4611 }
4612
4613 return pos - buf;
4614 }
4615
4616
ctrl_iface_get_capability_freq(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)4617 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4618 char *buf, size_t buflen)
4619 {
4620 struct hostapd_channel_data *chnl;
4621 int ret, i, j;
4622 char *pos, *end, *hmode;
4623
4624 pos = buf;
4625 end = pos + buflen;
4626
4627 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4628 switch (wpa_s->hw.modes[j].mode) {
4629 case HOSTAPD_MODE_IEEE80211B:
4630 hmode = "B";
4631 break;
4632 case HOSTAPD_MODE_IEEE80211G:
4633 hmode = "G";
4634 break;
4635 case HOSTAPD_MODE_IEEE80211A:
4636 hmode = "A";
4637 break;
4638 case HOSTAPD_MODE_IEEE80211AD:
4639 hmode = "AD";
4640 break;
4641 default:
4642 continue;
4643 }
4644 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4645 hmode);
4646 if (os_snprintf_error(end - pos, ret))
4647 return pos - buf;
4648 pos += ret;
4649 chnl = wpa_s->hw.modes[j].channels;
4650 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4651 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4652 continue;
4653 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
4654 chnl[i].chan, chnl[i].freq,
4655 chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4656 " (NO_IR)" : "",
4657 chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4658 " (DFS)" : "");
4659
4660 if (os_snprintf_error(end - pos, ret))
4661 return pos - buf;
4662 pos += ret;
4663 }
4664 ret = os_snprintf(pos, end - pos, "\n");
4665 if (os_snprintf_error(end - pos, ret))
4666 return pos - buf;
4667 pos += ret;
4668 }
4669
4670 return pos - buf;
4671 }
4672
4673
wpa_supplicant_ctrl_iface_get_capability(struct wpa_supplicant * wpa_s,const char * _field,char * buf,size_t buflen)4674 static int wpa_supplicant_ctrl_iface_get_capability(
4675 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4676 size_t buflen)
4677 {
4678 struct wpa_driver_capa capa;
4679 int res;
4680 char *next_param, *curr_param, *iftype = NULL;
4681 bool strict = false;
4682 char field[50];
4683 size_t len;
4684
4685 /* Determine whether or not strict checking was requested */
4686 len = os_strlcpy(field, _field, sizeof(field));
4687 if (len >= sizeof(field))
4688 return -1;
4689
4690 next_param = os_strchr(field, ' ');
4691 while (next_param) {
4692 *next_param++ = '\0';
4693 curr_param = next_param;
4694 next_param = os_strchr(next_param, ' ');
4695
4696 if (next_param)
4697 *next_param = '\0';
4698
4699 if (os_strcmp(curr_param, "strict") == 0)
4700 strict = true;
4701 else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4702 iftype = curr_param + 7;
4703 else
4704 return -1;
4705 }
4706
4707 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4708 field, iftype ? " iftype=" : "", iftype ? iftype : "",
4709 strict ? " strict" : "");
4710
4711 if (os_strcmp(field, "eap") == 0) {
4712 return eap_get_names(buf, buflen);
4713 }
4714
4715 res = wpa_drv_get_capa(wpa_s, &capa);
4716
4717 if (os_strcmp(field, "pairwise") == 0)
4718 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4719 buf, buflen);
4720
4721 if (os_strcmp(field, "group") == 0)
4722 return ctrl_iface_get_capability_group(res, strict, &capa,
4723 buf, buflen);
4724
4725 if (os_strcmp(field, "group_mgmt") == 0)
4726 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4727 buf, buflen);
4728
4729 if (os_strcmp(field, "key_mgmt") == 0)
4730 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
4731 iftype, buf, buflen);
4732
4733 if (os_strcmp(field, "proto") == 0)
4734 return ctrl_iface_get_capability_proto(res, strict, &capa,
4735 buf, buflen);
4736
4737 if (os_strcmp(field, "auth_alg") == 0)
4738 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4739 &capa, buf, buflen);
4740
4741 if (os_strcmp(field, "modes") == 0)
4742 return ctrl_iface_get_capability_modes(res, strict, &capa,
4743 buf, buflen);
4744
4745 if (os_strcmp(field, "channels") == 0)
4746 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4747
4748 if (os_strcmp(field, "freq") == 0)
4749 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4750
4751 #ifdef CONFIG_TDLS
4752 if (os_strcmp(field, "tdls") == 0)
4753 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4754 #endif /* CONFIG_TDLS */
4755
4756 #ifdef CONFIG_ERP
4757 if (os_strcmp(field, "erp") == 0) {
4758 res = os_snprintf(buf, buflen, "ERP");
4759 if (os_snprintf_error(buflen, res))
4760 return -1;
4761 return res;
4762 }
4763 #endif /* CONFIG_EPR */
4764
4765 #ifdef CONFIG_FIPS
4766 if (os_strcmp(field, "fips") == 0) {
4767 res = os_snprintf(buf, buflen, "FIPS");
4768 if (os_snprintf_error(buflen, res))
4769 return -1;
4770 return res;
4771 }
4772 #endif /* CONFIG_FIPS */
4773
4774 #ifdef CONFIG_ACS
4775 if (os_strcmp(field, "acs") == 0) {
4776 res = os_snprintf(buf, buflen, "ACS");
4777 if (os_snprintf_error(buflen, res))
4778 return -1;
4779 return res;
4780 }
4781 #endif /* CONFIG_ACS */
4782
4783 #ifdef CONFIG_FILS
4784 if (os_strcmp(field, "fils") == 0) {
4785 #ifdef CONFIG_FILS_SK_PFS
4786 if (wpa_is_fils_supported(wpa_s) &&
4787 wpa_is_fils_sk_pfs_supported(wpa_s)) {
4788 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4789 if (os_snprintf_error(buflen, res))
4790 return -1;
4791 return res;
4792 }
4793 #endif /* CONFIG_FILS_SK_PFS */
4794
4795 if (wpa_is_fils_supported(wpa_s)) {
4796 res = os_snprintf(buf, buflen, "FILS");
4797 if (os_snprintf_error(buflen, res))
4798 return -1;
4799 return res;
4800 }
4801 }
4802 #endif /* CONFIG_FILS */
4803
4804 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4805 res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4806 if (os_snprintf_error(buflen, res))
4807 return -1;
4808 return res;
4809 }
4810
4811 #ifdef CONFIG_DPP
4812 if (os_strcmp(field, "dpp") == 0) {
4813 #ifdef CONFIG_DPP2
4814 res = os_snprintf(buf, buflen, "DPP=2");
4815 #else /* CONFIG_DPP2 */
4816 res = os_snprintf(buf, buflen, "DPP=1");
4817 #endif /* CONFIG_DPP2 */
4818 if (os_snprintf_error(buflen, res))
4819 return -1;
4820 return res;
4821 }
4822 #endif /* CONFIG_DPP */
4823
4824 #ifdef CONFIG_SAE
4825 if (os_strcmp(field, "sae") == 0 &&
4826 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4827 #ifdef CONFIG_SAE_PK
4828 res = os_snprintf(buf, buflen, "H2E PK");
4829 #else /* CONFIG_SAE_PK */
4830 res = os_snprintf(buf, buflen, "H2E");
4831 #endif /* CONFIG_SAE_PK */
4832 if (os_snprintf_error(buflen, res))
4833 return -1;
4834 return res;
4835 }
4836 #endif /* CONFIG_SAE */
4837
4838 #ifdef CONFIG_OCV
4839 if (os_strcmp(field, "ocv") == 0) {
4840 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4841 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4842 res = os_snprintf(buf, buflen, "supported");
4843 else
4844 res = os_snprintf(buf, buflen, "not supported");
4845 if (os_snprintf_error(buflen, res))
4846 return -1;
4847 return res;
4848 }
4849 #endif /* CONFIG_OCV */
4850
4851 if (os_strcmp(field, "beacon_prot") == 0) {
4852 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4853 (wpa_s->drv_flags2 &
4854 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4855 res = os_snprintf(buf, buflen, "supported");
4856 else
4857 res = os_snprintf(buf, buflen, "not supported");
4858 if (os_snprintf_error(buflen, res))
4859 return -1;
4860 return res;
4861 }
4862
4863 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4864 field);
4865
4866 return -1;
4867 }
4868
4869
4870 #ifdef CONFIG_INTERWORKING
anqp_add_hex(char * pos,char * end,const char * title,struct wpabuf * data)4871 static char * anqp_add_hex(char *pos, char *end, const char *title,
4872 struct wpabuf *data)
4873 {
4874 char *start = pos;
4875 size_t i;
4876 int ret;
4877 const u8 *d;
4878
4879 if (data == NULL)
4880 return start;
4881
4882 ret = os_snprintf(pos, end - pos, "%s=", title);
4883 if (os_snprintf_error(end - pos, ret))
4884 return start;
4885 pos += ret;
4886
4887 d = wpabuf_head_u8(data);
4888 for (i = 0; i < wpabuf_len(data); i++) {
4889 ret = os_snprintf(pos, end - pos, "%02x", *d++);
4890 if (os_snprintf_error(end - pos, ret))
4891 return start;
4892 pos += ret;
4893 }
4894
4895 ret = os_snprintf(pos, end - pos, "\n");
4896 if (os_snprintf_error(end - pos, ret))
4897 return start;
4898 pos += ret;
4899
4900 return pos;
4901 }
4902 #endif /* CONFIG_INTERWORKING */
4903
4904
4905 #ifdef CONFIG_FILS
print_fils_indication(struct wpa_bss * bss,char * pos,char * end)4906 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
4907 {
4908 char *start = pos;
4909 const u8 *ie, *ie_end;
4910 u16 info, realms;
4911 int ret;
4912
4913 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
4914 if (!ie)
4915 return 0;
4916 ie_end = ie + 2 + ie[1];
4917 ie += 2;
4918 if (ie_end - ie < 2)
4919 return -1;
4920
4921 info = WPA_GET_LE16(ie);
4922 ie += 2;
4923 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
4924 if (os_snprintf_error(end - pos, ret))
4925 return 0;
4926 pos += ret;
4927
4928 if (info & BIT(7)) {
4929 /* Cache Identifier Included */
4930 if (ie_end - ie < 2)
4931 return -1;
4932 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
4933 ie[0], ie[1]);
4934 if (os_snprintf_error(end - pos, ret))
4935 return 0;
4936 pos += ret;
4937 ie += 2;
4938 }
4939
4940 if (info & BIT(8)) {
4941 /* HESSID Included */
4942 if (ie_end - ie < ETH_ALEN)
4943 return -1;
4944 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
4945 MAC2STR(ie));
4946 if (os_snprintf_error(end - pos, ret))
4947 return 0;
4948 pos += ret;
4949 ie += ETH_ALEN;
4950 }
4951
4952 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
4953 if (realms) {
4954 if (ie_end - ie < realms * 2)
4955 return -1;
4956 ret = os_snprintf(pos, end - pos, "fils_realms=");
4957 if (os_snprintf_error(end - pos, ret))
4958 return 0;
4959 pos += ret;
4960
4961 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
4962 if (ret <= 0)
4963 return 0;
4964 pos += ret;
4965 ie += realms * 2;
4966 ret = os_snprintf(pos, end - pos, "\n");
4967 if (os_snprintf_error(end - pos, ret))
4968 return 0;
4969 pos += ret;
4970 }
4971
4972 return pos - start;
4973 }
4974 #endif /* CONFIG_FILS */
4975
4976
print_bss_info(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,unsigned long mask,char * buf,size_t buflen)4977 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
4978 unsigned long mask, char *buf, size_t buflen)
4979 {
4980 size_t i;
4981 int ret;
4982 char *pos, *end;
4983 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
4984
4985 pos = buf;
4986 end = buf + buflen;
4987
4988 if (mask & WPA_BSS_MASK_ID) {
4989 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
4990 if (os_snprintf_error(end - pos, ret))
4991 return 0;
4992 pos += ret;
4993 }
4994
4995 if (mask & WPA_BSS_MASK_BSSID) {
4996 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
4997 MAC2STR(bss->bssid));
4998 if (os_snprintf_error(end - pos, ret))
4999 return 0;
5000 pos += ret;
5001 }
5002
5003 if (mask & WPA_BSS_MASK_FREQ) {
5004 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
5005 if (os_snprintf_error(end - pos, ret))
5006 return 0;
5007 pos += ret;
5008 }
5009
5010 if (mask & WPA_BSS_MASK_BEACON_INT) {
5011 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5012 bss->beacon_int);
5013 if (os_snprintf_error(end - pos, ret))
5014 return 0;
5015 pos += ret;
5016 }
5017
5018 if (mask & WPA_BSS_MASK_CAPABILITIES) {
5019 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5020 bss->caps);
5021 if (os_snprintf_error(end - pos, ret))
5022 return 0;
5023 pos += ret;
5024 }
5025
5026 if (mask & WPA_BSS_MASK_QUAL) {
5027 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
5028 if (os_snprintf_error(end - pos, ret))
5029 return 0;
5030 pos += ret;
5031 }
5032
5033 if (mask & WPA_BSS_MASK_NOISE) {
5034 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
5035 if (os_snprintf_error(end - pos, ret))
5036 return 0;
5037 pos += ret;
5038 }
5039
5040 if (mask & WPA_BSS_MASK_LEVEL) {
5041 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
5042 if (os_snprintf_error(end - pos, ret))
5043 return 0;
5044 pos += ret;
5045 }
5046
5047 if (mask & WPA_BSS_MASK_TSF) {
5048 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5049 (unsigned long long) bss->tsf);
5050 if (os_snprintf_error(end - pos, ret))
5051 return 0;
5052 pos += ret;
5053 }
5054
5055 if (mask & WPA_BSS_MASK_AGE) {
5056 struct os_reltime now;
5057
5058 os_get_reltime(&now);
5059 ret = os_snprintf(pos, end - pos, "age=%d\n",
5060 (int) (now.sec - bss->last_update.sec));
5061 if (os_snprintf_error(end - pos, ret))
5062 return 0;
5063 pos += ret;
5064 }
5065
5066 if (mask & WPA_BSS_MASK_IE) {
5067 ret = os_snprintf(pos, end - pos, "ie=");
5068 if (os_snprintf_error(end - pos, ret))
5069 return 0;
5070 pos += ret;
5071
5072 ie = wpa_bss_ie_ptr(bss);
5073 for (i = 0; i < bss->ie_len; i++) {
5074 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5075 if (os_snprintf_error(end - pos, ret))
5076 return 0;
5077 pos += ret;
5078 }
5079
5080 ret = os_snprintf(pos, end - pos, "\n");
5081 if (os_snprintf_error(end - pos, ret))
5082 return 0;
5083 pos += ret;
5084 }
5085
5086 if (mask & WPA_BSS_MASK_FLAGS) {
5087 ret = os_snprintf(pos, end - pos, "flags=");
5088 if (os_snprintf_error(end - pos, ret))
5089 return 0;
5090 pos += ret;
5091
5092 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5093
5094 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5095 if (ie)
5096 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5097 2 + ie[1]);
5098 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
5099 if (ie2)
5100 pos = wpa_supplicant_ie_txt(pos, end,
5101 mesh ? "RSN" : "WPA2", ie2,
5102 2 + ie2[1]);
5103 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
5104 if (rsnxe && rsnxe[1] >= 1) {
5105 if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
5106 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5107 if (os_snprintf_error(end - pos, ret))
5108 return -1;
5109 pos += ret;
5110 }
5111 if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
5112 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5113 if (os_snprintf_error(end - pos, ret))
5114 return -1;
5115 pos += ret;
5116 }
5117 }
5118 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5119 if (osen_ie)
5120 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5121 osen_ie, 2 + osen_ie[1]);
5122 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5123 if (owe) {
5124 ret = os_snprintf(
5125 pos, end - pos,
5126 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5127 if (os_snprintf_error(end - pos, ret))
5128 return 0;
5129 pos += ret;
5130 }
5131 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
5132 if (!ie && !ie2 && !osen_ie &&
5133 (bss->caps & IEEE80211_CAP_PRIVACY)) {
5134 ret = os_snprintf(pos, end - pos, "[WEP]");
5135 if (os_snprintf_error(end - pos, ret))
5136 return 0;
5137 pos += ret;
5138 }
5139
5140 if (mesh) {
5141 ret = os_snprintf(pos, end - pos, "[MESH]");
5142 if (os_snprintf_error(end - pos, ret))
5143 return 0;
5144 pos += ret;
5145 }
5146
5147 if (bss_is_dmg(bss)) {
5148 const char *s;
5149 ret = os_snprintf(pos, end - pos, "[DMG]");
5150 if (os_snprintf_error(end - pos, ret))
5151 return 0;
5152 pos += ret;
5153 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5154 case IEEE80211_CAP_DMG_IBSS:
5155 s = "[IBSS]";
5156 break;
5157 case IEEE80211_CAP_DMG_AP:
5158 s = "[ESS]";
5159 break;
5160 case IEEE80211_CAP_DMG_PBSS:
5161 s = "[PBSS]";
5162 break;
5163 default:
5164 s = "";
5165 break;
5166 }
5167 ret = os_snprintf(pos, end - pos, "%s", s);
5168 if (os_snprintf_error(end - pos, ret))
5169 return 0;
5170 pos += ret;
5171 } else {
5172 if (bss->caps & IEEE80211_CAP_IBSS) {
5173 ret = os_snprintf(pos, end - pos, "[IBSS]");
5174 if (os_snprintf_error(end - pos, ret))
5175 return 0;
5176 pos += ret;
5177 }
5178 if (bss->caps & IEEE80211_CAP_ESS) {
5179 ret = os_snprintf(pos, end - pos, "[ESS]");
5180 if (os_snprintf_error(end - pos, ret))
5181 return 0;
5182 pos += ret;
5183 }
5184 }
5185 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5186 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
5187 ret = os_snprintf(pos, end - pos, "[P2P]");
5188 if (os_snprintf_error(end - pos, ret))
5189 return 0;
5190 pos += ret;
5191 }
5192 #ifdef CONFIG_HS20
5193 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5194 ret = os_snprintf(pos, end - pos, "[HS20]");
5195 if (os_snprintf_error(end - pos, ret))
5196 return 0;
5197 pos += ret;
5198 }
5199 #endif /* CONFIG_HS20 */
5200 #ifdef CONFIG_FILS
5201 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5202 ret = os_snprintf(pos, end - pos, "[FILS]");
5203 if (os_snprintf_error(end - pos, ret))
5204 return 0;
5205 pos += ret;
5206 }
5207 #endif /* CONFIG_FILS */
5208 #ifdef CONFIG_FST
5209 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5210 ret = os_snprintf(pos, end - pos, "[FST]");
5211 if (os_snprintf_error(end - pos, ret))
5212 return 0;
5213 pos += ret;
5214 }
5215 #endif /* CONFIG_FST */
5216 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5217 ret = os_snprintf(pos, end - pos, "[UTF-8]");
5218 if (os_snprintf_error(end - pos, ret))
5219 return 0;
5220 pos += ret;
5221 }
5222
5223 ret = os_snprintf(pos, end - pos, "\n");
5224 if (os_snprintf_error(end - pos, ret))
5225 return 0;
5226 pos += ret;
5227 }
5228
5229 if (mask & WPA_BSS_MASK_SSID) {
5230 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5231 wpa_ssid_txt(bss->ssid, bss->ssid_len));
5232 if (os_snprintf_error(end - pos, ret))
5233 return 0;
5234 pos += ret;
5235 }
5236
5237 #ifdef CONFIG_WPS
5238 if (mask & WPA_BSS_MASK_WPS_SCAN) {
5239 ie = wpa_bss_ie_ptr(bss);
5240 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
5241 if (ret >= end - pos)
5242 return 0;
5243 if (ret > 0)
5244 pos += ret;
5245 }
5246 #endif /* CONFIG_WPS */
5247
5248 #ifdef CONFIG_P2P
5249 if (mask & WPA_BSS_MASK_P2P_SCAN) {
5250 ie = wpa_bss_ie_ptr(bss);
5251 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
5252 if (ret >= end - pos)
5253 return 0;
5254 if (ret > 0)
5255 pos += ret;
5256 }
5257 #endif /* CONFIG_P2P */
5258
5259 #ifdef CONFIG_WIFI_DISPLAY
5260 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5261 struct wpabuf *wfd;
5262
5263 ie = wpa_bss_ie_ptr(bss);
5264 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5265 WFD_IE_VENDOR_TYPE);
5266 if (wfd) {
5267 ret = os_snprintf(pos, end - pos, "wfd_subelems=");
5268 if (os_snprintf_error(end - pos, ret)) {
5269 wpabuf_free(wfd);
5270 return 0;
5271 }
5272 pos += ret;
5273
5274 pos += wpa_snprintf_hex(pos, end - pos,
5275 wpabuf_head(wfd),
5276 wpabuf_len(wfd));
5277 wpabuf_free(wfd);
5278
5279 ret = os_snprintf(pos, end - pos, "\n");
5280 if (os_snprintf_error(end - pos, ret))
5281 return 0;
5282 pos += ret;
5283 }
5284 }
5285 #endif /* CONFIG_WIFI_DISPLAY */
5286
5287 #ifdef CONFIG_INTERWORKING
5288 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5289 struct wpa_bss_anqp *anqp = bss->anqp;
5290 struct wpa_bss_anqp_elem *elem;
5291
5292 pos = anqp_add_hex(pos, end, "anqp_capability_list",
5293 anqp->capability_list);
5294 pos = anqp_add_hex(pos, end, "anqp_venue_name",
5295 anqp->venue_name);
5296 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
5297 anqp->network_auth_type);
5298 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
5299 anqp->roaming_consortium);
5300 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
5301 anqp->ip_addr_type_availability);
5302 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
5303 anqp->nai_realm);
5304 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
5305 pos = anqp_add_hex(pos, end, "anqp_domain_name",
5306 anqp->domain_name);
5307 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5308 anqp->fils_realm_info);
5309 #ifdef CONFIG_HS20
5310 pos = anqp_add_hex(pos, end, "hs20_capability_list",
5311 anqp->hs20_capability_list);
5312 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
5313 anqp->hs20_operator_friendly_name);
5314 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
5315 anqp->hs20_wan_metrics);
5316 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
5317 anqp->hs20_connection_capability);
5318 pos = anqp_add_hex(pos, end, "hs20_operating_class",
5319 anqp->hs20_operating_class);
5320 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5321 anqp->hs20_osu_providers_list);
5322 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5323 anqp->hs20_operator_icon_metadata);
5324 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5325 anqp->hs20_osu_providers_nai_list);
5326 #endif /* CONFIG_HS20 */
5327
5328 dl_list_for_each(elem, &anqp->anqp_elems,
5329 struct wpa_bss_anqp_elem, list) {
5330 char title[20];
5331
5332 os_snprintf(title, sizeof(title), "anqp[%u]",
5333 elem->infoid);
5334 pos = anqp_add_hex(pos, end, title, elem->payload);
5335 if (elem->protected_response) {
5336 ret = os_snprintf(pos, end - pos,
5337 "protected-anqp-info[%u]=1\n",
5338 elem->infoid);
5339 if (os_snprintf_error(end - pos, ret))
5340 return 0;
5341 pos += ret;
5342 }
5343 }
5344 }
5345 #endif /* CONFIG_INTERWORKING */
5346
5347 #ifdef CONFIG_MESH
5348 if (mask & WPA_BSS_MASK_MESH_SCAN) {
5349 ie = wpa_bss_ie_ptr(bss);
5350 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
5351 if (ret >= end - pos)
5352 return 0;
5353 if (ret > 0)
5354 pos += ret;
5355 }
5356 #endif /* CONFIG_MESH */
5357
5358 if (mask & WPA_BSS_MASK_SNR) {
5359 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5360 if (os_snprintf_error(end - pos, ret))
5361 return 0;
5362 pos += ret;
5363 }
5364
5365 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5366 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5367 bss->est_throughput);
5368 if (os_snprintf_error(end - pos, ret))
5369 return 0;
5370 pos += ret;
5371 }
5372
5373 #ifdef CONFIG_FST
5374 if (mask & WPA_BSS_MASK_FST) {
5375 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5376 if (ret < 0 || ret >= end - pos)
5377 return 0;
5378 pos += ret;
5379 }
5380 #endif /* CONFIG_FST */
5381
5382 if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5383 ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5384 bss->last_update_idx);
5385 if (os_snprintf_error(end - pos, ret))
5386 return 0;
5387 pos += ret;
5388 }
5389
5390 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5391 ret = os_snprintf(pos, end - pos, "beacon_ie=");
5392 if (os_snprintf_error(end - pos, ret))
5393 return 0;
5394 pos += ret;
5395
5396 ie = wpa_bss_ie_ptr(bss);
5397 ie += bss->ie_len;
5398 for (i = 0; i < bss->beacon_ie_len; i++) {
5399 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5400 if (os_snprintf_error(end - pos, ret))
5401 return 0;
5402 pos += ret;
5403 }
5404
5405 ret = os_snprintf(pos, end - pos, "\n");
5406 if (os_snprintf_error(end - pos, ret))
5407 return 0;
5408 pos += ret;
5409 }
5410
5411 #ifdef CONFIG_FILS
5412 if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5413 ret = print_fils_indication(bss, pos, end);
5414 if (ret < 0)
5415 return 0;
5416 pos += ret;
5417 }
5418 #endif /* CONFIG_FILS */
5419
5420 if (mask & WPA_BSS_MASK_DELIM) {
5421 ret = os_snprintf(pos, end - pos, "====\n");
5422 if (os_snprintf_error(end - pos, ret))
5423 return 0;
5424 pos += ret;
5425 }
5426
5427 return pos - buf;
5428 }
5429
5430
wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)5431 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5432 const char *cmd, char *buf,
5433 size_t buflen)
5434 {
5435 u8 bssid[ETH_ALEN];
5436 size_t i;
5437 struct wpa_bss *bss;
5438 struct wpa_bss *bsslast = NULL;
5439 struct dl_list *next;
5440 int ret = 0;
5441 int len;
5442 char *ctmp, *end = buf + buflen;
5443 unsigned long mask = WPA_BSS_MASK_ALL;
5444
5445 if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5446 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5447 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
5448 list_id);
5449 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5450 list_id);
5451 } else { /* N1-N2 */
5452 unsigned int id1, id2;
5453
5454 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5455 wpa_printf(MSG_INFO, "Wrong BSS range "
5456 "format");
5457 return 0;
5458 }
5459
5460 if (*(cmd + 6) == '-')
5461 id1 = 0;
5462 else
5463 id1 = atoi(cmd + 6);
5464 ctmp++;
5465 if (*ctmp >= '0' && *ctmp <= '9')
5466 id2 = atoi(ctmp);
5467 else
5468 id2 = (unsigned int) -1;
5469 bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5470 if (id2 == (unsigned int) -1)
5471 bsslast = dl_list_last(&wpa_s->bss_id,
5472 struct wpa_bss,
5473 list_id);
5474 else {
5475 bsslast = wpa_bss_get_id(wpa_s, id2);
5476 if (bsslast == NULL && bss && id2 > id1) {
5477 struct wpa_bss *tmp = bss;
5478 for (;;) {
5479 next = tmp->list_id.next;
5480 if (next == &wpa_s->bss_id)
5481 break;
5482 tmp = dl_list_entry(
5483 next, struct wpa_bss,
5484 list_id);
5485 if (tmp->id > id2)
5486 break;
5487 bsslast = tmp;
5488 }
5489 }
5490 }
5491 }
5492 } else if (os_strncmp(cmd, "FIRST", 5) == 0)
5493 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
5494 else if (os_strncmp(cmd, "LAST", 4) == 0)
5495 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
5496 else if (os_strncmp(cmd, "ID-", 3) == 0) {
5497 i = atoi(cmd + 3);
5498 bss = wpa_bss_get_id(wpa_s, i);
5499 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5500 i = atoi(cmd + 5);
5501 bss = wpa_bss_get_id(wpa_s, i);
5502 if (bss) {
5503 next = bss->list_id.next;
5504 if (next == &wpa_s->bss_id)
5505 bss = NULL;
5506 else
5507 bss = dl_list_entry(next, struct wpa_bss,
5508 list_id);
5509 }
5510 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5511 bss = wpa_s->current_bss;
5512 #ifdef CONFIG_P2P
5513 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5514 if (hwaddr_aton(cmd + 13, bssid) == 0)
5515 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5516 else
5517 bss = NULL;
5518 #endif /* CONFIG_P2P */
5519 } else if (hwaddr_aton(cmd, bssid) == 0)
5520 bss = wpa_bss_get_bssid(wpa_s, bssid);
5521 else {
5522 struct wpa_bss *tmp;
5523 i = atoi(cmd);
5524 bss = NULL;
5525 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5526 {
5527 if (i == 0) {
5528 bss = tmp;
5529 break;
5530 }
5531 i--;
5532 }
5533 }
5534
5535 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5536 mask = strtoul(ctmp + 5, NULL, 0x10);
5537 if (mask == 0)
5538 mask = WPA_BSS_MASK_ALL;
5539 }
5540
5541 if (bss == NULL)
5542 return 0;
5543
5544 if (bsslast == NULL)
5545 bsslast = bss;
5546 do {
5547 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5548 ret += len;
5549 buf += len;
5550 buflen -= len;
5551 if (bss == bsslast) {
5552 if ((mask & WPA_BSS_MASK_DELIM) && len &&
5553 (bss == dl_list_last(&wpa_s->bss_id,
5554 struct wpa_bss, list_id))) {
5555 int res;
5556
5557 res = os_snprintf(buf - 5, end - buf + 5,
5558 "####\n");
5559 if (os_snprintf_error(end - buf + 5, res)) {
5560 wpa_printf(MSG_DEBUG,
5561 "Could not add end delim");
5562 }
5563 }
5564 break;
5565 }
5566 next = bss->list_id.next;
5567 if (next == &wpa_s->bss_id)
5568 break;
5569 bss = dl_list_entry(next, struct wpa_bss, list_id);
5570 } while (bss && len);
5571
5572 return ret;
5573 }
5574
5575
wpa_supplicant_ctrl_iface_ap_scan(struct wpa_supplicant * wpa_s,char * cmd)5576 static int wpa_supplicant_ctrl_iface_ap_scan(
5577 struct wpa_supplicant *wpa_s, char *cmd)
5578 {
5579 int ap_scan = atoi(cmd);
5580 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5581 }
5582
5583
wpa_supplicant_ctrl_iface_scan_interval(struct wpa_supplicant * wpa_s,char * cmd)5584 static int wpa_supplicant_ctrl_iface_scan_interval(
5585 struct wpa_supplicant *wpa_s, char *cmd)
5586 {
5587 int scan_int = atoi(cmd);
5588 return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
5589 }
5590
5591
wpa_supplicant_ctrl_iface_bss_expire_age(struct wpa_supplicant * wpa_s,char * cmd)5592 static int wpa_supplicant_ctrl_iface_bss_expire_age(
5593 struct wpa_supplicant *wpa_s, char *cmd)
5594 {
5595 int expire_age = atoi(cmd);
5596 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5597 }
5598
5599
wpa_supplicant_ctrl_iface_bss_expire_count(struct wpa_supplicant * wpa_s,char * cmd)5600 static int wpa_supplicant_ctrl_iface_bss_expire_count(
5601 struct wpa_supplicant *wpa_s, char *cmd)
5602 {
5603 int expire_count = atoi(cmd);
5604 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5605 }
5606
5607
wpa_supplicant_ctrl_iface_bss_flush(struct wpa_supplicant * wpa_s,char * cmd)5608 static void wpa_supplicant_ctrl_iface_bss_flush(
5609 struct wpa_supplicant *wpa_s, char *cmd)
5610 {
5611 int flush_age = atoi(cmd);
5612
5613 if (flush_age == 0)
5614 wpa_bss_flush(wpa_s);
5615 else
5616 wpa_bss_flush_by_age(wpa_s, flush_age);
5617 }
5618
5619
5620 #ifdef CONFIG_TESTING_OPTIONS
wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant * wpa_s)5621 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5622 {
5623 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5624 /* MLME-DELETEKEYS.request */
5625 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
5626 0, KEY_FLAG_GROUP);
5627 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
5628 0, KEY_FLAG_GROUP);
5629 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
5630 0, KEY_FLAG_GROUP);
5631 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
5632 0, KEY_FLAG_GROUP);
5633 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
5634 0, KEY_FLAG_GROUP);
5635 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
5636 0, KEY_FLAG_GROUP);
5637
5638 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
5639 0, KEY_FLAG_PAIRWISE);
5640 if (wpa_sm_ext_key_id(wpa_s->wpa))
5641 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
5642 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
5643 /* MLME-SETPROTECTION.request(None) */
5644 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
5645 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
5646 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5647 wpa_sm_drop_sa(wpa_s->wpa);
5648 }
5649 #endif /* CONFIG_TESTING_OPTIONS */
5650
5651
wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant * wpa_s,char * addr)5652 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
5653 char *addr)
5654 {
5655 #ifdef CONFIG_NO_SCAN_PROCESSING
5656 return -1;
5657 #else /* CONFIG_NO_SCAN_PROCESSING */
5658 u8 bssid[ETH_ALEN];
5659 struct wpa_bss *bss;
5660 struct wpa_ssid *ssid = wpa_s->current_ssid;
5661
5662 if (hwaddr_aton(addr, bssid)) {
5663 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
5664 "address '%s'", addr);
5665 return -1;
5666 }
5667
5668 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
5669
5670 if (!ssid) {
5671 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
5672 "configuration known for the target AP");
5673 return -1;
5674 }
5675
5676 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
5677 if (!bss) {
5678 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
5679 "from BSS table");
5680 return -1;
5681 }
5682
5683 /*
5684 * TODO: Find best network configuration block from configuration to
5685 * allow roaming to other networks
5686 */
5687
5688 wpa_s->reassociate = 1;
5689 wpa_supplicant_connect(wpa_s, bss, ssid);
5690
5691 return 0;
5692 #endif /* CONFIG_NO_SCAN_PROCESSING */
5693 }
5694
5695
5696 #ifdef CONFIG_P2P
p2p_ctrl_find(struct wpa_supplicant * wpa_s,char * cmd)5697 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
5698 {
5699 unsigned int timeout = atoi(cmd);
5700 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
5701 u8 dev_id[ETH_ALEN], *_dev_id = NULL;
5702 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
5703 char *pos;
5704 unsigned int search_delay;
5705 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
5706 u8 seek_count = 0;
5707 int freq = 0;
5708
5709 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5710 wpa_dbg(wpa_s, MSG_INFO,
5711 "Reject P2P_FIND since interface is disabled");
5712 return -1;
5713 }
5714 if (os_strstr(cmd, "type=social"))
5715 type = P2P_FIND_ONLY_SOCIAL;
5716 else if (os_strstr(cmd, "type=progressive"))
5717 type = P2P_FIND_PROGRESSIVE;
5718
5719 pos = os_strstr(cmd, "dev_id=");
5720 if (pos) {
5721 pos += 7;
5722 if (hwaddr_aton(pos, dev_id))
5723 return -1;
5724 _dev_id = dev_id;
5725 }
5726
5727 pos = os_strstr(cmd, "dev_type=");
5728 if (pos) {
5729 pos += 9;
5730 if (wps_dev_type_str2bin(pos, dev_type) < 0)
5731 return -1;
5732 _dev_type = dev_type;
5733 }
5734
5735 pos = os_strstr(cmd, "delay=");
5736 if (pos) {
5737 pos += 6;
5738 search_delay = atoi(pos);
5739 } else
5740 search_delay = wpas_p2p_search_delay(wpa_s);
5741
5742 pos = os_strstr(cmd, "freq=");
5743 if (pos) {
5744 pos += 5;
5745 freq = atoi(pos);
5746 if (freq <= 0)
5747 return -1;
5748 }
5749
5750 /* Must be searched for last, because it adds nul termination */
5751 pos = os_strstr(cmd, " seek=");
5752 if (pos)
5753 pos += 6;
5754 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
5755 char *term;
5756
5757 _seek[seek_count++] = pos;
5758 seek = _seek;
5759 term = os_strchr(pos, ' ');
5760 if (!term)
5761 break;
5762 *term = '\0';
5763 pos = os_strstr(term + 1, "seek=");
5764 if (pos)
5765 pos += 5;
5766 }
5767 if (seek_count > P2P_MAX_QUERY_HASH) {
5768 seek[0] = NULL;
5769 seek_count = 1;
5770 }
5771
5772 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
5773 _dev_id, search_delay, seek_count, seek, freq);
5774 }
5775
5776
p2ps_ctrl_parse_cpt_priority(const char * pos,u8 * cpt)5777 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
5778 {
5779 const char *last = NULL;
5780 const char *token;
5781 long int token_len;
5782 unsigned int i;
5783
5784 /* Expected predefined CPT names delimited by ':' */
5785 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
5786 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
5787 wpa_printf(MSG_ERROR,
5788 "P2PS: CPT name list is too long, expected up to %d names",
5789 P2PS_FEATURE_CAPAB_CPT_MAX);
5790 cpt[0] = 0;
5791 return -1;
5792 }
5793
5794 token_len = last - token;
5795
5796 if (token_len == 3 &&
5797 os_memcmp(token, "UDP", token_len) == 0) {
5798 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5799 } else if (token_len == 3 &&
5800 os_memcmp(token, "MAC", token_len) == 0) {
5801 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
5802 } else {
5803 wpa_printf(MSG_ERROR,
5804 "P2PS: Unsupported CPT name '%s'", token);
5805 cpt[0] = 0;
5806 return -1;
5807 }
5808
5809 if (isblank((unsigned char) *last)) {
5810 i++;
5811 break;
5812 }
5813 }
5814 cpt[i] = 0;
5815 return 0;
5816 }
5817
5818
p2p_parse_asp_provision_cmd(const char * cmd)5819 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
5820 {
5821 struct p2ps_provision *p2ps_prov;
5822 char *pos;
5823 size_t info_len = 0;
5824 char *info = NULL;
5825 u8 role = P2PS_SETUP_NONE;
5826 long long unsigned val;
5827 int i;
5828
5829 pos = os_strstr(cmd, "info=");
5830 if (pos) {
5831 pos += 5;
5832 info_len = os_strlen(pos);
5833
5834 if (info_len) {
5835 info = os_malloc(info_len + 1);
5836 if (info) {
5837 info_len = utf8_unescape(pos, info_len,
5838 info, info_len + 1);
5839 } else
5840 info_len = 0;
5841 }
5842 }
5843
5844 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
5845 if (p2ps_prov == NULL) {
5846 os_free(info);
5847 return NULL;
5848 }
5849
5850 if (info) {
5851 os_memcpy(p2ps_prov->info, info, info_len);
5852 p2ps_prov->info[info_len] = '\0';
5853 os_free(info);
5854 }
5855
5856 pos = os_strstr(cmd, "status=");
5857 if (pos)
5858 p2ps_prov->status = atoi(pos + 7);
5859 else
5860 p2ps_prov->status = -1;
5861
5862 pos = os_strstr(cmd, "adv_id=");
5863 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
5864 goto invalid_args;
5865 p2ps_prov->adv_id = val;
5866
5867 pos = os_strstr(cmd, "method=");
5868 if (pos)
5869 p2ps_prov->method = strtol(pos + 7, NULL, 16);
5870 else
5871 p2ps_prov->method = 0;
5872
5873 pos = os_strstr(cmd, "session=");
5874 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
5875 goto invalid_args;
5876 p2ps_prov->session_id = val;
5877
5878 pos = os_strstr(cmd, "adv_mac=");
5879 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
5880 goto invalid_args;
5881
5882 pos = os_strstr(cmd, "session_mac=");
5883 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
5884 goto invalid_args;
5885
5886 pos = os_strstr(cmd, "cpt=");
5887 if (pos) {
5888 if (p2ps_ctrl_parse_cpt_priority(pos + 4,
5889 p2ps_prov->cpt_priority))
5890 goto invalid_args;
5891 } else {
5892 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5893 }
5894
5895 for (i = 0; p2ps_prov->cpt_priority[i]; i++)
5896 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
5897
5898 /* force conncap with tstCap (no sanity checks) */
5899 pos = os_strstr(cmd, "tstCap=");
5900 if (pos) {
5901 role = strtol(pos + 7, NULL, 16);
5902 } else {
5903 pos = os_strstr(cmd, "role=");
5904 if (pos) {
5905 role = strtol(pos + 5, NULL, 16);
5906 if (role != P2PS_SETUP_CLIENT &&
5907 role != P2PS_SETUP_GROUP_OWNER)
5908 role = P2PS_SETUP_NONE;
5909 }
5910 }
5911 p2ps_prov->role = role;
5912
5913 return p2ps_prov;
5914
5915 invalid_args:
5916 os_free(p2ps_prov);
5917 return NULL;
5918 }
5919
5920
p2p_ctrl_asp_provision_resp(struct wpa_supplicant * wpa_s,char * cmd)5921 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
5922 {
5923 u8 addr[ETH_ALEN];
5924 struct p2ps_provision *p2ps_prov;
5925 char *pos;
5926
5927 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
5928
5929 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5930
5931 if (hwaddr_aton(cmd, addr))
5932 return -1;
5933
5934 pos = cmd + 17;
5935 if (*pos != ' ')
5936 return -1;
5937
5938 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5939 if (!p2ps_prov)
5940 return -1;
5941
5942 if (p2ps_prov->status < 0) {
5943 os_free(p2ps_prov);
5944 return -1;
5945 }
5946
5947 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5948 p2ps_prov);
5949 }
5950
5951
p2p_ctrl_asp_provision(struct wpa_supplicant * wpa_s,char * cmd)5952 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
5953 {
5954 u8 addr[ETH_ALEN];
5955 struct p2ps_provision *p2ps_prov;
5956 char *pos;
5957
5958 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
5959 * session=<ses_id> mac=<ses_mac> [info=<infodata>]
5960 */
5961
5962 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5963 if (hwaddr_aton(cmd, addr))
5964 return -1;
5965
5966 pos = cmd + 17;
5967 if (*pos != ' ')
5968 return -1;
5969
5970 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5971 if (!p2ps_prov)
5972 return -1;
5973
5974 p2ps_prov->pd_seeker = 1;
5975
5976 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5977 p2ps_prov);
5978 }
5979
5980
parse_freq(int chwidth,int freq2)5981 static int parse_freq(int chwidth, int freq2)
5982 {
5983 if (freq2 < 0)
5984 return -1;
5985 if (freq2)
5986 return CHANWIDTH_80P80MHZ;
5987
5988 switch (chwidth) {
5989 case 0:
5990 case 20:
5991 case 40:
5992 return CHANWIDTH_USE_HT;
5993 case 80:
5994 return CHANWIDTH_80MHZ;
5995 case 160:
5996 return CHANWIDTH_160MHZ;
5997 default:
5998 wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
5999 chwidth);
6000 return -1;
6001 }
6002 }
6003
6004
p2p_ctrl_connect(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6005 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6006 char *buf, size_t buflen)
6007 {
6008 u8 addr[ETH_ALEN];
6009 char *pos, *pos2;
6010 char *pin = NULL;
6011 enum p2p_wps_method wps_method;
6012 int new_pin;
6013 int ret;
6014 int persistent_group, persistent_id = -1;
6015 int join;
6016 int auth;
6017 int automatic;
6018 int go_intent = -1;
6019 int freq = 0;
6020 int pd;
6021 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
6022 int edmg;
6023 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6024 size_t group_ssid_len = 0;
6025 int he;
6026
6027 if (!wpa_s->global->p2p_init_wpa_s)
6028 return -1;
6029 if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6030 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6031 wpa_s->global->p2p_init_wpa_s->ifname);
6032 wpa_s = wpa_s->global->p2p_init_wpa_s;
6033 }
6034
6035 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
6036 * [persistent|persistent=<network id>]
6037 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
6038 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
6039
6040 if (hwaddr_aton(cmd, addr))
6041 return -1;
6042
6043 pos = cmd + 17;
6044 if (*pos != ' ')
6045 return -1;
6046 pos++;
6047
6048 persistent_group = os_strstr(pos, " persistent") != NULL;
6049 pos2 = os_strstr(pos, " persistent=");
6050 if (pos2) {
6051 struct wpa_ssid *ssid;
6052 persistent_id = atoi(pos2 + 12);
6053 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6054 if (ssid == NULL || ssid->disabled != 2 ||
6055 ssid->mode != WPAS_MODE_P2P_GO) {
6056 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6057 "SSID id=%d for persistent P2P group (GO)",
6058 persistent_id);
6059 return -1;
6060 }
6061 }
6062 join = os_strstr(pos, " join") != NULL;
6063 auth = os_strstr(pos, " auth") != NULL;
6064 automatic = os_strstr(pos, " auto") != NULL;
6065 pd = os_strstr(pos, " provdisc") != NULL;
6066 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6067 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6068 vht;
6069 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6070 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6071
6072 pos2 = os_strstr(pos, " go_intent=");
6073 if (pos2) {
6074 pos2 += 11;
6075 go_intent = atoi(pos2);
6076 if (go_intent < 0 || go_intent > 15)
6077 return -1;
6078 }
6079
6080 pos2 = os_strstr(pos, " freq=");
6081 if (pos2) {
6082 pos2 += 6;
6083 freq = atoi(pos2);
6084 if (freq <= 0)
6085 return -1;
6086 }
6087
6088 pos2 = os_strstr(pos, " freq2=");
6089 if (pos2)
6090 freq2 = atoi(pos2 + 7);
6091
6092 pos2 = os_strstr(pos, " max_oper_chwidth=");
6093 if (pos2)
6094 chwidth = atoi(pos2 + 18);
6095
6096 max_oper_chwidth = parse_freq(chwidth, freq2);
6097 if (max_oper_chwidth < 0)
6098 return -1;
6099
6100 pos2 = os_strstr(pos, " ssid=");
6101 if (pos2) {
6102 char *end;
6103
6104 pos2 += 6;
6105 end = os_strchr(pos2, ' ');
6106 if (!end)
6107 group_ssid_len = os_strlen(pos2) / 2;
6108 else
6109 group_ssid_len = (end - pos2) / 2;
6110 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6111 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6112 return -1;
6113 group_ssid = _group_ssid;
6114 }
6115
6116 if (os_strncmp(pos, "pin", 3) == 0) {
6117 /* Request random PIN (to be displayed) and enable the PIN */
6118 wps_method = WPS_PIN_DISPLAY;
6119 } else if (os_strncmp(pos, "pbc", 3) == 0) {
6120 wps_method = WPS_PBC;
6121 } else if (os_strstr(pos, "p2ps") != NULL) {
6122 wps_method = WPS_P2PS;
6123 } else {
6124 pin = pos;
6125 pos = os_strchr(pin, ' ');
6126 wps_method = WPS_PIN_KEYPAD;
6127 if (pos) {
6128 *pos++ = '\0';
6129 if (os_strncmp(pos, "display", 7) == 0)
6130 wps_method = WPS_PIN_DISPLAY;
6131 }
6132 if (!wps_pin_str_valid(pin)) {
6133 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6134 return 17;
6135 }
6136 }
6137
6138 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
6139 persistent_group, automatic, join,
6140 auth, go_intent, freq, freq2, persistent_id,
6141 pd, ht40, vht, max_oper_chwidth, he, edmg,
6142 group_ssid, group_ssid_len);
6143 if (new_pin == -2) {
6144 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6145 return 25;
6146 }
6147 if (new_pin == -3) {
6148 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6149 return 25;
6150 }
6151 if (new_pin < 0)
6152 return -1;
6153 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6154 ret = os_snprintf(buf, buflen, "%08d", new_pin);
6155 if (os_snprintf_error(buflen, ret))
6156 return -1;
6157 return ret;
6158 }
6159
6160 os_memcpy(buf, "OK\n", 3);
6161 return 3;
6162 }
6163
6164
p2p_ctrl_listen(struct wpa_supplicant * wpa_s,char * cmd)6165 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6166 {
6167 unsigned int timeout = atoi(cmd);
6168 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6169 wpa_dbg(wpa_s, MSG_INFO,
6170 "Reject P2P_LISTEN since interface is disabled");
6171 return -1;
6172 }
6173 return wpas_p2p_listen(wpa_s, timeout);
6174 }
6175
6176
p2p_ctrl_prov_disc(struct wpa_supplicant * wpa_s,char * cmd)6177 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6178 {
6179 u8 addr[ETH_ALEN];
6180 char *pos;
6181 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
6182
6183 /* <addr> <config method> [join|auto] */
6184
6185 if (hwaddr_aton(cmd, addr))
6186 return -1;
6187
6188 pos = cmd + 17;
6189 if (*pos != ' ')
6190 return -1;
6191 pos++;
6192
6193 if (os_strstr(pos, " join") != NULL)
6194 use = WPAS_P2P_PD_FOR_JOIN;
6195 else if (os_strstr(pos, " auto") != NULL)
6196 use = WPAS_P2P_PD_AUTO;
6197
6198 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
6199 }
6200
6201
p2p_get_passphrase(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)6202 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6203 size_t buflen)
6204 {
6205 struct wpa_ssid *ssid = wpa_s->current_ssid;
6206
6207 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6208 ssid->passphrase == NULL)
6209 return -1;
6210
6211 os_strlcpy(buf, ssid->passphrase, buflen);
6212 return os_strlen(buf);
6213 }
6214
6215
p2p_ctrl_serv_disc_req(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6216 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6217 char *buf, size_t buflen)
6218 {
6219 u64 ref;
6220 int res;
6221 u8 dst_buf[ETH_ALEN], *dst;
6222 struct wpabuf *tlvs;
6223 char *pos;
6224 size_t len;
6225
6226 if (hwaddr_aton(cmd, dst_buf))
6227 return -1;
6228 dst = dst_buf;
6229 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6230 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6231 dst = NULL;
6232 pos = cmd + 17;
6233 if (*pos != ' ')
6234 return -1;
6235 pos++;
6236
6237 if (os_strncmp(pos, "upnp ", 5) == 0) {
6238 u8 version;
6239 pos += 5;
6240 if (hexstr2bin(pos, &version, 1) < 0)
6241 return -1;
6242 pos += 2;
6243 if (*pos != ' ')
6244 return -1;
6245 pos++;
6246 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
6247 #ifdef CONFIG_WIFI_DISPLAY
6248 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6249 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6250 #endif /* CONFIG_WIFI_DISPLAY */
6251 } else if (os_strncmp(pos, "asp ", 4) == 0) {
6252 char *svc_str;
6253 char *svc_info = NULL;
6254 u32 id;
6255
6256 pos += 4;
6257 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6258 return -1;
6259
6260 pos = os_strchr(pos, ' ');
6261 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6262 return -1;
6263
6264 svc_str = pos + 1;
6265
6266 pos = os_strchr(svc_str, ' ');
6267
6268 if (pos)
6269 *pos++ = '\0';
6270
6271 /* All remaining data is the svc_info string */
6272 if (pos && pos[0] && pos[0] != ' ') {
6273 len = os_strlen(pos);
6274
6275 /* Unescape in place */
6276 len = utf8_unescape(pos, len, pos, len);
6277 if (len > 0xff)
6278 return -1;
6279
6280 svc_info = pos;
6281 }
6282
6283 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6284 svc_str, svc_info);
6285 } else {
6286 len = os_strlen(pos);
6287 if (len & 1)
6288 return -1;
6289 len /= 2;
6290 tlvs = wpabuf_alloc(len);
6291 if (tlvs == NULL)
6292 return -1;
6293 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6294 wpabuf_free(tlvs);
6295 return -1;
6296 }
6297
6298 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
6299 wpabuf_free(tlvs);
6300 }
6301 if (ref == 0)
6302 return -1;
6303 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
6304 if (os_snprintf_error(buflen, res))
6305 return -1;
6306 return res;
6307 }
6308
6309
p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant * wpa_s,char * cmd)6310 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6311 char *cmd)
6312 {
6313 long long unsigned val;
6314 u64 req;
6315 if (sscanf(cmd, "%llx", &val) != 1)
6316 return -1;
6317 req = val;
6318 return wpas_p2p_sd_cancel_request(wpa_s, req);
6319 }
6320
6321
p2p_ctrl_serv_disc_resp(struct wpa_supplicant * wpa_s,char * cmd)6322 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6323 {
6324 int freq;
6325 u8 dst[ETH_ALEN];
6326 u8 dialog_token;
6327 struct wpabuf *resp_tlvs;
6328 char *pos, *pos2;
6329 size_t len;
6330
6331 pos = os_strchr(cmd, ' ');
6332 if (pos == NULL)
6333 return -1;
6334 *pos++ = '\0';
6335 freq = atoi(cmd);
6336 if (freq == 0)
6337 return -1;
6338
6339 if (hwaddr_aton(pos, dst))
6340 return -1;
6341 pos += 17;
6342 if (*pos != ' ')
6343 return -1;
6344 pos++;
6345
6346 pos2 = os_strchr(pos, ' ');
6347 if (pos2 == NULL)
6348 return -1;
6349 *pos2++ = '\0';
6350 dialog_token = atoi(pos);
6351
6352 len = os_strlen(pos2);
6353 if (len & 1)
6354 return -1;
6355 len /= 2;
6356 resp_tlvs = wpabuf_alloc(len);
6357 if (resp_tlvs == NULL)
6358 return -1;
6359 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6360 wpabuf_free(resp_tlvs);
6361 return -1;
6362 }
6363
6364 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6365 wpabuf_free(resp_tlvs);
6366 return 0;
6367 }
6368
6369
p2p_ctrl_serv_disc_external(struct wpa_supplicant * wpa_s,char * cmd)6370 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6371 char *cmd)
6372 {
6373 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6374 return -1;
6375 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6376 return 0;
6377 }
6378
6379
p2p_ctrl_service_add_bonjour(struct wpa_supplicant * wpa_s,char * cmd)6380 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6381 char *cmd)
6382 {
6383 char *pos;
6384 size_t len;
6385 struct wpabuf *query, *resp;
6386
6387 pos = os_strchr(cmd, ' ');
6388 if (pos == NULL)
6389 return -1;
6390 *pos++ = '\0';
6391
6392 len = os_strlen(cmd);
6393 if (len & 1)
6394 return -1;
6395 len /= 2;
6396 query = wpabuf_alloc(len);
6397 if (query == NULL)
6398 return -1;
6399 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6400 wpabuf_free(query);
6401 return -1;
6402 }
6403
6404 len = os_strlen(pos);
6405 if (len & 1) {
6406 wpabuf_free(query);
6407 return -1;
6408 }
6409 len /= 2;
6410 resp = wpabuf_alloc(len);
6411 if (resp == NULL) {
6412 wpabuf_free(query);
6413 return -1;
6414 }
6415 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
6416 wpabuf_free(query);
6417 wpabuf_free(resp);
6418 return -1;
6419 }
6420
6421 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
6422 wpabuf_free(query);
6423 wpabuf_free(resp);
6424 return -1;
6425 }
6426 return 0;
6427 }
6428
6429
p2p_ctrl_service_add_upnp(struct wpa_supplicant * wpa_s,char * cmd)6430 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6431 {
6432 char *pos;
6433 u8 version;
6434
6435 pos = os_strchr(cmd, ' ');
6436 if (pos == NULL)
6437 return -1;
6438 *pos++ = '\0';
6439
6440 if (hexstr2bin(cmd, &version, 1) < 0)
6441 return -1;
6442
6443 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6444 }
6445
6446
p2p_ctrl_service_add_asp(struct wpa_supplicant * wpa_s,u8 replace,char * cmd)6447 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6448 u8 replace, char *cmd)
6449 {
6450 char *pos;
6451 char *adv_str;
6452 u32 auto_accept, adv_id, svc_state, config_methods;
6453 char *svc_info = NULL;
6454 char *cpt_prio_str;
6455 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
6456
6457 pos = os_strchr(cmd, ' ');
6458 if (pos == NULL)
6459 return -1;
6460 *pos++ = '\0';
6461
6462 /* Auto-Accept value is mandatory, and must be one of the
6463 * single values (0, 1, 2, 4) */
6464 auto_accept = atoi(cmd);
6465 switch (auto_accept) {
6466 case P2PS_SETUP_NONE: /* No auto-accept */
6467 case P2PS_SETUP_NEW:
6468 case P2PS_SETUP_CLIENT:
6469 case P2PS_SETUP_GROUP_OWNER:
6470 break;
6471 default:
6472 return -1;
6473 }
6474
6475 /* Advertisement ID is mandatory */
6476 cmd = pos;
6477 pos = os_strchr(cmd, ' ');
6478 if (pos == NULL)
6479 return -1;
6480 *pos++ = '\0';
6481
6482 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6483 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6484 return -1;
6485
6486 /* Only allow replacements if exist, and adds if not */
6487 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6488 if (!replace)
6489 return -1;
6490 } else {
6491 if (replace)
6492 return -1;
6493 }
6494
6495 /* svc_state between 0 - 0xff is mandatory */
6496 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6497 return -1;
6498
6499 pos = os_strchr(pos, ' ');
6500 if (pos == NULL)
6501 return -1;
6502
6503 /* config_methods is mandatory */
6504 pos++;
6505 if (sscanf(pos, "%x", &config_methods) != 1)
6506 return -1;
6507
6508 if (!(config_methods &
6509 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6510 return -1;
6511
6512 pos = os_strchr(pos, ' ');
6513 if (pos == NULL)
6514 return -1;
6515
6516 pos++;
6517 adv_str = pos;
6518
6519 /* Advertisement string is mandatory */
6520 if (!pos[0] || pos[0] == ' ')
6521 return -1;
6522
6523 /* Terminate svc string */
6524 pos = os_strchr(pos, ' ');
6525 if (pos != NULL)
6526 *pos++ = '\0';
6527
6528 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6529 if (cpt_prio_str) {
6530 pos = os_strchr(pos, ' ');
6531 if (pos != NULL)
6532 *pos++ = '\0';
6533
6534 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6535 return -1;
6536 } else {
6537 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6538 cpt_prio[1] = 0;
6539 }
6540
6541 /* Service and Response Information are optional */
6542 if (pos && pos[0]) {
6543 size_t len;
6544
6545 /* Note the bare ' included, which cannot exist legally
6546 * in unescaped string. */
6547 svc_info = os_strstr(pos, "svc_info='");
6548
6549 if (svc_info) {
6550 svc_info += 9;
6551 len = os_strlen(svc_info);
6552 utf8_unescape(svc_info, len, svc_info, len);
6553 }
6554 }
6555
6556 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6557 (u8) svc_state, (u16) config_methods,
6558 svc_info, cpt_prio);
6559 }
6560
6561
p2p_ctrl_service_add(struct wpa_supplicant * wpa_s,char * cmd)6562 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6563 {
6564 char *pos;
6565
6566 pos = os_strchr(cmd, ' ');
6567 if (pos == NULL)
6568 return -1;
6569 *pos++ = '\0';
6570
6571 if (os_strcmp(cmd, "bonjour") == 0)
6572 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6573 if (os_strcmp(cmd, "upnp") == 0)
6574 return p2p_ctrl_service_add_upnp(wpa_s, pos);
6575 if (os_strcmp(cmd, "asp") == 0)
6576 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
6577 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6578 return -1;
6579 }
6580
6581
p2p_ctrl_service_del_bonjour(struct wpa_supplicant * wpa_s,char * cmd)6582 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6583 char *cmd)
6584 {
6585 size_t len;
6586 struct wpabuf *query;
6587 int ret;
6588
6589 len = os_strlen(cmd);
6590 if (len & 1)
6591 return -1;
6592 len /= 2;
6593 query = wpabuf_alloc(len);
6594 if (query == NULL)
6595 return -1;
6596 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6597 wpabuf_free(query);
6598 return -1;
6599 }
6600
6601 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6602 wpabuf_free(query);
6603 return ret;
6604 }
6605
6606
p2p_ctrl_service_del_upnp(struct wpa_supplicant * wpa_s,char * cmd)6607 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6608 {
6609 char *pos;
6610 u8 version;
6611
6612 pos = os_strchr(cmd, ' ');
6613 if (pos == NULL)
6614 return -1;
6615 *pos++ = '\0';
6616
6617 if (hexstr2bin(cmd, &version, 1) < 0)
6618 return -1;
6619
6620 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6621 }
6622
6623
p2p_ctrl_service_del_asp(struct wpa_supplicant * wpa_s,char * cmd)6624 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6625 {
6626 u32 adv_id;
6627
6628 if (os_strcmp(cmd, "all") == 0) {
6629 wpas_p2p_service_flush_asp(wpa_s);
6630 return 0;
6631 }
6632
6633 if (sscanf(cmd, "%x", &adv_id) != 1)
6634 return -1;
6635
6636 return wpas_p2p_service_del_asp(wpa_s, adv_id);
6637 }
6638
6639
p2p_ctrl_service_del(struct wpa_supplicant * wpa_s,char * cmd)6640 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6641 {
6642 char *pos;
6643
6644 pos = os_strchr(cmd, ' ');
6645 if (pos == NULL)
6646 return -1;
6647 *pos++ = '\0';
6648
6649 if (os_strcmp(cmd, "bonjour") == 0)
6650 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
6651 if (os_strcmp(cmd, "upnp") == 0)
6652 return p2p_ctrl_service_del_upnp(wpa_s, pos);
6653 if (os_strcmp(cmd, "asp") == 0)
6654 return p2p_ctrl_service_del_asp(wpa_s, pos);
6655 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6656 return -1;
6657 }
6658
6659
p2p_ctrl_service_replace(struct wpa_supplicant * wpa_s,char * cmd)6660 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
6661 {
6662 char *pos;
6663
6664 pos = os_strchr(cmd, ' ');
6665 if (pos == NULL)
6666 return -1;
6667 *pos++ = '\0';
6668
6669 if (os_strcmp(cmd, "asp") == 0)
6670 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
6671
6672 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6673 return -1;
6674 }
6675
6676
p2p_ctrl_reject(struct wpa_supplicant * wpa_s,char * cmd)6677 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
6678 {
6679 u8 addr[ETH_ALEN];
6680
6681 /* <addr> */
6682
6683 if (hwaddr_aton(cmd, addr))
6684 return -1;
6685
6686 return wpas_p2p_reject(wpa_s, addr);
6687 }
6688
6689
p2p_ctrl_invite_persistent(struct wpa_supplicant * wpa_s,char * cmd)6690 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
6691 {
6692 char *pos;
6693 int id;
6694 struct wpa_ssid *ssid;
6695 u8 *_peer = NULL, peer[ETH_ALEN];
6696 int freq = 0, pref_freq = 0;
6697 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
6698 int edmg;
6699
6700 id = atoi(cmd);
6701 pos = os_strstr(cmd, " peer=");
6702 if (pos) {
6703 pos += 6;
6704 if (hwaddr_aton(pos, peer))
6705 return -1;
6706 _peer = peer;
6707 }
6708 ssid = wpa_config_get_network(wpa_s->conf, id);
6709 if (ssid == NULL || ssid->disabled != 2) {
6710 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6711 "for persistent P2P group",
6712 id);
6713 return -1;
6714 }
6715
6716 pos = os_strstr(cmd, " freq=");
6717 if (pos) {
6718 pos += 6;
6719 freq = atoi(pos);
6720 if (freq <= 0)
6721 return -1;
6722 }
6723
6724 pos = os_strstr(cmd, " pref=");
6725 if (pos) {
6726 pos += 6;
6727 pref_freq = atoi(pos);
6728 if (pref_freq <= 0)
6729 return -1;
6730 }
6731
6732 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6733 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6734 vht;
6735 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
6736 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
6737
6738 pos = os_strstr(cmd, "freq2=");
6739 if (pos)
6740 freq2 = atoi(pos + 6);
6741
6742 pos = os_strstr(cmd, " max_oper_chwidth=");
6743 if (pos)
6744 chwidth = atoi(pos + 18);
6745
6746 max_oper_chwidth = parse_freq(chwidth, freq2);
6747 if (max_oper_chwidth < 0)
6748 return -1;
6749
6750 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
6751 max_oper_chwidth, pref_freq, he, edmg);
6752 }
6753
6754
p2p_ctrl_invite_group(struct wpa_supplicant * wpa_s,char * cmd)6755 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
6756 {
6757 char *pos;
6758 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
6759
6760 pos = os_strstr(cmd, " peer=");
6761 if (!pos)
6762 return -1;
6763
6764 *pos = '\0';
6765 pos += 6;
6766 if (hwaddr_aton(pos, peer)) {
6767 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
6768 return -1;
6769 }
6770
6771 pos = os_strstr(pos, " go_dev_addr=");
6772 if (pos) {
6773 pos += 13;
6774 if (hwaddr_aton(pos, go_dev_addr)) {
6775 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
6776 pos);
6777 return -1;
6778 }
6779 go_dev = go_dev_addr;
6780 }
6781
6782 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
6783 }
6784
6785
p2p_ctrl_invite(struct wpa_supplicant * wpa_s,char * cmd)6786 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
6787 {
6788 if (os_strncmp(cmd, "persistent=", 11) == 0)
6789 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
6790 if (os_strncmp(cmd, "group=", 6) == 0)
6791 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
6792
6793 return -1;
6794 }
6795
6796
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)6797 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
6798 int id, int freq, int vht_center_freq2,
6799 int ht40, int vht, int vht_chwidth,
6800 int he, int edmg)
6801 {
6802 struct wpa_ssid *ssid;
6803
6804 ssid = wpa_config_get_network(wpa_s->conf, id);
6805 if (ssid == NULL || ssid->disabled != 2) {
6806 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6807 "for persistent P2P group",
6808 id);
6809 return -1;
6810 }
6811
6812 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
6813 vht_center_freq2, 0, ht40, vht,
6814 vht_chwidth, he, edmg,
6815 NULL, 0, 0);
6816 }
6817
6818
p2p_ctrl_group_add(struct wpa_supplicant * wpa_s,char * cmd)6819 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
6820 {
6821 int freq = 0, persistent = 0, group_id = -1;
6822 int vht = wpa_s->conf->p2p_go_vht;
6823 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
6824 int he = wpa_s->conf->p2p_go_he;
6825 int edmg = wpa_s->conf->p2p_go_edmg;
6826 int max_oper_chwidth, chwidth = 0, freq2 = 0;
6827 char *token, *context = NULL;
6828 #ifdef CONFIG_ACS
6829 int acs = 0;
6830 #endif /* CONFIG_ACS */
6831
6832 while ((token = str_token(cmd, " ", &context))) {
6833 if (sscanf(token, "freq2=%d", &freq2) == 1 ||
6834 sscanf(token, "persistent=%d", &group_id) == 1 ||
6835 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
6836 continue;
6837 #ifdef CONFIG_ACS
6838 } else if (os_strcmp(token, "freq=acs") == 0) {
6839 acs = 1;
6840 #endif /* CONFIG_ACS */
6841 } else if (sscanf(token, "freq=%d", &freq) == 1) {
6842 continue;
6843 } else if (os_strcmp(token, "ht40") == 0) {
6844 ht40 = 1;
6845 } else if (os_strcmp(token, "vht") == 0) {
6846 vht = 1;
6847 ht40 = 1;
6848 } else if (os_strcmp(token, "he") == 0) {
6849 he = 1;
6850 } else if (os_strcmp(token, "edmg") == 0) {
6851 edmg = 1;
6852 } else if (os_strcmp(token, "persistent") == 0) {
6853 persistent = 1;
6854 } else {
6855 wpa_printf(MSG_DEBUG,
6856 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
6857 token);
6858 return -1;
6859 }
6860 }
6861
6862 #ifdef CONFIG_ACS
6863 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
6864 (acs || freq == 2 || freq == 5)) {
6865 if (freq == 2 && wpa_s->best_24_freq <= 0) {
6866 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
6867 wpa_s->p2p_go_do_acs = 1;
6868 freq = 0;
6869 } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
6870 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
6871 wpa_s->p2p_go_do_acs = 1;
6872 freq = 0;
6873 } else {
6874 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
6875 wpa_s->p2p_go_do_acs = 1;
6876 }
6877 } else {
6878 wpa_s->p2p_go_do_acs = 0;
6879 }
6880 #endif /* CONFIG_ACS */
6881
6882 max_oper_chwidth = parse_freq(chwidth, freq2);
6883 if (max_oper_chwidth < 0)
6884 return -1;
6885
6886 if (group_id >= 0)
6887 return p2p_ctrl_group_add_persistent(wpa_s, group_id,
6888 freq, freq2, ht40, vht,
6889 max_oper_chwidth, he,
6890 edmg);
6891
6892 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
6893 max_oper_chwidth, he, edmg);
6894 }
6895
6896
p2p_ctrl_group_member(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)6897 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
6898 char *buf, size_t buflen)
6899 {
6900 u8 dev_addr[ETH_ALEN];
6901 struct wpa_ssid *ssid;
6902 int res;
6903 const u8 *iaddr;
6904
6905 ssid = wpa_s->current_ssid;
6906 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
6907 hwaddr_aton(cmd, dev_addr))
6908 return -1;
6909
6910 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
6911 if (!iaddr)
6912 return -1;
6913 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
6914 if (os_snprintf_error(buflen, res))
6915 return -1;
6916 return res;
6917 }
6918
6919
wpas_find_p2p_dev_addr_bss(struct wpa_global * global,const u8 * p2p_dev_addr)6920 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
6921 const u8 *p2p_dev_addr)
6922 {
6923 struct wpa_supplicant *wpa_s;
6924
6925 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6926 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
6927 return 1;
6928 }
6929
6930 return 0;
6931 }
6932
6933
p2p_ctrl_peer(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)6934 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
6935 char *buf, size_t buflen)
6936 {
6937 u8 addr[ETH_ALEN], *addr_ptr, group_capab;
6938 int next, res;
6939 const struct p2p_peer_info *info;
6940 char *pos, *end;
6941 char devtype[WPS_DEV_TYPE_BUFSIZE];
6942 struct wpa_ssid *ssid;
6943 size_t i;
6944
6945 if (!wpa_s->global->p2p)
6946 return -1;
6947
6948 if (os_strcmp(cmd, "FIRST") == 0) {
6949 addr_ptr = NULL;
6950 next = 0;
6951 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
6952 if (hwaddr_aton(cmd + 5, addr) < 0)
6953 return -1;
6954 addr_ptr = addr;
6955 next = 1;
6956 } else {
6957 if (hwaddr_aton(cmd, addr) < 0)
6958 return -1;
6959 addr_ptr = addr;
6960 next = 0;
6961 }
6962
6963 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
6964 if (info == NULL)
6965 return -1;
6966 group_capab = info->group_capab;
6967
6968 if (group_capab &&
6969 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
6970 wpa_printf(MSG_DEBUG,
6971 "P2P: Could not find any BSS with p2p_dev_addr "
6972 MACSTR ", hence override group_capab from 0x%x to 0",
6973 MAC2STR(info->p2p_device_addr), group_capab);
6974 group_capab = 0;
6975 }
6976
6977 pos = buf;
6978 end = buf + buflen;
6979
6980 res = os_snprintf(pos, end - pos, MACSTR "\n"
6981 "pri_dev_type=%s\n"
6982 "device_name=%s\n"
6983 "manufacturer=%s\n"
6984 "model_name=%s\n"
6985 "model_number=%s\n"
6986 "serial_number=%s\n"
6987 "config_methods=0x%x\n"
6988 "dev_capab=0x%x\n"
6989 "group_capab=0x%x\n"
6990 "level=%d\n",
6991 MAC2STR(info->p2p_device_addr),
6992 wps_dev_type_bin2str(info->pri_dev_type,
6993 devtype, sizeof(devtype)),
6994 info->device_name,
6995 info->manufacturer,
6996 info->model_name,
6997 info->model_number,
6998 info->serial_number,
6999 info->config_methods,
7000 info->dev_capab,
7001 group_capab,
7002 info->level);
7003 if (os_snprintf_error(end - pos, res))
7004 return pos - buf;
7005 pos += res;
7006
7007 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7008 {
7009 const u8 *t;
7010 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7011 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7012 wps_dev_type_bin2str(t, devtype,
7013 sizeof(devtype)));
7014 if (os_snprintf_error(end - pos, res))
7015 return pos - buf;
7016 pos += res;
7017 }
7018
7019 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
7020 if (ssid) {
7021 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
7022 if (os_snprintf_error(end - pos, res))
7023 return pos - buf;
7024 pos += res;
7025 }
7026
7027 res = p2p_get_peer_info_txt(info, pos, end - pos);
7028 if (res < 0)
7029 return pos - buf;
7030 pos += res;
7031
7032 if (info->vendor_elems) {
7033 res = os_snprintf(pos, end - pos, "vendor_elems=");
7034 if (os_snprintf_error(end - pos, res))
7035 return pos - buf;
7036 pos += res;
7037
7038 pos += wpa_snprintf_hex(pos, end - pos,
7039 wpabuf_head(info->vendor_elems),
7040 wpabuf_len(info->vendor_elems));
7041
7042 res = os_snprintf(pos, end - pos, "\n");
7043 if (os_snprintf_error(end - pos, res))
7044 return pos - buf;
7045 pos += res;
7046 }
7047
7048 return pos - buf;
7049 }
7050
7051
p2p_ctrl_disallow_freq(struct wpa_supplicant * wpa_s,const char * param)7052 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7053 const char *param)
7054 {
7055 unsigned int i;
7056
7057 if (wpa_s->global->p2p == NULL)
7058 return -1;
7059
7060 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7061 return -1;
7062
7063 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7064 struct wpa_freq_range *freq;
7065 freq = &wpa_s->global->p2p_disallow_freq.range[i];
7066 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
7067 freq->min, freq->max);
7068 }
7069
7070 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
7071 return 0;
7072 }
7073
7074
p2p_ctrl_set(struct wpa_supplicant * wpa_s,char * cmd)7075 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7076 {
7077 char *param;
7078
7079 if (wpa_s->global->p2p == NULL)
7080 return -1;
7081
7082 param = os_strchr(cmd, ' ');
7083 if (param == NULL)
7084 return -1;
7085 *param++ = '\0';
7086
7087 if (os_strcmp(cmd, "discoverability") == 0) {
7088 p2p_set_client_discoverability(wpa_s->global->p2p,
7089 atoi(param));
7090 return 0;
7091 }
7092
7093 if (os_strcmp(cmd, "managed") == 0) {
7094 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7095 return 0;
7096 }
7097
7098 if (os_strcmp(cmd, "listen_channel") == 0) {
7099 char *pos;
7100 u8 channel, op_class;
7101
7102 channel = atoi(param);
7103 pos = os_strchr(param, ' ');
7104 op_class = pos ? atoi(pos) : 81;
7105
7106 return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7107 channel, 1);
7108 }
7109
7110 if (os_strcmp(cmd, "ssid_postfix") == 0) {
7111 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7112 os_strlen(param));
7113 }
7114
7115 if (os_strcmp(cmd, "noa") == 0) {
7116 char *pos;
7117 int count, start, duration;
7118 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
7119 count = atoi(param);
7120 pos = os_strchr(param, ',');
7121 if (pos == NULL)
7122 return -1;
7123 pos++;
7124 start = atoi(pos);
7125 pos = os_strchr(pos, ',');
7126 if (pos == NULL)
7127 return -1;
7128 pos++;
7129 duration = atoi(pos);
7130 if (count < 0 || count > 255 || start < 0 || duration < 0)
7131 return -1;
7132 if (count == 0 && duration > 0)
7133 return -1;
7134 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7135 "start=%d duration=%d", count, start, duration);
7136 return wpas_p2p_set_noa(wpa_s, count, start, duration);
7137 }
7138
7139 if (os_strcmp(cmd, "ps") == 0)
7140 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7141
7142 if (os_strcmp(cmd, "oppps") == 0)
7143 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7144
7145 if (os_strcmp(cmd, "ctwindow") == 0)
7146 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7147
7148 if (os_strcmp(cmd, "disabled") == 0) {
7149 wpa_s->global->p2p_disabled = atoi(param);
7150 wpa_printf(MSG_DEBUG, "P2P functionality %s",
7151 wpa_s->global->p2p_disabled ?
7152 "disabled" : "enabled");
7153 if (wpa_s->global->p2p_disabled) {
7154 wpas_p2p_stop_find(wpa_s);
7155 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7156 p2p_flush(wpa_s->global->p2p);
7157 }
7158 return 0;
7159 }
7160
7161 if (os_strcmp(cmd, "conc_pref") == 0) {
7162 if (os_strcmp(param, "sta") == 0)
7163 wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7164 else if (os_strcmp(param, "p2p") == 0)
7165 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
7166 else {
7167 wpa_printf(MSG_INFO, "Invalid conc_pref value");
7168 return -1;
7169 }
7170 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
7171 "%s", param);
7172 return 0;
7173 }
7174
7175 if (os_strcmp(cmd, "force_long_sd") == 0) {
7176 wpa_s->force_long_sd = atoi(param);
7177 return 0;
7178 }
7179
7180 if (os_strcmp(cmd, "peer_filter") == 0) {
7181 u8 addr[ETH_ALEN];
7182 if (hwaddr_aton(param, addr))
7183 return -1;
7184 p2p_set_peer_filter(wpa_s->global->p2p, addr);
7185 return 0;
7186 }
7187
7188 if (os_strcmp(cmd, "cross_connect") == 0)
7189 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7190
7191 if (os_strcmp(cmd, "go_apsd") == 0) {
7192 if (os_strcmp(param, "disable") == 0)
7193 wpa_s->set_ap_uapsd = 0;
7194 else {
7195 wpa_s->set_ap_uapsd = 1;
7196 wpa_s->ap_uapsd = atoi(param);
7197 }
7198 return 0;
7199 }
7200
7201 if (os_strcmp(cmd, "client_apsd") == 0) {
7202 if (os_strcmp(param, "disable") == 0)
7203 wpa_s->set_sta_uapsd = 0;
7204 else {
7205 int be, bk, vi, vo;
7206 char *pos;
7207 /* format: BE,BK,VI,VO;max SP Length */
7208 be = atoi(param);
7209 pos = os_strchr(param, ',');
7210 if (pos == NULL)
7211 return -1;
7212 pos++;
7213 bk = atoi(pos);
7214 pos = os_strchr(pos, ',');
7215 if (pos == NULL)
7216 return -1;
7217 pos++;
7218 vi = atoi(pos);
7219 pos = os_strchr(pos, ',');
7220 if (pos == NULL)
7221 return -1;
7222 pos++;
7223 vo = atoi(pos);
7224 /* ignore max SP Length for now */
7225
7226 wpa_s->set_sta_uapsd = 1;
7227 wpa_s->sta_uapsd = 0;
7228 if (be)
7229 wpa_s->sta_uapsd |= BIT(0);
7230 if (bk)
7231 wpa_s->sta_uapsd |= BIT(1);
7232 if (vi)
7233 wpa_s->sta_uapsd |= BIT(2);
7234 if (vo)
7235 wpa_s->sta_uapsd |= BIT(3);
7236 }
7237 return 0;
7238 }
7239
7240 if (os_strcmp(cmd, "disallow_freq") == 0)
7241 return p2p_ctrl_disallow_freq(wpa_s, param);
7242
7243 if (os_strcmp(cmd, "disc_int") == 0) {
7244 int min_disc_int, max_disc_int, max_disc_tu;
7245 char *pos;
7246
7247 pos = param;
7248
7249 min_disc_int = atoi(pos);
7250 pos = os_strchr(pos, ' ');
7251 if (pos == NULL)
7252 return -1;
7253 *pos++ = '\0';
7254
7255 max_disc_int = atoi(pos);
7256 pos = os_strchr(pos, ' ');
7257 if (pos == NULL)
7258 return -1;
7259 *pos++ = '\0';
7260
7261 max_disc_tu = atoi(pos);
7262
7263 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7264 max_disc_int, max_disc_tu);
7265 }
7266
7267 if (os_strcmp(cmd, "per_sta_psk") == 0) {
7268 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7269 return 0;
7270 }
7271
7272 #ifdef CONFIG_WPS_NFC
7273 if (os_strcmp(cmd, "nfc_tag") == 0)
7274 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7275 #endif /* CONFIG_WPS_NFC */
7276
7277 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7278 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7279 return 0;
7280 }
7281
7282 if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7283 int op_class, chan;
7284
7285 op_class = atoi(param);
7286 param = os_strchr(param, ':');
7287 if (!param)
7288 return -1;
7289 param++;
7290 chan = atoi(param);
7291 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7292 chan);
7293 return 0;
7294 }
7295
7296 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7297 cmd);
7298
7299 return -1;
7300 }
7301
7302
p2p_ctrl_flush(struct wpa_supplicant * wpa_s)7303 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7304 {
7305 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7306 wpa_s->force_long_sd = 0;
7307
7308 #ifdef CONFIG_TESTING_OPTIONS
7309 os_free(wpa_s->get_pref_freq_list_override);
7310 wpa_s->get_pref_freq_list_override = NULL;
7311 #endif /* CONFIG_TESTING_OPTIONS */
7312
7313 wpas_p2p_stop_find(wpa_s);
7314 wpa_s->parent->p2ps_method_config_any = 0;
7315 if (wpa_s->global->p2p)
7316 p2p_flush(wpa_s->global->p2p);
7317 }
7318
7319
p2p_ctrl_presence_req(struct wpa_supplicant * wpa_s,char * cmd)7320 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7321 {
7322 char *pos, *pos2;
7323 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7324
7325 if (cmd[0]) {
7326 pos = os_strchr(cmd, ' ');
7327 if (pos == NULL)
7328 return -1;
7329 *pos++ = '\0';
7330 dur1 = atoi(cmd);
7331
7332 pos2 = os_strchr(pos, ' ');
7333 if (pos2)
7334 *pos2++ = '\0';
7335 int1 = atoi(pos);
7336 } else
7337 pos2 = NULL;
7338
7339 if (pos2) {
7340 pos = os_strchr(pos2, ' ');
7341 if (pos == NULL)
7342 return -1;
7343 *pos++ = '\0';
7344 dur2 = atoi(pos2);
7345 int2 = atoi(pos);
7346 }
7347
7348 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7349 }
7350
7351
p2p_ctrl_ext_listen(struct wpa_supplicant * wpa_s,char * cmd)7352 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7353 {
7354 char *pos;
7355 unsigned int period = 0, interval = 0;
7356
7357 if (cmd[0]) {
7358 pos = os_strchr(cmd, ' ');
7359 if (pos == NULL)
7360 return -1;
7361 *pos++ = '\0';
7362 period = atoi(cmd);
7363 interval = atoi(pos);
7364 }
7365
7366 return wpas_p2p_ext_listen(wpa_s, period, interval);
7367 }
7368
7369
p2p_ctrl_remove_client(struct wpa_supplicant * wpa_s,const char * cmd)7370 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7371 {
7372 const char *pos;
7373 u8 peer[ETH_ALEN];
7374 int iface_addr = 0;
7375
7376 pos = cmd;
7377 if (os_strncmp(pos, "iface=", 6) == 0) {
7378 iface_addr = 1;
7379 pos += 6;
7380 }
7381 if (hwaddr_aton(pos, peer))
7382 return -1;
7383
7384 wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7385 return 0;
7386 }
7387
7388
p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant * wpa_s,char * cmd)7389 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7390 {
7391 int freq = 0, period = 0, interval = 0, count = 0;
7392
7393 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7394 {
7395 wpa_printf(MSG_DEBUG,
7396 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7397 return -1;
7398 }
7399
7400 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7401 }
7402
7403 #endif /* CONFIG_P2P */
7404
7405
freq_range_to_channel_list(struct wpa_supplicant * wpa_s,char * val)7406 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7407 {
7408 struct wpa_freq_range_list ranges;
7409 int *freqs = NULL;
7410 struct hostapd_hw_modes *mode;
7411 u16 i;
7412
7413 if (wpa_s->hw.modes == NULL)
7414 return NULL;
7415
7416 os_memset(&ranges, 0, sizeof(ranges));
7417 if (freq_range_list_parse(&ranges, val) < 0)
7418 return NULL;
7419
7420 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7421 int j;
7422
7423 mode = &wpa_s->hw.modes[i];
7424 for (j = 0; j < mode->num_channels; j++) {
7425 unsigned int freq;
7426
7427 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7428 continue;
7429
7430 freq = mode->channels[j].freq;
7431 if (!freq_range_list_includes(&ranges, freq))
7432 continue;
7433
7434 int_array_add_unique(&freqs, freq);
7435 }
7436 }
7437
7438 os_free(ranges.range);
7439 return freqs;
7440 }
7441
7442
7443 #ifdef CONFIG_INTERWORKING
7444
ctrl_interworking_select(struct wpa_supplicant * wpa_s,char * param)7445 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7446 {
7447 int auto_sel = 0;
7448 int *freqs = NULL;
7449
7450 if (param) {
7451 char *pos;
7452
7453 auto_sel = os_strstr(param, "auto") != NULL;
7454
7455 pos = os_strstr(param, "freq=");
7456 if (pos) {
7457 freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7458 if (freqs == NULL)
7459 return -1;
7460 }
7461
7462 }
7463
7464 return interworking_select(wpa_s, auto_sel, freqs);
7465 }
7466
7467
ctrl_interworking_connect(struct wpa_supplicant * wpa_s,char * dst,int only_add)7468 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7469 int only_add)
7470 {
7471 u8 bssid[ETH_ALEN];
7472 struct wpa_bss *bss;
7473
7474 if (hwaddr_aton(dst, bssid)) {
7475 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7476 return -1;
7477 }
7478
7479 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
7480 if (bss == NULL) {
7481 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7482 MAC2STR(bssid));
7483 return -1;
7484 }
7485
7486 if (bss->ssid_len == 0) {
7487 int found = 0;
7488
7489 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7490 " does not have SSID information", MAC2STR(bssid));
7491
7492 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7493 list) {
7494 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
7495 bss->ssid_len > 0) {
7496 found = 1;
7497 break;
7498 }
7499 }
7500
7501 if (!found)
7502 return -1;
7503 wpa_printf(MSG_DEBUG,
7504 "Found another matching BSS entry with SSID");
7505 }
7506
7507 return interworking_connect(wpa_s, bss, only_add);
7508 }
7509
7510
get_anqp(struct wpa_supplicant * wpa_s,char * dst)7511 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7512 {
7513 u8 dst_addr[ETH_ALEN];
7514 int used, freq = 0;
7515 char *pos;
7516 #define MAX_ANQP_INFO_ID 100
7517 u16 id[MAX_ANQP_INFO_ID];
7518 size_t num_id = 0;
7519 u32 subtypes = 0;
7520 u32 mbo_subtypes = 0;
7521
7522 used = hwaddr_aton2(dst, dst_addr);
7523 if (used < 0)
7524 return -1;
7525 pos = dst + used;
7526 if (*pos == ' ')
7527 pos++;
7528
7529 if (os_strncmp(pos, "freq=", 5) == 0) {
7530 freq = atoi(pos + 5);
7531 pos = os_strchr(pos, ' ');
7532 if (!pos)
7533 return -1;
7534 pos++;
7535 }
7536
7537 while (num_id < MAX_ANQP_INFO_ID) {
7538 if (os_strncmp(pos, "hs20:", 5) == 0) {
7539 #ifdef CONFIG_HS20
7540 int num = atoi(pos + 5);
7541 if (num <= 0 || num > 31)
7542 return -1;
7543 subtypes |= BIT(num);
7544 #else /* CONFIG_HS20 */
7545 return -1;
7546 #endif /* CONFIG_HS20 */
7547 } else if (os_strncmp(pos, "mbo:", 4) == 0) {
7548 #ifdef CONFIG_MBO
7549 int num = atoi(pos + 4);
7550
7551 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
7552 return -1;
7553 mbo_subtypes |= BIT(num);
7554 #else /* CONFIG_MBO */
7555 return -1;
7556 #endif /* CONFIG_MBO */
7557 } else {
7558 id[num_id] = atoi(pos);
7559 if (id[num_id])
7560 num_id++;
7561 }
7562 pos = os_strchr(pos + 1, ',');
7563 if (pos == NULL)
7564 break;
7565 pos++;
7566 }
7567
7568 if (num_id == 0 && !subtypes && !mbo_subtypes)
7569 return -1;
7570
7571 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
7572 mbo_subtypes);
7573 }
7574
7575
gas_request(struct wpa_supplicant * wpa_s,char * cmd)7576 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
7577 {
7578 u8 dst_addr[ETH_ALEN];
7579 struct wpabuf *advproto, *query = NULL;
7580 int used, ret = -1;
7581 char *pos, *end;
7582 size_t len;
7583
7584 used = hwaddr_aton2(cmd, dst_addr);
7585 if (used < 0)
7586 return -1;
7587
7588 pos = cmd + used;
7589 while (*pos == ' ')
7590 pos++;
7591
7592 /* Advertisement Protocol ID */
7593 end = os_strchr(pos, ' ');
7594 if (end)
7595 len = end - pos;
7596 else
7597 len = os_strlen(pos);
7598 if (len & 0x01)
7599 return -1;
7600 len /= 2;
7601 if (len == 0)
7602 return -1;
7603 advproto = wpabuf_alloc(len);
7604 if (advproto == NULL)
7605 return -1;
7606 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
7607 goto fail;
7608
7609 if (end) {
7610 /* Optional Query Request */
7611 pos = end + 1;
7612 while (*pos == ' ')
7613 pos++;
7614
7615 len = os_strlen(pos);
7616 if (len) {
7617 if (len & 0x01)
7618 goto fail;
7619 len /= 2;
7620 if (len == 0)
7621 goto fail;
7622 query = wpabuf_alloc(len);
7623 if (query == NULL)
7624 goto fail;
7625 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
7626 goto fail;
7627 }
7628 }
7629
7630 ret = gas_send_request(wpa_s, dst_addr, advproto, query);
7631
7632 fail:
7633 wpabuf_free(advproto);
7634 wpabuf_free(query);
7635
7636 return ret;
7637 }
7638
7639
gas_response_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)7640 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
7641 size_t buflen)
7642 {
7643 u8 addr[ETH_ALEN];
7644 int dialog_token;
7645 int used;
7646 char *pos;
7647 size_t resp_len, start, requested_len;
7648 struct wpabuf *resp;
7649 int ret;
7650
7651 used = hwaddr_aton2(cmd, addr);
7652 if (used < 0)
7653 return -1;
7654
7655 pos = cmd + used;
7656 while (*pos == ' ')
7657 pos++;
7658 dialog_token = atoi(pos);
7659
7660 if (wpa_s->last_gas_resp &&
7661 os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
7662 dialog_token == wpa_s->last_gas_dialog_token)
7663 resp = wpa_s->last_gas_resp;
7664 else if (wpa_s->prev_gas_resp &&
7665 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
7666 dialog_token == wpa_s->prev_gas_dialog_token)
7667 resp = wpa_s->prev_gas_resp;
7668 else
7669 return -1;
7670
7671 resp_len = wpabuf_len(resp);
7672 start = 0;
7673 requested_len = resp_len;
7674
7675 pos = os_strchr(pos, ' ');
7676 if (pos) {
7677 start = atoi(pos);
7678 if (start > resp_len)
7679 return os_snprintf(buf, buflen, "FAIL-Invalid range");
7680 pos = os_strchr(pos, ',');
7681 if (pos == NULL)
7682 return -1;
7683 pos++;
7684 requested_len = atoi(pos);
7685 if (start + requested_len > resp_len)
7686 return os_snprintf(buf, buflen, "FAIL-Invalid range");
7687 }
7688
7689 if (requested_len * 2 + 1 > buflen)
7690 return os_snprintf(buf, buflen, "FAIL-Too long response");
7691
7692 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
7693 requested_len);
7694
7695 if (start + requested_len == resp_len) {
7696 /*
7697 * Free memory by dropping the response after it has been
7698 * fetched.
7699 */
7700 if (resp == wpa_s->prev_gas_resp) {
7701 wpabuf_free(wpa_s->prev_gas_resp);
7702 wpa_s->prev_gas_resp = NULL;
7703 } else {
7704 wpabuf_free(wpa_s->last_gas_resp);
7705 wpa_s->last_gas_resp = NULL;
7706 }
7707 }
7708
7709 return ret;
7710 }
7711 #endif /* CONFIG_INTERWORKING */
7712
7713
7714 #ifdef CONFIG_HS20
7715
get_hs20_anqp(struct wpa_supplicant * wpa_s,char * dst)7716 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
7717 {
7718 u8 dst_addr[ETH_ALEN];
7719 int used;
7720 char *pos;
7721 u32 subtypes = 0;
7722
7723 used = hwaddr_aton2(dst, dst_addr);
7724 if (used < 0)
7725 return -1;
7726 pos = dst + used;
7727 if (*pos == ' ')
7728 pos++;
7729 for (;;) {
7730 int num = atoi(pos);
7731 if (num <= 0 || num > 31)
7732 return -1;
7733 subtypes |= BIT(num);
7734 pos = os_strchr(pos + 1, ',');
7735 if (pos == NULL)
7736 break;
7737 pos++;
7738 }
7739
7740 if (subtypes == 0)
7741 return -1;
7742
7743 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
7744 }
7745
7746
hs20_nai_home_realm_list(struct wpa_supplicant * wpa_s,const u8 * addr,const char * realm)7747 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7748 const u8 *addr, const char *realm)
7749 {
7750 u8 *buf;
7751 size_t rlen, len;
7752 int ret;
7753
7754 rlen = os_strlen(realm);
7755 len = 3 + rlen;
7756 buf = os_malloc(len);
7757 if (buf == NULL)
7758 return -1;
7759 buf[0] = 1; /* NAI Home Realm Count */
7760 buf[1] = 0; /* Formatted in accordance with RFC 4282 */
7761 buf[2] = rlen;
7762 os_memcpy(buf + 3, realm, rlen);
7763
7764 ret = hs20_anqp_send_req(wpa_s, addr,
7765 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
7766 buf, len, 0);
7767
7768 os_free(buf);
7769
7770 return ret;
7771 }
7772
7773
hs20_get_nai_home_realm_list(struct wpa_supplicant * wpa_s,char * dst)7774 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7775 char *dst)
7776 {
7777 struct wpa_cred *cred = wpa_s->conf->cred;
7778 u8 dst_addr[ETH_ALEN];
7779 int used;
7780 u8 *buf;
7781 size_t len;
7782 int ret;
7783
7784 used = hwaddr_aton2(dst, dst_addr);
7785 if (used < 0)
7786 return -1;
7787
7788 while (dst[used] == ' ')
7789 used++;
7790 if (os_strncmp(dst + used, "realm=", 6) == 0)
7791 return hs20_nai_home_realm_list(wpa_s, dst_addr,
7792 dst + used + 6);
7793
7794 len = os_strlen(dst + used);
7795
7796 if (len == 0 && cred && cred->realm)
7797 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
7798
7799 if (len & 1)
7800 return -1;
7801 len /= 2;
7802 buf = os_malloc(len);
7803 if (buf == NULL)
7804 return -1;
7805 if (hexstr2bin(dst + used, buf, len) < 0) {
7806 os_free(buf);
7807 return -1;
7808 }
7809
7810 ret = hs20_anqp_send_req(wpa_s, dst_addr,
7811 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
7812 buf, len, 0);
7813 os_free(buf);
7814
7815 return ret;
7816 }
7817
7818
get_hs20_icon(struct wpa_supplicant * wpa_s,char * cmd,char * reply,int buflen)7819 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
7820 int buflen)
7821 {
7822 u8 dst_addr[ETH_ALEN];
7823 int used;
7824 char *ctx = NULL, *icon, *poffset, *psize;
7825
7826 used = hwaddr_aton2(cmd, dst_addr);
7827 if (used < 0)
7828 return -1;
7829 cmd += used;
7830
7831 icon = str_token(cmd, " ", &ctx);
7832 poffset = str_token(cmd, " ", &ctx);
7833 psize = str_token(cmd, " ", &ctx);
7834 if (!icon || !poffset || !psize)
7835 return -1;
7836
7837 wpa_s->fetch_osu_icon_in_progress = 0;
7838 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
7839 reply, buflen);
7840 }
7841
7842
del_hs20_icon(struct wpa_supplicant * wpa_s,char * cmd)7843 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
7844 {
7845 u8 dst_addr[ETH_ALEN];
7846 int used;
7847 char *icon;
7848
7849 if (!cmd[0])
7850 return hs20_del_icon(wpa_s, NULL, NULL);
7851
7852 used = hwaddr_aton2(cmd, dst_addr);
7853 if (used < 0)
7854 return -1;
7855
7856 while (cmd[used] == ' ')
7857 used++;
7858 icon = cmd[used] ? &cmd[used] : NULL;
7859
7860 return hs20_del_icon(wpa_s, dst_addr, icon);
7861 }
7862
7863
hs20_icon_request(struct wpa_supplicant * wpa_s,char * cmd,int inmem)7864 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
7865 {
7866 u8 dst_addr[ETH_ALEN];
7867 int used;
7868 char *icon;
7869
7870 used = hwaddr_aton2(cmd, dst_addr);
7871 if (used < 0)
7872 return -1;
7873
7874 while (cmd[used] == ' ')
7875 used++;
7876 icon = &cmd[used];
7877
7878 wpa_s->fetch_osu_icon_in_progress = 0;
7879 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
7880 (u8 *) icon, os_strlen(icon), inmem);
7881 }
7882
7883 #endif /* CONFIG_HS20 */
7884
7885
7886 #ifdef CONFIG_AUTOSCAN
7887
wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant * wpa_s,char * cmd)7888 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
7889 char *cmd)
7890 {
7891 enum wpa_states state = wpa_s->wpa_state;
7892 char *new_params = NULL;
7893
7894 if (os_strlen(cmd) > 0) {
7895 new_params = os_strdup(cmd);
7896 if (new_params == NULL)
7897 return -1;
7898 }
7899
7900 os_free(wpa_s->conf->autoscan);
7901 wpa_s->conf->autoscan = new_params;
7902
7903 if (wpa_s->conf->autoscan == NULL)
7904 autoscan_deinit(wpa_s);
7905 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
7906 autoscan_init(wpa_s, 1);
7907 else if (state == WPA_SCANNING)
7908 wpa_supplicant_reinit_autoscan(wpa_s);
7909 else
7910 wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
7911 wpa_supplicant_state_txt(state));
7912
7913 return 0;
7914 }
7915
7916 #endif /* CONFIG_AUTOSCAN */
7917
7918
7919 #ifdef CONFIG_WNM
7920
wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant * wpa_s,char * cmd)7921 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
7922 {
7923 int enter;
7924 int intval = 0;
7925 char *pos;
7926 int ret;
7927 struct wpabuf *tfs_req = NULL;
7928
7929 if (os_strncmp(cmd, "enter", 5) == 0)
7930 enter = 1;
7931 else if (os_strncmp(cmd, "exit", 4) == 0)
7932 enter = 0;
7933 else
7934 return -1;
7935
7936 pos = os_strstr(cmd, " interval=");
7937 if (pos)
7938 intval = atoi(pos + 10);
7939
7940 pos = os_strstr(cmd, " tfs_req=");
7941 if (pos) {
7942 char *end;
7943 size_t len;
7944 pos += 9;
7945 end = os_strchr(pos, ' ');
7946 if (end)
7947 len = end - pos;
7948 else
7949 len = os_strlen(pos);
7950 if (len & 1)
7951 return -1;
7952 len /= 2;
7953 tfs_req = wpabuf_alloc(len);
7954 if (tfs_req == NULL)
7955 return -1;
7956 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
7957 wpabuf_free(tfs_req);
7958 return -1;
7959 }
7960 }
7961
7962 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
7963 WNM_SLEEP_MODE_EXIT, intval,
7964 tfs_req);
7965 wpabuf_free(tfs_req);
7966
7967 return ret;
7968 }
7969
7970
wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant * wpa_s,char * cmd)7971 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
7972 {
7973 int query_reason, list = 0;
7974 char *btm_candidates = NULL;
7975
7976 query_reason = atoi(cmd);
7977
7978 cmd = os_strchr(cmd, ' ');
7979 if (cmd) {
7980 if (os_strncmp(cmd, " list", 5) == 0)
7981 list = 1;
7982 else
7983 btm_candidates = cmd;
7984 }
7985
7986 wpa_printf(MSG_DEBUG,
7987 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
7988 query_reason, list ? " candidate list" : "");
7989
7990 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
7991 btm_candidates,
7992 list);
7993 }
7994
7995
wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant * wpa_s,char * cmd)7996 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
7997 char *cmd)
7998 {
7999 struct wpabuf *elems;
8000 int ret;
8001
8002 elems = wpabuf_parse_bin(cmd);
8003 if (!elems)
8004 return -1;
8005
8006 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8007 wpabuf_free(elems);
8008 return ret;
8009 }
8010
8011 #endif /* CONFIG_WNM */
8012
8013
wpa_supplicant_signal_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8014 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8015 size_t buflen)
8016 {
8017 struct wpa_signal_info si;
8018 int ret;
8019 char *pos, *end;
8020
8021 ret = wpa_drv_signal_poll(wpa_s, &si);
8022 if (ret)
8023 return -1;
8024
8025 pos = buf;
8026 end = buf + buflen;
8027
8028 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
8029 "NOISE=%d\nFREQUENCY=%u\n",
8030 si.current_signal, si.current_txrate / 1000,
8031 si.current_noise, si.frequency);
8032 if (os_snprintf_error(end - pos, ret))
8033 return -1;
8034 pos += ret;
8035
8036 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8037 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
8038 channel_width_to_string(si.chanwidth));
8039 if (os_snprintf_error(end - pos, ret))
8040 return -1;
8041 pos += ret;
8042 }
8043
8044 if (si.center_frq1 > 0) {
8045 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8046 si.center_frq1);
8047 if (os_snprintf_error(end - pos, ret))
8048 return -1;
8049 pos += ret;
8050 }
8051
8052 if (si.center_frq2 > 0) {
8053 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8054 si.center_frq2);
8055 if (os_snprintf_error(end - pos, ret))
8056 return -1;
8057 pos += ret;
8058 }
8059
8060 if (si.avg_signal) {
8061 ret = os_snprintf(pos, end - pos,
8062 "AVG_RSSI=%d\n", si.avg_signal);
8063 if (os_snprintf_error(end - pos, ret))
8064 return -1;
8065 pos += ret;
8066 }
8067
8068 if (si.avg_beacon_signal) {
8069 ret = os_snprintf(pos, end - pos,
8070 "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
8071 if (os_snprintf_error(end - pos, ret))
8072 return -1;
8073 pos += ret;
8074 }
8075
8076 return pos - buf;
8077 }
8078
8079
wpas_ctrl_iface_signal_monitor(struct wpa_supplicant * wpa_s,const char * cmd)8080 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8081 const char *cmd)
8082 {
8083 const char *pos;
8084 int threshold = 0;
8085 int hysteresis = 0;
8086
8087 if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8088 wpa_printf(MSG_DEBUG,
8089 "Reject SIGNAL_MONITOR command - bgscan is active");
8090 return -1;
8091 }
8092 pos = os_strstr(cmd, "THRESHOLD=");
8093 if (pos)
8094 threshold = atoi(pos + 10);
8095 pos = os_strstr(cmd, "HYSTERESIS=");
8096 if (pos)
8097 hysteresis = atoi(pos + 11);
8098 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8099 }
8100
8101
8102 #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,unsigned int * freq_list)8103 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8104 enum wpa_driver_if_type if_type,
8105 unsigned int *num,
8106 unsigned int *freq_list)
8107 {
8108 char *pos = wpa_s->get_pref_freq_list_override;
8109 char *end;
8110 unsigned int count = 0;
8111
8112 /* Override string format:
8113 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8114
8115 while (pos) {
8116 if (atoi(pos) == (int) if_type)
8117 break;
8118 pos = os_strchr(pos, ' ');
8119 if (pos)
8120 pos++;
8121 }
8122 if (!pos)
8123 return -1;
8124 pos = os_strchr(pos, ':');
8125 if (!pos)
8126 return -1;
8127 pos++;
8128 end = os_strchr(pos, ' ');
8129 while (pos && (!end || pos < end) && count < *num) {
8130 freq_list[count++] = atoi(pos);
8131 pos = os_strchr(pos, ',');
8132 if (pos)
8133 pos++;
8134 }
8135
8136 *num = count;
8137 return 0;
8138 }
8139 #endif /* CONFIG_TESTING_OPTIONS */
8140
8141
wpas_ctrl_iface_get_pref_freq_list(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8142 static int wpas_ctrl_iface_get_pref_freq_list(
8143 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8144 {
8145 unsigned int freq_list[100], num = 100, i;
8146 int ret;
8147 enum wpa_driver_if_type iface_type;
8148 char *pos, *end;
8149
8150 pos = buf;
8151 end = buf + buflen;
8152
8153 /* buf: "<interface_type>" */
8154 if (os_strcmp(cmd, "STATION") == 0)
8155 iface_type = WPA_IF_STATION;
8156 else if (os_strcmp(cmd, "AP") == 0)
8157 iface_type = WPA_IF_AP_BSS;
8158 else if (os_strcmp(cmd, "P2P_GO") == 0)
8159 iface_type = WPA_IF_P2P_GO;
8160 else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8161 iface_type = WPA_IF_P2P_CLIENT;
8162 else if (os_strcmp(cmd, "IBSS") == 0)
8163 iface_type = WPA_IF_IBSS;
8164 else if (os_strcmp(cmd, "TDLS") == 0)
8165 iface_type = WPA_IF_TDLS;
8166 else
8167 return -1;
8168
8169 wpa_printf(MSG_DEBUG,
8170 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
8171 iface_type, cmd);
8172
8173 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8174 if (ret)
8175 return -1;
8176
8177 for (i = 0; i < num; i++) {
8178 ret = os_snprintf(pos, end - pos, "%s%u",
8179 i > 0 ? "," : "", freq_list[i]);
8180 if (os_snprintf_error(end - pos, ret))
8181 return -1;
8182 pos += ret;
8183 }
8184
8185 return pos - buf;
8186 }
8187
8188
wpas_ctrl_iface_driver_flags(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8189 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8190 char *buf, size_t buflen)
8191 {
8192 int ret, i;
8193 char *pos, *end;
8194
8195 ret = os_snprintf(buf, buflen, "%016llX:\n",
8196 (long long unsigned) wpa_s->drv_flags);
8197 if (os_snprintf_error(buflen, ret))
8198 return -1;
8199
8200 pos = buf + ret;
8201 end = buf + buflen;
8202
8203 for (i = 0; i < 64; i++) {
8204 if (wpa_s->drv_flags & (1LLU << i)) {
8205 ret = os_snprintf(pos, end - pos, "%s\n",
8206 driver_flag_to_string(1LLU << i));
8207 if (os_snprintf_error(end - pos, ret))
8208 return -1;
8209 pos += ret;
8210 }
8211 }
8212
8213 return pos - buf;
8214 }
8215
8216
wpas_ctrl_iface_driver_flags2(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8217 static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8218 char *buf, size_t buflen)
8219 {
8220 int ret, i;
8221 char *pos, *end;
8222
8223 ret = os_snprintf(buf, buflen, "%016llX:\n",
8224 (long long unsigned) wpa_s->drv_flags2);
8225 if (os_snprintf_error(buflen, ret))
8226 return -1;
8227
8228 pos = buf + ret;
8229 end = buf + buflen;
8230
8231 for (i = 0; i < 64; i++) {
8232 if (wpa_s->drv_flags2 & (1LLU << i)) {
8233 ret = os_snprintf(pos, end - pos, "%s\n",
8234 driver_flag2_to_string(1LLU << i));
8235 if (os_snprintf_error(end - pos, ret))
8236 return -1;
8237 pos += ret;
8238 }
8239 }
8240
8241 return pos - buf;
8242 }
8243
8244
wpa_supplicant_pktcnt_poll(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8245 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8246 size_t buflen)
8247 {
8248 struct hostap_sta_driver_data sta;
8249 int ret;
8250
8251 ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8252 if (ret)
8253 return -1;
8254
8255 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
8256 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
8257 if (os_snprintf_error(buflen, ret))
8258 return -1;
8259 return ret;
8260 }
8261
8262
8263 #ifdef ANDROID
wpa_supplicant_driver_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8264 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8265 char *buf, size_t buflen)
8266 {
8267 int ret;
8268
8269 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
8270 if (ret == 0) {
8271 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8272 struct p2p_data *p2p = wpa_s->global->p2p;
8273 if (p2p) {
8274 char country[3];
8275 country[0] = cmd[8];
8276 country[1] = cmd[9];
8277 country[2] = 0x04;
8278 p2p_set_country(p2p, country);
8279 }
8280 }
8281 ret = os_snprintf(buf, buflen, "%s\n", "OK");
8282 if (os_snprintf_error(buflen, ret))
8283 ret = -1;
8284 }
8285 return ret;
8286 }
8287 #endif /* ANDROID */
8288
8289
wpa_supplicant_vendor_cmd(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8290 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8291 char *buf, size_t buflen)
8292 {
8293 int ret;
8294 char *pos, *temp = NULL;
8295 u8 *data = NULL;
8296 unsigned int vendor_id, subcmd;
8297 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
8298 struct wpabuf *reply;
8299 size_t data_len = 0;
8300
8301 /**
8302 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8303 * [nested=<0|1>]
8304 */
8305 vendor_id = strtoul(cmd, &pos, 16);
8306 if (!isblank((unsigned char) *pos))
8307 return -EINVAL;
8308
8309 subcmd = strtoul(pos, &pos, 10);
8310
8311 if (*pos != '\0') {
8312 if (!isblank((unsigned char) *pos++))
8313 return -EINVAL;
8314
8315 temp = os_strchr(pos, ' ');
8316 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
8317 }
8318
8319 if (data_len) {
8320 data_len /= 2;
8321 data = os_malloc(data_len);
8322 if (!data)
8323 return -1;
8324
8325 if (hexstr2bin(pos, data, data_len)) {
8326 wpa_printf(MSG_DEBUG,
8327 "Vendor command: wrong parameter format");
8328 os_free(data);
8329 return -EINVAL;
8330 }
8331 }
8332
8333 pos = os_strstr(cmd, "nested=");
8334 if (pos)
8335 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8336 NESTED_ATTR_NOT_USED;
8337
8338 reply = wpabuf_alloc((buflen - 1) / 2);
8339 if (!reply) {
8340 os_free(data);
8341 return -1;
8342 }
8343
8344 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
8345 nested_attr_flag, reply);
8346
8347 if (ret == 0)
8348 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8349 wpabuf_len(reply));
8350
8351 wpabuf_free(reply);
8352 os_free(data);
8353
8354 return ret;
8355 }
8356
8357
wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant * wpa_s)8358 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8359 {
8360 #ifdef CONFIG_P2P
8361 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8362 wpa_s->global->p2p_init_wpa_s : wpa_s;
8363 #endif /* CONFIG_P2P */
8364
8365 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8366
8367 if (wpas_abort_ongoing_scan(wpa_s) == 0)
8368 wpa_s->ignore_post_flush_scan_res = 1;
8369
8370 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8371 /*
8372 * Avoid possible auto connect re-connection on getting
8373 * disconnected due to state flush.
8374 */
8375 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8376 }
8377
8378 #ifdef CONFIG_P2P
8379 wpas_p2p_group_remove(p2p_wpa_s, "*");
8380 wpas_p2p_cancel(p2p_wpa_s);
8381 p2p_ctrl_flush(p2p_wpa_s);
8382 wpas_p2p_service_flush(p2p_wpa_s);
8383 p2p_wpa_s->global->p2p_disabled = 0;
8384 p2p_wpa_s->global->p2p_per_sta_psk = 0;
8385 p2p_wpa_s->conf->num_sec_device_types = 0;
8386 p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8387 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8388 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
8389 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
8390 p2p_wpa_s->global->pending_p2ps_group = 0;
8391 p2p_wpa_s->global->pending_p2ps_group_freq = 0;
8392 #endif /* CONFIG_P2P */
8393
8394 #ifdef CONFIG_WPS_TESTING
8395 wps_version_number = 0x20;
8396 wps_testing_dummy_cred = 0;
8397 wps_corrupt_pkhash = 0;
8398 wps_force_auth_types_in_use = 0;
8399 wps_force_encr_types_in_use = 0;
8400 #endif /* CONFIG_WPS_TESTING */
8401 #ifdef CONFIG_WPS
8402 wpa_s->wps_fragment_size = 0;
8403 wpas_wps_cancel(wpa_s);
8404 wps_registrar_flush(wpa_s->wps->registrar);
8405 #endif /* CONFIG_WPS */
8406 wpa_s->after_wps = 0;
8407 wpa_s->known_wps_freq = 0;
8408
8409 #ifdef CONFIG_DPP
8410 wpas_dpp_deinit(wpa_s);
8411 wpa_s->dpp_init_max_tries = 0;
8412 wpa_s->dpp_init_retry_time = 0;
8413 wpa_s->dpp_resp_wait_time = 0;
8414 wpa_s->dpp_resp_max_tries = 0;
8415 wpa_s->dpp_resp_retry_time = 0;
8416 #ifdef CONFIG_DPP2
8417 wpas_dpp_chirp_stop(wpa_s);
8418 wpa_s->dpp_pfs_fallback = 0;
8419 #endif /* CONFIG_DPP2 */
8420 #ifdef CONFIG_TESTING_OPTIONS
8421 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8422 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8423 dpp_pkex_ephemeral_key_override_len = 0;
8424 dpp_protocol_key_override_len = 0;
8425 dpp_nonce_override_len = 0;
8426 #ifdef CONFIG_DPP2
8427 dpp_version_override = 2;
8428 #else /* CONFIG_DPP2 */
8429 dpp_version_override = 1;
8430 #endif /* CONFIG_DPP2 */
8431 #endif /* CONFIG_TESTING_OPTIONS */
8432 #endif /* CONFIG_DPP */
8433
8434 #ifdef CONFIG_TDLS
8435 #ifdef CONFIG_TDLS_TESTING
8436 tdls_testing = 0;
8437 #endif /* CONFIG_TDLS_TESTING */
8438 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8439 wpa_tdls_enable(wpa_s->wpa, 1);
8440 #endif /* CONFIG_TDLS */
8441
8442 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8443 wpa_supplicant_stop_countermeasures(wpa_s, NULL);
8444 wpa_s->last_michael_mic_error.sec = 0;
8445
8446 wpa_s->no_keep_alive = 0;
8447 wpa_s->own_disconnect_req = 0;
8448 wpa_s->own_reconnect_req = 0;
8449 wpa_s->deny_ptk0_rekey = 0;
8450
8451 os_free(wpa_s->disallow_aps_bssid);
8452 wpa_s->disallow_aps_bssid = NULL;
8453 wpa_s->disallow_aps_bssid_count = 0;
8454 os_free(wpa_s->disallow_aps_ssid);
8455 wpa_s->disallow_aps_ssid = NULL;
8456 wpa_s->disallow_aps_ssid_count = 0;
8457
8458 wpa_s->set_sta_uapsd = 0;
8459 wpa_s->sta_uapsd = 0;
8460
8461 wpa_s->consecutive_conn_failures = 0;
8462
8463 wpa_drv_radio_disable(wpa_s, 0);
8464 wpa_bssid_ignore_clear(wpa_s);
8465 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8466 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
8467 wpa_config_flush_blobs(wpa_s->conf);
8468 wpa_s->conf->auto_interworking = 0;
8469 wpa_s->conf->okc = 0;
8470
8471 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
8472 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8473 rsn_preauth_deinit(wpa_s->wpa);
8474
8475 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8476 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8477 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
8478 eapol_sm_notify_logoff(wpa_s->eapol, false);
8479
8480 radio_remove_works(wpa_s, NULL, 1);
8481 wpa_s->ext_work_in_progress = 0;
8482
8483 wpa_s->next_ssid = NULL;
8484
8485 #ifdef CONFIG_INTERWORKING
8486 #ifdef CONFIG_HS20
8487 hs20_cancel_fetch_osu(wpa_s);
8488 hs20_del_icon(wpa_s, NULL, NULL);
8489 #endif /* CONFIG_HS20 */
8490 #endif /* CONFIG_INTERWORKING */
8491
8492 wpa_s->ext_mgmt_frame_handling = 0;
8493 wpa_s->ext_eapol_frame_io = 0;
8494 #ifdef CONFIG_TESTING_OPTIONS
8495 wpa_s->extra_roc_dur = 0;
8496 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
8497 wpa_s->p2p_go_csa_on_inv = 0;
8498 wpa_s->ignore_auth_resp = 0;
8499 wpa_s->ignore_assoc_disallow = 0;
8500 wpa_s->disable_sa_query = 0;
8501 wpa_s->testing_resend_assoc = 0;
8502 wpa_s->ignore_sae_h2e_only = 0;
8503 wpa_s->ft_rsnxe_used = 0;
8504 wpa_s->reject_btm_req_reason = 0;
8505 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
8506 os_free(wpa_s->get_pref_freq_list_override);
8507 wpa_s->get_pref_freq_list_override = NULL;
8508 wpabuf_free(wpa_s->sae_commit_override);
8509 wpa_s->sae_commit_override = NULL;
8510 os_free(wpa_s->extra_sae_rejected_groups);
8511 wpa_s->extra_sae_rejected_groups = NULL;
8512 wpabuf_free(wpa_s->rsne_override_eapol);
8513 wpa_s->rsne_override_eapol = NULL;
8514 wpabuf_free(wpa_s->rsnxe_override_assoc);
8515 wpa_s->rsnxe_override_assoc = NULL;
8516 wpabuf_free(wpa_s->rsnxe_override_eapol);
8517 wpa_s->rsnxe_override_eapol = NULL;
8518 wpas_clear_driver_signal_override(wpa_s);
8519 wpa_s->oci_freq_override_eapol = 0;
8520 wpa_s->oci_freq_override_saquery_req = 0;
8521 wpa_s->oci_freq_override_saquery_resp = 0;
8522 wpa_s->oci_freq_override_eapol_g2 = 0;
8523 wpa_s->oci_freq_override_ft_assoc = 0;
8524 wpa_s->oci_freq_override_fils_assoc = 0;
8525 wpa_s->oci_freq_override_wnm_sleep = 0;
8526 #ifdef CONFIG_DPP
8527 os_free(wpa_s->dpp_config_obj_override);
8528 wpa_s->dpp_config_obj_override = NULL;
8529 os_free(wpa_s->dpp_discovery_override);
8530 wpa_s->dpp_discovery_override = NULL;
8531 os_free(wpa_s->dpp_groups_override);
8532 wpa_s->dpp_groups_override = NULL;
8533 dpp_test = DPP_TEST_DISABLED;
8534 #endif /* CONFIG_DPP */
8535 #endif /* CONFIG_TESTING_OPTIONS */
8536
8537 wpa_s->disconnected = 0;
8538 os_free(wpa_s->next_scan_freqs);
8539 wpa_s->next_scan_freqs = NULL;
8540 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
8541 wpa_s->next_scan_bssid_wildcard_ssid = 0;
8542 os_free(wpa_s->select_network_scan_freqs);
8543 wpa_s->select_network_scan_freqs = NULL;
8544 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
8545
8546 wpa_bss_flush(wpa_s);
8547 if (!dl_list_empty(&wpa_s->bss)) {
8548 wpa_printf(MSG_DEBUG,
8549 "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8550 MACSTR " pending_bssid=" MACSTR,
8551 dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8552 MAC2STR(wpa_s->bssid),
8553 MAC2STR(wpa_s->pending_bssid));
8554 }
8555
8556 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
8557 wpa_s->wnmsleep_used = 0;
8558
8559 #ifdef CONFIG_SME
8560 wpa_s->sme.last_unprot_disconnect.sec = 0;
8561 wpa_s->sme.auth_alg = 0;
8562 #endif /* CONFIG_SME */
8563
8564 wpabuf_free(wpa_s->ric_ies);
8565 wpa_s->ric_ies = NULL;
8566
8567 wpa_supplicant_update_channel_list(wpa_s, NULL);
8568
8569 free_bss_tmp_disallowed(wpa_s);
8570
8571 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
8572
8573 #ifdef CONFIG_PASN
8574 wpas_pasn_auth_stop(wpa_s);
8575 #endif /* CONFIG_PASN */
8576
8577 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
8578 wpas_restore_permanent_mac_addr(wpa_s);
8579 }
8580
8581
wpas_ctrl_radio_work_show(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)8582 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
8583 char *buf, size_t buflen)
8584 {
8585 struct wpa_radio_work *work;
8586 char *pos, *end;
8587 struct os_reltime now, diff;
8588
8589 pos = buf;
8590 end = buf + buflen;
8591
8592 os_get_reltime(&now);
8593
8594 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8595 {
8596 int ret;
8597
8598 os_reltime_sub(&now, &work->time, &diff);
8599 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
8600 work->type, work->wpa_s->ifname, work->freq,
8601 work->started, diff.sec, diff.usec);
8602 if (os_snprintf_error(end - pos, ret))
8603 break;
8604 pos += ret;
8605 }
8606
8607 return pos - buf;
8608 }
8609
8610
wpas_ctrl_radio_work_timeout(void * eloop_ctx,void * timeout_ctx)8611 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
8612 {
8613 struct wpa_radio_work *work = eloop_ctx;
8614 struct wpa_external_work *ework = work->ctx;
8615
8616 wpa_dbg(work->wpa_s, MSG_DEBUG,
8617 "Timing out external radio work %u (%s)",
8618 ework->id, work->type);
8619 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
8620 work->wpa_s->ext_work_in_progress = 0;
8621 radio_work_done(work);
8622 os_free(ework);
8623 }
8624
8625
wpas_ctrl_radio_work_cb(struct wpa_radio_work * work,int deinit)8626 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
8627 {
8628 struct wpa_external_work *ework = work->ctx;
8629
8630 if (deinit) {
8631 if (work->started)
8632 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8633 work, NULL);
8634
8635 /*
8636 * work->type points to a buffer in ework, so need to replace
8637 * that here with a fixed string to avoid use of freed memory
8638 * in debug prints.
8639 */
8640 work->type = "freed-ext-work";
8641 work->ctx = NULL;
8642 os_free(ework);
8643 return;
8644 }
8645
8646 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
8647 ework->id, ework->type);
8648 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
8649 work->wpa_s->ext_work_in_progress = 1;
8650 if (!ework->timeout)
8651 ework->timeout = 10;
8652 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
8653 work, NULL);
8654 }
8655
8656
wpas_ctrl_radio_work_add(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8657 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
8658 char *buf, size_t buflen)
8659 {
8660 struct wpa_external_work *ework;
8661 char *pos, *pos2;
8662 size_t type_len;
8663 int ret;
8664 unsigned int freq = 0;
8665
8666 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
8667
8668 ework = os_zalloc(sizeof(*ework));
8669 if (ework == NULL)
8670 return -1;
8671
8672 pos = os_strchr(cmd, ' ');
8673 if (pos) {
8674 type_len = pos - cmd;
8675 pos++;
8676
8677 pos2 = os_strstr(pos, "freq=");
8678 if (pos2)
8679 freq = atoi(pos2 + 5);
8680
8681 pos2 = os_strstr(pos, "timeout=");
8682 if (pos2)
8683 ework->timeout = atoi(pos2 + 8);
8684 } else {
8685 type_len = os_strlen(cmd);
8686 }
8687 if (4 + type_len >= sizeof(ework->type))
8688 type_len = sizeof(ework->type) - 4 - 1;
8689 os_strlcpy(ework->type, "ext:", sizeof(ework->type));
8690 os_memcpy(ework->type + 4, cmd, type_len);
8691 ework->type[4 + type_len] = '\0';
8692
8693 wpa_s->ext_work_id++;
8694 if (wpa_s->ext_work_id == 0)
8695 wpa_s->ext_work_id++;
8696 ework->id = wpa_s->ext_work_id;
8697
8698 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
8699 ework) < 0) {
8700 os_free(ework);
8701 return -1;
8702 }
8703
8704 ret = os_snprintf(buf, buflen, "%u", ework->id);
8705 if (os_snprintf_error(buflen, ret))
8706 return -1;
8707 return ret;
8708 }
8709
8710
wpas_ctrl_radio_work_done(struct wpa_supplicant * wpa_s,char * cmd)8711 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
8712 {
8713 struct wpa_radio_work *work;
8714 unsigned int id = atoi(cmd);
8715
8716 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8717 {
8718 struct wpa_external_work *ework;
8719
8720 if (os_strncmp(work->type, "ext:", 4) != 0)
8721 continue;
8722 ework = work->ctx;
8723 if (id && ework->id != id)
8724 continue;
8725 wpa_dbg(wpa_s, MSG_DEBUG,
8726 "Completed external radio work %u (%s)",
8727 ework->id, ework->type);
8728 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
8729 wpa_s->ext_work_in_progress = 0;
8730 radio_work_done(work);
8731 os_free(ework);
8732 return 3; /* "OK\n" */
8733 }
8734
8735 return -1;
8736 }
8737
8738
wpas_ctrl_radio_work(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)8739 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
8740 char *buf, size_t buflen)
8741 {
8742 if (os_strcmp(cmd, "show") == 0)
8743 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
8744 if (os_strncmp(cmd, "add ", 4) == 0)
8745 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
8746 if (os_strncmp(cmd, "done ", 5) == 0)
8747 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
8748 return -1;
8749 }
8750
8751
wpas_ctrl_radio_work_flush(struct wpa_supplicant * wpa_s)8752 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
8753 {
8754 struct wpa_radio_work *work, *tmp;
8755
8756 if (!wpa_s || !wpa_s->radio)
8757 return;
8758
8759 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
8760 struct wpa_radio_work, list) {
8761 struct wpa_external_work *ework;
8762
8763 if (os_strncmp(work->type, "ext:", 4) != 0)
8764 continue;
8765 ework = work->ctx;
8766 wpa_dbg(wpa_s, MSG_DEBUG,
8767 "Flushing%s external radio work %u (%s)",
8768 work->started ? " started" : "", ework->id,
8769 ework->type);
8770 if (work->started)
8771 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8772 work, NULL);
8773 radio_work_done(work);
8774 os_free(ework);
8775 }
8776 }
8777
8778
wpas_ctrl_eapol_response(void * eloop_ctx,void * timeout_ctx)8779 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
8780 {
8781 struct wpa_supplicant *wpa_s = eloop_ctx;
8782 eapol_sm_notify_ctrl_response(wpa_s->eapol);
8783 }
8784
8785
scan_id_list_parse(struct wpa_supplicant * wpa_s,const char * value,unsigned int * scan_id_count,int scan_id[])8786 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
8787 unsigned int *scan_id_count, int scan_id[])
8788 {
8789 const char *pos = value;
8790
8791 while (pos) {
8792 if (*pos == ' ' || *pos == '\0')
8793 break;
8794 if (*scan_id_count == MAX_SCAN_ID)
8795 return -1;
8796 scan_id[(*scan_id_count)++] = atoi(pos);
8797 pos = os_strchr(pos, ',');
8798 if (pos)
8799 pos++;
8800 }
8801
8802 return 0;
8803 }
8804
8805
wpas_ctrl_scan(struct wpa_supplicant * wpa_s,char * params,char * reply,int reply_size,int * reply_len)8806 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
8807 char *reply, int reply_size, int *reply_len)
8808 {
8809 char *pos;
8810 unsigned int manual_scan_passive = 0;
8811 unsigned int manual_scan_use_id = 0;
8812 unsigned int manual_scan_only_new = 0;
8813 unsigned int scan_only = 0;
8814 unsigned int scan_id_count = 0;
8815 int scan_id[MAX_SCAN_ID];
8816 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
8817 struct wpa_scan_results *scan_res);
8818 int *manual_scan_freqs = NULL;
8819 struct wpa_ssid_value *ssid = NULL, *ns;
8820 unsigned int ssid_count = 0;
8821
8822 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
8823 *reply_len = -1;
8824 return;
8825 }
8826
8827 if (radio_work_pending(wpa_s, "scan")) {
8828 wpa_printf(MSG_DEBUG,
8829 "Pending scan scheduled - reject new request");
8830 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8831 return;
8832 }
8833
8834 #ifdef CONFIG_INTERWORKING
8835 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
8836 wpa_printf(MSG_DEBUG,
8837 "Interworking select in progress - reject new scan");
8838 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8839 return;
8840 }
8841 #endif /* CONFIG_INTERWORKING */
8842
8843 if (params) {
8844 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
8845 scan_only = 1;
8846
8847 pos = os_strstr(params, "freq=");
8848 if (pos) {
8849 manual_scan_freqs = freq_range_to_channel_list(wpa_s,
8850 pos + 5);
8851 if (manual_scan_freqs == NULL) {
8852 *reply_len = -1;
8853 goto done;
8854 }
8855 }
8856
8857 pos = os_strstr(params, "passive=");
8858 if (pos)
8859 manual_scan_passive = !!atoi(pos + 8);
8860
8861 pos = os_strstr(params, "use_id=");
8862 if (pos)
8863 manual_scan_use_id = atoi(pos + 7);
8864
8865 pos = os_strstr(params, "only_new=1");
8866 if (pos)
8867 manual_scan_only_new = 1;
8868
8869 pos = os_strstr(params, "scan_id=");
8870 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
8871 scan_id) < 0) {
8872 *reply_len = -1;
8873 goto done;
8874 }
8875
8876 pos = os_strstr(params, "bssid=");
8877 if (pos) {
8878 u8 bssid[ETH_ALEN];
8879
8880 pos += 6;
8881 if (hwaddr_aton(pos, bssid)) {
8882 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
8883 *reply_len = -1;
8884 goto done;
8885 }
8886 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
8887
8888 wpa_s->next_scan_bssid_wildcard_ssid =
8889 os_strstr(params, "wildcard_ssid=1") != NULL;
8890 }
8891
8892 pos = params;
8893 while (pos && *pos != '\0') {
8894 if (os_strncmp(pos, "ssid ", 5) == 0) {
8895 char *end;
8896
8897 pos += 5;
8898 end = pos;
8899 while (*end) {
8900 if (*end == '\0' || *end == ' ')
8901 break;
8902 end++;
8903 }
8904
8905 ns = os_realloc_array(
8906 ssid, ssid_count + 1,
8907 sizeof(struct wpa_ssid_value));
8908 if (ns == NULL) {
8909 *reply_len = -1;
8910 goto done;
8911 }
8912 ssid = ns;
8913
8914 if ((end - pos) & 0x01 ||
8915 end - pos > 2 * SSID_MAX_LEN ||
8916 hexstr2bin(pos, ssid[ssid_count].ssid,
8917 (end - pos) / 2) < 0) {
8918 wpa_printf(MSG_DEBUG,
8919 "Invalid SSID value '%s'",
8920 pos);
8921 *reply_len = -1;
8922 goto done;
8923 }
8924 ssid[ssid_count].ssid_len = (end - pos) / 2;
8925 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
8926 ssid[ssid_count].ssid,
8927 ssid[ssid_count].ssid_len);
8928 ssid_count++;
8929 pos = end;
8930 }
8931
8932 pos = os_strchr(pos, ' ');
8933 if (pos)
8934 pos++;
8935 }
8936 }
8937
8938 wpa_s->num_ssids_from_scan_req = ssid_count;
8939 os_free(wpa_s->ssids_from_scan_req);
8940 if (ssid_count) {
8941 wpa_s->ssids_from_scan_req = ssid;
8942 ssid = NULL;
8943 } else {
8944 wpa_s->ssids_from_scan_req = NULL;
8945 }
8946
8947 if (scan_only)
8948 scan_res_handler = scan_only_handler;
8949 else if (wpa_s->scan_res_handler == scan_only_handler)
8950 scan_res_handler = NULL;
8951 else
8952 scan_res_handler = wpa_s->scan_res_handler;
8953
8954 if (!wpa_s->sched_scanning && !wpa_s->scanning &&
8955 ((wpa_s->wpa_state <= WPA_SCANNING) ||
8956 (wpa_s->wpa_state == WPA_COMPLETED))) {
8957 wpa_s->manual_scan_passive = manual_scan_passive;
8958 wpa_s->manual_scan_use_id = manual_scan_use_id;
8959 wpa_s->manual_scan_only_new = manual_scan_only_new;
8960 wpa_s->scan_id_count = scan_id_count;
8961 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
8962 wpa_s->scan_res_handler = scan_res_handler;
8963 os_free(wpa_s->manual_scan_freqs);
8964 wpa_s->manual_scan_freqs = manual_scan_freqs;
8965 manual_scan_freqs = NULL;
8966
8967 wpa_s->normal_scans = 0;
8968 wpa_s->scan_req = MANUAL_SCAN_REQ;
8969 wpa_s->after_wps = 0;
8970 wpa_s->known_wps_freq = 0;
8971 wpa_supplicant_req_scan(wpa_s, 0, 0);
8972 if (wpa_s->manual_scan_use_id) {
8973 wpa_s->manual_scan_id++;
8974 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
8975 wpa_s->manual_scan_id);
8976 *reply_len = os_snprintf(reply, reply_size, "%u\n",
8977 wpa_s->manual_scan_id);
8978 }
8979 } else if (wpa_s->sched_scanning) {
8980 wpa_s->manual_scan_passive = manual_scan_passive;
8981 wpa_s->manual_scan_use_id = manual_scan_use_id;
8982 wpa_s->manual_scan_only_new = manual_scan_only_new;
8983 wpa_s->scan_id_count = scan_id_count;
8984 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
8985 wpa_s->scan_res_handler = scan_res_handler;
8986 os_free(wpa_s->manual_scan_freqs);
8987 wpa_s->manual_scan_freqs = manual_scan_freqs;
8988 manual_scan_freqs = NULL;
8989
8990 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
8991 wpa_supplicant_cancel_sched_scan(wpa_s);
8992 wpa_s->scan_req = MANUAL_SCAN_REQ;
8993 wpa_supplicant_req_scan(wpa_s, 0, 0);
8994 if (wpa_s->manual_scan_use_id) {
8995 wpa_s->manual_scan_id++;
8996 *reply_len = os_snprintf(reply, reply_size, "%u\n",
8997 wpa_s->manual_scan_id);
8998 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
8999 wpa_s->manual_scan_id);
9000 }
9001 } else {
9002 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9003 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9004 }
9005
9006 done:
9007 os_free(manual_scan_freqs);
9008 os_free(ssid);
9009 }
9010
9011
9012 #ifdef CONFIG_TESTING_OPTIONS
9013
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)9014 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9015 unsigned int freq, const u8 *dst,
9016 const u8 *src, const u8 *bssid,
9017 const u8 *data, size_t data_len,
9018 enum offchannel_send_action_result
9019 result)
9020 {
9021 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9022 " src=" MACSTR " bssid=" MACSTR " result=%s",
9023 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9024 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9025 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9026 "NO_ACK" : "FAILED"));
9027 }
9028
9029
wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant * wpa_s,char * cmd)9030 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9031 {
9032 char *pos, *param;
9033 size_t len;
9034 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9035 int res, used;
9036 int freq = 0, no_cck = 0, wait_time = 0;
9037
9038 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9039 * <action=Action frame payload> */
9040
9041 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9042
9043 pos = cmd;
9044 used = hwaddr_aton2(pos, da);
9045 if (used < 0)
9046 return -1;
9047 pos += used;
9048 while (*pos == ' ')
9049 pos++;
9050 used = hwaddr_aton2(pos, bssid);
9051 if (used < 0)
9052 return -1;
9053 pos += used;
9054
9055 param = os_strstr(pos, " freq=");
9056 if (param) {
9057 param += 6;
9058 freq = atoi(param);
9059 }
9060
9061 param = os_strstr(pos, " no_cck=");
9062 if (param) {
9063 param += 8;
9064 no_cck = atoi(param);
9065 }
9066
9067 param = os_strstr(pos, " wait_time=");
9068 if (param) {
9069 param += 11;
9070 wait_time = atoi(param);
9071 }
9072
9073 param = os_strstr(pos, " action=");
9074 if (param == NULL)
9075 return -1;
9076 param += 8;
9077
9078 len = os_strlen(param);
9079 if (len & 1)
9080 return -1;
9081 len /= 2;
9082
9083 buf = os_malloc(len);
9084 if (buf == NULL)
9085 return -1;
9086
9087 if (hexstr2bin(param, buf, len) < 0) {
9088 os_free(buf);
9089 return -1;
9090 }
9091
9092 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9093 buf, len, wait_time,
9094 wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9095 os_free(buf);
9096 return res;
9097 }
9098
9099
wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant * wpa_s)9100 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9101 {
9102 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9103 offchannel_send_action_done(wpa_s);
9104 }
9105
9106
wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant * wpa_s,char * cmd)9107 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9108 char *cmd)
9109 {
9110 char *pos, *param;
9111 size_t len;
9112 u8 *buf;
9113 int freq = 0, datarate = 0, ssi_signal = 0;
9114 union wpa_event_data event;
9115
9116 if (!wpa_s->ext_mgmt_frame_handling)
9117 return -1;
9118
9119 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9120
9121 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9122
9123 pos = cmd;
9124 param = os_strstr(pos, "freq=");
9125 if (param) {
9126 param += 5;
9127 freq = atoi(param);
9128 }
9129
9130 param = os_strstr(pos, " datarate=");
9131 if (param) {
9132 param += 10;
9133 datarate = atoi(param);
9134 }
9135
9136 param = os_strstr(pos, " ssi_signal=");
9137 if (param) {
9138 param += 12;
9139 ssi_signal = atoi(param);
9140 }
9141
9142 param = os_strstr(pos, " frame=");
9143 if (param == NULL)
9144 return -1;
9145 param += 7;
9146
9147 len = os_strlen(param);
9148 if (len & 1)
9149 return -1;
9150 len /= 2;
9151
9152 buf = os_malloc(len);
9153 if (buf == NULL)
9154 return -1;
9155
9156 if (hexstr2bin(param, buf, len) < 0) {
9157 os_free(buf);
9158 return -1;
9159 }
9160
9161 os_memset(&event, 0, sizeof(event));
9162 event.rx_mgmt.freq = freq;
9163 event.rx_mgmt.frame = buf;
9164 event.rx_mgmt.frame_len = len;
9165 event.rx_mgmt.ssi_signal = ssi_signal;
9166 event.rx_mgmt.datarate = datarate;
9167 wpa_s->ext_mgmt_frame_handling = 0;
9168 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9169 wpa_s->ext_mgmt_frame_handling = 1;
9170
9171 os_free(buf);
9172
9173 return 0;
9174 }
9175
9176
wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant * wpa_s,char * param)9177 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9178 char *param)
9179 {
9180 struct wpa_scan_res *res;
9181 struct os_reltime now;
9182 char *pos, *end;
9183 int ret = -1;
9184
9185 if (!param)
9186 return -1;
9187
9188 if (os_strcmp(param, "START") == 0) {
9189 wpa_bss_update_start(wpa_s);
9190 return 0;
9191 }
9192
9193 if (os_strcmp(param, "END") == 0) {
9194 wpa_bss_update_end(wpa_s, NULL, 1);
9195 return 0;
9196 }
9197
9198 if (os_strncmp(param, "BSS ", 4) != 0)
9199 return -1;
9200 param += 3;
9201
9202 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9203 if (!res)
9204 return -1;
9205
9206 pos = os_strstr(param, " flags=");
9207 if (pos)
9208 res->flags = strtol(pos + 7, NULL, 16);
9209
9210 pos = os_strstr(param, " bssid=");
9211 if (pos && hwaddr_aton(pos + 7, res->bssid))
9212 goto fail;
9213
9214 pos = os_strstr(param, " freq=");
9215 if (pos)
9216 res->freq = atoi(pos + 6);
9217
9218 pos = os_strstr(param, " beacon_int=");
9219 if (pos)
9220 res->beacon_int = atoi(pos + 12);
9221
9222 pos = os_strstr(param, " caps=");
9223 if (pos)
9224 res->caps = strtol(pos + 6, NULL, 16);
9225
9226 pos = os_strstr(param, " qual=");
9227 if (pos)
9228 res->qual = atoi(pos + 6);
9229
9230 pos = os_strstr(param, " noise=");
9231 if (pos)
9232 res->noise = atoi(pos + 7);
9233
9234 pos = os_strstr(param, " level=");
9235 if (pos)
9236 res->level = atoi(pos + 7);
9237
9238 pos = os_strstr(param, " tsf=");
9239 if (pos)
9240 res->tsf = strtoll(pos + 5, NULL, 16);
9241
9242 pos = os_strstr(param, " age=");
9243 if (pos)
9244 res->age = atoi(pos + 5);
9245
9246 pos = os_strstr(param, " est_throughput=");
9247 if (pos)
9248 res->est_throughput = atoi(pos + 16);
9249
9250 pos = os_strstr(param, " snr=");
9251 if (pos)
9252 res->snr = atoi(pos + 5);
9253
9254 pos = os_strstr(param, " parent_tsf=");
9255 if (pos)
9256 res->parent_tsf = strtoll(pos + 7, NULL, 16);
9257
9258 pos = os_strstr(param, " tsf_bssid=");
9259 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9260 goto fail;
9261
9262 pos = os_strstr(param, " ie=");
9263 if (pos) {
9264 pos += 4;
9265 end = os_strchr(pos, ' ');
9266 if (!end)
9267 end = pos + os_strlen(pos);
9268 res->ie_len = (end - pos) / 2;
9269 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9270 goto fail;
9271 }
9272
9273 pos = os_strstr(param, " beacon_ie=");
9274 if (pos) {
9275 pos += 11;
9276 end = os_strchr(pos, ' ');
9277 if (!end)
9278 end = pos + os_strlen(pos);
9279 res->beacon_ie_len = (end - pos) / 2;
9280 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9281 res->beacon_ie_len))
9282 goto fail;
9283 }
9284
9285 os_get_reltime(&now);
9286 wpa_bss_update_scan_res(wpa_s, res, &now);
9287 ret = 0;
9288 fail:
9289 os_free(res);
9290
9291 return ret;
9292 }
9293
9294
wpas_ctrl_iface_driver_event(struct wpa_supplicant * wpa_s,char * cmd)9295 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9296 {
9297 char *pos, *param;
9298 union wpa_event_data event;
9299 enum wpa_event_type ev;
9300
9301 /* <event name> [parameters..] */
9302
9303 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9304
9305 pos = cmd;
9306 param = os_strchr(pos, ' ');
9307 if (param)
9308 *param++ = '\0';
9309
9310 os_memset(&event, 0, sizeof(event));
9311
9312 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9313 ev = EVENT_INTERFACE_ENABLED;
9314 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9315 ev = EVENT_INTERFACE_DISABLED;
9316 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9317 ev = EVENT_AVOID_FREQUENCIES;
9318 if (param == NULL)
9319 param = "";
9320 if (freq_range_list_parse(&event.freq_range, param) < 0)
9321 return -1;
9322 wpa_supplicant_event(wpa_s, ev, &event);
9323 os_free(event.freq_range.range);
9324 return 0;
9325 } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
9326 return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
9327 } else {
9328 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
9329 cmd);
9330 return -1;
9331 }
9332
9333 wpa_supplicant_event(wpa_s, ev, &event);
9334
9335 return 0;
9336 }
9337
9338
wpas_ctrl_iface_eapol_rx(struct wpa_supplicant * wpa_s,char * cmd)9339 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
9340 {
9341 char *pos;
9342 u8 src[ETH_ALEN], *buf;
9343 int used;
9344 size_t len;
9345
9346 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
9347
9348 pos = cmd;
9349 used = hwaddr_aton2(pos, src);
9350 if (used < 0)
9351 return -1;
9352 pos += used;
9353 while (*pos == ' ')
9354 pos++;
9355
9356 len = os_strlen(pos);
9357 if (len & 1)
9358 return -1;
9359 len /= 2;
9360
9361 buf = os_malloc(len);
9362 if (buf == NULL)
9363 return -1;
9364
9365 if (hexstr2bin(pos, buf, len) < 0) {
9366 os_free(buf);
9367 return -1;
9368 }
9369
9370 wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
9371 os_free(buf);
9372
9373 return 0;
9374 }
9375
9376
ipv4_hdr_checksum(const void * buf,size_t len)9377 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
9378 {
9379 size_t i;
9380 u32 sum = 0;
9381 const u16 *pos = buf;
9382
9383 for (i = 0; i < len / 2; i++)
9384 sum += *pos++;
9385
9386 while (sum >> 16)
9387 sum = (sum & 0xffff) + (sum >> 16);
9388
9389 return sum ^ 0xffff;
9390 }
9391
9392
9393 #define HWSIM_PACKETLEN 1500
9394 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
9395
wpas_data_test_rx(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)9396 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
9397 size_t len)
9398 {
9399 struct wpa_supplicant *wpa_s = ctx;
9400 const struct ether_header *eth;
9401 struct ip ip;
9402 const u8 *pos;
9403 unsigned int i;
9404 char extra[30];
9405
9406 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
9407 wpa_printf(MSG_DEBUG,
9408 "test data: RX - ignore unexpected length %d",
9409 (int) len);
9410 return;
9411 }
9412
9413 eth = (const struct ether_header *) buf;
9414 os_memcpy(&ip, eth + 1, sizeof(ip));
9415 pos = &buf[sizeof(*eth) + sizeof(ip)];
9416
9417 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
9418 wpa_printf(MSG_DEBUG,
9419 "test data: RX - ignore unexpected IP header");
9420 return;
9421 }
9422
9423 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
9424 if (*pos != (u8) i) {
9425 wpa_printf(MSG_DEBUG,
9426 "test data: RX - ignore mismatching payload");
9427 return;
9428 }
9429 pos++;
9430 }
9431 extra[0] = '\0';
9432 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
9433 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
9434 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
9435 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
9436 }
9437
9438
wpas_ctrl_iface_data_test_config(struct wpa_supplicant * wpa_s,char * cmd)9439 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
9440 char *cmd)
9441 {
9442 int enabled = atoi(cmd);
9443 char *pos;
9444 const char *ifname;
9445
9446 if (!enabled) {
9447 if (wpa_s->l2_test) {
9448 l2_packet_deinit(wpa_s->l2_test);
9449 wpa_s->l2_test = NULL;
9450 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
9451 }
9452 return 0;
9453 }
9454
9455 if (wpa_s->l2_test)
9456 return 0;
9457
9458 pos = os_strstr(cmd, " ifname=");
9459 if (pos)
9460 ifname = pos + 8;
9461 else
9462 ifname = wpa_s->ifname;
9463
9464 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
9465 ETHERTYPE_IP, wpas_data_test_rx,
9466 wpa_s, 1);
9467 if (wpa_s->l2_test == NULL)
9468 return -1;
9469
9470 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
9471
9472 return 0;
9473 }
9474
9475
wpas_ctrl_iface_data_test_tx(struct wpa_supplicant * wpa_s,char * cmd)9476 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
9477 {
9478 u8 dst[ETH_ALEN], src[ETH_ALEN];
9479 char *pos, *pos2;
9480 int used;
9481 long int val;
9482 u8 tos;
9483 u8 buf[2 + HWSIM_PACKETLEN];
9484 struct ether_header *eth;
9485 struct ip *ip;
9486 u8 *dpos;
9487 unsigned int i;
9488 size_t send_len = HWSIM_IP_LEN;
9489
9490 if (wpa_s->l2_test == NULL)
9491 return -1;
9492
9493 /* format: <dst> <src> <tos> [len=<length>] */
9494
9495 pos = cmd;
9496 used = hwaddr_aton2(pos, dst);
9497 if (used < 0)
9498 return -1;
9499 pos += used;
9500 while (*pos == ' ')
9501 pos++;
9502 used = hwaddr_aton2(pos, src);
9503 if (used < 0)
9504 return -1;
9505 pos += used;
9506
9507 val = strtol(pos, &pos2, 0);
9508 if (val < 0 || val > 0xff)
9509 return -1;
9510 tos = val;
9511
9512 pos = os_strstr(pos2, " len=");
9513 if (pos) {
9514 i = atoi(pos + 5);
9515 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
9516 return -1;
9517 send_len = i;
9518 }
9519
9520 eth = (struct ether_header *) &buf[2];
9521 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
9522 os_memcpy(eth->ether_shost, src, ETH_ALEN);
9523 eth->ether_type = htons(ETHERTYPE_IP);
9524 ip = (struct ip *) (eth + 1);
9525 os_memset(ip, 0, sizeof(*ip));
9526 ip->ip_hl = 5;
9527 ip->ip_v = 4;
9528 ip->ip_ttl = 64;
9529 ip->ip_tos = tos;
9530 ip->ip_len = htons(send_len);
9531 ip->ip_p = 1;
9532 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
9533 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
9534 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
9535 dpos = (u8 *) (ip + 1);
9536 for (i = 0; i < send_len - sizeof(*ip); i++)
9537 *dpos++ = i;
9538
9539 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
9540 sizeof(struct ether_header) + send_len) < 0)
9541 return -1;
9542
9543 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
9544 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
9545
9546 return 0;
9547 }
9548
9549
wpas_ctrl_iface_data_test_frame(struct wpa_supplicant * wpa_s,char * cmd)9550 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
9551 char *cmd)
9552 {
9553 u8 *buf;
9554 struct ether_header *eth;
9555 struct l2_packet_data *l2 = NULL;
9556 size_t len;
9557 u16 ethertype;
9558 int res = -1;
9559
9560 len = os_strlen(cmd);
9561 if (len & 1 || len < ETH_HLEN * 2)
9562 return -1;
9563 len /= 2;
9564
9565 buf = os_malloc(len);
9566 if (buf == NULL)
9567 return -1;
9568
9569 if (hexstr2bin(cmd, buf, len) < 0)
9570 goto done;
9571
9572 eth = (struct ether_header *) buf;
9573 ethertype = ntohs(eth->ether_type);
9574
9575 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
9576 wpas_data_test_rx, wpa_s, 1);
9577 if (l2 == NULL)
9578 goto done;
9579
9580 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
9581 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
9582 done:
9583 if (l2)
9584 l2_packet_deinit(l2);
9585 os_free(buf);
9586
9587 return res < 0 ? -1 : 0;
9588 }
9589
9590
wpas_ctrl_test_alloc_fail(struct wpa_supplicant * wpa_s,char * cmd)9591 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
9592 {
9593 #ifdef WPA_TRACE_BFD
9594 char *pos;
9595
9596 wpa_trace_fail_after = atoi(cmd);
9597 pos = os_strchr(cmd, ':');
9598 if (pos) {
9599 pos++;
9600 os_strlcpy(wpa_trace_fail_func, pos,
9601 sizeof(wpa_trace_fail_func));
9602 } else {
9603 wpa_trace_fail_after = 0;
9604 }
9605 return 0;
9606 #else /* WPA_TRACE_BFD */
9607 return -1;
9608 #endif /* WPA_TRACE_BFD */
9609 }
9610
9611
wpas_ctrl_get_alloc_fail(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)9612 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
9613 char *buf, size_t buflen)
9614 {
9615 #ifdef WPA_TRACE_BFD
9616 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
9617 wpa_trace_fail_func);
9618 #else /* WPA_TRACE_BFD */
9619 return -1;
9620 #endif /* WPA_TRACE_BFD */
9621 }
9622
9623
wpas_ctrl_test_fail(struct wpa_supplicant * wpa_s,char * cmd)9624 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
9625 {
9626 #ifdef WPA_TRACE_BFD
9627 char *pos;
9628
9629 wpa_trace_test_fail_after = atoi(cmd);
9630 pos = os_strchr(cmd, ':');
9631 if (pos) {
9632 pos++;
9633 os_strlcpy(wpa_trace_test_fail_func, pos,
9634 sizeof(wpa_trace_test_fail_func));
9635 } else {
9636 wpa_trace_test_fail_after = 0;
9637 }
9638 return 0;
9639 #else /* WPA_TRACE_BFD */
9640 return -1;
9641 #endif /* WPA_TRACE_BFD */
9642 }
9643
9644
wpas_ctrl_get_fail(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)9645 static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
9646 char *buf, size_t buflen)
9647 {
9648 #ifdef WPA_TRACE_BFD
9649 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
9650 wpa_trace_test_fail_func);
9651 #else /* WPA_TRACE_BFD */
9652 return -1;
9653 #endif /* WPA_TRACE_BFD */
9654 }
9655
9656
wpas_ctrl_event_test_cb(void * eloop_ctx,void * timeout_ctx)9657 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
9658 {
9659 struct wpa_supplicant *wpa_s = eloop_ctx;
9660 int i, count = (intptr_t) timeout_ctx;
9661
9662 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
9663 count);
9664 for (i = 0; i < count; i++) {
9665 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
9666 i + 1, count);
9667 }
9668 }
9669
9670
wpas_ctrl_event_test(struct wpa_supplicant * wpa_s,const char * cmd)9671 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
9672 {
9673 int count;
9674
9675 count = atoi(cmd);
9676 if (count <= 0)
9677 return -1;
9678
9679 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
9680 (void *) (intptr_t) count);
9681 }
9682
9683
wpas_ctrl_test_assoc_ie(struct wpa_supplicant * wpa_s,const char * cmd)9684 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
9685 const char *cmd)
9686 {
9687 struct wpabuf *buf;
9688 size_t len;
9689
9690 len = os_strlen(cmd);
9691 if (len & 1)
9692 return -1;
9693 len /= 2;
9694
9695 if (len == 0) {
9696 buf = NULL;
9697 } else {
9698 buf = wpabuf_alloc(len);
9699 if (buf == NULL)
9700 return -1;
9701
9702 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
9703 wpabuf_free(buf);
9704 return -1;
9705 }
9706 }
9707
9708 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
9709 return 0;
9710 }
9711
9712
wpas_ctrl_reset_pn(struct wpa_supplicant * wpa_s)9713 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
9714 {
9715 u8 zero[WPA_TK_MAX_LEN];
9716
9717 if (wpa_s->last_tk_alg == WPA_ALG_NONE)
9718 return -1;
9719
9720 wpa_printf(MSG_INFO, "TESTING: Reset PN");
9721 os_memset(zero, 0, sizeof(zero));
9722
9723 /* First, use a zero key to avoid any possible duplicate key avoidance
9724 * in the driver. */
9725 if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9726 wpa_s->last_tk_key_idx, 1, zero, 6,
9727 zero, wpa_s->last_tk_len,
9728 KEY_FLAG_PAIRWISE_RX_TX) < 0)
9729 return -1;
9730
9731 /* Set the previously configured key to reset its TSC/RSC */
9732 return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9733 wpa_s->last_tk_key_idx, 1, zero, 6,
9734 wpa_s->last_tk, wpa_s->last_tk_len,
9735 KEY_FLAG_PAIRWISE_RX_TX);
9736 }
9737
9738
wpas_ctrl_key_request(struct wpa_supplicant * wpa_s,const char * cmd)9739 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
9740 {
9741 const char *pos = cmd;
9742 int error, pairwise;
9743
9744 error = atoi(pos);
9745 pos = os_strchr(pos, ' ');
9746 if (!pos)
9747 return -1;
9748 pairwise = atoi(pos);
9749 wpa_sm_key_request(wpa_s->wpa, error, pairwise);
9750 return 0;
9751 }
9752
9753
wpas_ctrl_resend_assoc(struct wpa_supplicant * wpa_s)9754 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
9755 {
9756 #ifdef CONFIG_SME
9757 struct wpa_driver_associate_params params;
9758 int ret;
9759
9760 os_memset(¶ms, 0, sizeof(params));
9761 params.bssid = wpa_s->bssid;
9762 params.ssid = wpa_s->sme.ssid;
9763 params.ssid_len = wpa_s->sme.ssid_len;
9764 params.freq.freq = wpa_s->sme.freq;
9765 if (wpa_s->last_assoc_req_wpa_ie) {
9766 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
9767 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
9768 }
9769 params.pairwise_suite = wpa_s->pairwise_cipher;
9770 params.group_suite = wpa_s->group_cipher;
9771 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
9772 params.key_mgmt_suite = wpa_s->key_mgmt;
9773 params.wpa_proto = wpa_s->wpa_proto;
9774 params.mgmt_frame_protection = wpa_s->sme.mfp;
9775 params.rrm_used = wpa_s->rrm.rrm_used;
9776 if (wpa_s->sme.prev_bssid_set)
9777 params.prev_bssid = wpa_s->sme.prev_bssid;
9778 wpa_printf(MSG_INFO, "TESTING: Resend association request");
9779 ret = wpa_drv_associate(wpa_s, ¶ms);
9780 wpa_s->testing_resend_assoc = 1;
9781 return ret;
9782 #else /* CONFIG_SME */
9783 return -1;
9784 #endif /* CONFIG_SME */
9785 }
9786
9787 #endif /* CONFIG_TESTING_OPTIONS */
9788
9789
wpas_ctrl_vendor_elem_add(struct wpa_supplicant * wpa_s,char * cmd)9790 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
9791 {
9792 char *pos = cmd;
9793 int frame;
9794 size_t len;
9795 struct wpabuf *buf;
9796 struct ieee802_11_elems elems;
9797
9798 frame = atoi(pos);
9799 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9800 return -1;
9801 wpa_s = wpas_vendor_elem(wpa_s, frame);
9802
9803 pos = os_strchr(pos, ' ');
9804 if (pos == NULL)
9805 return -1;
9806 pos++;
9807
9808 len = os_strlen(pos);
9809 if (len == 0)
9810 return 0;
9811 if (len & 1)
9812 return -1;
9813 len /= 2;
9814
9815 buf = wpabuf_alloc(len);
9816 if (buf == NULL)
9817 return -1;
9818
9819 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
9820 wpabuf_free(buf);
9821 return -1;
9822 }
9823
9824 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
9825 ParseFailed) {
9826 wpabuf_free(buf);
9827 return -1;
9828 }
9829
9830 if (wpa_s->vendor_elem[frame] == NULL) {
9831 wpa_s->vendor_elem[frame] = buf;
9832 goto update_ies;
9833 }
9834
9835 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
9836 wpabuf_free(buf);
9837 return -1;
9838 }
9839
9840 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
9841 wpabuf_free(buf);
9842
9843 update_ies:
9844 wpas_vendor_elem_update(wpa_s);
9845
9846 if (frame == VENDOR_ELEM_PROBE_REQ ||
9847 frame == VENDOR_ELEM_PROBE_REQ_P2P)
9848 wpa_supplicant_set_default_scan_ies(wpa_s);
9849
9850 return 0;
9851 }
9852
9853
wpas_ctrl_vendor_elem_get(struct wpa_supplicant * wpa_s,char * cmd,char * buf,size_t buflen)9854 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
9855 char *buf, size_t buflen)
9856 {
9857 int frame = atoi(cmd);
9858
9859 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9860 return -1;
9861 wpa_s = wpas_vendor_elem(wpa_s, frame);
9862
9863 if (wpa_s->vendor_elem[frame] == NULL)
9864 return 0;
9865
9866 return wpa_snprintf_hex(buf, buflen,
9867 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
9868 wpabuf_len(wpa_s->vendor_elem[frame]));
9869 }
9870
9871
wpas_ctrl_vendor_elem_remove(struct wpa_supplicant * wpa_s,char * cmd)9872 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
9873 {
9874 char *pos = cmd;
9875 int frame;
9876 size_t len;
9877 u8 *buf;
9878 struct ieee802_11_elems elems;
9879 int res;
9880
9881 frame = atoi(pos);
9882 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
9883 return -1;
9884 wpa_s = wpas_vendor_elem(wpa_s, frame);
9885
9886 pos = os_strchr(pos, ' ');
9887 if (pos == NULL)
9888 return -1;
9889 pos++;
9890
9891 if (*pos == '*') {
9892 wpabuf_free(wpa_s->vendor_elem[frame]);
9893 wpa_s->vendor_elem[frame] = NULL;
9894 wpas_vendor_elem_update(wpa_s);
9895 return 0;
9896 }
9897
9898 if (wpa_s->vendor_elem[frame] == NULL)
9899 return -1;
9900
9901 len = os_strlen(pos);
9902 if (len == 0)
9903 return 0;
9904 if (len & 1)
9905 return -1;
9906 len /= 2;
9907
9908 buf = os_malloc(len);
9909 if (buf == NULL)
9910 return -1;
9911
9912 if (hexstr2bin(pos, buf, len) < 0) {
9913 os_free(buf);
9914 return -1;
9915 }
9916
9917 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
9918 os_free(buf);
9919 return -1;
9920 }
9921
9922 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
9923 os_free(buf);
9924 return res;
9925 }
9926
9927
wpas_ctrl_neighbor_rep_cb(void * ctx,struct wpabuf * neighbor_rep)9928 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
9929 {
9930 struct wpa_supplicant *wpa_s = ctx;
9931 size_t len;
9932 const u8 *data;
9933
9934 /*
9935 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
9936 * BSSID[6]
9937 * BSSID Information[4]
9938 * Operating Class[1]
9939 * Channel Number[1]
9940 * PHY Type[1]
9941 * Optional Subelements[variable]
9942 */
9943 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
9944
9945 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
9946 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
9947 goto out;
9948 }
9949
9950 data = wpabuf_head_u8(neighbor_rep);
9951 len = wpabuf_len(neighbor_rep);
9952
9953 while (len >= 2 + NR_IE_MIN_LEN) {
9954 const u8 *nr;
9955 char lci[256 * 2 + 1];
9956 char civic[256 * 2 + 1];
9957 u8 nr_len = data[1];
9958 const u8 *pos = data, *end;
9959
9960 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
9961 nr_len < NR_IE_MIN_LEN) {
9962 wpa_dbg(wpa_s, MSG_DEBUG,
9963 "CTRL: Invalid Neighbor Report element: id=%u len=%u",
9964 data[0], nr_len);
9965 goto out;
9966 }
9967
9968 if (2U + nr_len > len) {
9969 wpa_dbg(wpa_s, MSG_DEBUG,
9970 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
9971 data[0], len, nr_len);
9972 goto out;
9973 }
9974 pos += 2;
9975 end = pos + nr_len;
9976
9977 nr = pos;
9978 pos += NR_IE_MIN_LEN;
9979
9980 lci[0] = '\0';
9981 civic[0] = '\0';
9982 while (end - pos > 2) {
9983 u8 s_id, s_len;
9984
9985 s_id = *pos++;
9986 s_len = *pos++;
9987 if (s_len > end - pos)
9988 goto out;
9989 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
9990 /* Measurement Token[1] */
9991 /* Measurement Report Mode[1] */
9992 /* Measurement Type[1] */
9993 /* Measurement Report[variable] */
9994 switch (pos[2]) {
9995 case MEASURE_TYPE_LCI:
9996 if (lci[0])
9997 break;
9998 wpa_snprintf_hex(lci, sizeof(lci),
9999 pos, s_len);
10000 break;
10001 case MEASURE_TYPE_LOCATION_CIVIC:
10002 if (civic[0])
10003 break;
10004 wpa_snprintf_hex(civic, sizeof(civic),
10005 pos, s_len);
10006 break;
10007 }
10008 }
10009
10010 pos += s_len;
10011 }
10012
10013 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10014 "bssid=" MACSTR
10015 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10016 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10017 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10018 nr[ETH_ALEN + 6],
10019 lci[0] ? " lci=" : "", lci,
10020 civic[0] ? " civic=" : "", civic);
10021
10022 data = end;
10023 len -= 2 + nr_len;
10024 }
10025
10026 out:
10027 wpabuf_free(neighbor_rep);
10028 }
10029
10030
wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant * wpa_s,char * cmd)10031 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10032 char *cmd)
10033 {
10034 struct wpa_ssid_value ssid, *ssid_p = NULL;
10035 int ret, lci = 0, civic = 0;
10036 char *ssid_s;
10037
10038 ssid_s = os_strstr(cmd, "ssid=");
10039 if (ssid_s) {
10040 if (ssid_parse(ssid_s + 5, &ssid)) {
10041 wpa_msg(wpa_s, MSG_INFO,
10042 "CTRL: Send Neighbor Report: bad SSID");
10043 return -1;
10044 }
10045
10046 ssid_p = &ssid;
10047
10048 /*
10049 * Move cmd after the SSID text that may include "lci" or
10050 * "civic".
10051 */
10052 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10053 if (cmd)
10054 cmd++;
10055
10056 }
10057
10058 if (cmd && os_strstr(cmd, "lci"))
10059 lci = 1;
10060
10061 if (cmd && os_strstr(cmd, "civic"))
10062 civic = 1;
10063
10064 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
10065 wpas_ctrl_neighbor_rep_cb,
10066 wpa_s);
10067
10068 return ret;
10069 }
10070
10071
wpas_ctrl_iface_erp_flush(struct wpa_supplicant * wpa_s)10072 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10073 {
10074 eapol_sm_erp_flush(wpa_s->eapol);
10075 return 0;
10076 }
10077
10078
wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant * wpa_s,char * cmd)10079 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10080 char *cmd)
10081 {
10082 char *token, *context = NULL;
10083 unsigned int enable = ~0, type = 0;
10084 u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10085 u8 *addr = NULL, *mask = NULL;
10086
10087 while ((token = str_token(cmd, " ", &context))) {
10088 if (os_strcasecmp(token, "scan") == 0) {
10089 type |= MAC_ADDR_RAND_SCAN;
10090 } else if (os_strcasecmp(token, "sched") == 0) {
10091 type |= MAC_ADDR_RAND_SCHED_SCAN;
10092 } else if (os_strcasecmp(token, "pno") == 0) {
10093 type |= MAC_ADDR_RAND_PNO;
10094 } else if (os_strcasecmp(token, "all") == 0) {
10095 type = wpa_s->mac_addr_rand_supported;
10096 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
10097 enable = atoi(token + 7);
10098 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
10099 addr = _addr;
10100 if (hwaddr_aton(token + 5, addr)) {
10101 wpa_printf(MSG_INFO,
10102 "CTRL: Invalid MAC address: %s",
10103 token);
10104 return -1;
10105 }
10106 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
10107 mask = _mask;
10108 if (hwaddr_aton(token + 5, mask)) {
10109 wpa_printf(MSG_INFO,
10110 "CTRL: Invalid MAC address mask: %s",
10111 token);
10112 return -1;
10113 }
10114 } else {
10115 wpa_printf(MSG_INFO,
10116 "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10117 token);
10118 return -1;
10119 }
10120 }
10121
10122 if (!type) {
10123 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10124 return -1;
10125 }
10126
10127 if (enable > 1) {
10128 wpa_printf(MSG_INFO,
10129 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10130 return -1;
10131 }
10132
10133 if (!enable)
10134 return wpas_disable_mac_addr_randomization(wpa_s, type);
10135
10136 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
10137 }
10138
10139
wpas_ctrl_iface_pmksa(struct wpa_supplicant * wpa_s,char * buf,size_t buflen)10140 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10141 char *buf, size_t buflen)
10142 {
10143 size_t reply_len;
10144
10145 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10146 #ifdef CONFIG_AP
10147 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10148 buflen - reply_len);
10149 #endif /* CONFIG_AP */
10150 return reply_len;
10151 }
10152
10153
wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant * wpa_s)10154 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10155 {
10156 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
10157 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10158 #ifdef CONFIG_AP
10159 wpas_ap_pmksa_cache_flush(wpa_s);
10160 #endif /* CONFIG_AP */
10161 }
10162
10163
10164 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10165
wpas_ctrl_iface_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)10166 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
10167 const char *cmd, char *buf, size_t buflen)
10168 {
10169 struct rsn_pmksa_cache_entry *entry;
10170 struct wpa_ssid *ssid;
10171 char *pos, *pos2, *end;
10172 int ret;
10173 struct os_reltime now;
10174
10175 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10176 if (!ssid)
10177 return -1;
10178
10179 pos = buf;
10180 end = buf + buflen;
10181
10182 os_get_reltime(&now);
10183
10184 /*
10185 * Entry format:
10186 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10187 * <expiration in seconds> <akmp> <opportunistic>
10188 * [FILS Cache Identifier]
10189 */
10190
10191 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
10192 entry = entry->next) {
10193 if (entry->network_ctx != ssid)
10194 continue;
10195
10196 pos2 = pos;
10197 ret = os_snprintf(pos2, end - pos2, MACSTR " ",
10198 MAC2STR(entry->aa));
10199 if (os_snprintf_error(end - pos2, ret))
10200 break;
10201 pos2 += ret;
10202
10203 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
10204 PMKID_LEN);
10205
10206 ret = os_snprintf(pos2, end - pos2, " ");
10207 if (os_snprintf_error(end - pos2, ret))
10208 break;
10209 pos2 += ret;
10210
10211 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
10212 entry->pmk_len);
10213
10214 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
10215 (int) (entry->reauth_time - now.sec),
10216 (int) (entry->expiration - now.sec),
10217 entry->akmp,
10218 entry->opportunistic);
10219 if (os_snprintf_error(end - pos2, ret))
10220 break;
10221 pos2 += ret;
10222
10223 if (entry->fils_cache_id_set) {
10224 ret = os_snprintf(pos2, end - pos2, " %02x%02x",
10225 entry->fils_cache_id[0],
10226 entry->fils_cache_id[1]);
10227 if (os_snprintf_error(end - pos2, ret))
10228 break;
10229 pos2 += ret;
10230 }
10231
10232 ret = os_snprintf(pos2, end - pos2, "\n");
10233 if (os_snprintf_error(end - pos2, ret))
10234 break;
10235 pos2 += ret;
10236
10237 pos = pos2;
10238 }
10239
10240 return pos - buf;
10241 }
10242
10243
wpas_ctrl_iface_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)10244 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
10245 char *cmd)
10246 {
10247 struct rsn_pmksa_cache_entry *entry;
10248 struct wpa_ssid *ssid;
10249 char *pos, *pos2;
10250 int ret = -1;
10251 struct os_reltime now;
10252 int reauth_time = 0, expiration = 0, i;
10253
10254 /*
10255 * Entry format:
10256 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10257 * <expiration in seconds> <akmp> <opportunistic>
10258 * [FILS Cache Identifier]
10259 */
10260
10261 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10262 if (!ssid)
10263 return -1;
10264
10265 pos = os_strchr(cmd, ' ');
10266 if (!pos)
10267 return -1;
10268 pos++;
10269
10270 entry = os_zalloc(sizeof(*entry));
10271 if (!entry)
10272 return -1;
10273
10274 if (hwaddr_aton(pos, entry->aa))
10275 goto fail;
10276
10277 pos = os_strchr(pos, ' ');
10278 if (!pos)
10279 goto fail;
10280 pos++;
10281
10282 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
10283 goto fail;
10284
10285 pos = os_strchr(pos, ' ');
10286 if (!pos)
10287 goto fail;
10288 pos++;
10289
10290 pos2 = os_strchr(pos, ' ');
10291 if (!pos2)
10292 goto fail;
10293 entry->pmk_len = (pos2 - pos) / 2;
10294 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
10295 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
10296 goto fail;
10297
10298 pos = os_strchr(pos, ' ');
10299 if (!pos)
10300 goto fail;
10301 pos++;
10302
10303 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
10304 &entry->akmp, &entry->opportunistic) != 4)
10305 goto fail;
10306 for (i = 0; i < 4; i++) {
10307 pos = os_strchr(pos, ' ');
10308 if (!pos) {
10309 if (i < 3)
10310 goto fail;
10311 break;
10312 }
10313 pos++;
10314 }
10315 if (pos) {
10316 if (hexstr2bin(pos, entry->fils_cache_id,
10317 FILS_CACHE_ID_LEN) < 0)
10318 goto fail;
10319 entry->fils_cache_id_set = 1;
10320 }
10321 os_get_reltime(&now);
10322 entry->expiration = now.sec + expiration;
10323 entry->reauth_time = now.sec + reauth_time;
10324
10325 entry->network_ctx = ssid;
10326
10327 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
10328 entry = NULL;
10329 ret = 0;
10330 fail:
10331 os_free(entry);
10332 return ret;
10333 }
10334
10335
10336 #ifdef CONFIG_MESH
10337
wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant * wpa_s,const char * cmd,char * buf,size_t buflen)10338 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
10339 const char *cmd, char *buf,
10340 size_t buflen)
10341 {
10342 u8 spa[ETH_ALEN];
10343
10344 if (!wpa_s->ifmsh)
10345 return -1;
10346
10347 if (os_strcasecmp(cmd, "any") == 0)
10348 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
10349
10350 if (hwaddr_aton(cmd, spa))
10351 return -1;
10352
10353 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
10354 }
10355
10356
wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant * wpa_s,char * cmd)10357 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
10358 char *cmd)
10359 {
10360 /*
10361 * We do not check mesh interface existence because PMKSA should be
10362 * stored before wpa_s->ifmsh creation to suppress commit message
10363 * creation.
10364 */
10365 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
10366 }
10367
10368 #endif /* CONFIG_MESH */
10369 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
10370
10371
10372 #ifdef CONFIG_FILS
wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant * wpa_s,const char * cmd)10373 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
10374 const char *cmd)
10375 {
10376 struct fils_hlp_req *req;
10377 const char *pos;
10378
10379 /* format: <dst> <packet starting from ethertype> */
10380
10381 req = os_zalloc(sizeof(*req));
10382 if (!req)
10383 return -1;
10384
10385 if (hwaddr_aton(cmd, req->dst))
10386 goto fail;
10387
10388 pos = os_strchr(cmd, ' ');
10389 if (!pos)
10390 goto fail;
10391 pos++;
10392 req->pkt = wpabuf_parse_bin(pos);
10393 if (!req->pkt)
10394 goto fail;
10395
10396 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
10397 return 0;
10398 fail:
10399 wpabuf_free(req->pkt);
10400 os_free(req);
10401 return -1;
10402 }
10403 #endif /* CONFIG_FILS */
10404
10405
wpas_ctrl_cmd_debug_level(const char * cmd)10406 static int wpas_ctrl_cmd_debug_level(const char *cmd)
10407 {
10408 if (os_strcmp(cmd, "PING") == 0 ||
10409 os_strncmp(cmd, "BSS ", 4) == 0 ||
10410 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
10411 os_strncmp(cmd, "STATUS", 6) == 0 ||
10412 os_strncmp(cmd, "STA ", 4) == 0 ||
10413 os_strncmp(cmd, "STA-", 4) == 0)
10414 return MSG_EXCESSIVE;
10415 return MSG_DEBUG;
10416 }
10417
10418
wpas_ctrl_iface_configure_mscs(struct wpa_supplicant * wpa_s,const char * cmd)10419 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
10420 const char *cmd)
10421 {
10422 size_t frame_classifier_len;
10423 const char *pos, *end;
10424 struct robust_av_data *robust_av = &wpa_s->robust_av;
10425 int val;
10426
10427 /*
10428 * format:
10429 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
10430 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
10431 */
10432 os_memset(robust_av, 0, sizeof(struct robust_av_data));
10433 if (os_strncmp(cmd, "add ", 4) == 0) {
10434 robust_av->request_type = SCS_REQ_ADD;
10435 } else if (os_strcmp(cmd, "remove") == 0) {
10436 robust_av->request_type = SCS_REQ_REMOVE;
10437 robust_av->valid_config = false;
10438 return wpas_send_mscs_req(wpa_s);
10439 } else if (os_strncmp(cmd, "change ", 7) == 0) {
10440 robust_av->request_type = SCS_REQ_CHANGE;
10441 } else {
10442 return -1;
10443 }
10444
10445 pos = os_strstr(cmd, "up_bitmap=");
10446 if (!pos)
10447 return -1;
10448
10449 val = hex2byte(pos + 10);
10450 if (val < 0)
10451 return -1;
10452 robust_av->up_bitmap = val;
10453
10454 pos = os_strstr(cmd, "up_limit=");
10455 if (!pos)
10456 return -1;
10457
10458 robust_av->up_limit = atoi(pos + 9);
10459
10460 pos = os_strstr(cmd, "stream_timeout=");
10461 if (!pos)
10462 return -1;
10463
10464 robust_av->stream_timeout = atoi(pos + 15);
10465 if (robust_av->stream_timeout == 0)
10466 return -1;
10467
10468 pos = os_strstr(cmd, "frame_classifier=");
10469 if (!pos)
10470 return -1;
10471
10472 pos += 17;
10473 end = os_strchr(pos, ' ');
10474 if (!end)
10475 end = pos + os_strlen(pos);
10476
10477 frame_classifier_len = (end - pos) / 2;
10478 if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
10479 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
10480 return -1;
10481
10482 robust_av->frame_classifier_len = frame_classifier_len;
10483 robust_av->valid_config = true;
10484
10485 return wpas_send_mscs_req(wpa_s);
10486 }
10487
10488
10489 #ifdef CONFIG_PASN
wpas_ctrl_iface_pasn_start(struct wpa_supplicant * wpa_s,char * cmd)10490 static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
10491 {
10492 char *token, *context = NULL;
10493 u8 bssid[ETH_ALEN];
10494 int akmp = -1, cipher = -1, got_bssid = 0;
10495 u16 group = 0xFFFF;
10496 int id = 0;
10497
10498 /*
10499 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
10500 */
10501 while ((token = str_token(cmd, " ", &context))) {
10502 if (os_strncmp(token, "bssid=", 6) == 0) {
10503 if (hwaddr_aton(token + 6, bssid))
10504 return -1;
10505 got_bssid = 1;
10506 } else if (os_strcmp(token, "akmp=PASN") == 0) {
10507 akmp = WPA_KEY_MGMT_PASN;
10508 #ifdef CONFIG_IEEE80211R
10509 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
10510 akmp = WPA_KEY_MGMT_FT_PSK;
10511 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
10512 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
10513 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
10514 akmp = WPA_KEY_MGMT_FT_IEEE8021X;
10515 #endif /* CONFIG_IEEE80211R */
10516 #ifdef CONFIG_SAE
10517 } else if (os_strcmp(token, "akmp=SAE") == 0) {
10518 akmp = WPA_KEY_MGMT_SAE;
10519 #endif /* CONFIG_SAE */
10520 #ifdef CONFIG_FILS
10521 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
10522 akmp = WPA_KEY_MGMT_FILS_SHA256;
10523 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
10524 akmp = WPA_KEY_MGMT_FILS_SHA384;
10525 #endif /* CONFIG_FILS */
10526 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
10527 cipher = WPA_CIPHER_CCMP_256;
10528 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
10529 cipher = WPA_CIPHER_GCMP_256;
10530 } else if (os_strcmp(token, "cipher=CCMP") == 0) {
10531 cipher = WPA_CIPHER_CCMP;
10532 } else if (os_strcmp(token, "cipher=GCMP") == 0) {
10533 cipher = WPA_CIPHER_GCMP;
10534 } else if (os_strncmp(token, "group=", 6) == 0) {
10535 group = atoi(token + 6);
10536 } else if (os_strncmp(token, "nid=", 4) == 0) {
10537 id = atoi(token + 4);
10538 } else {
10539 wpa_printf(MSG_DEBUG,
10540 "CTRL: PASN Invalid parameter: '%s'",
10541 token);
10542 return -1;
10543 }
10544 }
10545
10546 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
10547 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
10548 return -1;
10549 }
10550
10551 return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
10552 }
10553 #endif /* CONFIG_PASN */
10554
10555
wpa_supplicant_ctrl_iface_process(struct wpa_supplicant * wpa_s,char * buf,size_t * resp_len)10556 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
10557 char *buf, size_t *resp_len)
10558 {
10559 char *reply;
10560 const int reply_size = 4096;
10561 int reply_len;
10562
10563 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
10564 os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
10565 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
10566 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
10567 if (wpa_debug_show_keys)
10568 wpa_dbg(wpa_s, MSG_DEBUG,
10569 "Control interface command '%s'", buf);
10570 else
10571 wpa_dbg(wpa_s, MSG_DEBUG,
10572 "Control interface command '%s [REMOVED]'",
10573 os_strncmp(buf, WPA_CTRL_RSP,
10574 os_strlen(WPA_CTRL_RSP)) == 0 ?
10575 WPA_CTRL_RSP :
10576 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
10577 "SET_NETWORK" : "key-add"));
10578 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
10579 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
10580 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
10581 (const u8 *) buf, os_strlen(buf));
10582 } else {
10583 int level = wpas_ctrl_cmd_debug_level(buf);
10584 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
10585 }
10586
10587 reply = os_malloc(reply_size);
10588 if (reply == NULL) {
10589 *resp_len = 1;
10590 return NULL;
10591 }
10592
10593 os_memcpy(reply, "OK\n", 3);
10594 reply_len = 3;
10595
10596 if (os_strcmp(buf, "PING") == 0) {
10597 os_memcpy(reply, "PONG\n", 5);
10598 reply_len = 5;
10599 } else if (os_strcmp(buf, "IFNAME") == 0) {
10600 reply_len = os_strlen(wpa_s->ifname);
10601 os_memcpy(reply, wpa_s->ifname, reply_len);
10602 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
10603 if (wpa_debug_reopen_file() < 0)
10604 reply_len = -1;
10605 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
10606 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
10607 } else if (os_strcmp(buf, "MIB") == 0) {
10608 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
10609 if (reply_len >= 0) {
10610 reply_len += eapol_sm_get_mib(wpa_s->eapol,
10611 reply + reply_len,
10612 reply_size - reply_len);
10613 #ifdef CONFIG_MACSEC
10614 reply_len += ieee802_1x_kay_get_mib(
10615 wpa_s->kay, reply + reply_len,
10616 reply_size - reply_len);
10617 #endif /* CONFIG_MACSEC */
10618 }
10619 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
10620 reply_len = wpa_supplicant_ctrl_iface_status(
10621 wpa_s, buf + 6, reply, reply_size);
10622 } else if (os_strcmp(buf, "PMKSA") == 0) {
10623 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
10624 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
10625 wpas_ctrl_iface_pmksa_flush(wpa_s);
10626 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10627 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
10628 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
10629 reply, reply_size);
10630 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
10631 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
10632 reply_len = -1;
10633 #ifdef CONFIG_MESH
10634 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
10635 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
10636 reply, reply_size);
10637 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
10638 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
10639 reply_len = -1;
10640 #endif /* CONFIG_MESH */
10641 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
10642 } else if (os_strncmp(buf, "SET ", 4) == 0) {
10643 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
10644 reply_len = -1;
10645 } else if (os_strncmp(buf, "DUMP", 4) == 0) {
10646 reply_len = wpa_config_dump_values(wpa_s->conf,
10647 reply, reply_size);
10648 } else if (os_strncmp(buf, "GET ", 4) == 0) {
10649 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
10650 reply, reply_size);
10651 } else if (os_strcmp(buf, "LOGON") == 0) {
10652 eapol_sm_notify_logoff(wpa_s->eapol, false);
10653 } else if (os_strcmp(buf, "LOGOFF") == 0) {
10654 eapol_sm_notify_logoff(wpa_s->eapol, true);
10655 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
10656 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
10657 reply_len = -1;
10658 else
10659 wpas_request_connection(wpa_s);
10660 } else if (os_strcmp(buf, "REATTACH") == 0) {
10661 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
10662 !wpa_s->current_ssid)
10663 reply_len = -1;
10664 else {
10665 wpa_s->reattach = 1;
10666 wpas_request_connection(wpa_s);
10667 }
10668 } else if (os_strcmp(buf, "RECONNECT") == 0) {
10669 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
10670 reply_len = -1;
10671 else if (wpa_s->disconnected)
10672 wpas_request_connection(wpa_s);
10673 #ifdef IEEE8021X_EAPOL
10674 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
10675 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
10676 reply_len = -1;
10677 #endif /* IEEE8021X_EAPOL */
10678 #ifdef CONFIG_IEEE80211R
10679 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
10680 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
10681 reply_len = -1;
10682 #endif /* CONFIG_IEEE80211R */
10683 #ifdef CONFIG_WPS
10684 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
10685 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
10686 if (res == -2) {
10687 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10688 reply_len = 17;
10689 } else if (res)
10690 reply_len = -1;
10691 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
10692 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
10693 if (res == -2) {
10694 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10695 reply_len = 17;
10696 } else if (res)
10697 reply_len = -1;
10698 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
10699 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
10700 reply,
10701 reply_size);
10702 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
10703 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
10704 wpa_s, buf + 14, reply, reply_size);
10705 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
10706 if (wpas_wps_cancel(wpa_s))
10707 reply_len = -1;
10708 #ifdef CONFIG_WPS_NFC
10709 } else if (os_strcmp(buf, "WPS_NFC") == 0) {
10710 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
10711 reply_len = -1;
10712 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
10713 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
10714 reply_len = -1;
10715 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
10716 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
10717 wpa_s, buf + 21, reply, reply_size);
10718 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
10719 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
10720 wpa_s, buf + 14, reply, reply_size);
10721 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
10722 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
10723 buf + 17))
10724 reply_len = -1;
10725 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
10726 reply_len = wpas_ctrl_nfc_get_handover_req(
10727 wpa_s, buf + 21, reply, reply_size);
10728 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
10729 reply_len = wpas_ctrl_nfc_get_handover_sel(
10730 wpa_s, buf + 21, reply, reply_size);
10731 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
10732 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
10733 reply_len = -1;
10734 #endif /* CONFIG_WPS_NFC */
10735 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
10736 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
10737 reply_len = -1;
10738 #ifdef CONFIG_AP
10739 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
10740 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
10741 wpa_s, buf + 11, reply, reply_size);
10742 #endif /* CONFIG_AP */
10743 #ifdef CONFIG_WPS_ER
10744 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
10745 if (wpas_wps_er_start(wpa_s, NULL))
10746 reply_len = -1;
10747 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
10748 if (wpas_wps_er_start(wpa_s, buf + 13))
10749 reply_len = -1;
10750 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
10751 wpas_wps_er_stop(wpa_s);
10752 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
10753 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
10754 reply_len = -1;
10755 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
10756 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
10757 if (ret == -2) {
10758 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
10759 reply_len = 17;
10760 } else if (ret == -3) {
10761 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
10762 reply_len = 18;
10763 } else if (ret == -4) {
10764 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
10765 reply_len = 20;
10766 } else if (ret)
10767 reply_len = -1;
10768 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
10769 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
10770 reply_len = -1;
10771 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
10772 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
10773 buf + 18))
10774 reply_len = -1;
10775 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
10776 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
10777 reply_len = -1;
10778 #ifdef CONFIG_WPS_NFC
10779 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
10780 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
10781 wpa_s, buf + 24, reply, reply_size);
10782 #endif /* CONFIG_WPS_NFC */
10783 #endif /* CONFIG_WPS_ER */
10784 #endif /* CONFIG_WPS */
10785 #ifdef CONFIG_IBSS_RSN
10786 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
10787 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
10788 reply_len = -1;
10789 #endif /* CONFIG_IBSS_RSN */
10790 #ifdef CONFIG_MESH
10791 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
10792 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
10793 wpa_s, buf + 19, reply, reply_size);
10794 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
10795 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
10796 wpa_s, "", reply, reply_size);
10797 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
10798 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
10799 reply_len = -1;
10800 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
10801 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
10802 buf + 18))
10803 reply_len = -1;
10804 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
10805 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
10806 reply_len = -1;
10807 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
10808 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
10809 reply_len = -1;
10810 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
10811 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
10812 reply_len = -1;
10813 #endif /* CONFIG_MESH */
10814 #ifdef CONFIG_P2P
10815 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
10816 if (p2p_ctrl_find(wpa_s, buf + 8))
10817 reply_len = -1;
10818 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
10819 if (p2p_ctrl_find(wpa_s, ""))
10820 reply_len = -1;
10821 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
10822 wpas_p2p_stop_find(wpa_s);
10823 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
10824 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
10825 reply_len = -1;
10826 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
10827 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
10828 reply_len = -1;
10829 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
10830 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
10831 reply_size);
10832 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
10833 if (p2p_ctrl_listen(wpa_s, buf + 11))
10834 reply_len = -1;
10835 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
10836 if (p2p_ctrl_listen(wpa_s, ""))
10837 reply_len = -1;
10838 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
10839 if (wpas_p2p_group_remove(wpa_s, buf + 17))
10840 reply_len = -1;
10841 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
10842 if (p2p_ctrl_group_add(wpa_s, ""))
10843 reply_len = -1;
10844 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
10845 if (p2p_ctrl_group_add(wpa_s, buf + 14))
10846 reply_len = -1;
10847 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
10848 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
10849 reply_size);
10850 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
10851 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
10852 reply_len = -1;
10853 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
10854 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
10855 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
10856 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
10857 reply_size);
10858 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
10859 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
10860 reply_len = -1;
10861 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
10862 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
10863 reply_len = -1;
10864 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
10865 wpas_p2p_sd_service_update(wpa_s);
10866 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
10867 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
10868 reply_len = -1;
10869 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
10870 wpas_p2p_service_flush(wpa_s);
10871 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
10872 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
10873 reply_len = -1;
10874 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
10875 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
10876 reply_len = -1;
10877 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
10878 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
10879 reply_len = -1;
10880 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
10881 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
10882 reply_len = -1;
10883 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
10884 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
10885 reply_len = -1;
10886 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
10887 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
10888 reply_size);
10889 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
10890 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
10891 reply_len = -1;
10892 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
10893 p2p_ctrl_flush(wpa_s);
10894 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
10895 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
10896 reply_len = -1;
10897 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
10898 if (wpas_p2p_cancel(wpa_s))
10899 reply_len = -1;
10900 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
10901 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
10902 reply_len = -1;
10903 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
10904 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
10905 reply_len = -1;
10906 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
10907 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
10908 reply_len = -1;
10909 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
10910 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
10911 reply_len = -1;
10912 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
10913 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
10914 reply_len = -1;
10915 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
10916 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
10917 reply_len = -1;
10918 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
10919 if (wpas_p2p_lo_stop(wpa_s))
10920 reply_len = -1;
10921 #endif /* CONFIG_P2P */
10922 #ifdef CONFIG_WIFI_DISPLAY
10923 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
10924 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
10925 reply_len = -1;
10926 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
10927 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
10928 reply, reply_size);
10929 #endif /* CONFIG_WIFI_DISPLAY */
10930 #ifdef CONFIG_INTERWORKING
10931 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
10932 if (interworking_fetch_anqp(wpa_s) < 0)
10933 reply_len = -1;
10934 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
10935 interworking_stop_fetch_anqp(wpa_s);
10936 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
10937 if (ctrl_interworking_select(wpa_s, NULL) < 0)
10938 reply_len = -1;
10939 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
10940 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
10941 reply_len = -1;
10942 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
10943 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
10944 reply_len = -1;
10945 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
10946 int id;
10947
10948 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
10949 if (id < 0)
10950 reply_len = -1;
10951 else {
10952 reply_len = os_snprintf(reply, reply_size, "%d\n", id);
10953 if (os_snprintf_error(reply_size, reply_len))
10954 reply_len = -1;
10955 }
10956 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
10957 if (get_anqp(wpa_s, buf + 9) < 0)
10958 reply_len = -1;
10959 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
10960 if (gas_request(wpa_s, buf + 12) < 0)
10961 reply_len = -1;
10962 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
10963 reply_len = gas_response_get(wpa_s, buf + 17, reply,
10964 reply_size);
10965 #endif /* CONFIG_INTERWORKING */
10966 #ifdef CONFIG_HS20
10967 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
10968 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
10969 reply_len = -1;
10970 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
10971 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
10972 reply_len = -1;
10973 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
10974 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
10975 reply_len = -1;
10976 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
10977 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
10978 reply_len = -1;
10979 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
10980 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
10981 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
10982 if (del_hs20_icon(wpa_s, buf + 14) < 0)
10983 reply_len = -1;
10984 } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
10985 if (hs20_fetch_osu(wpa_s, 0) < 0)
10986 reply_len = -1;
10987 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
10988 if (hs20_fetch_osu(wpa_s, 1) < 0)
10989 reply_len = -1;
10990 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
10991 hs20_cancel_fetch_osu(wpa_s);
10992 #endif /* CONFIG_HS20 */
10993 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
10994 {
10995 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
10996 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
10997 reply_len = -1;
10998 else {
10999 /*
11000 * Notify response from timeout to allow the control
11001 * interface response to be sent first.
11002 */
11003 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
11004 wpa_s, NULL);
11005 }
11006 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
11007 if (wpa_supplicant_reload_configuration(wpa_s))
11008 reply_len = -1;
11009 } else if (os_strcmp(buf, "TERMINATE") == 0) {
11010 wpa_supplicant_terminate_proc(wpa_s->global);
11011 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
11012 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
11013 reply_len = -1;
11014 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
11015 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
11016 wpa_s, buf + 12, reply, reply_size);
11017 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
11018 /* deprecated backwards compatibility alias for BSSID_IGNORE */
11019 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
11020 wpa_s, buf + 9, reply, reply_size);
11021 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
11022 reply_len = wpa_supplicant_ctrl_iface_log_level(
11023 wpa_s, buf + 9, reply, reply_size);
11024 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
11025 reply_len = wpa_supplicant_ctrl_iface_list_networks(
11026 wpa_s, buf + 14, reply, reply_size);
11027 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
11028 reply_len = wpa_supplicant_ctrl_iface_list_networks(
11029 wpa_s, NULL, reply, reply_size);
11030 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
11031 wpas_request_disconnection(wpa_s);
11032 } else if (os_strcmp(buf, "SCAN") == 0) {
11033 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
11034 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
11035 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
11036 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
11037 reply_len = wpa_supplicant_ctrl_iface_scan_results(
11038 wpa_s, reply, reply_size);
11039 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
11040 if (wpas_abort_ongoing_scan(wpa_s) < 0)
11041 reply_len = -1;
11042 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
11043 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
11044 reply_len = -1;
11045 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
11046 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
11047 reply_len = -1;
11048 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
11049 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
11050 reply_len = -1;
11051 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
11052 reply_len = wpa_supplicant_ctrl_iface_add_network(
11053 wpa_s, reply, reply_size);
11054 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
11055 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
11056 reply_len = -1;
11057 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
11058 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
11059 reply_len = -1;
11060 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
11061 reply_len = wpa_supplicant_ctrl_iface_get_network(
11062 wpa_s, buf + 12, reply, reply_size);
11063 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
11064 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
11065 wpa_s))
11066 reply_len = -1;
11067 } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
11068 reply_len = wpa_supplicant_ctrl_iface_list_creds(
11069 wpa_s, reply, reply_size);
11070 } else if (os_strcmp(buf, "ADD_CRED") == 0) {
11071 reply_len = wpa_supplicant_ctrl_iface_add_cred(
11072 wpa_s, reply, reply_size);
11073 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
11074 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
11075 reply_len = -1;
11076 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
11077 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
11078 reply_len = -1;
11079 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
11080 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
11081 reply,
11082 reply_size);
11083 #ifndef CONFIG_NO_CONFIG_WRITE
11084 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
11085 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
11086 reply_len = -1;
11087 #endif /* CONFIG_NO_CONFIG_WRITE */
11088 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
11089 reply_len = wpa_supplicant_ctrl_iface_get_capability(
11090 wpa_s, buf + 15, reply, reply_size);
11091 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
11092 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
11093 reply_len = -1;
11094 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
11095 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
11096 reply_len = -1;
11097 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
11098 reply_len = wpa_supplicant_global_iface_list(
11099 wpa_s->global, reply, reply_size);
11100 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
11101 reply_len = wpa_supplicant_global_iface_interfaces(
11102 wpa_s->global, buf + 10, reply, reply_size);
11103 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
11104 reply_len = wpa_supplicant_ctrl_iface_bss(
11105 wpa_s, buf + 4, reply, reply_size);
11106 #ifdef CONFIG_AP
11107 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
11108 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
11109 } else if (os_strncmp(buf, "STA ", 4) == 0) {
11110 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
11111 reply_size);
11112 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
11113 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
11114 reply_size);
11115 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
11116 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
11117 reply_len = -1;
11118 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
11119 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
11120 reply_len = -1;
11121 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
11122 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
11123 reply_len = -1;
11124 } else if (os_strcmp(buf, "STOP_AP") == 0) {
11125 if (wpas_ap_stop_ap(wpa_s))
11126 reply_len = -1;
11127 #endif /* CONFIG_AP */
11128 } else if (os_strcmp(buf, "SUSPEND") == 0) {
11129 wpas_notify_suspend(wpa_s->global);
11130 } else if (os_strcmp(buf, "RESUME") == 0) {
11131 wpas_notify_resume(wpa_s->global);
11132 #ifdef CONFIG_TESTING_OPTIONS
11133 } else if (os_strcmp(buf, "DROP_SA") == 0) {
11134 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
11135 #endif /* CONFIG_TESTING_OPTIONS */
11136 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
11137 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
11138 reply_len = -1;
11139 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
11140 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
11141 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
11142 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
11143 reply_len = -1;
11144 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
11145 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
11146 buf + 17))
11147 reply_len = -1;
11148 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
11149 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
11150 #ifdef CONFIG_TDLS
11151 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
11152 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
11153 reply_len = -1;
11154 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
11155 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
11156 reply_len = -1;
11157 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
11158 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
11159 reply_len = -1;
11160 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
11161 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
11162 buf + 17))
11163 reply_len = -1;
11164 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
11165 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
11166 buf + 24))
11167 reply_len = -1;
11168 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
11169 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
11170 wpa_s, buf + 17, reply, reply_size);
11171 #endif /* CONFIG_TDLS */
11172 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
11173 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
11174 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
11175 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
11176 reply_len = -1;
11177 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
11178 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
11179 reply_len = -1;
11180 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
11181 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
11182 reply_size);
11183 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
11184 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
11185 reply_len = -1;
11186 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
11187 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
11188 reply_size);
11189 #ifdef CONFIG_AUTOSCAN
11190 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
11191 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
11192 reply_len = -1;
11193 #endif /* CONFIG_AUTOSCAN */
11194 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
11195 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
11196 reply_size);
11197 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
11198 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
11199 reply_size);
11200 #ifdef ANDROID
11201 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
11202 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
11203 reply_size);
11204 #endif /* ANDROID */
11205 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
11206 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
11207 reply_size);
11208 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
11209 pmksa_cache_clear_current(wpa_s->wpa);
11210 eapol_sm_request_reauth(wpa_s->eapol);
11211 #ifdef CONFIG_WNM
11212 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
11213 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
11214 reply_len = -1;
11215 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
11216 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
11217 reply_len = -1;
11218 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
11219 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
11220 reply_len = -1;
11221 #endif /* CONFIG_WNM */
11222 } else if (os_strcmp(buf, "FLUSH") == 0) {
11223 wpa_supplicant_ctrl_iface_flush(wpa_s);
11224 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
11225 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
11226 reply_size);
11227 #ifdef CONFIG_TESTING_OPTIONS
11228 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
11229 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
11230 reply_len = -1;
11231 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
11232 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
11233 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
11234 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
11235 reply_len = -1;
11236 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
11237 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
11238 reply_len = -1;
11239 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
11240 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
11241 reply_len = -1;
11242 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
11243 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
11244 reply_len = -1;
11245 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
11246 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
11247 reply_len = -1;
11248 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
11249 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
11250 reply_len = -1;
11251 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
11252 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
11253 reply_len = -1;
11254 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
11255 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
11256 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
11257 if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
11258 reply_len = -1;
11259 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
11260 reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
11261 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
11262 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
11263 reply_len = -1;
11264 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
11265 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
11266 reply_len = -1;
11267 } else if (os_strcmp(buf, "RESET_PN") == 0) {
11268 if (wpas_ctrl_reset_pn(wpa_s) < 0)
11269 reply_len = -1;
11270 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
11271 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
11272 reply_len = -1;
11273 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
11274 if (wpas_ctrl_resend_assoc(wpa_s) < 0)
11275 reply_len = -1;
11276 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
11277 sme_event_unprot_disconnect(
11278 wpa_s, wpa_s->bssid, NULL,
11279 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
11280 #endif /* CONFIG_TESTING_OPTIONS */
11281 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
11282 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
11283 reply_len = -1;
11284 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
11285 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
11286 reply_size);
11287 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
11288 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
11289 reply_len = -1;
11290 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
11291 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
11292 reply_len = -1;
11293 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
11294 wpas_ctrl_iface_erp_flush(wpa_s);
11295 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
11296 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
11297 reply_len = -1;
11298 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
11299 reply_len = wpas_ctrl_iface_get_pref_freq_list(
11300 wpa_s, buf + 19, reply, reply_size);
11301 #ifdef CONFIG_FILS
11302 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
11303 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
11304 reply_len = -1;
11305 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
11306 wpas_flush_fils_hlp_req(wpa_s);
11307 #endif /* CONFIG_FILS */
11308 #ifdef CONFIG_DPP
11309 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
11310 int res;
11311
11312 res = wpas_dpp_qr_code(wpa_s, buf + 12);
11313 if (res < 0) {
11314 reply_len = -1;
11315 } else {
11316 reply_len = os_snprintf(reply, reply_size, "%d", res);
11317 if (os_snprintf_error(reply_size, reply_len))
11318 reply_len = -1;
11319 }
11320 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
11321 int res;
11322
11323 res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
11324 if (res < 0) {
11325 reply_len = -1;
11326 } else {
11327 reply_len = os_snprintf(reply, reply_size, "%d", res);
11328 if (os_snprintf_error(reply_size, reply_len))
11329 reply_len = -1;
11330 }
11331 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
11332 int res;
11333
11334 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
11335 if (res < 0) {
11336 reply_len = -1;
11337 } else {
11338 reply_len = os_snprintf(reply, reply_size, "%d", res);
11339 if (os_snprintf_error(reply_size, reply_len))
11340 reply_len = -1;
11341 }
11342 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
11343 int res;
11344
11345 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
11346 if (res < 0) {
11347 reply_len = -1;
11348 } else {
11349 reply_len = os_snprintf(reply, reply_size, "%d", res);
11350 if (os_snprintf_error(reply_size, reply_len))
11351 reply_len = -1;
11352 }
11353 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
11354 int res;
11355
11356 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
11357 if (res < 0) {
11358 reply_len = -1;
11359 } else {
11360 reply_len = os_snprintf(reply, reply_size, "%d", res);
11361 if (os_snprintf_error(reply_size, reply_len))
11362 reply_len = -1;
11363 }
11364 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
11365 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
11366 reply_len = -1;
11367 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
11368 const char *uri;
11369
11370 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
11371 if (!uri) {
11372 reply_len = -1;
11373 } else {
11374 reply_len = os_snprintf(reply, reply_size, "%s", uri);
11375 if (os_snprintf_error(reply_size, reply_len))
11376 reply_len = -1;
11377 }
11378 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
11379 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
11380 reply, reply_size);
11381 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
11382 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
11383 os_strchr(buf + 18, ' ')) < 0)
11384 reply_len = -1;
11385 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
11386 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
11387 reply_len = -1;
11388 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
11389 if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
11390 reply_len = -1;
11391 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
11392 wpas_dpp_stop(wpa_s);
11393 wpas_dpp_listen_stop(wpa_s);
11394 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
11395 int res;
11396
11397 res = dpp_configurator_add(wpa_s->dpp, buf + 20);
11398 if (res < 0) {
11399 reply_len = -1;
11400 } else {
11401 reply_len = os_snprintf(reply, reply_size, "%d", res);
11402 if (os_snprintf_error(reply_size, reply_len))
11403 reply_len = -1;
11404 }
11405 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
11406 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
11407 reply_len = -1;
11408 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
11409 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
11410 reply_len = -1;
11411 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
11412 reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
11413 atoi(buf + 25),
11414 reply, reply_size);
11415 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
11416 int res;
11417
11418 res = wpas_dpp_pkex_add(wpa_s, buf + 12);
11419 if (res < 0) {
11420 reply_len = -1;
11421 } else {
11422 reply_len = os_snprintf(reply, reply_size, "%d", res);
11423 if (os_snprintf_error(reply_size, reply_len))
11424 reply_len = -1;
11425 }
11426 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
11427 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
11428 reply_len = -1;
11429 #ifdef CONFIG_DPP2
11430 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
11431 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
11432 reply_len = -1;
11433 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
11434 if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
11435 reply_len = -1;
11436 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
11437 dpp_controller_stop(wpa_s->dpp);
11438 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
11439 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
11440 reply_len = -1;
11441 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
11442 wpas_dpp_chirp_stop(wpa_s);
11443 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
11444 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
11445 reply_len = -1;
11446 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
11447 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
11448 reply_len = -1;
11449 #endif /* CONFIG_DPP2 */
11450 #endif /* CONFIG_DPP */
11451 } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
11452 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
11453 reply_len = -1;
11454 #ifdef CONFIG_PASN
11455 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
11456 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
11457 reply_len = -1;
11458 } else if (os_strcmp(buf, "PASN_STOP") == 0) {
11459 wpas_pasn_auth_stop(wpa_s);
11460 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
11461 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
11462 #endif /* CONFIG_PASN */
11463 } else {
11464 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
11465 reply_len = 16;
11466 }
11467
11468 if (reply_len < 0) {
11469 os_memcpy(reply, "FAIL\n", 5);
11470 reply_len = 5;
11471 }
11472
11473 *resp_len = reply_len;
11474 return reply;
11475 }
11476
11477
wpa_supplicant_global_iface_add(struct wpa_global * global,char * cmd)11478 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
11479 char *cmd)
11480 {
11481 struct wpa_interface iface;
11482 char *pos, *extra;
11483 struct wpa_supplicant *wpa_s;
11484 unsigned int create_iface = 0;
11485 u8 mac_addr[ETH_ALEN];
11486 enum wpa_driver_if_type type = WPA_IF_STATION;
11487
11488 /*
11489 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
11490 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
11491 */
11492 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
11493
11494 os_memset(&iface, 0, sizeof(iface));
11495
11496 do {
11497 iface.ifname = pos = cmd;
11498 pos = os_strchr(pos, '\t');
11499 if (pos)
11500 *pos++ = '\0';
11501 if (iface.ifname[0] == '\0')
11502 return -1;
11503 if (pos == NULL)
11504 break;
11505
11506 iface.confname = pos;
11507 pos = os_strchr(pos, '\t');
11508 if (pos)
11509 *pos++ = '\0';
11510 if (iface.confname[0] == '\0')
11511 iface.confname = NULL;
11512 if (pos == NULL)
11513 break;
11514
11515 iface.driver = pos;
11516 pos = os_strchr(pos, '\t');
11517 if (pos)
11518 *pos++ = '\0';
11519 if (iface.driver[0] == '\0')
11520 iface.driver = NULL;
11521 if (pos == NULL)
11522 break;
11523
11524 iface.ctrl_interface = pos;
11525 pos = os_strchr(pos, '\t');
11526 if (pos)
11527 *pos++ = '\0';
11528 if (iface.ctrl_interface[0] == '\0')
11529 iface.ctrl_interface = NULL;
11530 if (pos == NULL)
11531 break;
11532
11533 iface.driver_param = pos;
11534 pos = os_strchr(pos, '\t');
11535 if (pos)
11536 *pos++ = '\0';
11537 if (iface.driver_param[0] == '\0')
11538 iface.driver_param = NULL;
11539 if (pos == NULL)
11540 break;
11541
11542 iface.bridge_ifname = pos;
11543 pos = os_strchr(pos, '\t');
11544 if (pos)
11545 *pos++ = '\0';
11546 if (iface.bridge_ifname[0] == '\0')
11547 iface.bridge_ifname = NULL;
11548 if (pos == NULL)
11549 break;
11550
11551 extra = pos;
11552 pos = os_strchr(pos, '\t');
11553 if (pos)
11554 *pos++ = '\0';
11555 if (!extra[0])
11556 break;
11557
11558 if (os_strcmp(extra, "create") == 0) {
11559 create_iface = 1;
11560 if (!pos)
11561 break;
11562
11563 if (os_strcmp(pos, "sta") == 0) {
11564 type = WPA_IF_STATION;
11565 } else if (os_strcmp(pos, "ap") == 0) {
11566 type = WPA_IF_AP_BSS;
11567 } else {
11568 wpa_printf(MSG_DEBUG,
11569 "INTERFACE_ADD unsupported interface type: '%s'",
11570 pos);
11571 return -1;
11572 }
11573 } else {
11574 wpa_printf(MSG_DEBUG,
11575 "INTERFACE_ADD unsupported extra parameter: '%s'",
11576 extra);
11577 return -1;
11578 }
11579 } while (0);
11580
11581 if (create_iface) {
11582 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
11583 iface.ifname);
11584 if (!global->ifaces)
11585 return -1;
11586 if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
11587 NULL, NULL, NULL, mac_addr, NULL) < 0) {
11588 wpa_printf(MSG_ERROR,
11589 "CTRL_IFACE interface creation failed");
11590 return -1;
11591 }
11592
11593 wpa_printf(MSG_DEBUG,
11594 "CTRL_IFACE interface '%s' created with MAC addr: "
11595 MACSTR, iface.ifname, MAC2STR(mac_addr));
11596 }
11597
11598 if (wpa_supplicant_get_iface(global, iface.ifname))
11599 goto fail;
11600
11601 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
11602 if (!wpa_s)
11603 goto fail;
11604 wpa_s->added_vif = create_iface;
11605 return 0;
11606
11607 fail:
11608 if (create_iface)
11609 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
11610 return -1;
11611 }
11612
11613
wpa_supplicant_global_iface_remove(struct wpa_global * global,char * cmd)11614 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
11615 char *cmd)
11616 {
11617 struct wpa_supplicant *wpa_s;
11618 int ret;
11619 unsigned int delete_iface;
11620
11621 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
11622
11623 wpa_s = wpa_supplicant_get_iface(global, cmd);
11624 if (wpa_s == NULL)
11625 return -1;
11626 delete_iface = wpa_s->added_vif;
11627 ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
11628 if (!ret && delete_iface) {
11629 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
11630 cmd);
11631 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
11632 }
11633 return ret;
11634 }
11635
11636
wpa_free_iface_info(struct wpa_interface_info * iface)11637 static void wpa_free_iface_info(struct wpa_interface_info *iface)
11638 {
11639 struct wpa_interface_info *prev;
11640
11641 while (iface) {
11642 prev = iface;
11643 iface = iface->next;
11644
11645 os_free(prev->ifname);
11646 os_free(prev->desc);
11647 os_free(prev);
11648 }
11649 }
11650
11651
wpa_supplicant_global_iface_list(struct wpa_global * global,char * buf,int len)11652 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
11653 char *buf, int len)
11654 {
11655 int i, res;
11656 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
11657 char *pos, *end;
11658
11659 for (i = 0; wpa_drivers[i]; i++) {
11660 const struct wpa_driver_ops *drv = wpa_drivers[i];
11661 if (drv->get_interfaces == NULL)
11662 continue;
11663 tmp = drv->get_interfaces(global->drv_priv[i]);
11664 if (tmp == NULL)
11665 continue;
11666
11667 if (last == NULL)
11668 iface = last = tmp;
11669 else
11670 last->next = tmp;
11671 while (last->next)
11672 last = last->next;
11673 }
11674
11675 pos = buf;
11676 end = buf + len;
11677 for (tmp = iface; tmp; tmp = tmp->next) {
11678 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
11679 tmp->drv_name, tmp->ifname,
11680 tmp->desc ? tmp->desc : "");
11681 if (os_snprintf_error(end - pos, res)) {
11682 *pos = '\0';
11683 break;
11684 }
11685 pos += res;
11686 }
11687
11688 wpa_free_iface_info(iface);
11689
11690 return pos - buf;
11691 }
11692
11693
wpa_supplicant_global_iface_interfaces(struct wpa_global * global,const char * input,char * buf,int len)11694 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
11695 const char *input,
11696 char *buf, int len)
11697 {
11698 int res;
11699 char *pos, *end;
11700 struct wpa_supplicant *wpa_s;
11701 int show_ctrl = 0;
11702
11703 if (input)
11704 show_ctrl = !!os_strstr(input, "ctrl");
11705
11706 wpa_s = global->ifaces;
11707 pos = buf;
11708 end = buf + len;
11709
11710 while (wpa_s) {
11711 if (show_ctrl)
11712 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
11713 wpa_s->ifname,
11714 wpa_s->conf->ctrl_interface ?
11715 wpa_s->conf->ctrl_interface : "N/A");
11716 else
11717 res = os_snprintf(pos, end - pos, "%s\n",
11718 wpa_s->ifname);
11719
11720 if (os_snprintf_error(end - pos, res)) {
11721 *pos = '\0';
11722 break;
11723 }
11724 pos += res;
11725 wpa_s = wpa_s->next;
11726 }
11727 return pos - buf;
11728 }
11729
11730
wpas_global_ctrl_iface_ifname(struct wpa_global * global,const char * ifname,char * cmd,size_t * resp_len)11731 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
11732 const char *ifname,
11733 char *cmd, size_t *resp_len)
11734 {
11735 struct wpa_supplicant *wpa_s;
11736
11737 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
11738 if (os_strcmp(ifname, wpa_s->ifname) == 0)
11739 break;
11740 }
11741
11742 if (wpa_s == NULL) {
11743 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
11744 if (resp)
11745 *resp_len = os_strlen(resp);
11746 else
11747 *resp_len = 1;
11748 return resp;
11749 }
11750
11751 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
11752 }
11753
11754
wpas_global_ctrl_iface_redir_p2p(struct wpa_global * global,char * buf,size_t * resp_len)11755 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
11756 char *buf, size_t *resp_len)
11757 {
11758 #ifdef CONFIG_P2P
11759 static const char * cmd[] = {
11760 "LIST_NETWORKS",
11761 "P2P_FIND",
11762 "P2P_STOP_FIND",
11763 "P2P_LISTEN",
11764 "P2P_GROUP_ADD",
11765 "P2P_GET_PASSPHRASE",
11766 "P2P_SERVICE_UPDATE",
11767 "P2P_SERVICE_FLUSH",
11768 "P2P_FLUSH",
11769 "P2P_CANCEL",
11770 "P2P_PRESENCE_REQ",
11771 "P2P_EXT_LISTEN",
11772 #ifdef CONFIG_AP
11773 "STA-FIRST",
11774 #endif /* CONFIG_AP */
11775 NULL
11776 };
11777 static const char * prefix[] = {
11778 #ifdef ANDROID
11779 "DRIVER ",
11780 #endif /* ANDROID */
11781 "GET_CAPABILITY ",
11782 "GET_NETWORK ",
11783 "REMOVE_NETWORK ",
11784 "P2P_FIND ",
11785 "P2P_CONNECT ",
11786 "P2P_LISTEN ",
11787 "P2P_GROUP_REMOVE ",
11788 "P2P_GROUP_ADD ",
11789 "P2P_GROUP_MEMBER ",
11790 "P2P_PROV_DISC ",
11791 "P2P_SERV_DISC_REQ ",
11792 "P2P_SERV_DISC_CANCEL_REQ ",
11793 "P2P_SERV_DISC_RESP ",
11794 "P2P_SERV_DISC_EXTERNAL ",
11795 "P2P_SERVICE_ADD ",
11796 "P2P_SERVICE_DEL ",
11797 "P2P_SERVICE_REP ",
11798 "P2P_REJECT ",
11799 "P2P_INVITE ",
11800 "P2P_PEER ",
11801 "P2P_SET ",
11802 "P2P_UNAUTHORIZE ",
11803 "P2P_PRESENCE_REQ ",
11804 "P2P_EXT_LISTEN ",
11805 "P2P_REMOVE_CLIENT ",
11806 "WPS_NFC_TOKEN ",
11807 "WPS_NFC_TAG_READ ",
11808 "NFC_GET_HANDOVER_SEL ",
11809 "NFC_GET_HANDOVER_REQ ",
11810 "NFC_REPORT_HANDOVER ",
11811 "P2P_ASP_PROVISION ",
11812 "P2P_ASP_PROVISION_RESP ",
11813 #ifdef CONFIG_AP
11814 "STA ",
11815 "STA-NEXT ",
11816 #endif /* CONFIG_AP */
11817 NULL
11818 };
11819 int found = 0;
11820 int i;
11821
11822 if (global->p2p_init_wpa_s == NULL)
11823 return NULL;
11824
11825 for (i = 0; !found && cmd[i]; i++) {
11826 if (os_strcmp(buf, cmd[i]) == 0)
11827 found = 1;
11828 }
11829
11830 for (i = 0; !found && prefix[i]; i++) {
11831 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
11832 found = 1;
11833 }
11834
11835 if (found)
11836 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
11837 buf, resp_len);
11838 #endif /* CONFIG_P2P */
11839 return NULL;
11840 }
11841
11842
wpas_global_ctrl_iface_redir_wfd(struct wpa_global * global,char * buf,size_t * resp_len)11843 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
11844 char *buf, size_t *resp_len)
11845 {
11846 #ifdef CONFIG_WIFI_DISPLAY
11847 if (global->p2p_init_wpa_s == NULL)
11848 return NULL;
11849 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
11850 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
11851 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
11852 buf, resp_len);
11853 #endif /* CONFIG_WIFI_DISPLAY */
11854 return NULL;
11855 }
11856
11857
wpas_global_ctrl_iface_redir(struct wpa_global * global,char * buf,size_t * resp_len)11858 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
11859 char *buf, size_t *resp_len)
11860 {
11861 char *ret;
11862
11863 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
11864 if (ret)
11865 return ret;
11866
11867 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
11868 if (ret)
11869 return ret;
11870
11871 return NULL;
11872 }
11873
11874
wpas_global_ctrl_iface_set(struct wpa_global * global,char * cmd)11875 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
11876 {
11877 char *value;
11878
11879 value = os_strchr(cmd, ' ');
11880 if (value == NULL)
11881 return -1;
11882 *value++ = '\0';
11883
11884 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
11885
11886 #ifdef CONFIG_WIFI_DISPLAY
11887 if (os_strcasecmp(cmd, "wifi_display") == 0) {
11888 wifi_display_enable(global, !!atoi(value));
11889 return 0;
11890 }
11891 #endif /* CONFIG_WIFI_DISPLAY */
11892
11893 /* Restore cmd to its original value to allow redirection */
11894 value[-1] = ' ';
11895
11896 return -1;
11897 }
11898
11899
wpas_global_ctrl_iface_dup_network(struct wpa_global * global,char * cmd)11900 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
11901 char *cmd)
11902 {
11903 struct wpa_supplicant *wpa_s[2]; /* src, dst */
11904 char *p;
11905 unsigned int i;
11906
11907 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
11908 * <variable name> */
11909
11910 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
11911 p = os_strchr(cmd, ' ');
11912 if (p == NULL)
11913 return -1;
11914 *p = '\0';
11915
11916 wpa_s[i] = global->ifaces;
11917 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
11918 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
11919 break;
11920 }
11921
11922 if (!wpa_s[i]) {
11923 wpa_printf(MSG_DEBUG,
11924 "CTRL_IFACE: Could not find iface=%s", cmd);
11925 return -1;
11926 }
11927
11928 cmd = p + 1;
11929 }
11930
11931 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
11932 }
11933
11934
11935 #ifndef CONFIG_NO_CONFIG_WRITE
wpas_global_ctrl_iface_save_config(struct wpa_global * global)11936 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
11937 {
11938 int ret = 0, saved = 0;
11939 struct wpa_supplicant *wpa_s;
11940
11941 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
11942 if (!wpa_s->conf->update_config) {
11943 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
11944 continue;
11945 }
11946
11947 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
11948 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
11949 ret = 1;
11950 } else {
11951 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
11952 saved++;
11953 }
11954 }
11955
11956 if (!saved && !ret) {
11957 wpa_dbg(wpa_s, MSG_DEBUG,
11958 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
11959 ret = 1;
11960 }
11961
11962 return ret;
11963 }
11964 #endif /* CONFIG_NO_CONFIG_WRITE */
11965
11966
wpas_global_ctrl_iface_status(struct wpa_global * global,char * buf,size_t buflen)11967 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
11968 char *buf, size_t buflen)
11969 {
11970 char *pos, *end;
11971 int ret;
11972 struct wpa_supplicant *wpa_s;
11973
11974 pos = buf;
11975 end = buf + buflen;
11976
11977 #ifdef CONFIG_P2P
11978 if (global->p2p && !global->p2p_disabled) {
11979 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
11980 "\n"
11981 "p2p_state=%s\n",
11982 MAC2STR(global->p2p_dev_addr),
11983 p2p_get_state_txt(global->p2p));
11984 if (os_snprintf_error(end - pos, ret))
11985 return pos - buf;
11986 pos += ret;
11987 } else if (global->p2p) {
11988 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
11989 if (os_snprintf_error(end - pos, ret))
11990 return pos - buf;
11991 pos += ret;
11992 }
11993 #endif /* CONFIG_P2P */
11994
11995 #ifdef CONFIG_WIFI_DISPLAY
11996 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
11997 !!global->wifi_display);
11998 if (os_snprintf_error(end - pos, ret))
11999 return pos - buf;
12000 pos += ret;
12001 #endif /* CONFIG_WIFI_DISPLAY */
12002
12003 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
12004 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
12005 "address=" MACSTR "\n",
12006 wpa_s->ifname, MAC2STR(wpa_s->own_addr));
12007 if (os_snprintf_error(end - pos, ret))
12008 return pos - buf;
12009 pos += ret;
12010 }
12011
12012 return pos - buf;
12013 }
12014
12015
12016 #ifdef CONFIG_FST
12017
wpas_global_ctrl_iface_fst_attach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)12018 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
12019 char *cmd, char *buf,
12020 size_t reply_size)
12021 {
12022 char ifname[IFNAMSIZ + 1];
12023 struct fst_iface_cfg cfg;
12024 struct wpa_supplicant *wpa_s;
12025 struct fst_wpa_obj iface_obj;
12026
12027 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
12028 wpa_s = wpa_supplicant_get_iface(global, ifname);
12029 if (wpa_s) {
12030 if (wpa_s->fst) {
12031 wpa_printf(MSG_INFO, "FST: Already attached");
12032 return -1;
12033 }
12034 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
12035 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
12036 &iface_obj, &cfg);
12037 if (wpa_s->fst)
12038 return os_snprintf(buf, reply_size, "OK\n");
12039 }
12040 }
12041
12042 return -1;
12043 }
12044
12045
wpas_global_ctrl_iface_fst_detach(struct wpa_global * global,char * cmd,char * buf,size_t reply_size)12046 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
12047 char *cmd, char *buf,
12048 size_t reply_size)
12049 {
12050 char ifname[IFNAMSIZ + 1];
12051 struct wpa_supplicant *wpa_s;
12052
12053 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
12054 wpa_s = wpa_supplicant_get_iface(global, ifname);
12055 if (wpa_s) {
12056 if (!fst_iface_detach(ifname)) {
12057 wpa_s->fst = NULL;
12058 return os_snprintf(buf, reply_size, "OK\n");
12059 }
12060 }
12061 }
12062
12063 return -1;
12064 }
12065
12066 #endif /* CONFIG_FST */
12067
12068
wpa_supplicant_global_ctrl_iface_process(struct wpa_global * global,char * buf,size_t * resp_len)12069 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
12070 char *buf, size_t *resp_len)
12071 {
12072 char *reply;
12073 const int reply_size = 2048;
12074 int reply_len;
12075 int level = MSG_DEBUG;
12076
12077 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
12078 char *pos = os_strchr(buf + 7, ' ');
12079 if (pos) {
12080 *pos++ = '\0';
12081 return wpas_global_ctrl_iface_ifname(global,
12082 buf + 7, pos,
12083 resp_len);
12084 }
12085 }
12086
12087 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
12088 if (reply)
12089 return reply;
12090
12091 if (os_strcmp(buf, "PING") == 0)
12092 level = MSG_EXCESSIVE;
12093 wpa_hexdump_ascii(level, "RX global ctrl_iface",
12094 (const u8 *) buf, os_strlen(buf));
12095
12096 reply = os_malloc(reply_size);
12097 if (reply == NULL) {
12098 *resp_len = 1;
12099 return NULL;
12100 }
12101
12102 os_memcpy(reply, "OK\n", 3);
12103 reply_len = 3;
12104
12105 if (os_strcmp(buf, "PING") == 0) {
12106 os_memcpy(reply, "PONG\n", 5);
12107 reply_len = 5;
12108 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
12109 if (wpa_supplicant_global_iface_add(global, buf + 14))
12110 reply_len = -1;
12111 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
12112 if (wpa_supplicant_global_iface_remove(global, buf + 17))
12113 reply_len = -1;
12114 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
12115 reply_len = wpa_supplicant_global_iface_list(
12116 global, reply, reply_size);
12117 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
12118 reply_len = wpa_supplicant_global_iface_interfaces(
12119 global, buf + 10, reply, reply_size);
12120 #ifdef CONFIG_FST
12121 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
12122 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
12123 reply,
12124 reply_size);
12125 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
12126 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
12127 reply,
12128 reply_size);
12129 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
12130 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
12131 #endif /* CONFIG_FST */
12132 } else if (os_strcmp(buf, "TERMINATE") == 0) {
12133 wpa_supplicant_terminate_proc(global);
12134 } else if (os_strcmp(buf, "SUSPEND") == 0) {
12135 wpas_notify_suspend(global);
12136 } else if (os_strcmp(buf, "RESUME") == 0) {
12137 wpas_notify_resume(global);
12138 } else if (os_strncmp(buf, "SET ", 4) == 0) {
12139 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
12140 #ifdef CONFIG_P2P
12141 if (global->p2p_init_wpa_s) {
12142 os_free(reply);
12143 /* Check if P2P redirection would work for this
12144 * command. */
12145 return wpa_supplicant_ctrl_iface_process(
12146 global->p2p_init_wpa_s,
12147 buf, resp_len);
12148 }
12149 #endif /* CONFIG_P2P */
12150 reply_len = -1;
12151 }
12152 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
12153 if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
12154 reply_len = -1;
12155 #ifndef CONFIG_NO_CONFIG_WRITE
12156 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
12157 if (wpas_global_ctrl_iface_save_config(global))
12158 reply_len = -1;
12159 #endif /* CONFIG_NO_CONFIG_WRITE */
12160 } else if (os_strcmp(buf, "STATUS") == 0) {
12161 reply_len = wpas_global_ctrl_iface_status(global, reply,
12162 reply_size);
12163 #ifdef CONFIG_MODULE_TESTS
12164 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
12165 if (wpas_module_tests() < 0)
12166 reply_len = -1;
12167 #endif /* CONFIG_MODULE_TESTS */
12168 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
12169 if (wpa_debug_reopen_file() < 0)
12170 reply_len = -1;
12171 } else {
12172 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
12173 reply_len = 16;
12174 }
12175
12176 if (reply_len < 0) {
12177 os_memcpy(reply, "FAIL\n", 5);
12178 reply_len = 5;
12179 }
12180
12181 *resp_len = reply_len;
12182 return reply;
12183 }
12184