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