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