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