blob: e8a81182eb08130ce2f2580094b21b45cc864100 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant / Control interface (shared code for all backends)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003 * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080011#include <netinet/ip.h>
12#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013
14#include "utils/common.h"
15#include "utils/eloop.h"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080016#include "utils/uuid.h"
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -070017#include "utils/module_tests.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "common/version.h"
19#include "common/ieee802_11_defs.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070020#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "common/wpa_ctrl.h"
Roshan Pius3a1667e2018-07-03 15:17:14 -070022#ifdef CONFIG_DPP
23#include "common/dpp.h"
24#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -080025#include "common/ptksa_cache.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080026#include "crypto/tls.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080027#include "ap/hostapd.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070028#include "eap_peer/eap.h"
29#include "eapol_supp/eapol_supp_sm.h"
30#include "rsn_supp/wpa.h"
31#include "rsn_supp/preauth.h"
32#include "rsn_supp/pmksa_cache.h"
33#include "l2_packet/l2_packet.h"
34#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080035#include "fst/fst.h"
36#include "fst/fst_ctrl_iface.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037#include "config.h"
38#include "wpa_supplicant_i.h"
39#include "driver_i.h"
40#include "wps_supplicant.h"
41#include "ibss_rsn.h"
Hai Shaloma20dcd72022-02-04 13:43:00 -080042#include "wpas_glue.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "ap.h"
44#include "p2p_supplicant.h"
45#include "p2p/p2p.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070046#include "hs20_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070047#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "notify.h"
49#include "bss.h"
50#include "scan.h"
51#include "ctrl_iface.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "interworking.h"
Hai Shalom60840252021-02-19 19:02:11 -080053#include "bssid_ignore.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "autoscan.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080055#include "wnm_sta.h"
Dmitry Shmidt818ea482014-03-10 13:15:21 -070056#include "offchannel.h"
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070057#include "drivers/driver.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080058#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070059#include "dpp_supplicant.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080060#include "sme.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070061
Hai Shalomc3565922019-10-28 11:58:20 -070062#ifdef __NetBSD__
63#include <net/if_ether.h>
64#elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS)
65#include <net/ethernet.h>
66#endif
67
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070068static int wpa_supplicant_global_iface_list(struct wpa_global *global,
69 char *buf, int len);
70static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080071 const char *input,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072 char *buf, int len);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -070073static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
74 char *val);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070076
Dmitry Shmidt04949592012-07-19 12:16:46 -070077static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
78{
79 char *pos;
80 u8 addr[ETH_ALEN], *filter = NULL, *n;
81 size_t count = 0;
82
83 pos = val;
84 while (pos) {
85 if (*pos == '\0')
86 break;
87 if (hwaddr_aton(pos, addr)) {
88 os_free(filter);
89 return -1;
90 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070091 n = os_realloc_array(filter, count + 1, ETH_ALEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -070092 if (n == NULL) {
93 os_free(filter);
94 return -1;
95 }
96 filter = n;
97 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
98 count++;
99
100 pos = os_strchr(pos, ' ');
101 if (pos)
102 pos++;
103 }
104
105 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
106 os_free(wpa_s->bssid_filter);
107 wpa_s->bssid_filter = filter;
108 wpa_s->bssid_filter_count = count;
109
110 return 0;
111}
112
113
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800114static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
115{
116 char *pos;
117 u8 addr[ETH_ALEN], *bssid = NULL, *n;
118 struct wpa_ssid_value *ssid = NULL, *ns;
119 size_t count = 0, ssid_count = 0;
120 struct wpa_ssid *c;
121
122 /*
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800123 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800124 * SSID_SPEC ::= ssid <SSID_HEX>
125 * BSSID_SPEC ::= bssid <BSSID_HEX>
126 */
127
128 pos = val;
129 while (pos) {
130 if (*pos == '\0')
131 break;
132 if (os_strncmp(pos, "bssid ", 6) == 0) {
133 int res;
134 pos += 6;
135 res = hwaddr_aton2(pos, addr);
136 if (res < 0) {
137 os_free(ssid);
138 os_free(bssid);
139 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
140 "BSSID value '%s'", pos);
141 return -1;
142 }
143 pos += res;
144 n = os_realloc_array(bssid, count + 1, ETH_ALEN);
145 if (n == NULL) {
146 os_free(ssid);
147 os_free(bssid);
148 return -1;
149 }
150 bssid = n;
151 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
152 count++;
153 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
154 char *end;
155 pos += 5;
156
157 end = pos;
158 while (*end) {
159 if (*end == '\0' || *end == ' ')
160 break;
161 end++;
162 }
163
164 ns = os_realloc_array(ssid, ssid_count + 1,
165 sizeof(struct wpa_ssid_value));
166 if (ns == NULL) {
167 os_free(ssid);
168 os_free(bssid);
169 return -1;
170 }
171 ssid = ns;
172
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700173 if ((end - pos) & 0x01 ||
174 end - pos > 2 * SSID_MAX_LEN ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800175 hexstr2bin(pos, ssid[ssid_count].ssid,
176 (end - pos) / 2) < 0) {
177 os_free(ssid);
178 os_free(bssid);
179 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
180 "SSID value '%s'", pos);
181 return -1;
182 }
183 ssid[ssid_count].ssid_len = (end - pos) / 2;
184 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
185 ssid[ssid_count].ssid,
186 ssid[ssid_count].ssid_len);
187 ssid_count++;
188 pos = end;
189 } else {
190 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
191 "'%s'", pos);
192 os_free(ssid);
193 os_free(bssid);
194 return -1;
195 }
196
197 pos = os_strchr(pos, ' ');
198 if (pos)
199 pos++;
200 }
201
202 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
203 os_free(wpa_s->disallow_aps_bssid);
204 wpa_s->disallow_aps_bssid = bssid;
205 wpa_s->disallow_aps_bssid_count = count;
206
207 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
208 os_free(wpa_s->disallow_aps_ssid);
209 wpa_s->disallow_aps_ssid = ssid;
210 wpa_s->disallow_aps_ssid_count = ssid_count;
211
212 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
213 return 0;
214
215 c = wpa_s->current_ssid;
216 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
217 return 0;
218
219 if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
220 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
221 return 0;
222
223 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
224 "because current AP was marked disallowed");
225
226#ifdef CONFIG_SME
227 wpa_s->sme.prev_bssid_set = 0;
228#endif /* CONFIG_SME */
229 wpa_s->reassociate = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800230 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800231 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
232 wpa_supplicant_req_scan(wpa_s, 0, 0);
233
234 return 0;
235}
236
237
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700238#ifndef CONFIG_NO_CONFIG_BLOBS
239static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
240{
241 char *name = pos;
242 struct wpa_config_blob *blob;
243 size_t len;
244
245 pos = os_strchr(pos, ' ');
246 if (pos == NULL)
247 return -1;
248 *pos++ = '\0';
249 len = os_strlen(pos);
250 if (len & 1)
251 return -1;
252
253 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
254 blob = os_zalloc(sizeof(*blob));
255 if (blob == NULL)
256 return -1;
257 blob->name = os_strdup(name);
258 blob->data = os_malloc(len / 2);
259 if (blob->name == NULL || blob->data == NULL) {
260 wpa_config_free_blob(blob);
261 return -1;
262 }
263
264 if (hexstr2bin(pos, blob->data, len / 2) < 0) {
265 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
266 wpa_config_free_blob(blob);
267 return -1;
268 }
269 blob->len = len / 2;
270
271 wpa_config_set_blob(wpa_s->conf, blob);
272
273 return 0;
274}
275#endif /* CONFIG_NO_CONFIG_BLOBS */
276
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700277
278static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
279{
280 char *params;
281 char *pos;
282 int *freqs = NULL;
283 int ret;
284
285 if (atoi(cmd)) {
286 params = os_strchr(cmd, ' ');
287 os_free(wpa_s->manual_sched_scan_freqs);
288 if (params) {
289 params++;
290 pos = os_strstr(params, "freq=");
291 if (pos)
292 freqs = freq_range_to_channel_list(wpa_s,
293 pos + 5);
294 }
295 wpa_s->manual_sched_scan_freqs = freqs;
296 ret = wpas_start_pno(wpa_s);
297 } else {
298 ret = wpas_stop_pno(wpa_s);
299 }
300 return ret;
301}
302
303
Hai Shalom60840252021-02-19 19:02:11 -0800304static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
Ravi Joshie6ccb162015-07-16 17:45:41 -0700305{
306 union wpa_event_data event;
Hai Shalom60840252021-02-19 19:02:11 -0800307 u32 setband_mask = WPA_SETBAND_AUTO;
Ravi Joshie6ccb162015-07-16 17:45:41 -0700308
Hai Shalom60840252021-02-19 19:02:11 -0800309 /*
310 * For example:
311 * SET setband 2G,6G
312 * SET setband 5G
313 * SET setband AUTO
314 */
315 if (!os_strstr(bands, "AUTO")) {
316 if (os_strstr(bands, "5G"))
317 setband_mask |= WPA_SETBAND_5G;
318 if (os_strstr(bands, "6G"))
319 setband_mask |= WPA_SETBAND_6G;
320 if (os_strstr(bands, "2G"))
321 setband_mask |= WPA_SETBAND_2G;
322 if (setband_mask == WPA_SETBAND_AUTO)
323 return -1;
324 }
Ravi Joshie6ccb162015-07-16 17:45:41 -0700325
Hai Shalom60840252021-02-19 19:02:11 -0800326 wpa_s->setband_mask = setband_mask;
327 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
Ravi Joshie6ccb162015-07-16 17:45:41 -0700328 os_memset(&event, 0, sizeof(event));
329 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
330 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
331 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
332 }
333
334 return 0;
335}
336
337
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700338static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
339 const char *cmd)
340{
341 struct wpabuf *lci;
342
343 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
344 wpabuf_free(wpa_s->lci);
345 wpa_s->lci = NULL;
346 return 0;
347 }
348
349 lci = wpabuf_parse_bin(cmd);
350 if (!lci)
351 return -1;
352
353 if (os_get_reltime(&wpa_s->lci_time)) {
354 wpabuf_free(lci);
355 return -1;
356 }
357
358 wpabuf_free(wpa_s->lci);
359 wpa_s->lci = lci;
360
361 return 0;
362}
363
364
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800365static int
366wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
367{
368 int relative_rssi;
369
370 if (os_strcmp(cmd, "disable") == 0) {
371 wpa_s->srp.relative_rssi_set = 0;
372 return 0;
373 }
374
375 relative_rssi = atoi(cmd);
376 if (relative_rssi < 0 || relative_rssi > 100)
377 return -1;
378 wpa_s->srp.relative_rssi = relative_rssi;
379 wpa_s->srp.relative_rssi_set = 1;
380 return 0;
381}
382
383
384static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
385 const char *cmd)
386{
387 char *pos;
388 int adjust_rssi;
389
390 /* <band>:adjust_value */
391 pos = os_strchr(cmd, ':');
392 if (!pos)
393 return -1;
394 pos++;
395 adjust_rssi = atoi(pos);
396 if (adjust_rssi < -100 || adjust_rssi > 100)
397 return -1;
398
399 if (os_strncmp(cmd, "2G", 2) == 0)
400 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
401 else if (os_strncmp(cmd, "5G", 2) == 0)
402 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
403 else
404 return -1;
405
406 wpa_s->srp.relative_adjust_rssi = adjust_rssi;
407
408 return 0;
409}
410
411
412static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
413 const char *cmd)
414{
415 struct wpabuf *ric_ies;
416
417 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
418 wpabuf_free(wpa_s->ric_ies);
419 wpa_s->ric_ies = NULL;
420 return 0;
421 }
422
423 ric_ies = wpabuf_parse_bin(cmd);
424 if (!ric_ies)
425 return -1;
426
427 wpabuf_free(wpa_s->ric_ies);
428 wpa_s->ric_ies = ric_ies;
429
430 return 0;
431}
432
433
Hai Shalomfdcde762020-04-02 11:19:20 -0700434#ifdef CONFIG_TESTING_OPTIONS
435static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
436 const char *val)
437{
438 u8 bssid[ETH_ALEN];
439 const char *pos = val;
440 struct driver_signal_override *dso = NULL, *tmp, parsed;
441
442 if (hwaddr_aton(pos, bssid))
443 return -1;
444 pos = os_strchr(pos, ' ');
445
446 dl_list_for_each(tmp, &wpa_s->drv_signal_override,
447 struct driver_signal_override, list) {
448 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
449 dso = tmp;
450 break;
451 }
452 }
453
454 if (!pos) {
455 /* Remove existing entry */
456 if (dso) {
457 dl_list_del(&dso->list);
458 os_free(dso);
459 }
460 return 0;
461 }
462 pos++;
463
464 /* Update an existing entry or add a new one */
465 os_memset(&parsed, 0, sizeof(parsed));
466 if (sscanf(pos, "%d %d %d %d %d",
467 &parsed.si_current_signal,
468 &parsed.si_avg_signal,
469 &parsed.si_avg_beacon_signal,
470 &parsed.si_current_noise,
471 &parsed.scan_level) != 5)
472 return -1;
473
474 if (!dso) {
475 dso = os_zalloc(sizeof(*dso));
476 if (!dso)
477 return -1;
478 os_memcpy(dso->bssid, bssid, ETH_ALEN);
479 dl_list_add(&wpa_s->drv_signal_override, &dso->list);
480 }
481 dso->si_current_signal = parsed.si_current_signal;
482 dso->si_avg_signal = parsed.si_avg_signal;
483 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
484 dso->si_current_noise = parsed.si_current_noise;
485 dso->scan_level = parsed.scan_level;
486
487 return 0;
488}
489#endif /* CONFIG_TESTING_OPTIONS */
490
491
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700492static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
493 char *cmd)
494{
495 char *value;
496 int ret = 0;
497
498 value = os_strchr(cmd, ' ');
499 if (value == NULL)
500 return -1;
501 *value++ = '\0';
502
503 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
504 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
505 eapol_sm_configure(wpa_s->eapol,
506 atoi(value), -1, -1, -1);
507 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
508 eapol_sm_configure(wpa_s->eapol,
509 -1, atoi(value), -1, -1);
510 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
511 eapol_sm_configure(wpa_s->eapol,
512 -1, -1, atoi(value), -1);
513 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
514 eapol_sm_configure(wpa_s->eapol,
515 -1, -1, -1, atoi(value));
Hai Shaloma20dcd72022-02-04 13:43:00 -0800516#ifdef CONFIG_TESTING_OPTIONS
517 } else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
518 if (os_strcmp(value, "Auto") == 0)
519 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
520 else if (os_strcmp(value, "ForceUnauthorized") == 0)
521 eapol_sm_notify_portControl(wpa_s->eapol,
522 ForceUnauthorized);
523 else if (os_strcmp(value, "ForceAuthorized") == 0)
524 eapol_sm_notify_portControl(wpa_s->eapol,
525 ForceAuthorized);
526 else
527 ret = -1;
528#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
530 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
Paul Stewart092955c2017-02-06 09:13:09 -0800531 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800533 } else {
534 value[-1] = '=';
535 wpa_config_process_global(wpa_s->conf, cmd, -1);
536 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
538 0) {
539 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
Paul Stewart092955c2017-02-06 09:13:09 -0800540 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800542 } else {
543 value[-1] = '=';
544 wpa_config_process_global(wpa_s->conf, cmd, -1);
545 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
Paul Stewart092955c2017-02-06 09:13:09 -0800547 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
548 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800550 } else {
551 value[-1] = '=';
552 wpa_config_process_global(wpa_s->conf, cmd, -1);
553 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
555 wpa_s->wps_fragment_size = atoi(value);
556#ifdef CONFIG_WPS_TESTING
557 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
558 long int val;
559 val = strtol(value, NULL, 0);
560 if (val < 0 || val > 0xff) {
561 ret = -1;
562 wpa_printf(MSG_DEBUG, "WPS: Invalid "
563 "wps_version_number %ld", val);
564 } else {
565 wps_version_number = val;
566 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
567 "version %u.%u",
568 (wps_version_number & 0xf0) >> 4,
569 wps_version_number & 0x0f);
570 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800571 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
572 wps_testing_stub_cred = atoi(value);
573 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
574 wps_testing_stub_cred);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800575 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
576 wps_corrupt_pkhash = atoi(value);
577 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
578 wps_corrupt_pkhash);
Dmitry Shmidtde47be72016-01-07 12:52:55 -0800579 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
580 if (value[0] == '\0') {
581 wps_force_auth_types_in_use = 0;
582 } else {
583 wps_force_auth_types = strtol(value, NULL, 0);
584 wps_force_auth_types_in_use = 1;
585 }
586 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
587 if (value[0] == '\0') {
588 wps_force_encr_types_in_use = 0;
589 } else {
590 wps_force_encr_types = strtol(value, NULL, 0);
591 wps_force_encr_types_in_use = 1;
592 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593#endif /* CONFIG_WPS_TESTING */
594 } else if (os_strcasecmp(cmd, "ampdu") == 0) {
595 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
596 ret = -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800597#ifdef CONFIG_TDLS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598#ifdef CONFIG_TDLS_TESTING
599 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700600 tdls_testing = strtol(value, NULL, 0);
601 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
602#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
604 int disabled = atoi(value);
605 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
606 if (disabled) {
607 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
608 ret = -1;
609 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
610 ret = -1;
611 wpa_tdls_enable(wpa_s->wpa, !disabled);
612#endif /* CONFIG_TDLS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800613 } else if (os_strcasecmp(cmd, "pno") == 0) {
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700614 ret = wpas_ctrl_pno(wpa_s, value);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700615 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
616 int disabled = atoi(value);
617 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
618 ret = -1;
619 else if (disabled)
620 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
621 } else if (os_strcasecmp(cmd, "uapsd") == 0) {
622 if (os_strcmp(value, "disable") == 0)
623 wpa_s->set_sta_uapsd = 0;
624 else {
625 int be, bk, vi, vo;
626 char *pos;
627 /* format: BE,BK,VI,VO;max SP Length */
628 be = atoi(value);
629 pos = os_strchr(value, ',');
630 if (pos == NULL)
631 return -1;
632 pos++;
633 bk = atoi(pos);
634 pos = os_strchr(pos, ',');
635 if (pos == NULL)
636 return -1;
637 pos++;
638 vi = atoi(pos);
639 pos = os_strchr(pos, ',');
640 if (pos == NULL)
641 return -1;
642 pos++;
643 vo = atoi(pos);
644 /* ignore max SP Length for now */
645
646 wpa_s->set_sta_uapsd = 1;
647 wpa_s->sta_uapsd = 0;
648 if (be)
649 wpa_s->sta_uapsd |= BIT(0);
650 if (bk)
651 wpa_s->sta_uapsd |= BIT(1);
652 if (vi)
653 wpa_s->sta_uapsd |= BIT(2);
654 if (vo)
655 wpa_s->sta_uapsd |= BIT(3);
656 }
Jouni Malinen21d6bc82012-04-10 16:17:59 -0700657 } else if (os_strcasecmp(cmd, "ps") == 0) {
658 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700659#ifdef CONFIG_WIFI_DISPLAY
660 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
Dmitry Shmidted003d22014-02-06 10:09:12 -0800661 int enabled = !!atoi(value);
662 if (enabled && !wpa_s->global->p2p)
663 ret = -1;
664 else
665 wifi_display_enable(wpa_s->global, enabled);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700666#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700667 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
668 ret = set_bssid_filter(wpa_s, value);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800669 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
670 ret = set_disallow_aps(wpa_s, value);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800671 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
672 wpa_s->no_keep_alive = !!atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673#ifdef CONFIG_DPP
674 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
675 os_free(wpa_s->dpp_configurator_params);
676 wpa_s->dpp_configurator_params = os_strdup(value);
Sunil Ravia04bd252022-05-02 22:54:18 -0700677#ifdef CONFIG_DPP2
678 dpp_controller_set_params(wpa_s->dpp, value);
679#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
681 wpa_s->dpp_init_max_tries = atoi(value);
682 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
683 wpa_s->dpp_init_retry_time = atoi(value);
684 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
685 wpa_s->dpp_resp_wait_time = atoi(value);
686 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
687 wpa_s->dpp_resp_max_tries = atoi(value);
688 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
689 wpa_s->dpp_resp_retry_time = atoi(value);
690#ifdef CONFIG_TESTING_OPTIONS
691 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
692 if (hwaddr_aton(value, dpp_pkex_own_mac_override))
693 ret = -1;
694 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
695 if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
696 ret = -1;
697 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
698 size_t hex_len = os_strlen(value);
699
700 if (hex_len >
701 2 * sizeof(dpp_pkex_ephemeral_key_override))
702 ret = -1;
703 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
704 hex_len / 2))
705 ret = -1;
706 else
707 dpp_pkex_ephemeral_key_override_len = hex_len / 2;
708 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
709 size_t hex_len = os_strlen(value);
710
711 if (hex_len > 2 * sizeof(dpp_protocol_key_override))
712 ret = -1;
713 else if (hexstr2bin(value, dpp_protocol_key_override,
714 hex_len / 2))
715 ret = -1;
716 else
717 dpp_protocol_key_override_len = hex_len / 2;
718 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
719 size_t hex_len = os_strlen(value);
720
721 if (hex_len > 2 * sizeof(dpp_nonce_override))
722 ret = -1;
723 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
724 ret = -1;
725 else
726 dpp_nonce_override_len = hex_len / 2;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700727 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
728 dpp_version_override = atoi(value);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700729#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700730#endif /* CONFIG_DPP */
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700731#ifdef CONFIG_TESTING_OPTIONS
732 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
733 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800734 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
735 wpa_s->ext_eapol_frame_io = !!atoi(value);
736#ifdef CONFIG_AP
737 if (wpa_s->ap_iface) {
738 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
739 wpa_s->ext_eapol_frame_io;
740 }
741#endif /* CONFIG_AP */
742 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
743 wpa_s->extra_roc_dur = atoi(value);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800744 } else if (os_strcasecmp(cmd, "test_failure") == 0) {
745 wpa_s->test_failure = atoi(value);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800746 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
747 wpa_s->p2p_go_csa_on_inv = !!atoi(value);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700748 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
749 wpa_s->ignore_auth_resp = !!atoi(value);
750 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
751 wpa_s->ignore_assoc_disallow = !!atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700752 wpa_drv_ignore_assoc_disallow(wpa_s,
753 wpa_s->ignore_assoc_disallow);
Hai Shalomfdcde762020-04-02 11:19:20 -0700754 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
755 wpa_s->disable_sa_query = !!atoi(value);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800756 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
757 wpa_s->ignore_sae_h2e_only = !!atoi(value);
758 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
759 char *pos;
760
761 os_free(wpa_s->extra_sae_rejected_groups);
762 wpa_s->extra_sae_rejected_groups = NULL;
763 pos = value;
764 while (pos && pos[0]) {
765 int group;
766
767 group = atoi(pos);
768 wpa_printf(MSG_DEBUG,
769 "TESTING: Extra rejection of SAE group %d",
770 group);
771 if (group)
772 int_array_add_unique(
773 &wpa_s->extra_sae_rejected_groups,
774 group);
775 pos = os_strchr(pos, ' ');
776 if (!pos)
777 break;
778 pos++;
779 }
Hai Shalomb755a2a2020-04-23 21:49:02 -0700780 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
781 wpa_s->ft_rsnxe_used = atoi(value);
Hai Shalom899fcc72020-10-19 14:38:18 -0700782 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
783 wpa_s->oci_freq_override_eapol = atoi(value);
784 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
785 wpa_s->oci_freq_override_saquery_req = atoi(value);
786 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
787 wpa_s->oci_freq_override_saquery_resp = atoi(value);
788 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
789 wpa_s->oci_freq_override_eapol_g2 = atoi(value);
790 /* Populate value to wpa_sm if already associated. */
791 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
792 wpa_s->oci_freq_override_eapol_g2);
793 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
794 wpa_s->oci_freq_override_ft_assoc = atoi(value);
795 /* Populate value to wpa_sm if already associated. */
796 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
797 wpa_s->oci_freq_override_ft_assoc);
798 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
799 wpa_s->oci_freq_override_fils_assoc = atoi(value);
800 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
801 wpa_s->oci_freq_override_wnm_sleep = atoi(value);
Hai Shalomfdcde762020-04-02 11:19:20 -0700802 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
803 wpabuf_free(wpa_s->rsne_override_eapol);
804 if (os_strcmp(value, "NULL") == 0)
805 wpa_s->rsne_override_eapol = NULL;
806 else
807 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800808 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
809 wpabuf_free(wpa_s->rsnxe_override_assoc);
810 if (os_strcmp(value, "NULL") == 0)
811 wpa_s->rsnxe_override_assoc = NULL;
812 else
813 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
814 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
815 wpabuf_free(wpa_s->rsnxe_override_eapol);
816 if (os_strcmp(value, "NULL") == 0)
817 wpa_s->rsnxe_override_eapol = NULL;
818 else
819 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700820 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
821 wpa_s->reject_btm_req_reason = atoi(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800822 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
823 os_free(wpa_s->get_pref_freq_list_override);
824 if (!value[0])
825 wpa_s->get_pref_freq_list_override = NULL;
826 else
827 wpa_s->get_pref_freq_list_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700828 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
829 wpabuf_free(wpa_s->sae_commit_override);
830 if (value[0] == '\0')
831 wpa_s->sae_commit_override = NULL;
832 else
833 wpa_s->sae_commit_override = wpabuf_parse_bin(value);
Hai Shalomfdcde762020-04-02 11:19:20 -0700834 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
835 ret = wpas_ctrl_iface_set_dso(wpa_s, value);
Jimmy Chenaace8cd2021-04-13 14:55:52 +0800836 } else if (os_strcasecmp(cmd, "force_hunting_and_pecking_pwe") == 0) {
837 wpa_s->force_hunting_and_pecking_pwe = (atoi(value) != 0) ? 1 : 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800838 } else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
839 wpa_s->disable_scs_support = !!atoi(value);
840 } else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
841 wpa_s->disable_mscs_support = !!atoi(value);
Sunil Ravia04bd252022-05-02 22:54:18 -0700842 } else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
843 wpa_s->disable_eapol_g2_tx = !!atoi(value);
844 /* Populate value to wpa_sm if already associated. */
845 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
846 wpa_s->disable_eapol_g2_tx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700847#ifdef CONFIG_DPP
848 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
849 os_free(wpa_s->dpp_config_obj_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700850 if (value[0] == '\0')
851 wpa_s->dpp_config_obj_override = NULL;
852 else
853 wpa_s->dpp_config_obj_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700854 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
855 os_free(wpa_s->dpp_discovery_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700856 if (value[0] == '\0')
857 wpa_s->dpp_discovery_override = NULL;
858 else
859 wpa_s->dpp_discovery_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700860 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
861 os_free(wpa_s->dpp_groups_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700862 if (value[0] == '\0')
863 wpa_s->dpp_groups_override = NULL;
864 else
865 wpa_s->dpp_groups_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700866 } else if (os_strcasecmp(cmd,
867 "dpp_ignore_netaccesskey_mismatch") == 0) {
868 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700869 } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
870 dpp_test = atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700871#endif /* CONFIG_DPP */
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700872#endif /* CONFIG_TESTING_OPTIONS */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700873#ifdef CONFIG_FILS
874 } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
875 wpa_s->disable_fils = !!atoi(value);
876 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
877 wpa_supplicant_set_default_scan_ies(wpa_s);
878#endif /* CONFIG_FILS */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700879#ifndef CONFIG_NO_CONFIG_BLOBS
880 } else if (os_strcmp(cmd, "blob") == 0) {
881 ret = wpas_ctrl_set_blob(wpa_s, value);
882#endif /* CONFIG_NO_CONFIG_BLOBS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800883 } else if (os_strcasecmp(cmd, "setband") == 0) {
Ravi Joshie6ccb162015-07-16 17:45:41 -0700884 ret = wpas_ctrl_set_band(wpa_s, value);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800885#ifdef CONFIG_MBO
886 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
887 ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
Paul Stewart092955c2017-02-06 09:13:09 -0800888 if (ret == 0) {
889 value[-1] = '=';
890 wpa_config_process_global(wpa_s->conf, cmd, -1);
891 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800892 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
893 wpas_mbo_update_cell_capa(wpa_s, atoi(value));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700894 } else if (os_strcasecmp(cmd, "oce") == 0) {
895 wpa_s->conf->oce = atoi(value);
896 if (wpa_s->conf->oce) {
897 if ((wpa_s->conf->oce & OCE_STA) &&
898 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
899 wpa_s->enable_oce = OCE_STA;
900
901 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
902 (wpa_s->drv_flags &
903 WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
904 /* TODO: Need to add STA-CFON support */
905 wpa_printf(MSG_ERROR,
906 "OCE STA-CFON feature is not yet supported");
907 return -1;
908 }
909 } else {
910 wpa_s->enable_oce = 0;
911 }
912 wpa_supplicant_set_default_scan_ies(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800913#endif /* CONFIG_MBO */
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700914 } else if (os_strcasecmp(cmd, "lci") == 0) {
915 ret = wpas_ctrl_iface_set_lci(wpa_s, value);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800916 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
917 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800918 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
919 ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
920 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
921 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
922 } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
923 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700924 } else if (os_strcasecmp(cmd, "roaming") == 0) {
925 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800926#ifdef CONFIG_WNM
927 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
928 struct wpabuf *elems;
929
930 elems = wpabuf_parse_bin(value);
931 if (!elems)
932 return -1;
933 wnm_set_coloc_intf_elems(wpa_s, elems);
934#endif /* CONFIG_WNM */
Hai Shaloma20dcd72022-02-04 13:43:00 -0800935 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
936 wpa_s->enable_dscp_policy_capa = !!atoi(value);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700937 } else {
938 value[-1] = '=';
939 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
940 if (ret == 0)
941 wpa_supplicant_update_config(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -0700942 else if (ret == 1)
943 ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700944 }
945
946 return ret;
947}
948
949
950static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
951 char *cmd, char *buf, size_t buflen)
952{
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700953 int res = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700954
955 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
956
957 if (os_strcmp(cmd, "version") == 0) {
958 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700959 } else if (os_strcasecmp(cmd, "max_command_len") == 0) {
960 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700961 } else if (os_strcasecmp(cmd, "country") == 0) {
962 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
963 res = os_snprintf(buf, buflen, "%c%c",
964 wpa_s->conf->country[0],
965 wpa_s->conf->country[1]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700966#ifdef CONFIG_WIFI_DISPLAY
967 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
Dmitry Shmidted003d22014-02-06 10:09:12 -0800968 int enabled;
969 if (wpa_s->global->p2p == NULL ||
970 wpa_s->global->p2p_disabled)
971 enabled = 0;
972 else
973 enabled = wpa_s->global->wifi_display;
974 res = os_snprintf(buf, buflen, "%d", enabled);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700975#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700976#ifdef CONFIG_TESTING_GET_GTK
977 } else if (os_strcmp(cmd, "gtk") == 0) {
978 if (wpa_s->last_gtk_len == 0)
979 return -1;
980 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
981 wpa_s->last_gtk_len);
982 return res;
983#endif /* CONFIG_TESTING_GET_GTK */
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800984 } else if (os_strcmp(cmd, "tls_library") == 0) {
985 res = tls_get_library_version(buf, buflen);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700986#ifdef CONFIG_TESTING_OPTIONS
987 } else if (os_strcmp(cmd, "anonce") == 0) {
988 return wpa_snprintf_hex(buf, buflen,
989 wpa_sm_get_anonce(wpa_s->wpa),
990 WPA_NONCE_LEN);
Hai Shalomfdcde762020-04-02 11:19:20 -0700991 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
992 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700993#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800994 } else {
995 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 }
997
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800998 if (os_snprintf_error(buflen, res))
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700999 return -1;
1000 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001}
1002
1003
1004#ifdef IEEE8021X_EAPOL
1005static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1006 char *addr)
1007{
1008 u8 bssid[ETH_ALEN];
1009 struct wpa_ssid *ssid = wpa_s->current_ssid;
1010
1011 if (hwaddr_aton(addr, bssid)) {
1012 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1013 "'%s'", addr);
1014 return -1;
1015 }
1016
1017 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1018 rsn_preauth_deinit(wpa_s->wpa);
1019 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1020 return -1;
1021
1022 return 0;
1023}
1024#endif /* IEEE8021X_EAPOL */
1025
1026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027#ifdef CONFIG_TDLS
1028
1029static int wpa_supplicant_ctrl_iface_tdls_discover(
1030 struct wpa_supplicant *wpa_s, char *addr)
1031{
1032 u8 peer[ETH_ALEN];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001033 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034
1035 if (hwaddr_aton(addr, peer)) {
1036 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1037 "address '%s'", addr);
1038 return -1;
1039 }
1040
1041 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1042 MAC2STR(peer));
1043
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001044 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1045 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1046 else
1047 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1048
1049 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050}
1051
1052
1053static int wpa_supplicant_ctrl_iface_tdls_setup(
1054 struct wpa_supplicant *wpa_s, char *addr)
1055{
1056 u8 peer[ETH_ALEN];
1057 int ret;
1058
1059 if (hwaddr_aton(addr, peer)) {
1060 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1061 "address '%s'", addr);
1062 return -1;
1063 }
1064
1065 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1066 MAC2STR(peer));
1067
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001068 if ((wpa_s->conf->tdls_external_control) &&
1069 wpa_tdls_is_external_setup(wpa_s->wpa))
1070 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1071
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001072 wpa_tdls_remove(wpa_s->wpa, peer);
1073
1074 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1075 ret = wpa_tdls_start(wpa_s->wpa, peer);
1076 else
1077 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079 return ret;
1080}
1081
1082
1083static int wpa_supplicant_ctrl_iface_tdls_teardown(
1084 struct wpa_supplicant *wpa_s, char *addr)
1085{
1086 u8 peer[ETH_ALEN];
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001087 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001089 if (os_strcmp(addr, "*") == 0) {
1090 /* remove everyone */
1091 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1092 wpa_tdls_teardown_peers(wpa_s->wpa);
1093 return 0;
1094 }
1095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 if (hwaddr_aton(addr, peer)) {
1097 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1098 "address '%s'", addr);
1099 return -1;
1100 }
1101
1102 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1103 MAC2STR(peer));
1104
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001105 if ((wpa_s->conf->tdls_external_control) &&
1106 wpa_tdls_is_external_setup(wpa_s->wpa))
1107 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1108
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001109 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1110 ret = wpa_tdls_teardown_link(
1111 wpa_s->wpa, peer,
1112 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1113 else
1114 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1115
1116 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117}
1118
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001119
1120static int ctrl_iface_get_capability_tdls(
1121 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1122{
1123 int ret;
1124
1125 ret = os_snprintf(buf, buflen, "%s\n",
1126 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1127 (wpa_s->drv_flags &
1128 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1129 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001130 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001131 return -1;
1132 return ret;
1133}
1134
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001135
1136static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1137 struct wpa_supplicant *wpa_s, char *cmd)
1138{
1139 u8 peer[ETH_ALEN];
1140 struct hostapd_freq_params freq_params;
1141 u8 oper_class;
1142 char *pos, *end;
1143
1144 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1145 wpa_printf(MSG_INFO,
1146 "tdls_chanswitch: Only supported with external setup");
1147 return -1;
1148 }
1149
1150 os_memset(&freq_params, 0, sizeof(freq_params));
1151
1152 pos = os_strchr(cmd, ' ');
1153 if (pos == NULL)
1154 return -1;
1155 *pos++ = '\0';
1156
1157 oper_class = strtol(pos, &end, 10);
1158 if (pos == end) {
1159 wpa_printf(MSG_INFO,
1160 "tdls_chanswitch: Invalid op class provided");
1161 return -1;
1162 }
1163
1164 pos = end;
1165 freq_params.freq = atoi(pos);
1166 if (freq_params.freq == 0) {
1167 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1168 return -1;
1169 }
1170
1171#define SET_FREQ_SETTING(str) \
1172 do { \
1173 const char *pos2 = os_strstr(pos, " " #str "="); \
1174 if (pos2) { \
1175 pos2 += sizeof(" " #str "=") - 1; \
1176 freq_params.str = atoi(pos2); \
1177 } \
1178 } while (0)
1179
1180 SET_FREQ_SETTING(center_freq1);
1181 SET_FREQ_SETTING(center_freq2);
1182 SET_FREQ_SETTING(bandwidth);
1183 SET_FREQ_SETTING(sec_channel_offset);
1184#undef SET_FREQ_SETTING
1185
1186 freq_params.ht_enabled = !!os_strstr(pos, " ht");
1187 freq_params.vht_enabled = !!os_strstr(pos, " vht");
1188
1189 if (hwaddr_aton(cmd, peer)) {
1190 wpa_printf(MSG_DEBUG,
1191 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1192 cmd);
1193 return -1;
1194 }
1195
1196 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1197 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1198 MAC2STR(peer), oper_class, freq_params.freq,
1199 freq_params.center_freq1, freq_params.center_freq2,
1200 freq_params.bandwidth, freq_params.sec_channel_offset,
1201 freq_params.ht_enabled ? " HT" : "",
1202 freq_params.vht_enabled ? " VHT" : "");
1203
1204 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1205 &freq_params);
1206}
1207
1208
1209static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1210 struct wpa_supplicant *wpa_s, char *cmd)
1211{
1212 u8 peer[ETH_ALEN];
1213
1214 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1215 wpa_printf(MSG_INFO,
1216 "tdls_chanswitch: Only supported with external setup");
1217 return -1;
1218 }
1219
1220 if (hwaddr_aton(cmd, peer)) {
1221 wpa_printf(MSG_DEBUG,
1222 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1223 cmd);
1224 return -1;
1225 }
1226
1227 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1228 MAC2STR(peer));
1229
1230 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1231}
1232
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07001233
1234static int wpa_supplicant_ctrl_iface_tdls_link_status(
1235 struct wpa_supplicant *wpa_s, const char *addr,
1236 char *buf, size_t buflen)
1237{
1238 u8 peer[ETH_ALEN];
1239 const char *tdls_status;
1240 int ret;
1241
1242 if (hwaddr_aton(addr, peer)) {
1243 wpa_printf(MSG_DEBUG,
1244 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1245 addr);
1246 return -1;
1247 }
1248 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1249 MAC2STR(peer));
1250
1251 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1252 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1253 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1254 if (os_snprintf_error(buflen, ret))
1255 return -1;
1256
1257 return ret;
1258}
1259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001260#endif /* CONFIG_TDLS */
1261
1262
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001263static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1264{
1265 char *token, *context = NULL;
1266 struct wmm_ac_ts_setup_params params = {
1267 .tsid = 0xff,
1268 .direction = 0xff,
1269 };
1270
1271 while ((token = str_token(cmd, " ", &context))) {
1272 if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1273 sscanf(token, "up=%i", &params.user_priority) == 1 ||
1274 sscanf(token, "nominal_msdu_size=%i",
1275 &params.nominal_msdu_size) == 1 ||
1276 sscanf(token, "mean_data_rate=%i",
1277 &params.mean_data_rate) == 1 ||
1278 sscanf(token, "min_phy_rate=%i",
1279 &params.minimum_phy_rate) == 1 ||
1280 sscanf(token, "sba=%i",
1281 &params.surplus_bandwidth_allowance) == 1)
1282 continue;
1283
1284 if (os_strcasecmp(token, "downlink") == 0) {
1285 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1286 } else if (os_strcasecmp(token, "uplink") == 0) {
1287 params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1288 } else if (os_strcasecmp(token, "bidi") == 0) {
1289 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1290 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1291 params.fixed_nominal_msdu = 1;
1292 } else {
1293 wpa_printf(MSG_DEBUG,
1294 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1295 token);
1296 return -1;
1297 }
1298
1299 }
1300
1301 return wpas_wmm_ac_addts(wpa_s, &params);
1302}
1303
1304
1305static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1306{
1307 u8 tsid = atoi(cmd);
1308
1309 return wpas_wmm_ac_delts(wpa_s, tsid);
1310}
1311
1312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313#ifdef CONFIG_IEEE80211R
1314static int wpa_supplicant_ctrl_iface_ft_ds(
1315 struct wpa_supplicant *wpa_s, char *addr)
1316{
1317 u8 target_ap[ETH_ALEN];
1318 struct wpa_bss *bss;
1319 const u8 *mdie;
1320
1321 if (hwaddr_aton(addr, target_ap)) {
1322 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1323 "address '%s'", addr);
1324 return -1;
1325 }
1326
1327 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1328
1329 bss = wpa_bss_get_bssid(wpa_s, target_ap);
1330 if (bss)
1331 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1332 else
1333 mdie = NULL;
1334
1335 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
1336}
1337#endif /* CONFIG_IEEE80211R */
1338
1339
1340#ifdef CONFIG_WPS
1341static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1342 char *cmd)
1343{
1344 u8 bssid[ETH_ALEN], *_bssid = bssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001345#ifdef CONFIG_P2P
1346 u8 p2p_dev_addr[ETH_ALEN];
1347#endif /* CONFIG_P2P */
1348#ifdef CONFIG_AP
1349 u8 *_p2p_dev_addr = NULL;
1350#endif /* CONFIG_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001351 char *pos;
1352 int multi_ap = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001353
Hai Shalom021b0b52019-04-10 11:17:58 -07001354 if (!cmd || os_strcmp(cmd, "any") == 0 ||
1355 os_strncmp(cmd, "any ", 4) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356 _bssid = NULL;
1357#ifdef CONFIG_P2P
1358 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1359 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1360 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1361 "P2P Device Address '%s'",
1362 cmd + 13);
1363 return -1;
1364 }
1365 _p2p_dev_addr = p2p_dev_addr;
1366#endif /* CONFIG_P2P */
Hai Shalom021b0b52019-04-10 11:17:58 -07001367 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1368 _bssid = NULL;
1369 multi_ap = atoi(cmd + 9);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370 } else if (hwaddr_aton(cmd, bssid)) {
1371 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1372 cmd);
1373 return -1;
1374 }
1375
Hai Shalom021b0b52019-04-10 11:17:58 -07001376 if (cmd) {
1377 pos = os_strstr(cmd, " multi_ap=");
1378 if (pos) {
1379 pos += 10;
1380 multi_ap = atoi(pos);
1381 }
1382 }
1383
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001384#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385 if (wpa_s->ap_iface)
1386 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1387#endif /* CONFIG_AP */
1388
Hai Shalom021b0b52019-04-10 11:17:58 -07001389 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390}
1391
1392
1393static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1394 char *cmd, char *buf,
1395 size_t buflen)
1396{
1397 u8 bssid[ETH_ALEN], *_bssid = bssid;
1398 char *pin;
1399 int ret;
1400
1401 pin = os_strchr(cmd, ' ');
1402 if (pin)
1403 *pin++ = '\0';
1404
1405 if (os_strcmp(cmd, "any") == 0)
1406 _bssid = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001407 else if (os_strcmp(cmd, "get") == 0) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001408 if (wps_generate_pin((unsigned int *) &ret) < 0)
1409 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001410 goto done;
1411 } else if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1413 cmd);
1414 return -1;
1415 }
1416
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001417#ifdef CONFIG_AP
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001418 if (wpa_s->ap_iface) {
1419 int timeout = 0;
1420 char *pos;
1421
1422 if (pin) {
1423 pos = os_strchr(pin, ' ');
1424 if (pos) {
1425 *pos++ = '\0';
1426 timeout = atoi(pos);
1427 }
1428 }
1429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001431 buf, buflen, timeout);
1432 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433#endif /* CONFIG_AP */
1434
1435 if (pin) {
1436 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1437 DEV_PW_DEFAULT);
1438 if (ret < 0)
1439 return -1;
1440 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001441 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 return -1;
1443 return ret;
1444 }
1445
1446 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1447 if (ret < 0)
1448 return -1;
1449
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001450done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451 /* Return the generated PIN */
1452 ret = os_snprintf(buf, buflen, "%08d", ret);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001453 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454 return -1;
1455 return ret;
1456}
1457
1458
1459static int wpa_supplicant_ctrl_iface_wps_check_pin(
1460 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1461{
1462 char pin[9];
1463 size_t len;
1464 char *pos;
1465 int ret;
1466
1467 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1468 (u8 *) cmd, os_strlen(cmd));
1469 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1470 if (*pos < '0' || *pos > '9')
1471 continue;
1472 pin[len++] = *pos;
1473 if (len == 9) {
1474 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1475 return -1;
1476 }
1477 }
1478 if (len != 4 && len != 8) {
1479 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1480 return -1;
1481 }
1482 pin[len] = '\0';
1483
1484 if (len == 8) {
1485 unsigned int pin_val;
1486 pin_val = atoi(pin);
1487 if (!wps_pin_valid(pin_val)) {
1488 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1489 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001490 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 return -1;
1492 return ret;
1493 }
1494 }
1495
1496 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001497 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 return -1;
1499
1500 return ret;
1501}
1502
1503
Dmitry Shmidt04949592012-07-19 12:16:46 -07001504#ifdef CONFIG_WPS_NFC
1505
1506static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1507 char *cmd)
1508{
1509 u8 bssid[ETH_ALEN], *_bssid = bssid;
1510
1511 if (cmd == NULL || cmd[0] == '\0')
1512 _bssid = NULL;
1513 else if (hwaddr_aton(cmd, bssid))
1514 return -1;
1515
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001516 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1517 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001518}
1519
1520
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001521static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1522 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1523{
1524 int ndef;
1525 struct wpabuf *buf;
1526 int res;
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001527 char *pos;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001528
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001529 pos = os_strchr(cmd, ' ');
1530 if (pos)
1531 *pos++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001532 if (os_strcmp(cmd, "WPS") == 0)
1533 ndef = 0;
1534 else if (os_strcmp(cmd, "NDEF") == 0)
1535 ndef = 1;
1536 else
1537 return -1;
1538
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001539 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001540 if (buf == NULL)
1541 return -1;
1542
1543 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1544 wpabuf_len(buf));
1545 reply[res++] = '\n';
1546 reply[res] = '\0';
1547
1548 wpabuf_free(buf);
1549
1550 return res;
1551}
1552
1553
Dmitry Shmidt04949592012-07-19 12:16:46 -07001554static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1555 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1556{
1557 int ndef;
1558 struct wpabuf *buf;
1559 int res;
1560
1561 if (os_strcmp(cmd, "WPS") == 0)
1562 ndef = 0;
1563 else if (os_strcmp(cmd, "NDEF") == 0)
1564 ndef = 1;
1565 else
1566 return -1;
1567
1568 buf = wpas_wps_nfc_token(wpa_s, ndef);
1569 if (buf == NULL)
1570 return -1;
1571
1572 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1573 wpabuf_len(buf));
1574 reply[res++] = '\n';
1575 reply[res] = '\0';
1576
1577 wpabuf_free(buf);
1578
1579 return res;
1580}
1581
1582
1583static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1584 struct wpa_supplicant *wpa_s, char *pos)
1585{
1586 size_t len;
1587 struct wpabuf *buf;
1588 int ret;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001589 char *freq;
1590 int forced_freq = 0;
1591
1592 freq = strstr(pos, " freq=");
1593 if (freq) {
1594 *freq = '\0';
1595 freq += 6;
1596 forced_freq = atoi(freq);
1597 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001598
1599 len = os_strlen(pos);
1600 if (len & 0x01)
1601 return -1;
1602 len /= 2;
1603
1604 buf = wpabuf_alloc(len);
1605 if (buf == NULL)
1606 return -1;
1607 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1608 wpabuf_free(buf);
1609 return -1;
1610 }
1611
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001612 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001613 wpabuf_free(buf);
1614
1615 return ret;
1616}
1617
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001618
1619static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001620 char *reply, size_t max_len,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001621 int ndef)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001622{
1623 struct wpabuf *buf;
1624 int res;
1625
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001626 buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001627 if (buf == NULL)
1628 return -1;
1629
1630 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1631 wpabuf_len(buf));
1632 reply[res++] = '\n';
1633 reply[res] = '\0';
1634
1635 wpabuf_free(buf);
1636
1637 return res;
1638}
1639
1640
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001641#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001642static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1643 char *reply, size_t max_len,
1644 int ndef)
1645{
1646 struct wpabuf *buf;
1647 int res;
1648
1649 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1650 if (buf == NULL) {
1651 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1652 return -1;
1653 }
1654
1655 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1656 wpabuf_len(buf));
1657 reply[res++] = '\n';
1658 reply[res] = '\0';
1659
1660 wpabuf_free(buf);
1661
1662 return res;
1663}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001664#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001665
1666
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001667static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1668 char *cmd, char *reply,
1669 size_t max_len)
1670{
1671 char *pos;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001672 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001673
1674 pos = os_strchr(cmd, ' ');
1675 if (pos == NULL)
1676 return -1;
1677 *pos++ = '\0';
1678
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001679 if (os_strcmp(cmd, "WPS") == 0)
1680 ndef = 0;
1681 else if (os_strcmp(cmd, "NDEF") == 0)
1682 ndef = 1;
1683 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001684 return -1;
1685
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001686 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001687 if (!ndef)
1688 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001689 return wpas_ctrl_nfc_get_handover_req_wps(
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001690 wpa_s, reply, max_len, ndef);
1691 }
1692
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001693#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001694 if (os_strcmp(pos, "P2P-CR") == 0) {
1695 return wpas_ctrl_nfc_get_handover_req_p2p(
1696 wpa_s, reply, max_len, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001697 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001698#endif /* CONFIG_P2P */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001699
1700 return -1;
1701}
1702
1703
1704static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001705 char *reply, size_t max_len,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001706 int ndef, int cr, char *uuid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001707{
1708 struct wpabuf *buf;
1709 int res;
1710
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001711 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001712 if (buf == NULL)
1713 return -1;
1714
1715 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1716 wpabuf_len(buf));
1717 reply[res++] = '\n';
1718 reply[res] = '\0';
1719
1720 wpabuf_free(buf);
1721
1722 return res;
1723}
1724
1725
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001726#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001727static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1728 char *reply, size_t max_len,
1729 int ndef, int tag)
1730{
1731 struct wpabuf *buf;
1732 int res;
1733
1734 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1735 if (buf == NULL)
1736 return -1;
1737
1738 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1739 wpabuf_len(buf));
1740 reply[res++] = '\n';
1741 reply[res] = '\0';
1742
1743 wpabuf_free(buf);
1744
1745 return res;
1746}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001747#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001748
1749
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001750static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1751 char *cmd, char *reply,
1752 size_t max_len)
1753{
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001754 char *pos, *pos2;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001755 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001756
1757 pos = os_strchr(cmd, ' ');
1758 if (pos == NULL)
1759 return -1;
1760 *pos++ = '\0';
1761
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001762 if (os_strcmp(cmd, "WPS") == 0)
1763 ndef = 0;
1764 else if (os_strcmp(cmd, "NDEF") == 0)
1765 ndef = 1;
1766 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001767 return -1;
1768
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001769 pos2 = os_strchr(pos, ' ');
1770 if (pos2)
1771 *pos2++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001772 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001773 if (!ndef)
1774 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001775 return wpas_ctrl_nfc_get_handover_sel_wps(
1776 wpa_s, reply, max_len, ndef,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001777 os_strcmp(pos, "WPS-CR") == 0, pos2);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001778 }
1779
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001780#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001781 if (os_strcmp(pos, "P2P-CR") == 0) {
1782 return wpas_ctrl_nfc_get_handover_sel_p2p(
1783 wpa_s, reply, max_len, ndef, 0);
1784 }
1785
1786 if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1787 return wpas_ctrl_nfc_get_handover_sel_p2p(
1788 wpa_s, reply, max_len, ndef, 1);
1789 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001790#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001791
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001792 return -1;
1793}
1794
1795
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001796static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1797 char *cmd)
1798{
1799 size_t len;
1800 struct wpabuf *req, *sel;
1801 int ret;
1802 char *pos, *role, *type, *pos2;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001803#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001804 char *freq;
1805 int forced_freq = 0;
1806
1807 freq = strstr(cmd, " freq=");
1808 if (freq) {
1809 *freq = '\0';
1810 freq += 6;
1811 forced_freq = atoi(freq);
1812 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001813#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001814
1815 role = cmd;
1816 pos = os_strchr(role, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001817 if (pos == NULL) {
1818 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001819 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001820 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001821 *pos++ = '\0';
1822
1823 type = pos;
1824 pos = os_strchr(type, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001825 if (pos == NULL) {
1826 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001827 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001828 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001829 *pos++ = '\0';
1830
1831 pos2 = os_strchr(pos, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001832 if (pos2 == NULL) {
1833 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001834 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001835 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001836 *pos2++ = '\0';
1837
1838 len = os_strlen(pos);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001839 if (len & 0x01) {
1840 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001841 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001842 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001843 len /= 2;
1844
1845 req = wpabuf_alloc(len);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001846 if (req == NULL) {
1847 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001848 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001849 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001850 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001851 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001852 wpabuf_free(req);
1853 return -1;
1854 }
1855
1856 len = os_strlen(pos2);
1857 if (len & 0x01) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001858 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001859 wpabuf_free(req);
1860 return -1;
1861 }
1862 len /= 2;
1863
1864 sel = wpabuf_alloc(len);
1865 if (sel == NULL) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001866 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001867 wpabuf_free(req);
1868 return -1;
1869 }
1870 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001871 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001872 wpabuf_free(req);
1873 wpabuf_free(sel);
1874 return -1;
1875 }
1876
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001877 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1878 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1879
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001880 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1881 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001882#ifdef CONFIG_AP
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001883 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1884 {
1885 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1886 if (ret < 0)
1887 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001888#endif /* CONFIG_AP */
1889#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001890 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1891 {
1892 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1893 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1894 {
1895 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1896 forced_freq);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001897#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001898 } else {
1899 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1900 "reported: role=%s type=%s", role, type);
1901 ret = -1;
1902 }
1903 wpabuf_free(req);
1904 wpabuf_free(sel);
1905
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001906 if (ret)
1907 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1908
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001909 return ret;
1910}
1911
Dmitry Shmidt04949592012-07-19 12:16:46 -07001912#endif /* CONFIG_WPS_NFC */
1913
1914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001915static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1916 char *cmd)
1917{
1918 u8 bssid[ETH_ALEN];
1919 char *pin;
1920 char *new_ssid;
1921 char *new_auth;
1922 char *new_encr;
1923 char *new_key;
1924 struct wps_new_ap_settings ap;
1925
1926 pin = os_strchr(cmd, ' ');
1927 if (pin == NULL)
1928 return -1;
1929 *pin++ = '\0';
1930
1931 if (hwaddr_aton(cmd, bssid)) {
1932 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1933 cmd);
1934 return -1;
1935 }
1936
1937 new_ssid = os_strchr(pin, ' ');
1938 if (new_ssid == NULL)
1939 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1940 *new_ssid++ = '\0';
1941
1942 new_auth = os_strchr(new_ssid, ' ');
1943 if (new_auth == NULL)
1944 return -1;
1945 *new_auth++ = '\0';
1946
1947 new_encr = os_strchr(new_auth, ' ');
1948 if (new_encr == NULL)
1949 return -1;
1950 *new_encr++ = '\0';
1951
1952 new_key = os_strchr(new_encr, ' ');
1953 if (new_key == NULL)
1954 return -1;
1955 *new_key++ = '\0';
1956
1957 os_memset(&ap, 0, sizeof(ap));
1958 ap.ssid_hex = new_ssid;
1959 ap.auth = new_auth;
1960 ap.encr = new_encr;
1961 ap.key_hex = new_key;
1962 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1963}
1964
1965
1966#ifdef CONFIG_AP
1967static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1968 char *cmd, char *buf,
1969 size_t buflen)
1970{
1971 int timeout = 300;
1972 char *pos;
1973 const char *pin_txt;
1974
1975 if (!wpa_s->ap_iface)
1976 return -1;
1977
1978 pos = os_strchr(cmd, ' ');
1979 if (pos)
1980 *pos++ = '\0';
1981
1982 if (os_strcmp(cmd, "disable") == 0) {
1983 wpas_wps_ap_pin_disable(wpa_s);
1984 return os_snprintf(buf, buflen, "OK\n");
1985 }
1986
1987 if (os_strcmp(cmd, "random") == 0) {
1988 if (pos)
1989 timeout = atoi(pos);
1990 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1991 if (pin_txt == NULL)
1992 return -1;
1993 return os_snprintf(buf, buflen, "%s", pin_txt);
1994 }
1995
1996 if (os_strcmp(cmd, "get") == 0) {
1997 pin_txt = wpas_wps_ap_pin_get(wpa_s);
1998 if (pin_txt == NULL)
1999 return -1;
2000 return os_snprintf(buf, buflen, "%s", pin_txt);
2001 }
2002
2003 if (os_strcmp(cmd, "set") == 0) {
2004 char *pin;
2005 if (pos == NULL)
2006 return -1;
2007 pin = pos;
2008 pos = os_strchr(pos, ' ');
2009 if (pos) {
2010 *pos++ = '\0';
2011 timeout = atoi(pos);
2012 }
2013 if (os_strlen(pin) > buflen)
2014 return -1;
2015 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2016 return -1;
2017 return os_snprintf(buf, buflen, "%s", pin);
2018 }
2019
2020 return -1;
2021}
2022#endif /* CONFIG_AP */
2023
2024
2025#ifdef CONFIG_WPS_ER
2026static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2027 char *cmd)
2028{
2029 char *uuid = cmd, *pin, *pos;
2030 u8 addr_buf[ETH_ALEN], *addr = NULL;
2031 pin = os_strchr(uuid, ' ');
2032 if (pin == NULL)
2033 return -1;
2034 *pin++ = '\0';
2035 pos = os_strchr(pin, ' ');
2036 if (pos) {
2037 *pos++ = '\0';
2038 if (hwaddr_aton(pos, addr_buf) == 0)
2039 addr = addr_buf;
2040 }
2041 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2042}
2043
2044
2045static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2046 char *cmd)
2047{
2048 char *uuid = cmd, *pin;
2049 pin = os_strchr(uuid, ' ');
2050 if (pin == NULL)
2051 return -1;
2052 *pin++ = '\0';
2053 return wpas_wps_er_learn(wpa_s, uuid, pin);
2054}
2055
2056
2057static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2058 struct wpa_supplicant *wpa_s, char *cmd)
2059{
2060 char *uuid = cmd, *id;
2061 id = os_strchr(uuid, ' ');
2062 if (id == NULL)
2063 return -1;
2064 *id++ = '\0';
2065 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2066}
2067
2068
2069static int wpa_supplicant_ctrl_iface_wps_er_config(
2070 struct wpa_supplicant *wpa_s, char *cmd)
2071{
2072 char *pin;
2073 char *new_ssid;
2074 char *new_auth;
2075 char *new_encr;
2076 char *new_key;
2077 struct wps_new_ap_settings ap;
2078
2079 pin = os_strchr(cmd, ' ');
2080 if (pin == NULL)
2081 return -1;
2082 *pin++ = '\0';
2083
2084 new_ssid = os_strchr(pin, ' ');
2085 if (new_ssid == NULL)
2086 return -1;
2087 *new_ssid++ = '\0';
2088
2089 new_auth = os_strchr(new_ssid, ' ');
2090 if (new_auth == NULL)
2091 return -1;
2092 *new_auth++ = '\0';
2093
2094 new_encr = os_strchr(new_auth, ' ');
2095 if (new_encr == NULL)
2096 return -1;
2097 *new_encr++ = '\0';
2098
2099 new_key = os_strchr(new_encr, ' ');
2100 if (new_key == NULL)
2101 return -1;
2102 *new_key++ = '\0';
2103
2104 os_memset(&ap, 0, sizeof(ap));
2105 ap.ssid_hex = new_ssid;
2106 ap.auth = new_auth;
2107 ap.encr = new_encr;
2108 ap.key_hex = new_key;
2109 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2110}
Dmitry Shmidt04949592012-07-19 12:16:46 -07002111
2112
2113#ifdef CONFIG_WPS_NFC
2114static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2115 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2116{
2117 int ndef;
2118 struct wpabuf *buf;
2119 int res;
2120 char *uuid;
2121
2122 uuid = os_strchr(cmd, ' ');
2123 if (uuid == NULL)
2124 return -1;
2125 *uuid++ = '\0';
2126
2127 if (os_strcmp(cmd, "WPS") == 0)
2128 ndef = 0;
2129 else if (os_strcmp(cmd, "NDEF") == 0)
2130 ndef = 1;
2131 else
2132 return -1;
2133
2134 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2135 if (buf == NULL)
2136 return -1;
2137
2138 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2139 wpabuf_len(buf));
2140 reply[res++] = '\n';
2141 reply[res] = '\0';
2142
2143 wpabuf_free(buf);
2144
2145 return res;
2146}
2147#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148#endif /* CONFIG_WPS_ER */
2149
2150#endif /* CONFIG_WPS */
2151
2152
2153#ifdef CONFIG_IBSS_RSN
2154static int wpa_supplicant_ctrl_iface_ibss_rsn(
2155 struct wpa_supplicant *wpa_s, char *addr)
2156{
2157 u8 peer[ETH_ALEN];
2158
2159 if (hwaddr_aton(addr, peer)) {
2160 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2161 "address '%s'", addr);
2162 return -1;
2163 }
2164
2165 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2166 MAC2STR(peer));
2167
2168 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2169}
2170#endif /* CONFIG_IBSS_RSN */
2171
2172
2173static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2174 char *rsp)
2175{
2176#ifdef IEEE8021X_EAPOL
2177 char *pos, *id_pos;
2178 int id;
2179 struct wpa_ssid *ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180
2181 pos = os_strchr(rsp, '-');
2182 if (pos == NULL)
2183 return -1;
2184 *pos++ = '\0';
2185 id_pos = pos;
2186 pos = os_strchr(pos, ':');
2187 if (pos == NULL)
2188 return -1;
2189 *pos++ = '\0';
2190 id = atoi(id_pos);
2191 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2192 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2193 (u8 *) pos, os_strlen(pos));
2194
2195 ssid = wpa_config_get_network(wpa_s->conf, id);
2196 if (ssid == NULL) {
2197 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2198 "to update", id);
2199 return -1;
2200 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002201
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002202 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2203 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204#else /* IEEE8021X_EAPOL */
2205 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2206 return -1;
2207#endif /* IEEE8021X_EAPOL */
2208}
2209
2210
2211static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2212 const char *params,
2213 char *buf, size_t buflen)
2214{
2215 char *pos, *end, tmp[30];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002216 int res, verbose, wps, ret;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002217#ifdef CONFIG_HS20
2218 const u8 *hs20;
2219#endif /* CONFIG_HS20 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002220 const u8 *sess_id;
2221 size_t sess_id_len;
Dmitry Shmidt44da0252011-08-23 12:30:30 -07002222
Dmitry Shmidt56052862013-10-04 10:23:25 -07002223 if (os_strcmp(params, "-DRIVER") == 0)
2224 return wpa_drv_status(wpa_s, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225 verbose = os_strcmp(params, "-VERBOSE") == 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002226 wps = os_strcmp(params, "-WPS") == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002227 pos = buf;
2228 end = buf + buflen;
2229 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2230 struct wpa_ssid *ssid = wpa_s->current_ssid;
2231 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2232 MAC2STR(wpa_s->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002233 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234 return pos - buf;
2235 pos += ret;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002236 ret = os_snprintf(pos, end - pos, "freq=%u\n",
2237 wpa_s->assoc_freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002238 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002239 return pos - buf;
2240 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 if (ssid) {
2242 u8 *_ssid = ssid->ssid;
2243 size_t ssid_len = ssid->ssid_len;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002244 u8 ssid_buf[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245 if (ssid_len == 0) {
2246 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2247 if (_res < 0)
2248 ssid_len = 0;
2249 else
2250 ssid_len = _res;
2251 _ssid = ssid_buf;
2252 }
2253 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2254 wpa_ssid_txt(_ssid, ssid_len),
2255 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002256 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 return pos - buf;
2258 pos += ret;
2259
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002260 if (wps && ssid->passphrase &&
2261 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2262 (ssid->mode == WPAS_MODE_AP ||
2263 ssid->mode == WPAS_MODE_P2P_GO)) {
2264 ret = os_snprintf(pos, end - pos,
2265 "passphrase=%s\n",
2266 ssid->passphrase);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002267 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002268 return pos - buf;
2269 pos += ret;
2270 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 if (ssid->id_str) {
2272 ret = os_snprintf(pos, end - pos,
2273 "id_str=%s\n",
2274 ssid->id_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002275 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 return pos - buf;
2277 pos += ret;
2278 }
2279
2280 switch (ssid->mode) {
2281 case WPAS_MODE_INFRA:
2282 ret = os_snprintf(pos, end - pos,
2283 "mode=station\n");
2284 break;
2285 case WPAS_MODE_IBSS:
2286 ret = os_snprintf(pos, end - pos,
2287 "mode=IBSS\n");
2288 break;
2289 case WPAS_MODE_AP:
2290 ret = os_snprintf(pos, end - pos,
2291 "mode=AP\n");
2292 break;
2293 case WPAS_MODE_P2P_GO:
2294 ret = os_snprintf(pos, end - pos,
2295 "mode=P2P GO\n");
2296 break;
2297 case WPAS_MODE_P2P_GROUP_FORMATION:
2298 ret = os_snprintf(pos, end - pos,
2299 "mode=P2P GO - group "
2300 "formation\n");
2301 break;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002302 case WPAS_MODE_MESH:
2303 ret = os_snprintf(pos, end - pos,
2304 "mode=mesh\n");
2305 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 default:
2307 ret = 0;
2308 break;
2309 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002310 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002311 return pos - buf;
2312 pos += ret;
2313 }
2314
Hai Shalom021b0b52019-04-10 11:17:58 -07002315 if (wpa_s->connection_set &&
2316 (wpa_s->connection_ht || wpa_s->connection_vht ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002317 wpa_s->connection_he || wpa_s->connection_eht)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002318 ret = os_snprintf(pos, end - pos,
2319 "wifi_generation=%u\n",
Sunil Ravia04bd252022-05-02 22:54:18 -07002320 wpa_s->connection_eht ? 7 :
2321 (wpa_s->connection_he ? 6 :
2322 (wpa_s->connection_vht ? 5 : 4)));
Hai Shalom021b0b52019-04-10 11:17:58 -07002323 if (os_snprintf_error(end - pos, ret))
2324 return pos - buf;
2325 pos += ret;
2326 }
2327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328#ifdef CONFIG_AP
2329 if (wpa_s->ap_iface) {
2330 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2331 end - pos,
2332 verbose);
2333 } else
2334#endif /* CONFIG_AP */
2335 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2336 }
Paul Stewart092955c2017-02-06 09:13:09 -08002337#ifdef CONFIG_SME
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002338#ifdef CONFIG_SAE
2339 if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002340#ifdef CONFIG_AP
2341 !wpa_s->ap_iface &&
2342#endif /* CONFIG_AP */
2343 wpa_s->sme.sae.state == SAE_ACCEPTED) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002344 ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2345 "sae_h2e=%d\n"
2346 "sae_pk=%d\n",
2347 wpa_s->sme.sae.group,
2348 wpa_s->sme.sae.h2e,
2349 wpa_s->sme.sae.pk);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002350 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002351 return pos - buf;
2352 pos += ret;
2353 }
2354#endif /* CONFIG_SAE */
Paul Stewart092955c2017-02-06 09:13:09 -08002355#endif /* CONFIG_SME */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2357 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002358 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 return pos - buf;
2360 pos += ret;
2361
2362 if (wpa_s->l2 &&
2363 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2364 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002365 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 return pos - buf;
2367 pos += ret;
2368 }
2369
2370#ifdef CONFIG_P2P
2371 if (wpa_s->global->p2p) {
2372 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2373 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002374 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002375 return pos - buf;
2376 pos += ret;
2377 }
2378#endif /* CONFIG_P2P */
2379
2380 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2381 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002382 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 return pos - buf;
2384 pos += ret;
2385
Dmitry Shmidt04949592012-07-19 12:16:46 -07002386#ifdef CONFIG_HS20
2387 if (wpa_s->current_bss &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002388 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2389 HS20_IE_VENDOR_TYPE)) &&
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002390 wpa_s->wpa_proto == WPA_PROTO_RSN &&
2391 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002392 int release = 1;
2393 if (hs20[1] >= 5) {
2394 u8 rel_num = (hs20[6] & 0xf0) >> 4;
2395 release = rel_num + 1;
2396 }
2397 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002398 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07002399 return pos - buf;
2400 pos += ret;
2401 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002402
2403 if (wpa_s->current_ssid) {
2404 struct wpa_cred *cred;
2405 char *type;
2406
2407 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002408 size_t i;
2409
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002410 if (wpa_s->current_ssid->parent_cred != cred)
2411 continue;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002412
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002413 if (cred->provisioning_sp) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002414 ret = os_snprintf(pos, end - pos,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002415 "provisioning_sp=%s\n",
2416 cred->provisioning_sp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002417 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt051af732013-10-22 13:52:46 -07002418 return pos - buf;
2419 pos += ret;
2420 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002421
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002422 if (!cred->domain)
2423 goto no_domain;
2424
2425 i = 0;
2426 if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2427 struct wpabuf *names =
2428 wpa_s->current_bss->anqp->domain_name;
2429 for (i = 0; names && i < cred->num_domain; i++)
2430 {
2431 if (domain_name_list_contains(
2432 names, cred->domain[i], 1))
2433 break;
2434 }
2435 if (i == cred->num_domain)
2436 i = 0; /* show first entry by default */
2437 }
2438 ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2439 cred->domain[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002440 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002441 return pos - buf;
2442 pos += ret;
2443
2444 no_domain:
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002445 if (wpa_s->current_bss == NULL ||
2446 wpa_s->current_bss->anqp == NULL)
2447 res = -1;
2448 else
2449 res = interworking_home_sp_cred(
2450 wpa_s, cred,
2451 wpa_s->current_bss->anqp->domain_name);
2452 if (res > 0)
2453 type = "home";
2454 else if (res == 0)
2455 type = "roaming";
2456 else
2457 type = "unknown";
2458
2459 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002460 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002461 return pos - buf;
2462 pos += ret;
2463
2464 break;
2465 }
2466 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002467#endif /* CONFIG_HS20 */
2468
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2470 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2471 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2472 verbose);
2473 if (res >= 0)
2474 pos += res;
2475 }
2476
Dmitry Shmidt29333592017-01-09 12:27:11 -08002477#ifdef CONFIG_MACSEC
2478 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2479 if (res > 0)
2480 pos += res;
2481#endif /* CONFIG_MACSEC */
2482
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002483 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2484 if (sess_id) {
2485 char *start = pos;
2486
2487 ret = os_snprintf(pos, end - pos, "eap_session_id=");
2488 if (os_snprintf_error(end - pos, ret))
2489 return start - buf;
2490 pos += ret;
2491 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2492 if (ret <= 0)
2493 return start - buf;
2494 pos += ret;
2495 ret = os_snprintf(pos, end - pos, "\n");
2496 if (os_snprintf_error(end - pos, ret))
2497 return start - buf;
2498 pos += ret;
2499 }
2500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2502 if (res >= 0)
2503 pos += res;
2504
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002505#ifdef CONFIG_WPS
2506 {
2507 char uuid_str[100];
2508 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2509 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002510 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002511 return pos - buf;
2512 pos += ret;
2513 }
2514#endif /* CONFIG_WPS */
2515
Roshan Pius3a1667e2018-07-03 15:17:14 -07002516 if (wpa_s->ieee80211ac) {
2517 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2518 if (os_snprintf_error(end - pos, ret))
2519 return pos - buf;
2520 pos += ret;
2521 }
2522
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002523#ifdef ANDROID
vandwalleffc70182014-09-11 11:40:14 -07002524 /*
2525 * Allow using the STATUS command with default behavior, say for debug,
2526 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2527 * events with STATUS-NO_EVENTS.
2528 */
2529 if (os_strcmp(params, "-NO_EVENTS")) {
2530 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2531 "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2532 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2533 wpa_s->wpa_state,
2534 MAC2STR(wpa_s->bssid),
2535 wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2536 wpa_ssid_txt(wpa_s->current_ssid->ssid,
2537 wpa_s->current_ssid->ssid_len) : "");
2538 if (wpa_s->wpa_state == WPA_COMPLETED) {
2539 struct wpa_ssid *ssid = wpa_s->current_ssid;
2540 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2541 "- connection to " MACSTR
2542 " completed %s [id=%d id_str=%s]",
2543 MAC2STR(wpa_s->bssid), "(auth)",
2544 ssid ? ssid->id : -1,
2545 ssid && ssid->id_str ? ssid->id_str : "");
2546 }
Irfan Sheriffbf5edf42012-01-11 16:54:57 -08002547 }
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002548#endif /* ANDROID */
2549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550 return pos - buf;
2551}
2552
2553
2554static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2555 char *cmd)
2556{
2557 char *pos;
2558 int id;
2559 struct wpa_ssid *ssid;
2560 u8 bssid[ETH_ALEN];
2561
2562 /* cmd: "<network id> <BSSID>" */
2563 pos = os_strchr(cmd, ' ');
2564 if (pos == NULL)
2565 return -1;
2566 *pos++ = '\0';
2567 id = atoi(cmd);
2568 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2569 if (hwaddr_aton(pos, bssid)) {
2570 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2571 return -1;
2572 }
2573
2574 ssid = wpa_config_get_network(wpa_s->conf, id);
2575 if (ssid == NULL) {
2576 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2577 "to update", id);
2578 return -1;
2579 }
2580
2581 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2582 ssid->bssid_set = !is_zero_ether_addr(bssid);
2583
2584 return 0;
2585}
2586
2587
Hai Shalom60840252021-02-19 19:02:11 -08002588static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2589 char *cmd, char *buf,
2590 size_t buflen)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002591{
2592 u8 bssid[ETH_ALEN];
Hai Shalom60840252021-02-19 19:02:11 -08002593 struct wpa_bssid_ignore *e;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002594 char *pos, *end;
2595 int ret;
2596
Hai Shalom60840252021-02-19 19:02:11 -08002597 /* cmd: "BSSID_IGNORE [<BSSID>]" */
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002598 if (*cmd == '\0') {
2599 pos = buf;
2600 end = buf + buflen;
Hai Shalom60840252021-02-19 19:02:11 -08002601 e = wpa_s->bssid_ignore;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002602 while (e) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002603 ret = os_snprintf(pos, end - pos, MACSTR "\n",
2604 MAC2STR(e->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002605 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002606 return pos - buf;
2607 pos += ret;
2608 e = e->next;
2609 }
2610 return pos - buf;
2611 }
2612
2613 cmd++;
2614 if (os_strncmp(cmd, "clear", 5) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -08002615 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002616 os_memcpy(buf, "OK\n", 3);
2617 return 3;
2618 }
2619
Hai Shalom60840252021-02-19 19:02:11 -08002620 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002621 if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002622 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002623 return -1;
2624 }
2625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002626 /*
2627 * Add the BSSID twice, so its count will be 2, causing it to be
2628 * skipped when processing scan results.
2629 */
Hai Shalom60840252021-02-19 19:02:11 -08002630 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002631 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002632 return -1;
Hai Shalom60840252021-02-19 19:02:11 -08002633 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002634 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002635 return -1;
2636 os_memcpy(buf, "OK\n", 3);
2637 return 3;
2638}
2639
2640
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002641static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2642 char *cmd, char *buf,
2643 size_t buflen)
2644{
2645 char *pos, *end, *stamp;
2646 int ret;
2647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002648 /* cmd: "LOG_LEVEL [<level>]" */
2649 if (*cmd == '\0') {
2650 pos = buf;
2651 end = buf + buflen;
2652 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2653 "Timestamp: %d\n",
2654 debug_level_str(wpa_debug_level),
2655 wpa_debug_timestamp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002656 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002657 ret = 0;
2658
2659 return ret;
2660 }
2661
2662 while (*cmd == ' ')
2663 cmd++;
2664
2665 stamp = os_strchr(cmd, ' ');
2666 if (stamp) {
2667 *stamp++ = '\0';
2668 while (*stamp == ' ') {
2669 stamp++;
2670 }
2671 }
2672
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002673 if (os_strlen(cmd)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002674 int level = str_to_debug_level(cmd);
2675 if (level < 0)
2676 return -1;
2677 wpa_debug_level = level;
2678 }
2679
2680 if (stamp && os_strlen(stamp))
2681 wpa_debug_timestamp = atoi(stamp);
2682
2683 os_memcpy(buf, "OK\n", 3);
2684 return 3;
2685}
2686
2687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002688static int wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002689 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690{
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002691 char *pos, *end, *prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 struct wpa_ssid *ssid;
2693 int ret;
2694
2695 pos = buf;
2696 end = buf + buflen;
2697 ret = os_snprintf(pos, end - pos,
2698 "network id / ssid / bssid / flags\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002699 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 return pos - buf;
2701 pos += ret;
2702
2703 ssid = wpa_s->conf->ssid;
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002704
2705 /* skip over ssids until we find next one */
2706 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2707 int last_id = atoi(cmd + 8);
2708 if (last_id != -1) {
2709 while (ssid != NULL && ssid->id <= last_id) {
2710 ssid = ssid->next;
2711 }
2712 }
2713 }
2714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002715 while (ssid) {
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002716 prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 ret = os_snprintf(pos, end - pos, "%d\t%s",
2718 ssid->id,
2719 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002720 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002721 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 pos += ret;
2723 if (ssid->bssid_set) {
2724 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2725 MAC2STR(ssid->bssid));
2726 } else {
2727 ret = os_snprintf(pos, end - pos, "\tany");
2728 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002729 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002730 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 pos += ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 ssid == wpa_s->current_ssid ?
2734 "[CURRENT]" : "",
2735 ssid->disabled ? "[DISABLED]" : "",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 ssid->disabled_until.sec ?
2737 "[TEMP-DISABLED]" : "",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2739 "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002740 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002741 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 pos += ret;
2743 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002744 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002745 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 pos += ret;
2747
2748 ssid = ssid->next;
2749 }
2750
2751 return pos - buf;
2752}
2753
2754
2755static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2756{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002757 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 ret = os_snprintf(pos, end - pos, "-");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002759 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002760 return pos;
2761 pos += ret;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002762 ret = wpa_write_ciphers(pos, end, cipher, "+");
2763 if (ret < 0)
2764 return pos;
2765 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 return pos;
2767}
2768
2769
2770static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2771 const u8 *ie, size_t ie_len)
2772{
2773 struct wpa_ie_data data;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002774 char *start;
2775 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776
2777 ret = os_snprintf(pos, end - pos, "[%s-", proto);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002778 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 return pos;
2780 pos += ret;
2781
2782 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2783 ret = os_snprintf(pos, end - pos, "?]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002784 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002785 return pos;
2786 pos += ret;
2787 return pos;
2788 }
2789
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002790 start = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002792 ret = os_snprintf(pos, end - pos, "%sEAP",
2793 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002794 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 return pos;
2796 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 }
2798 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002799 ret = os_snprintf(pos, end - pos, "%sPSK",
2800 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002801 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 return pos;
2803 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804 }
2805 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002806 ret = os_snprintf(pos, end - pos, "%sNone",
2807 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002808 if (os_snprintf_error(end - pos, ret))
2809 return pos;
2810 pos += ret;
2811 }
2812 if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2813 ret = os_snprintf(pos, end - pos, "%sSAE",
2814 pos == start ? "" : "+");
2815 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 return pos;
2817 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 }
2819#ifdef CONFIG_IEEE80211R
2820 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2821 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002822 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002823 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 return pos;
2825 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 }
2827 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2828 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002829 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002830 if (os_snprintf_error(end - pos, ret))
2831 return pos;
2832 pos += ret;
2833 }
2834 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2835 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2836 pos == start ? "" : "+");
2837 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 return pos;
2839 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840 }
2841#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2843 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002844 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002845 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002846 return pos;
2847 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848 }
2849 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2850 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002851 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002852 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002853 return pos;
2854 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002855 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002857#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002858 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2859 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2860 pos == start ? "" : "+");
2861 if (os_snprintf_error(end - pos, ret))
2862 return pos;
2863 pos += ret;
2864 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002865#endif /* CONFIG_SUITEB */
2866
2867#ifdef CONFIG_SUITEB192
2868 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2869 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2870 pos == start ? "" : "+");
2871 if (os_snprintf_error(end - pos, ret))
2872 return pos;
2873 pos += ret;
2874 }
2875#endif /* CONFIG_SUITEB192 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002876
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002877#ifdef CONFIG_FILS
2878 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2879 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2880 pos == start ? "" : "+");
2881 if (os_snprintf_error(end - pos, ret))
2882 return pos;
2883 pos += ret;
2884 }
2885 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2886 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2887 pos == start ? "" : "+");
2888 if (os_snprintf_error(end - pos, ret))
2889 return pos;
2890 pos += ret;
2891 }
2892#ifdef CONFIG_IEEE80211R
2893 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2894 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2895 pos == start ? "" : "+");
2896 if (os_snprintf_error(end - pos, ret))
2897 return pos;
2898 pos += ret;
2899 }
2900 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2901 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2902 pos == start ? "" : "+");
2903 if (os_snprintf_error(end - pos, ret))
2904 return pos;
2905 pos += ret;
2906 }
2907#endif /* CONFIG_IEEE80211R */
2908#endif /* CONFIG_FILS */
2909
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002910#ifdef CONFIG_OWE
2911 if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2912 ret = os_snprintf(pos, end - pos, "%sOWE",
2913 pos == start ? "" : "+");
2914 if (os_snprintf_error(end - pos, ret))
2915 return pos;
2916 pos += ret;
2917 }
2918#endif /* CONFIG_OWE */
2919
2920#ifdef CONFIG_DPP
2921 if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
2922 ret = os_snprintf(pos, end - pos, "%sDPP",
2923 pos == start ? "" : "+");
2924 if (os_snprintf_error(end - pos, ret))
2925 return pos;
2926 pos += ret;
2927 }
2928#endif /* CONFIG_DPP */
2929
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002930 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
2931 ret = os_snprintf(pos, end - pos, "%sOSEN",
2932 pos == start ? "" : "+");
2933 if (os_snprintf_error(end - pos, ret))
2934 return pos;
2935 pos += ret;
2936 }
2937
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002938 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2939
2940 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2941 ret = os_snprintf(pos, end - pos, "-preauth");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002942 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943 return pos;
2944 pos += ret;
2945 }
2946
2947 ret = os_snprintf(pos, end - pos, "]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002948 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 return pos;
2950 pos += ret;
2951
2952 return pos;
2953}
2954
2955
2956#ifdef CONFIG_WPS
2957static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2958 char *pos, char *end,
2959 struct wpabuf *wps_ie)
2960{
2961 int ret;
2962 const char *txt;
2963
2964 if (wps_ie == NULL)
2965 return pos;
2966 if (wps_is_selected_pbc_registrar(wps_ie))
2967 txt = "[WPS-PBC]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2969 txt = "[WPS-AUTH]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002970 else if (wps_is_selected_pin_registrar(wps_ie))
2971 txt = "[WPS-PIN]";
2972 else
2973 txt = "[WPS]";
2974
2975 ret = os_snprintf(pos, end - pos, "%s", txt);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002976 if (!os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 pos += ret;
2978 wpabuf_free(wps_ie);
2979 return pos;
2980}
2981#endif /* CONFIG_WPS */
2982
2983
2984static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2985 char *pos, char *end,
2986 const struct wpa_bss *bss)
2987{
2988#ifdef CONFIG_WPS
2989 struct wpabuf *wps_ie;
2990 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2991 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2992#else /* CONFIG_WPS */
2993 return pos;
2994#endif /* CONFIG_WPS */
2995}
2996
2997
2998/* Format one result on one text line into a buffer. */
2999static int wpa_supplicant_ctrl_iface_scan_result(
3000 struct wpa_supplicant *wpa_s,
3001 const struct wpa_bss *bss, char *buf, size_t buflen)
3002{
3003 char *pos, *end;
3004 int ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003005 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003006
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003007 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003008 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt96571392013-10-14 12:54:46 -07003009 if (!p2p)
3010 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3012 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3013 0)
3014 return 0; /* Do not show P2P listen discovery results here */
3015
3016 pos = buf;
3017 end = buf + buflen;
3018
3019 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3020 MAC2STR(bss->bssid), bss->freq, bss->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003021 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003022 return -1;
3023 pos += ret;
3024 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3025 if (ie)
3026 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
3027 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003028 if (ie2) {
3029 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3030 ie2, 2 + ie2[1]);
3031 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003032 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003033 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3034 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3035 if (os_snprintf_error(end - pos, ret))
3036 return -1;
3037 pos += ret;
3038 }
3039 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3040 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3041 if (os_snprintf_error(end - pos, ret))
3042 return -1;
3043 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003044 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003045 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3046 if (osen_ie)
3047 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3048 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003049 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3050 if (owe) {
3051 ret = os_snprintf(pos, end - pos,
3052 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3053 if (os_snprintf_error(end - pos, ret))
3054 return -1;
3055 pos += ret;
3056 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003057 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003058 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003059 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003060 if (os_snprintf_error(end - pos, ret))
3061 return -1;
3062 pos += ret;
3063 }
3064 if (mesh) {
3065 ret = os_snprintf(pos, end - pos, "[MESH]");
3066 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 return -1;
3068 pos += ret;
3069 }
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003070 if (bss_is_dmg(bss)) {
3071 const char *s;
Hai Shalomc3565922019-10-28 11:58:20 -07003072
Hai Shalom60840252021-02-19 19:02:11 -08003073 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
Hai Shalomc3565922019-10-28 11:58:20 -07003074 ret = os_snprintf(pos, end - pos, "[EDMG]");
3075 if (os_snprintf_error(end - pos, ret))
3076 return -1;
3077 pos += ret;
3078 }
3079
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003080 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003081 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082 return -1;
3083 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003084 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3085 case IEEE80211_CAP_DMG_IBSS:
3086 s = "[IBSS]";
3087 break;
3088 case IEEE80211_CAP_DMG_AP:
3089 s = "[ESS]";
3090 break;
3091 case IEEE80211_CAP_DMG_PBSS:
3092 s = "[PBSS]";
3093 break;
3094 default:
3095 s = "";
3096 break;
3097 }
3098 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003099 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003100 return -1;
3101 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003102 } else {
3103 if (bss->caps & IEEE80211_CAP_IBSS) {
3104 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003105 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003106 return -1;
3107 pos += ret;
3108 }
3109 if (bss->caps & IEEE80211_CAP_ESS) {
3110 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003111 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003112 return -1;
3113 pos += ret;
3114 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003115 }
3116 if (p2p) {
3117 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003118 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 return -1;
3120 pos += ret;
3121 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003122#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003123 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003124 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003125 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003126 return -1;
3127 pos += ret;
3128 }
3129#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003130#ifdef CONFIG_FILS
3131 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3132 ret = os_snprintf(pos, end - pos, "[FILS]");
3133 if (os_snprintf_error(end - pos, ret))
3134 return -1;
3135 pos += ret;
3136 }
3137#endif /* CONFIG_FILS */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003138#ifdef CONFIG_FST
3139 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3140 ret = os_snprintf(pos, end - pos, "[FST]");
3141 if (os_snprintf_error(end - pos, ret))
3142 return -1;
3143 pos += ret;
3144 }
3145#endif /* CONFIG_FST */
Hai Shalom74f70d42019-02-11 14:42:39 -08003146 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3147 ret = os_snprintf(pos, end - pos, "[UTF-8]");
3148 if (os_snprintf_error(end - pos, ret))
3149 return -1;
3150 pos += ret;
3151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003152
3153 ret = os_snprintf(pos, end - pos, "\t%s",
3154 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003155 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003156 return -1;
3157 pos += ret;
3158
3159 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003160 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003161 return -1;
3162 pos += ret;
3163
3164 return pos - buf;
3165}
3166
3167
3168static int wpa_supplicant_ctrl_iface_scan_results(
3169 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3170{
3171 char *pos, *end;
3172 struct wpa_bss *bss;
3173 int ret;
3174
3175 pos = buf;
3176 end = buf + buflen;
3177 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3178 "flags / ssid\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003179 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003180 return pos - buf;
3181 pos += ret;
3182
3183 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3184 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3185 end - pos);
3186 if (ret < 0 || ret >= end - pos)
3187 return pos - buf;
3188 pos += ret;
3189 }
3190
3191 return pos - buf;
3192}
3193
3194
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003195#ifdef CONFIG_MESH
3196
3197static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3198 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3199{
3200 char *pos, ifname[IFNAMSIZ + 1];
3201
3202 ifname[0] = '\0';
3203
3204 pos = os_strstr(cmd, "ifname=");
3205 if (pos) {
3206 pos += 7;
3207 os_strlcpy(ifname, pos, sizeof(ifname));
3208 }
3209
3210 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3211 return -1;
3212
3213 os_strlcpy(reply, ifname, max_len);
3214 return os_strlen(ifname);
3215}
3216
3217
3218static int wpa_supplicant_ctrl_iface_mesh_group_add(
3219 struct wpa_supplicant *wpa_s, char *cmd)
3220{
3221 int id;
3222 struct wpa_ssid *ssid;
3223
3224 id = atoi(cmd);
3225 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3226
3227 ssid = wpa_config_get_network(wpa_s->conf, id);
3228 if (ssid == NULL) {
3229 wpa_printf(MSG_DEBUG,
3230 "CTRL_IFACE: Could not find network id=%d", id);
3231 return -1;
3232 }
3233 if (ssid->mode != WPAS_MODE_MESH) {
3234 wpa_printf(MSG_DEBUG,
3235 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3236 return -1;
3237 }
3238 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
3239 ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
3240 wpa_printf(MSG_ERROR,
3241 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3242 return -1;
3243 }
3244
3245 /*
3246 * TODO: If necessary write our own group_add function,
3247 * for now we can reuse select_network
3248 */
3249 wpa_supplicant_select_network(wpa_s, ssid);
3250
3251 return 0;
3252}
3253
3254
3255static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3256 struct wpa_supplicant *wpa_s, char *cmd)
3257{
3258 struct wpa_supplicant *orig;
3259 struct wpa_global *global;
3260 int found = 0;
3261
3262 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3263
3264 global = wpa_s->global;
3265 orig = wpa_s;
3266
3267 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3268 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3269 found = 1;
3270 break;
3271 }
3272 }
3273 if (!found) {
3274 wpa_printf(MSG_ERROR,
3275 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3276 cmd);
3277 return -1;
3278 }
3279 if (wpa_s->mesh_if_created && wpa_s == orig) {
3280 wpa_printf(MSG_ERROR,
3281 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3282 return -1;
3283 }
3284
3285 wpa_s->reassociate = 0;
3286 wpa_s->disconnected = 1;
3287 wpa_supplicant_cancel_sched_scan(wpa_s);
3288 wpa_supplicant_cancel_scan(wpa_s);
3289
3290 /*
3291 * TODO: If necessary write our own group_remove function,
3292 * for now we can reuse deauthenticate
3293 */
3294 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3295
3296 if (wpa_s->mesh_if_created)
3297 wpa_supplicant_remove_iface(global, wpa_s, 0);
3298
3299 return 0;
3300}
3301
Dmitry Shmidte4663042016-04-04 10:07:49 -07003302
3303static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3304 struct wpa_supplicant *wpa_s, char *cmd)
3305{
3306 u8 addr[ETH_ALEN];
3307
3308 if (hwaddr_aton(cmd, addr) < 0)
3309 return -1;
3310
3311 return wpas_mesh_peer_remove(wpa_s, addr);
3312}
3313
3314
3315static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3316 struct wpa_supplicant *wpa_s, char *cmd)
3317{
3318 u8 addr[ETH_ALEN];
3319 int duration;
3320 char *pos;
3321
3322 pos = os_strstr(cmd, " duration=");
3323 if (pos) {
3324 *pos = '\0';
3325 duration = atoi(pos + 10);
3326 } else {
3327 duration = -1;
3328 }
3329
3330 if (hwaddr_aton(cmd, addr))
3331 return -1;
3332
3333 return wpas_mesh_peer_add(wpa_s, addr, duration);
3334}
3335
Hai Shalom81f62d82019-07-22 12:10:00 -07003336
3337static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3338 struct wpa_supplicant *wpa_s, char *cmd)
3339{
3340 struct ether_header *eth;
3341 u8 addr[ETH_ALEN];
3342 u8 *buf;
3343 char *pos;
3344 size_t payload_len = 0, len;
3345 int ret = -1;
3346
3347 if (hwaddr_aton(cmd, addr))
3348 return -1;
3349
3350 pos = os_strstr(cmd, " payload=");
3351 if (pos) {
3352 pos = pos + 9;
3353 payload_len = os_strlen(pos);
3354 if (payload_len & 1)
3355 return -1;
3356
3357 payload_len /= 2;
3358 }
3359
3360 len = ETH_HLEN + payload_len;
3361 buf = os_malloc(len);
3362 if (!buf)
3363 return -1;
3364
3365 eth = (struct ether_header *) buf;
3366 os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3367 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3368 eth->ether_type = htons(ETH_P_802_3);
3369
3370 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3371 goto fail;
3372
3373 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3374fail:
3375 os_free(buf);
3376 return -ret;
3377}
3378
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003379#endif /* CONFIG_MESH */
3380
3381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382static int wpa_supplicant_ctrl_iface_select_network(
3383 struct wpa_supplicant *wpa_s, char *cmd)
3384{
3385 int id;
3386 struct wpa_ssid *ssid;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003387 char *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003388
3389 /* cmd: "<network id>" or "any" */
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003390 if (os_strncmp(cmd, "any", 3) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3392 ssid = NULL;
3393 } else {
3394 id = atoi(cmd);
3395 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3396
3397 ssid = wpa_config_get_network(wpa_s->conf, id);
3398 if (ssid == NULL) {
3399 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3400 "network id=%d", id);
3401 return -1;
3402 }
3403 if (ssid->disabled == 2) {
3404 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3405 "SELECT_NETWORK with persistent P2P group");
3406 return -1;
3407 }
3408 }
3409
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003410 pos = os_strstr(cmd, " freq=");
3411 if (pos) {
3412 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3413 if (freqs) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003414 os_free(wpa_s->select_network_scan_freqs);
3415 wpa_s->select_network_scan_freqs = freqs;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003416 }
3417 }
3418
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003419 wpa_s->scan_min_time.sec = 0;
3420 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421 wpa_supplicant_select_network(wpa_s, ssid);
3422
3423 return 0;
3424}
3425
3426
3427static int wpa_supplicant_ctrl_iface_enable_network(
3428 struct wpa_supplicant *wpa_s, char *cmd)
3429{
3430 int id;
3431 struct wpa_ssid *ssid;
3432
3433 /* cmd: "<network id>" or "all" */
3434 if (os_strcmp(cmd, "all") == 0) {
3435 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3436 ssid = NULL;
3437 } else {
3438 id = atoi(cmd);
3439 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3440
3441 ssid = wpa_config_get_network(wpa_s->conf, id);
3442 if (ssid == NULL) {
3443 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3444 "network id=%d", id);
3445 return -1;
3446 }
3447 if (ssid->disabled == 2) {
3448 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3449 "ENABLE_NETWORK with persistent P2P group");
3450 return -1;
3451 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003452
3453 if (os_strstr(cmd, " no-connect")) {
3454 ssid->disabled = 0;
3455 return 0;
3456 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003457 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003458 wpa_s->scan_min_time.sec = 0;
3459 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460 wpa_supplicant_enable_network(wpa_s, ssid);
3461
3462 return 0;
3463}
3464
3465
3466static int wpa_supplicant_ctrl_iface_disable_network(
3467 struct wpa_supplicant *wpa_s, char *cmd)
3468{
3469 int id;
3470 struct wpa_ssid *ssid;
3471
3472 /* cmd: "<network id>" or "all" */
3473 if (os_strcmp(cmd, "all") == 0) {
3474 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3475 ssid = NULL;
3476 } else {
3477 id = atoi(cmd);
3478 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3479
3480 ssid = wpa_config_get_network(wpa_s->conf, id);
3481 if (ssid == NULL) {
3482 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3483 "network id=%d", id);
3484 return -1;
3485 }
3486 if (ssid->disabled == 2) {
3487 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3488 "DISABLE_NETWORK with persistent P2P "
3489 "group");
3490 return -1;
3491 }
3492 }
3493 wpa_supplicant_disable_network(wpa_s, ssid);
3494
3495 return 0;
3496}
3497
3498
3499static int wpa_supplicant_ctrl_iface_add_network(
3500 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3501{
3502 struct wpa_ssid *ssid;
3503 int ret;
3504
3505 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3506
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003507 ssid = wpa_supplicant_add_network(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 if (ssid == NULL)
3509 return -1;
3510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003512 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513 return -1;
3514 return ret;
3515}
3516
3517
3518static int wpa_supplicant_ctrl_iface_remove_network(
3519 struct wpa_supplicant *wpa_s, char *cmd)
3520{
3521 int id;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003522 int result;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523
3524 /* cmd: "<network id>" or "all" */
3525 if (os_strcmp(cmd, "all") == 0) {
3526 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
Hai Shalom899fcc72020-10-19 14:38:18 -07003527 return wpa_supplicant_remove_all_networks(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003528 }
3529
3530 id = atoi(cmd);
3531 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3532
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003533 result = wpa_supplicant_remove_network(wpa_s, id);
3534 if (result == -1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3536 "id=%d", id);
3537 return -1;
3538 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003539 if (result == -2) {
Deepthi Gowria831d782012-09-03 11:55:38 +03003540 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3541 "network id=%d", id);
3542 return -1;
3543 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003544 return 0;
3545}
3546
3547
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003548static int wpa_supplicant_ctrl_iface_update_network(
3549 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3550 char *name, char *value)
3551{
Dmitry Shmidte4663042016-04-04 10:07:49 -07003552 int ret;
3553
3554 ret = wpa_config_set(ssid, name, value, 0);
3555 if (ret < 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003556 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3557 "variable '%s'", name);
3558 return -1;
3559 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07003560 if (ret == 1)
3561 return 0; /* No change to the previously configured value */
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003562
Hai Shalom899fcc72020-10-19 14:38:18 -07003563#ifdef CONFIG_BGSCAN
3564 if (os_strcmp(name, "bgscan") == 0) {
3565 /*
3566 * Reset the bgscan parameters for the current network and
3567 * return. There's no need to flush caches for bgscan parameter
3568 * changes.
3569 */
3570 if (wpa_s->current_ssid == ssid &&
3571 wpa_s->wpa_state == WPA_COMPLETED)
3572 wpa_supplicant_reset_bgscan(wpa_s);
3573 return 0;
3574 }
3575#endif /* CONFIG_BGSCAN */
3576
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003577 if (os_strcmp(name, "bssid") != 0 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003578 os_strcmp(name, "bssid_hint") != 0 &&
Dmitry Shmidte4663042016-04-04 10:07:49 -07003579 os_strcmp(name, "priority") != 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003580 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3581
Dmitry Shmidte4663042016-04-04 10:07:49 -07003582 if (wpa_s->current_ssid == ssid ||
3583 wpa_s->current_ssid == NULL) {
3584 /*
3585 * Invalidate the EAP session cache if anything in the
3586 * current or previously used configuration changes.
3587 */
3588 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3589 }
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003590 }
3591
3592 if ((os_strcmp(name, "psk") == 0 &&
3593 value[0] == '"' && ssid->ssid_len) ||
3594 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3595 wpa_config_update_psk(ssid);
3596 else if (os_strcmp(name, "priority") == 0)
3597 wpa_config_update_prio_list(wpa_s->conf);
3598
3599 return 0;
3600}
3601
3602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003603static int wpa_supplicant_ctrl_iface_set_network(
3604 struct wpa_supplicant *wpa_s, char *cmd)
3605{
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003606 int id, ret, prev_bssid_set, prev_disabled;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 struct wpa_ssid *ssid;
3608 char *name, *value;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003609 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610
3611 /* cmd: "<network id> <variable name> <value>" */
3612 name = os_strchr(cmd, ' ');
3613 if (name == NULL)
3614 return -1;
3615 *name++ = '\0';
3616
3617 value = os_strchr(name, ' ');
3618 if (value == NULL)
3619 return -1;
3620 *value++ = '\0';
3621
3622 id = atoi(cmd);
3623 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3624 id, name);
3625 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3626 (u8 *) value, os_strlen(value));
3627
3628 ssid = wpa_config_get_network(wpa_s->conf, id);
3629 if (ssid == NULL) {
3630 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3631 "id=%d", id);
3632 return -1;
3633 }
3634
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003635 prev_bssid_set = ssid->bssid_set;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003636 prev_disabled = ssid->disabled;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003637 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3638 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3639 value);
3640 if (ret == 0 &&
3641 (ssid->bssid_set != prev_bssid_set ||
3642 os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
3643 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003644
3645 if (prev_disabled != ssid->disabled &&
3646 (prev_disabled == 2 || ssid->disabled == 2))
3647 wpas_notify_network_type_changed(wpa_s, ssid);
3648
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003649 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650}
3651
3652
3653static int wpa_supplicant_ctrl_iface_get_network(
3654 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3655{
3656 int id;
3657 size_t res;
3658 struct wpa_ssid *ssid;
3659 char *name, *value;
3660
3661 /* cmd: "<network id> <variable name>" */
3662 name = os_strchr(cmd, ' ');
3663 if (name == NULL || buflen == 0)
3664 return -1;
3665 *name++ = '\0';
3666
3667 id = atoi(cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003668 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 id, name);
3670
3671 ssid = wpa_config_get_network(wpa_s->conf, id);
3672 if (ssid == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003673 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 "id=%d", id);
3675 return -1;
3676 }
3677
3678 value = wpa_config_get_no_key(ssid, name);
3679 if (value == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003680 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 "variable '%s'", name);
3682 return -1;
3683 }
3684
3685 res = os_strlcpy(buf, value, buflen);
3686 if (res >= buflen) {
3687 os_free(value);
3688 return -1;
3689 }
3690
3691 os_free(value);
3692
3693 return res;
3694}
3695
3696
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003697static int wpa_supplicant_ctrl_iface_dup_network(
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003698 struct wpa_supplicant *wpa_s, char *cmd,
3699 struct wpa_supplicant *dst_wpa_s)
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003700{
3701 struct wpa_ssid *ssid_s, *ssid_d;
3702 char *name, *id, *value;
3703 int id_s, id_d, ret;
3704
3705 /* cmd: "<src network id> <dst network id> <variable name>" */
3706 id = os_strchr(cmd, ' ');
3707 if (id == NULL)
3708 return -1;
3709 *id++ = '\0';
3710
3711 name = os_strchr(id, ' ');
3712 if (name == NULL)
3713 return -1;
3714 *name++ = '\0';
3715
3716 id_s = atoi(cmd);
3717 id_d = atoi(id);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003718
3719 wpa_printf(MSG_DEBUG,
3720 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3721 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003722
3723 ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3724 if (ssid_s == NULL) {
3725 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3726 "network id=%d", id_s);
3727 return -1;
3728 }
3729
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003730 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003731 if (ssid_d == NULL) {
3732 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003733 "network id=%d", id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003734 return -1;
3735 }
3736
3737 value = wpa_config_get(ssid_s, name);
3738 if (value == NULL) {
3739 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3740 "variable '%s'", name);
3741 return -1;
3742 }
3743
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003744 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003745 value);
3746
3747 os_free(value);
3748
3749 return ret;
3750}
3751
3752
Dmitry Shmidt04949592012-07-19 12:16:46 -07003753static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3754 char *buf, size_t buflen)
3755{
3756 char *pos, *end;
3757 struct wpa_cred *cred;
3758 int ret;
3759
3760 pos = buf;
3761 end = buf + buflen;
3762 ret = os_snprintf(pos, end - pos,
3763 "cred id / realm / username / domain / imsi\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003764 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003765 return pos - buf;
3766 pos += ret;
3767
3768 cred = wpa_s->conf->cred;
3769 while (cred) {
3770 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3771 cred->id, cred->realm ? cred->realm : "",
3772 cred->username ? cred->username : "",
Dmitry Shmidt051af732013-10-22 13:52:46 -07003773 cred->domain ? cred->domain[0] : "",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003774 cred->imsi ? cred->imsi : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003775 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003776 return pos - buf;
3777 pos += ret;
3778
3779 cred = cred->next;
3780 }
3781
3782 return pos - buf;
3783}
3784
3785
3786static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3787 char *buf, size_t buflen)
3788{
3789 struct wpa_cred *cred;
3790 int ret;
3791
3792 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3793
3794 cred = wpa_config_add_cred(wpa_s->conf);
3795 if (cred == NULL)
3796 return -1;
3797
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003798 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3799
Dmitry Shmidt04949592012-07-19 12:16:46 -07003800 ret = os_snprintf(buf, buflen, "%d\n", cred->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003801 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003802 return -1;
3803 return ret;
3804}
3805
3806
3807static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3808 char *cmd)
3809{
3810 int id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003811 struct wpa_cred *cred, *prev;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003812
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003813 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3814 * "provisioning_sp=<FQDN> */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003815 if (os_strcmp(cmd, "all") == 0) {
3816 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003817 return wpas_remove_all_creds(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003818 }
3819
3820 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3821 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3822 cmd + 8);
3823 cred = wpa_s->conf->cred;
3824 while (cred) {
3825 prev = cred;
3826 cred = cred->next;
Dmitry Shmidt051af732013-10-22 13:52:46 -07003827 if (prev->domain) {
3828 size_t i;
3829 for (i = 0; i < prev->num_domain; i++) {
3830 if (os_strcmp(prev->domain[i], cmd + 8)
3831 != 0)
3832 continue;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003833 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidt051af732013-10-22 13:52:46 -07003834 break;
3835 }
3836 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003837 }
3838 return 0;
3839 }
3840
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003841 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3842 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3843 cmd + 16);
3844 cred = wpa_s->conf->cred;
3845 while (cred) {
3846 prev = cred;
3847 cred = cred->next;
3848 if (prev->provisioning_sp &&
3849 os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
Hai Shaloma20dcd72022-02-04 13:43:00 -08003850 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003851 }
3852 return 0;
3853 }
3854
Dmitry Shmidt04949592012-07-19 12:16:46 -07003855 id = atoi(cmd);
3856 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3857
3858 cred = wpa_config_get_cred(wpa_s->conf, id);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003859 return wpas_remove_cred(wpa_s, cred);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003860}
3861
3862
3863static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3864 char *cmd)
3865{
3866 int id;
3867 struct wpa_cred *cred;
3868 char *name, *value;
3869
3870 /* cmd: "<cred id> <variable name> <value>" */
3871 name = os_strchr(cmd, ' ');
3872 if (name == NULL)
3873 return -1;
3874 *name++ = '\0';
3875
3876 value = os_strchr(name, ' ');
3877 if (value == NULL)
3878 return -1;
3879 *value++ = '\0';
3880
3881 id = atoi(cmd);
3882 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3883 id, name);
3884 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3885 (u8 *) value, os_strlen(value));
3886
3887 cred = wpa_config_get_cred(wpa_s->conf, id);
3888 if (cred == NULL) {
3889 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3890 id);
3891 return -1;
3892 }
3893
3894 if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3895 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3896 "variable '%s'", name);
3897 return -1;
3898 }
3899
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003900 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3901
Dmitry Shmidt04949592012-07-19 12:16:46 -07003902 return 0;
3903}
3904
3905
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003906static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3907 char *cmd, char *buf,
3908 size_t buflen)
3909{
3910 int id;
3911 size_t res;
3912 struct wpa_cred *cred;
3913 char *name, *value;
3914
3915 /* cmd: "<cred id> <variable name>" */
3916 name = os_strchr(cmd, ' ');
3917 if (name == NULL)
3918 return -1;
3919 *name++ = '\0';
3920
3921 id = atoi(cmd);
3922 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3923 id, name);
3924
3925 cred = wpa_config_get_cred(wpa_s->conf, id);
3926 if (cred == NULL) {
3927 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3928 id);
3929 return -1;
3930 }
3931
3932 value = wpa_config_get_cred_no_key(cred, name);
3933 if (value == NULL) {
3934 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
3935 name);
3936 return -1;
3937 }
3938
3939 res = os_strlcpy(buf, value, buflen);
3940 if (res >= buflen) {
3941 os_free(value);
3942 return -1;
3943 }
3944
3945 os_free(value);
3946
3947 return res;
3948}
3949
3950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951#ifndef CONFIG_NO_CONFIG_WRITE
3952static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
3953{
3954 int ret;
3955
3956 if (!wpa_s->conf->update_config) {
3957 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
3958 "to update configuration (update_config=0)");
3959 return -1;
3960 }
3961
3962 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
3963 if (ret) {
3964 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
3965 "update configuration");
3966 } else {
3967 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
3968 " updated");
3969 }
3970
3971 return ret;
3972}
3973#endif /* CONFIG_NO_CONFIG_WRITE */
3974
3975
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003976struct cipher_info {
3977 unsigned int capa;
3978 const char *name;
3979 int group_only;
3980};
3981
3982static const struct cipher_info ciphers[] = {
3983 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
3984 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
3985 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
3986 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07003987#ifndef CONFIG_NO_TKIP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003988 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07003989#endif /* CONFIG_NO_TKIP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003990 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
Hai Shalomfdcde762020-04-02 11:19:20 -07003991#ifdef CONFIG_WEP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003992 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
3993 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003994#endif /* CONFIG_WEP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003995};
3996
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003997static const struct cipher_info ciphers_group_mgmt[] = {
3998 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
3999 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4000 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4001 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4002};
4003
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004004
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004005static int ctrl_iface_get_capability_pairwise(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004006 struct wpa_driver_capa *capa,
4007 char *buf, size_t buflen)
4008{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004009 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004010 char *pos, *end;
4011 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004012 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004013
4014 pos = buf;
4015 end = pos + buflen;
4016
4017 if (res < 0) {
4018 if (strict)
4019 return 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07004020#ifdef CONFIG_NO_TKIP
4021 len = os_strlcpy(buf, "CCMP NONE", buflen);
4022#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004024#endif /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025 if (len >= buflen)
4026 return -1;
4027 return len;
4028 }
4029
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004030 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4031 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4032 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004033 pos == buf ? "" : " ",
4034 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004035 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004036 return pos - buf;
4037 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004038 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004039 }
4040
4041 return pos - buf;
4042}
4043
4044
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004045static int ctrl_iface_get_capability_group(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046 struct wpa_driver_capa *capa,
4047 char *buf, size_t buflen)
4048{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004049 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050 char *pos, *end;
4051 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004052 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004053
4054 pos = buf;
4055 end = pos + buflen;
4056
4057 if (res < 0) {
4058 if (strict)
4059 return 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004060#ifdef CONFIG_WEP
Hai Shalomb755a2a2020-04-23 21:49:02 -07004061#ifdef CONFIG_NO_TKIP
4062 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4063#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004065#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004066#else /* CONFIG_WEP */
Hai Shalomb755a2a2020-04-23 21:49:02 -07004067#ifdef CONFIG_NO_TKIP
4068 len = os_strlcpy(buf, "CCMP", buflen);
4069#else /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004070 len = os_strlcpy(buf, "CCMP TKIP", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004071#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004072#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 if (len >= buflen)
4074 return -1;
4075 return len;
4076 }
4077
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004078 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4079 if (capa->enc & ciphers[i].capa) {
4080 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004081 pos == buf ? "" : " ",
4082 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004083 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004084 return pos - buf;
4085 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004086 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004087 }
4088
4089 return pos - buf;
4090}
4091
4092
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004093static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004094 struct wpa_driver_capa *capa,
4095 char *buf, size_t buflen)
4096{
4097 int ret;
4098 char *pos, *end;
4099 unsigned int i;
4100
4101 pos = buf;
4102 end = pos + buflen;
4103
4104 if (res < 0)
4105 return 0;
4106
4107 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4108 if (capa->enc & ciphers_group_mgmt[i].capa) {
4109 ret = os_snprintf(pos, end - pos, "%s%s",
4110 pos == buf ? "" : " ",
4111 ciphers_group_mgmt[i].name);
4112 if (os_snprintf_error(end - pos, ret))
4113 return pos - buf;
4114 pos += ret;
4115 }
4116 }
4117
4118 return pos - buf;
4119}
4120
4121
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004122static int iftype_str_to_index(const char *iftype_str)
4123{
4124 if (!iftype_str)
4125 return WPA_IF_MAX;
4126
4127 if (os_strcmp(iftype_str, "STATION") == 0)
4128 return WPA_IF_STATION;
4129
4130 if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4131 return WPA_IF_AP_VLAN;
4132
4133 if (os_strcmp(iftype_str, "AP") == 0)
4134 return WPA_IF_AP_BSS;
4135
4136 if (os_strcmp(iftype_str, "P2P_GO") == 0)
4137 return WPA_IF_P2P_GO;
4138
4139 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4140 return WPA_IF_P2P_CLIENT;
4141
4142 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4143 return WPA_IF_P2P_DEVICE;
4144
4145 if (os_strcmp(iftype_str, "MESH") == 0)
4146 return WPA_IF_MESH;
4147
4148 if (os_strcmp(iftype_str, "IBSS") == 0)
4149 return WPA_IF_IBSS;
4150
4151 if (os_strcmp(iftype_str, "NAN") == 0)
4152 return WPA_IF_NAN;
4153
4154 return WPA_IF_MAX;
4155}
4156
4157
4158static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004159 struct wpa_driver_capa *capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004160 const char *iftype_str,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 char *buf, size_t buflen)
4162{
4163 int ret;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004164 unsigned int key_mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004165 char *pos, *end;
4166 size_t len;
4167
4168 pos = buf;
4169 end = pos + buflen;
4170
4171 if (res < 0) {
4172 if (strict)
4173 return 0;
4174 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4175 "NONE", buflen);
4176 if (len >= buflen)
4177 return -1;
4178 return len;
4179 }
4180
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004181 if (iftype_str) {
4182 enum wpa_driver_if_type iftype;
4183
4184 iftype = iftype_str_to_index(iftype_str);
4185 if (iftype == WPA_IF_MAX)
4186 return -1;
4187 key_mgmt = capa->key_mgmt_iftype[iftype];
4188 } else {
4189 key_mgmt = capa->key_mgmt;
4190 }
4191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004192 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004193 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 return pos - buf;
4195 pos += ret;
4196
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004197 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4198 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 ret = os_snprintf(pos, end - pos, " WPA-EAP");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004200 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 return pos - buf;
4202 pos += ret;
4203 }
4204
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004205 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4206 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 ret = os_snprintf(pos, end - pos, " WPA-PSK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004208 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004209 return pos - buf;
4210 pos += ret;
4211 }
4212
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004213 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004214 ret = os_snprintf(pos, end - pos, " WPA-NONE");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004215 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004216 return pos - buf;
4217 pos += ret;
4218 }
4219
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304220 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4221 ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4222 if (os_snprintf_error(end - pos, ret))
4223 return pos - buf;
4224 pos += ret;
4225 }
4226
4227 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4228 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4229 if (os_snprintf_error(end - pos, ret))
4230 return pos - buf;
4231 pos += ret;
4232 }
4233
4234 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4235 ret = os_snprintf(pos, end - pos, " CCKM");
4236 if (os_snprintf_error(end - pos, ret))
4237 return pos - buf;
4238 pos += ret;
4239 }
4240
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004241#ifdef CONFIG_SUITEB
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004242 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004243 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4244 if (os_snprintf_error(end - pos, ret))
4245 return pos - buf;
4246 pos += ret;
4247 }
4248#endif /* CONFIG_SUITEB */
4249#ifdef CONFIG_SUITEB192
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004250 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004251 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4252 if (os_snprintf_error(end - pos, ret))
4253 return pos - buf;
4254 pos += ret;
4255 }
4256#endif /* CONFIG_SUITEB192 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004257#ifdef CONFIG_OWE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004258 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004259 ret = os_snprintf(pos, end - pos, " OWE");
4260 if (os_snprintf_error(end - pos, ret))
4261 return pos - buf;
4262 pos += ret;
4263 }
4264#endif /* CONFIG_OWE */
4265#ifdef CONFIG_DPP
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004266 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004267 ret = os_snprintf(pos, end - pos, " DPP");
4268 if (os_snprintf_error(end - pos, ret))
4269 return pos - buf;
4270 pos += ret;
4271 }
4272#endif /* CONFIG_DPP */
4273#ifdef CONFIG_FILS
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004274 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004275 ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4276 if (os_snprintf_error(end - pos, ret))
4277 return pos - buf;
4278 pos += ret;
4279 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004280 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004281 ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4282 if (os_snprintf_error(end - pos, ret))
4283 return pos - buf;
4284 pos += ret;
4285 }
4286#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004287 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004288 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4289 if (os_snprintf_error(end - pos, ret))
4290 return pos - buf;
4291 pos += ret;
4292 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004293 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004294 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4295 if (os_snprintf_error(end - pos, ret))
4296 return pos - buf;
4297 pos += ret;
4298 }
4299#endif /* CONFIG_IEEE80211R */
4300#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08004301#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004302 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004303 ret = os_snprintf(pos, end - pos, " FT-PSK");
4304 if (os_snprintf_error(end - pos, ret))
4305 return pos - buf;
4306 pos += ret;
4307 }
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304308 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4309 ret = os_snprintf(pos, end - pos, " FT-EAP");
4310 if (os_snprintf_error(end - pos, ret))
4311 return pos - buf;
4312 pos += ret;
4313 }
4314#ifdef CONFIG_SAE
4315 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4316 ret = os_snprintf(pos, end - pos, " FT-SAE");
4317 if (os_snprintf_error(end - pos, ret))
4318 return pos - buf;
4319 pos += ret;
4320 }
4321#endif /* CONFIG_SAE */
4322#ifdef CONFIG_SHA384
4323 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4324 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4325 if (os_snprintf_error(end - pos, ret))
4326 return pos - buf;
4327 pos += ret;
4328 }
4329#endif /* CONFIG_SHA384 */
Hai Shalom74f70d42019-02-11 14:42:39 -08004330#endif /* CONFIG_IEEE80211R */
4331#ifdef CONFIG_SAE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004332 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004333 ret = os_snprintf(pos, end - pos, " SAE");
4334 if (os_snprintf_error(end - pos, ret))
4335 return pos - buf;
4336 pos += ret;
4337 }
4338#endif /* CONFIG_SAE */
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304339#ifdef CONFIG_SHA256
4340 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4341 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4342 if (os_snprintf_error(end - pos, ret))
4343 return pos - buf;
4344 pos += ret;
4345 }
4346
4347 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4348 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4349 if (os_snprintf_error(end - pos, ret))
4350 return pos - buf;
4351 pos += ret;
4352 }
4353#endif /* CONFIG_SHA256 */
4354#ifdef CONFIG_HS20
4355 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4356 ret = os_snprintf(pos, end - pos, " OSEN");
4357 if (os_snprintf_error(end - pos, ret))
4358 return pos - buf;
4359 pos += ret;
4360 }
4361#endif /* CONFIG_HS20 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 return pos - buf;
4364}
4365
4366
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004367static int ctrl_iface_get_capability_proto(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 struct wpa_driver_capa *capa,
4369 char *buf, size_t buflen)
4370{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004371 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004372 char *pos, *end;
4373 size_t len;
4374
4375 pos = buf;
4376 end = pos + buflen;
4377
4378 if (res < 0) {
4379 if (strict)
4380 return 0;
4381 len = os_strlcpy(buf, "RSN WPA", buflen);
4382 if (len >= buflen)
4383 return -1;
4384 return len;
4385 }
4386
4387 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4388 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004389 ret = os_snprintf(pos, end - pos, "%sRSN",
4390 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004391 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392 return pos - buf;
4393 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 }
4395
4396 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4397 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004398 ret = os_snprintf(pos, end - pos, "%sWPA",
4399 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004400 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401 return pos - buf;
4402 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403 }
4404
4405 return pos - buf;
4406}
4407
4408
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004409static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004410 int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004411 struct wpa_driver_capa *capa,
4412 char *buf, size_t buflen)
4413{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004414 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004415 char *pos, *end;
4416 size_t len;
4417
4418 pos = buf;
4419 end = pos + buflen;
4420
4421 if (res < 0) {
4422 if (strict)
4423 return 0;
4424 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4425 if (len >= buflen)
4426 return -1;
4427 return len;
4428 }
4429
4430 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004431 ret = os_snprintf(pos, end - pos, "%sOPEN",
4432 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004433 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004434 return pos - buf;
4435 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 }
4437
4438 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4439 ret = os_snprintf(pos, end - pos, "%sSHARED",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004440 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004441 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004442 return pos - buf;
4443 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004444 }
4445
4446 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004447 ret = os_snprintf(pos, end - pos, "%sLEAP",
4448 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004449 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004450 return pos - buf;
4451 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 }
4453
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004454#ifdef CONFIG_SAE
4455 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4456 ret = os_snprintf(pos, end - pos, "%sSAE",
4457 pos == buf ? "" : " ");
4458 if (os_snprintf_error(end - pos, ret))
4459 return pos - buf;
4460 pos += ret;
4461 }
4462#endif /* CONFIG_SAE */
4463
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004464#ifdef CONFIG_FILS
4465 if (wpa_is_fils_supported(wpa_s)) {
4466 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4467 pos == buf ? "" : " ");
4468 if (os_snprintf_error(end - pos, ret))
4469 return pos - buf;
4470 pos += ret;
4471 }
4472
4473#ifdef CONFIG_FILS_SK_PFS
4474 if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4475 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4476 pos == buf ? "" : " ");
4477 if (os_snprintf_error(end - pos, ret))
4478 return pos - buf;
4479 pos += ret;
4480 }
4481#endif /* CONFIG_FILS_SK_PFS */
4482#endif /* CONFIG_FILS */
4483
Hai Shalom60840252021-02-19 19:02:11 -08004484#ifdef CONFIG_PASN
4485 ret = os_snprintf(pos, end - pos, "%sPASN",
4486 pos == buf ? "" : " ");
4487 if (os_snprintf_error(end - pos, ret))
4488 return pos - buf;
4489 pos += ret;
4490
4491#endif /* CONFIG_PASN */
4492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004493 return pos - buf;
4494}
4495
4496
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004497static int ctrl_iface_get_capability_modes(int res, bool strict,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004498 struct wpa_driver_capa *capa,
4499 char *buf, size_t buflen)
4500{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004501 int ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004502 char *pos, *end;
4503 size_t len;
4504
4505 pos = buf;
4506 end = pos + buflen;
4507
4508 if (res < 0) {
4509 if (strict)
4510 return 0;
4511 len = os_strlcpy(buf, "IBSS AP", buflen);
4512 if (len >= buflen)
4513 return -1;
4514 return len;
4515 }
4516
4517 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004518 ret = os_snprintf(pos, end - pos, "%sIBSS",
4519 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004520 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004521 return pos - buf;
4522 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004523 }
4524
4525 if (capa->flags & WPA_DRIVER_FLAGS_AP) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004526 ret = os_snprintf(pos, end - pos, "%sAP",
4527 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004528 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004529 return pos - buf;
4530 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004531 }
4532
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004533#ifdef CONFIG_MESH
4534 if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4535 ret = os_snprintf(pos, end - pos, "%sMESH",
4536 pos == buf ? "" : " ");
4537 if (os_snprintf_error(end - pos, ret))
4538 return pos - buf;
4539 pos += ret;
4540 }
4541#endif /* CONFIG_MESH */
4542
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004543 return pos - buf;
4544}
4545
4546
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004547static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4548 char *buf, size_t buflen)
4549{
4550 struct hostapd_channel_data *chnl;
4551 int ret, i, j;
4552 char *pos, *end, *hmode;
4553
4554 pos = buf;
4555 end = pos + buflen;
4556
4557 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4558 switch (wpa_s->hw.modes[j].mode) {
4559 case HOSTAPD_MODE_IEEE80211B:
4560 hmode = "B";
4561 break;
4562 case HOSTAPD_MODE_IEEE80211G:
4563 hmode = "G";
4564 break;
4565 case HOSTAPD_MODE_IEEE80211A:
4566 hmode = "A";
4567 break;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004568 case HOSTAPD_MODE_IEEE80211AD:
4569 hmode = "AD";
4570 break;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004571 default:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004572 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004573 }
4574 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004575 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004576 return pos - buf;
4577 pos += ret;
4578 chnl = wpa_s->hw.modes[j].channels;
4579 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004580 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4581 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004582 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004583 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004584 return pos - buf;
4585 pos += ret;
4586 }
4587 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004588 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004589 return pos - buf;
4590 pos += ret;
4591 }
4592
4593 return pos - buf;
4594}
4595
4596
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004597static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4598 char *buf, size_t buflen)
4599{
4600 struct hostapd_channel_data *chnl;
4601 int ret, i, j;
4602 char *pos, *end, *hmode;
4603
4604 pos = buf;
4605 end = pos + buflen;
4606
4607 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4608 switch (wpa_s->hw.modes[j].mode) {
4609 case HOSTAPD_MODE_IEEE80211B:
4610 hmode = "B";
4611 break;
4612 case HOSTAPD_MODE_IEEE80211G:
4613 hmode = "G";
4614 break;
4615 case HOSTAPD_MODE_IEEE80211A:
4616 hmode = "A";
4617 break;
4618 case HOSTAPD_MODE_IEEE80211AD:
4619 hmode = "AD";
4620 break;
4621 default:
4622 continue;
4623 }
4624 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4625 hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004626 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004627 return pos - buf;
4628 pos += ret;
4629 chnl = wpa_s->hw.modes[j].channels;
4630 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4631 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4632 continue;
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004633 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004634 chnl[i].chan, chnl[i].freq,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004635 chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4636 " (NO_IR)" : "",
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004637 chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4638 " (DFS)" : "");
4639
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004640 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004641 return pos - buf;
4642 pos += ret;
4643 }
4644 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004645 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004646 return pos - buf;
4647 pos += ret;
4648 }
4649
4650 return pos - buf;
4651}
4652
4653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654static int wpa_supplicant_ctrl_iface_get_capability(
4655 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4656 size_t buflen)
4657{
4658 struct wpa_driver_capa capa;
4659 int res;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004660 char *next_param, *curr_param, *iftype = NULL;
4661 bool strict = false;
4662 char field[50];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004663 size_t len;
4664
4665 /* Determine whether or not strict checking was requested */
4666 len = os_strlcpy(field, _field, sizeof(field));
4667 if (len >= sizeof(field))
4668 return -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004669
4670 next_param = os_strchr(field, ' ');
4671 while (next_param) {
4672 *next_param++ = '\0';
4673 curr_param = next_param;
4674 next_param = os_strchr(next_param, ' ');
4675
4676 if (next_param)
4677 *next_param = '\0';
4678
4679 if (os_strcmp(curr_param, "strict") == 0)
4680 strict = true;
4681 else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4682 iftype = curr_param + 7;
4683 else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004684 return -1;
4685 }
4686
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004687 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4688 field, iftype ? " iftype=" : "", iftype ? iftype : "",
4689 strict ? " strict" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004690
4691 if (os_strcmp(field, "eap") == 0) {
4692 return eap_get_names(buf, buflen);
4693 }
4694
4695 res = wpa_drv_get_capa(wpa_s, &capa);
4696
4697 if (os_strcmp(field, "pairwise") == 0)
4698 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4699 buf, buflen);
4700
4701 if (os_strcmp(field, "group") == 0)
4702 return ctrl_iface_get_capability_group(res, strict, &capa,
4703 buf, buflen);
4704
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004705 if (os_strcmp(field, "group_mgmt") == 0)
4706 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4707 buf, buflen);
4708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 if (os_strcmp(field, "key_mgmt") == 0)
4710 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004711 iftype, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004712
4713 if (os_strcmp(field, "proto") == 0)
4714 return ctrl_iface_get_capability_proto(res, strict, &capa,
4715 buf, buflen);
4716
4717 if (os_strcmp(field, "auth_alg") == 0)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004718 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4719 &capa, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004721 if (os_strcmp(field, "modes") == 0)
4722 return ctrl_iface_get_capability_modes(res, strict, &capa,
4723 buf, buflen);
4724
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004725 if (os_strcmp(field, "channels") == 0)
4726 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4727
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004728 if (os_strcmp(field, "freq") == 0)
4729 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4730
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004731#ifdef CONFIG_TDLS
4732 if (os_strcmp(field, "tdls") == 0)
4733 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4734#endif /* CONFIG_TDLS */
4735
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004736#ifdef CONFIG_ERP
4737 if (os_strcmp(field, "erp") == 0) {
4738 res = os_snprintf(buf, buflen, "ERP");
4739 if (os_snprintf_error(buflen, res))
4740 return -1;
4741 return res;
4742 }
4743#endif /* CONFIG_EPR */
4744
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004745#ifdef CONFIG_FIPS
4746 if (os_strcmp(field, "fips") == 0) {
4747 res = os_snprintf(buf, buflen, "FIPS");
4748 if (os_snprintf_error(buflen, res))
4749 return -1;
4750 return res;
4751 }
4752#endif /* CONFIG_FIPS */
4753
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08004754#ifdef CONFIG_ACS
4755 if (os_strcmp(field, "acs") == 0) {
4756 res = os_snprintf(buf, buflen, "ACS");
4757 if (os_snprintf_error(buflen, res))
4758 return -1;
4759 return res;
4760 }
4761#endif /* CONFIG_ACS */
4762
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004763#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004764 if (os_strcmp(field, "fils") == 0) {
4765#ifdef CONFIG_FILS_SK_PFS
4766 if (wpa_is_fils_supported(wpa_s) &&
4767 wpa_is_fils_sk_pfs_supported(wpa_s)) {
4768 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4769 if (os_snprintf_error(buflen, res))
4770 return -1;
4771 return res;
4772 }
4773#endif /* CONFIG_FILS_SK_PFS */
4774
4775 if (wpa_is_fils_supported(wpa_s)) {
4776 res = os_snprintf(buf, buflen, "FILS");
4777 if (os_snprintf_error(buflen, res))
4778 return -1;
4779 return res;
4780 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004781 }
4782#endif /* CONFIG_FILS */
4783
Hai Shalom74f70d42019-02-11 14:42:39 -08004784 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4785 res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4786 if (os_snprintf_error(buflen, res))
4787 return -1;
4788 return res;
4789 }
4790
Hai Shalom021b0b52019-04-10 11:17:58 -07004791#ifdef CONFIG_DPP
4792 if (os_strcmp(field, "dpp") == 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004793#ifdef CONFIG_DPP3
4794 res = os_snprintf(buf, buflen, "DPP=3");
4795#elif defined(CONFIG_DPP2)
Hai Shalom021b0b52019-04-10 11:17:58 -07004796 res = os_snprintf(buf, buflen, "DPP=2");
4797#else /* CONFIG_DPP2 */
4798 res = os_snprintf(buf, buflen, "DPP=1");
4799#endif /* CONFIG_DPP2 */
4800 if (os_snprintf_error(buflen, res))
4801 return -1;
4802 return res;
4803 }
4804#endif /* CONFIG_DPP */
4805
Hai Shalom899fcc72020-10-19 14:38:18 -07004806#ifdef CONFIG_SAE
4807 if (os_strcmp(field, "sae") == 0 &&
4808 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4809#ifdef CONFIG_SAE_PK
4810 res = os_snprintf(buf, buflen, "H2E PK");
4811#else /* CONFIG_SAE_PK */
4812 res = os_snprintf(buf, buflen, "H2E");
4813#endif /* CONFIG_SAE_PK */
4814 if (os_snprintf_error(buflen, res))
4815 return -1;
4816 return res;
4817 }
4818#endif /* CONFIG_SAE */
4819
Hai Shalom60840252021-02-19 19:02:11 -08004820#ifdef CONFIG_OCV
4821 if (os_strcmp(field, "ocv") == 0) {
4822 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4823 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4824 res = os_snprintf(buf, buflen, "supported");
4825 else
4826 res = os_snprintf(buf, buflen, "not supported");
4827 if (os_snprintf_error(buflen, res))
4828 return -1;
4829 return res;
4830 }
4831#endif /* CONFIG_OCV */
4832
4833 if (os_strcmp(field, "beacon_prot") == 0) {
4834 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4835 (wpa_s->drv_flags2 &
4836 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4837 res = os_snprintf(buf, buflen, "supported");
4838 else
4839 res = os_snprintf(buf, buflen, "not supported");
4840 if (os_snprintf_error(buflen, res))
4841 return -1;
4842 return res;
4843 }
4844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004845 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4846 field);
4847
4848 return -1;
4849}
4850
4851
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004852#ifdef CONFIG_INTERWORKING
4853static char * anqp_add_hex(char *pos, char *end, const char *title,
4854 struct wpabuf *data)
4855{
4856 char *start = pos;
4857 size_t i;
4858 int ret;
4859 const u8 *d;
4860
4861 if (data == NULL)
4862 return start;
4863
4864 ret = os_snprintf(pos, end - pos, "%s=", title);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004865 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004866 return start;
4867 pos += ret;
4868
4869 d = wpabuf_head_u8(data);
4870 for (i = 0; i < wpabuf_len(data); i++) {
4871 ret = os_snprintf(pos, end - pos, "%02x", *d++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004872 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004873 return start;
4874 pos += ret;
4875 }
4876
4877 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004878 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004879 return start;
4880 pos += ret;
4881
4882 return pos;
4883}
4884#endif /* CONFIG_INTERWORKING */
4885
4886
Dmitry Shmidt29333592017-01-09 12:27:11 -08004887#ifdef CONFIG_FILS
4888static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
4889{
4890 char *start = pos;
4891 const u8 *ie, *ie_end;
4892 u16 info, realms;
4893 int ret;
4894
4895 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
4896 if (!ie)
4897 return 0;
4898 ie_end = ie + 2 + ie[1];
4899 ie += 2;
4900 if (ie_end - ie < 2)
4901 return -1;
4902
4903 info = WPA_GET_LE16(ie);
4904 ie += 2;
4905 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
4906 if (os_snprintf_error(end - pos, ret))
4907 return 0;
4908 pos += ret;
4909
4910 if (info & BIT(7)) {
4911 /* Cache Identifier Included */
4912 if (ie_end - ie < 2)
4913 return -1;
4914 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
4915 ie[0], ie[1]);
4916 if (os_snprintf_error(end - pos, ret))
4917 return 0;
4918 pos += ret;
4919 ie += 2;
4920 }
4921
4922 if (info & BIT(8)) {
4923 /* HESSID Included */
4924 if (ie_end - ie < ETH_ALEN)
4925 return -1;
4926 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
4927 MAC2STR(ie));
4928 if (os_snprintf_error(end - pos, ret))
4929 return 0;
4930 pos += ret;
4931 ie += ETH_ALEN;
4932 }
4933
4934 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
4935 if (realms) {
4936 if (ie_end - ie < realms * 2)
4937 return -1;
4938 ret = os_snprintf(pos, end - pos, "fils_realms=");
4939 if (os_snprintf_error(end - pos, ret))
4940 return 0;
4941 pos += ret;
4942
4943 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
4944 if (ret <= 0)
4945 return 0;
4946 pos += ret;
4947 ie += realms * 2;
4948 ret = os_snprintf(pos, end - pos, "\n");
4949 if (os_snprintf_error(end - pos, ret))
4950 return 0;
4951 pos += ret;
4952 }
4953
4954 return pos - start;
4955}
4956#endif /* CONFIG_FILS */
4957
4958
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004959static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
4960 unsigned long mask, char *buf, size_t buflen)
4961{
4962 size_t i;
4963 int ret;
4964 char *pos, *end;
Hai Shalom899fcc72020-10-19 14:38:18 -07004965 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004966
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004967 pos = buf;
4968 end = buf + buflen;
4969
4970 if (mask & WPA_BSS_MASK_ID) {
4971 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004972 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004973 return 0;
4974 pos += ret;
4975 }
4976
4977 if (mask & WPA_BSS_MASK_BSSID) {
4978 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
4979 MAC2STR(bss->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004980 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004981 return 0;
4982 pos += ret;
4983 }
4984
4985 if (mask & WPA_BSS_MASK_FREQ) {
4986 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004987 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004988 return 0;
4989 pos += ret;
4990 }
4991
4992 if (mask & WPA_BSS_MASK_BEACON_INT) {
4993 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
4994 bss->beacon_int);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004995 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07004996 return 0;
4997 pos += ret;
4998 }
4999
5000 if (mask & WPA_BSS_MASK_CAPABILITIES) {
5001 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5002 bss->caps);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005003 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005004 return 0;
5005 pos += ret;
5006 }
5007
5008 if (mask & WPA_BSS_MASK_QUAL) {
5009 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005010 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005011 return 0;
5012 pos += ret;
5013 }
5014
5015 if (mask & WPA_BSS_MASK_NOISE) {
5016 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005017 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005018 return 0;
5019 pos += ret;
5020 }
5021
5022 if (mask & WPA_BSS_MASK_LEVEL) {
5023 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005024 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005025 return 0;
5026 pos += ret;
5027 }
5028
5029 if (mask & WPA_BSS_MASK_TSF) {
5030 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5031 (unsigned long long) bss->tsf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005032 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005033 return 0;
5034 pos += ret;
5035 }
5036
5037 if (mask & WPA_BSS_MASK_AGE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005038 struct os_reltime now;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005039
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005040 os_get_reltime(&now);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005041 ret = os_snprintf(pos, end - pos, "age=%d\n",
5042 (int) (now.sec - bss->last_update.sec));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005043 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005044 return 0;
5045 pos += ret;
5046 }
5047
5048 if (mask & WPA_BSS_MASK_IE) {
5049 ret = os_snprintf(pos, end - pos, "ie=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005050 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005051 return 0;
5052 pos += ret;
5053
Hai Shalom60840252021-02-19 19:02:11 -08005054 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005055 for (i = 0; i < bss->ie_len; i++) {
5056 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005057 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005058 return 0;
5059 pos += ret;
5060 }
5061
5062 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005063 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005064 return 0;
5065 pos += ret;
5066 }
5067
5068 if (mask & WPA_BSS_MASK_FLAGS) {
5069 ret = os_snprintf(pos, end - pos, "flags=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005070 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005071 return 0;
5072 pos += ret;
5073
Dmitry Shmidt29333592017-01-09 12:27:11 -08005074 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5075
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005076 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5077 if (ie)
5078 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5079 2 + ie[1]);
5080 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
5081 if (ie2)
Dmitry Shmidt29333592017-01-09 12:27:11 -08005082 pos = wpa_supplicant_ie_txt(pos, end,
5083 mesh ? "RSN" : "WPA2", ie2,
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005084 2 + ie2[1]);
Hai Shalom899fcc72020-10-19 14:38:18 -07005085 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Hai Shaloma20dcd72022-02-04 13:43:00 -08005086 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5087 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5088 if (os_snprintf_error(end - pos, ret))
5089 return -1;
5090 pos += ret;
5091 }
5092 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5093 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5094 if (os_snprintf_error(end - pos, ret))
5095 return -1;
5096 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07005097 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005098 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5099 if (osen_ie)
5100 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5101 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005102 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5103 if (owe) {
5104 ret = os_snprintf(
5105 pos, end - pos,
5106 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5107 if (os_snprintf_error(end - pos, ret))
5108 return 0;
5109 pos += ret;
5110 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005111 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005112 if (!ie && !ie2 && !osen_ie &&
5113 (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005114 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005115 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005116 return 0;
5117 pos += ret;
5118 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005119
5120 if (mesh) {
5121 ret = os_snprintf(pos, end - pos, "[MESH]");
5122 if (os_snprintf_error(end - pos, ret))
5123 return 0;
5124 pos += ret;
5125 }
5126
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005127 if (bss_is_dmg(bss)) {
5128 const char *s;
5129 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005130 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005131 return 0;
5132 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005133 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5134 case IEEE80211_CAP_DMG_IBSS:
5135 s = "[IBSS]";
5136 break;
5137 case IEEE80211_CAP_DMG_AP:
5138 s = "[ESS]";
5139 break;
5140 case IEEE80211_CAP_DMG_PBSS:
5141 s = "[PBSS]";
5142 break;
5143 default:
5144 s = "";
5145 break;
5146 }
5147 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005148 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005149 return 0;
5150 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005151 } else {
5152 if (bss->caps & IEEE80211_CAP_IBSS) {
5153 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005154 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005155 return 0;
5156 pos += ret;
5157 }
5158 if (bss->caps & IEEE80211_CAP_ESS) {
5159 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005160 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005161 return 0;
5162 pos += ret;
5163 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005164 }
Dmitry Shmidt96571392013-10-14 12:54:46 -07005165 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5166 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005167 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005168 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005169 return 0;
5170 pos += ret;
5171 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005172#ifdef CONFIG_HS20
5173 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5174 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005175 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005176 return 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005177 pos += ret;
5178 }
5179#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005180#ifdef CONFIG_FILS
5181 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5182 ret = os_snprintf(pos, end - pos, "[FILS]");
5183 if (os_snprintf_error(end - pos, ret))
5184 return 0;
5185 pos += ret;
5186 }
5187#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08005188#ifdef CONFIG_FST
5189 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5190 ret = os_snprintf(pos, end - pos, "[FST]");
5191 if (os_snprintf_error(end - pos, ret))
5192 return 0;
5193 pos += ret;
5194 }
5195#endif /* CONFIG_FST */
5196 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5197 ret = os_snprintf(pos, end - pos, "[UTF-8]");
5198 if (os_snprintf_error(end - pos, ret))
5199 return 0;
5200 pos += ret;
5201 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005202
5203 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005204 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005205 return 0;
5206 pos += ret;
5207 }
5208
5209 if (mask & WPA_BSS_MASK_SSID) {
5210 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5211 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005212 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005213 return 0;
5214 pos += ret;
5215 }
5216
5217#ifdef CONFIG_WPS
5218 if (mask & WPA_BSS_MASK_WPS_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005219 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005220 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005221 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005222 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005223 if (ret > 0)
5224 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005225 }
5226#endif /* CONFIG_WPS */
5227
5228#ifdef CONFIG_P2P
5229 if (mask & WPA_BSS_MASK_P2P_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005230 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005231 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005232 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005233 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005234 if (ret > 0)
5235 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005236 }
5237#endif /* CONFIG_P2P */
5238
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005239#ifdef CONFIG_WIFI_DISPLAY
5240 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5241 struct wpabuf *wfd;
Hai Shalom60840252021-02-19 19:02:11 -08005242
5243 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005244 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5245 WFD_IE_VENDOR_TYPE);
5246 if (wfd) {
5247 ret = os_snprintf(pos, end - pos, "wfd_subelems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005248 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005249 wpabuf_free(wfd);
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005250 return 0;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005251 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005252 pos += ret;
5253
5254 pos += wpa_snprintf_hex(pos, end - pos,
5255 wpabuf_head(wfd),
5256 wpabuf_len(wfd));
5257 wpabuf_free(wfd);
5258
5259 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005260 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005261 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005262 pos += ret;
5263 }
5264 }
5265#endif /* CONFIG_WIFI_DISPLAY */
5266
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005267#ifdef CONFIG_INTERWORKING
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005268 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5269 struct wpa_bss_anqp *anqp = bss->anqp;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005270 struct wpa_bss_anqp_elem *elem;
5271
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005272 pos = anqp_add_hex(pos, end, "anqp_capability_list",
5273 anqp->capability_list);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005274 pos = anqp_add_hex(pos, end, "anqp_venue_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005275 anqp->venue_name);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005276 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005277 anqp->network_auth_type);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005278 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005279 anqp->roaming_consortium);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005280 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005281 anqp->ip_addr_type_availability);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005282 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005283 anqp->nai_realm);
5284 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005285 pos = anqp_add_hex(pos, end, "anqp_domain_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005286 anqp->domain_name);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005287 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5288 anqp->fils_realm_info);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005289#ifdef CONFIG_HS20
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005290 pos = anqp_add_hex(pos, end, "hs20_capability_list",
5291 anqp->hs20_capability_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005292 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005293 anqp->hs20_operator_friendly_name);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005294 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005295 anqp->hs20_wan_metrics);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005296 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005297 anqp->hs20_connection_capability);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005298 pos = anqp_add_hex(pos, end, "hs20_operating_class",
5299 anqp->hs20_operating_class);
5300 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5301 anqp->hs20_osu_providers_list);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005302 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5303 anqp->hs20_operator_icon_metadata);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005304 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5305 anqp->hs20_osu_providers_nai_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005306#endif /* CONFIG_HS20 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005307
5308 dl_list_for_each(elem, &anqp->anqp_elems,
5309 struct wpa_bss_anqp_elem, list) {
5310 char title[20];
5311
5312 os_snprintf(title, sizeof(title), "anqp[%u]",
5313 elem->infoid);
5314 pos = anqp_add_hex(pos, end, title, elem->payload);
Hai Shalom60840252021-02-19 19:02:11 -08005315 if (elem->protected_response) {
5316 ret = os_snprintf(pos, end - pos,
5317 "protected-anqp-info[%u]=1\n",
5318 elem->infoid);
5319 if (os_snprintf_error(end - pos, ret))
5320 return 0;
5321 pos += ret;
5322 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005323 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005324 }
5325#endif /* CONFIG_INTERWORKING */
5326
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005327#ifdef CONFIG_MESH
5328 if (mask & WPA_BSS_MASK_MESH_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005329 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005330 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005331 if (ret >= end - pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005332 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005333 if (ret > 0)
5334 pos += ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005335 }
5336#endif /* CONFIG_MESH */
5337
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005338 if (mask & WPA_BSS_MASK_SNR) {
5339 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5340 if (os_snprintf_error(end - pos, ret))
5341 return 0;
5342 pos += ret;
5343 }
5344
5345 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5346 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5347 bss->est_throughput);
5348 if (os_snprintf_error(end - pos, ret))
5349 return 0;
5350 pos += ret;
5351 }
5352
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005353#ifdef CONFIG_FST
5354 if (mask & WPA_BSS_MASK_FST) {
5355 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5356 if (ret < 0 || ret >= end - pos)
5357 return 0;
5358 pos += ret;
5359 }
5360#endif /* CONFIG_FST */
5361
Dmitry Shmidt29333592017-01-09 12:27:11 -08005362 if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5363 ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5364 bss->last_update_idx);
5365 if (os_snprintf_error(end - pos, ret))
5366 return 0;
5367 pos += ret;
5368 }
5369
5370 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5371 ret = os_snprintf(pos, end - pos, "beacon_ie=");
5372 if (os_snprintf_error(end - pos, ret))
5373 return 0;
5374 pos += ret;
5375
Hai Shalom60840252021-02-19 19:02:11 -08005376 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005377 ie += bss->ie_len;
5378 for (i = 0; i < bss->beacon_ie_len; i++) {
5379 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5380 if (os_snprintf_error(end - pos, ret))
5381 return 0;
5382 pos += ret;
5383 }
5384
5385 ret = os_snprintf(pos, end - pos, "\n");
5386 if (os_snprintf_error(end - pos, ret))
5387 return 0;
5388 pos += ret;
5389 }
5390
5391#ifdef CONFIG_FILS
5392 if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5393 ret = print_fils_indication(bss, pos, end);
5394 if (ret < 0)
5395 return 0;
5396 pos += ret;
5397 }
5398#endif /* CONFIG_FILS */
5399
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005400 if (mask & WPA_BSS_MASK_DELIM) {
5401 ret = os_snprintf(pos, end - pos, "====\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005402 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005403 return 0;
5404 pos += ret;
5405 }
Irfan Sheriffe2ea0082012-08-13 10:56:16 -07005406
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005407 return pos - buf;
5408}
5409
Dmitry Shmidt04949592012-07-19 12:16:46 -07005410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005411static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5412 const char *cmd, char *buf,
5413 size_t buflen)
5414{
5415 u8 bssid[ETH_ALEN];
5416 size_t i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005417 struct wpa_bss *bss;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005418 struct wpa_bss *bsslast = NULL;
5419 struct dl_list *next;
5420 int ret = 0;
5421 int len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005422 char *ctmp, *end = buf + buflen;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005423 unsigned long mask = WPA_BSS_MASK_ALL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005424
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005425 if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5426 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5427 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005428 list_id);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005429 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5430 list_id);
5431 } else { /* N1-N2 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005432 unsigned int id1, id2;
5433
5434 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5435 wpa_printf(MSG_INFO, "Wrong BSS range "
5436 "format");
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005437 return 0;
5438 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005439
Dmitry Shmidtf8623282013-02-20 14:34:59 -08005440 if (*(cmd + 6) == '-')
5441 id1 = 0;
5442 else
5443 id1 = atoi(cmd + 6);
5444 ctmp++;
5445 if (*ctmp >= '0' && *ctmp <= '9')
5446 id2 = atoi(ctmp);
5447 else
5448 id2 = (unsigned int) -1;
5449 bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5450 if (id2 == (unsigned int) -1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005451 bsslast = dl_list_last(&wpa_s->bss_id,
5452 struct wpa_bss,
5453 list_id);
5454 else {
5455 bsslast = wpa_bss_get_id(wpa_s, id2);
5456 if (bsslast == NULL && bss && id2 > id1) {
5457 struct wpa_bss *tmp = bss;
5458 for (;;) {
5459 next = tmp->list_id.next;
5460 if (next == &wpa_s->bss_id)
5461 break;
5462 tmp = dl_list_entry(
5463 next, struct wpa_bss,
5464 list_id);
5465 if (tmp->id > id2)
5466 break;
5467 bsslast = tmp;
5468 }
5469 }
5470 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005471 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005472 } else if (os_strncmp(cmd, "FIRST", 5) == 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005473 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005474 else if (os_strncmp(cmd, "LAST", 4) == 0)
5475 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005476 else if (os_strncmp(cmd, "ID-", 3) == 0) {
5477 i = atoi(cmd + 3);
5478 bss = wpa_bss_get_id(wpa_s, i);
5479 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5480 i = atoi(cmd + 5);
5481 bss = wpa_bss_get_id(wpa_s, i);
5482 if (bss) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005483 next = bss->list_id.next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005484 if (next == &wpa_s->bss_id)
5485 bss = NULL;
5486 else
5487 bss = dl_list_entry(next, struct wpa_bss,
5488 list_id);
5489 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005490 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5491 bss = wpa_s->current_bss;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005492#ifdef CONFIG_P2P
5493 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5494 if (hwaddr_aton(cmd + 13, bssid) == 0)
5495 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5496 else
5497 bss = NULL;
5498#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005499 } else if (hwaddr_aton(cmd, bssid) == 0)
5500 bss = wpa_bss_get_bssid(wpa_s, bssid);
5501 else {
5502 struct wpa_bss *tmp;
5503 i = atoi(cmd);
5504 bss = NULL;
5505 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5506 {
Hai Shalom021b0b52019-04-10 11:17:58 -07005507 if (i == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005508 bss = tmp;
5509 break;
5510 }
Hai Shalom021b0b52019-04-10 11:17:58 -07005511 i--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512 }
5513 }
5514
Dmitry Shmidt04949592012-07-19 12:16:46 -07005515 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5516 mask = strtoul(ctmp + 5, NULL, 0x10);
5517 if (mask == 0)
5518 mask = WPA_BSS_MASK_ALL;
5519 }
5520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005521 if (bss == NULL)
5522 return 0;
5523
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005524 if (bsslast == NULL)
5525 bsslast = bss;
5526 do {
5527 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5528 ret += len;
5529 buf += len;
5530 buflen -= len;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005531 if (bss == bsslast) {
5532 if ((mask & WPA_BSS_MASK_DELIM) && len &&
5533 (bss == dl_list_last(&wpa_s->bss_id,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005534 struct wpa_bss, list_id))) {
5535 int res;
5536
5537 res = os_snprintf(buf - 5, end - buf + 5,
5538 "####\n");
5539 if (os_snprintf_error(end - buf + 5, res)) {
5540 wpa_printf(MSG_DEBUG,
5541 "Could not add end delim");
5542 }
5543 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005544 break;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005545 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005546 next = bss->list_id.next;
5547 if (next == &wpa_s->bss_id)
5548 break;
5549 bss = dl_list_entry(next, struct wpa_bss, list_id);
5550 } while (bss && len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005551
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005552 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005553}
5554
5555
5556static int wpa_supplicant_ctrl_iface_ap_scan(
5557 struct wpa_supplicant *wpa_s, char *cmd)
5558{
5559 int ap_scan = atoi(cmd);
5560 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5561}
5562
5563
5564static int wpa_supplicant_ctrl_iface_scan_interval(
5565 struct wpa_supplicant *wpa_s, char *cmd)
5566{
5567 int scan_int = atoi(cmd);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005568 return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569}
5570
5571
5572static int wpa_supplicant_ctrl_iface_bss_expire_age(
5573 struct wpa_supplicant *wpa_s, char *cmd)
5574{
5575 int expire_age = atoi(cmd);
5576 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5577}
5578
5579
5580static int wpa_supplicant_ctrl_iface_bss_expire_count(
5581 struct wpa_supplicant *wpa_s, char *cmd)
5582{
5583 int expire_count = atoi(cmd);
5584 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5585}
5586
5587
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005588static void wpa_supplicant_ctrl_iface_bss_flush(
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005589 struct wpa_supplicant *wpa_s, char *cmd)
5590{
5591 int flush_age = atoi(cmd);
5592
5593 if (flush_age == 0)
5594 wpa_bss_flush(wpa_s);
5595 else
5596 wpa_bss_flush_by_age(wpa_s, flush_age);
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005597}
5598
5599
Dmitry Shmidt21de2142014-04-08 10:50:52 -07005600#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005601static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5602{
5603 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5604 /* MLME-DELETEKEYS.request */
Hai Shalomfdcde762020-04-02 11:19:20 -07005605 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
5606 0, KEY_FLAG_GROUP);
5607 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
5608 0, KEY_FLAG_GROUP);
5609 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
5610 0, KEY_FLAG_GROUP);
5611 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
5612 0, KEY_FLAG_GROUP);
5613 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
5614 0, KEY_FLAG_GROUP);
5615 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
5616 0, KEY_FLAG_GROUP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617
5618 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005619 0, KEY_FLAG_PAIRWISE);
5620 if (wpa_sm_ext_key_id(wpa_s->wpa))
5621 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
5622 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005623 /* MLME-SETPROTECTION.request(None) */
5624 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
5625 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
5626 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5627 wpa_sm_drop_sa(wpa_s->wpa);
5628}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07005629#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005630
5631
5632static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
5633 char *addr)
5634{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005635#ifdef CONFIG_NO_SCAN_PROCESSING
5636 return -1;
5637#else /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005638 u8 bssid[ETH_ALEN];
5639 struct wpa_bss *bss;
5640 struct wpa_ssid *ssid = wpa_s->current_ssid;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005641 struct wpa_radio_work *already_connecting;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005642
5643 if (hwaddr_aton(addr, bssid)) {
5644 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
5645 "address '%s'", addr);
5646 return -1;
5647 }
5648
5649 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
5650
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005651 if (!ssid) {
5652 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
5653 "configuration known for the target AP");
5654 return -1;
5655 }
5656
5657 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005658 if (!bss) {
5659 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
5660 "from BSS table");
5661 return -1;
5662 }
5663
5664 /*
5665 * TODO: Find best network configuration block from configuration to
5666 * allow roaming to other networks
5667 */
5668
Hai Shaloma20dcd72022-02-04 13:43:00 -08005669 already_connecting = radio_work_pending(wpa_s, "sme-connect");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005670 wpa_s->reassociate = 1;
5671 wpa_supplicant_connect(wpa_s, bss, ssid);
5672
Hai Shaloma20dcd72022-02-04 13:43:00 -08005673 /*
5674 * Indicate that an explicitly requested roam is in progress so scan
5675 * results that come in before the 'sme-connect' radio work gets
5676 * executed do not override the original connection attempt.
5677 */
5678 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
5679 wpa_s->roam_in_progress = true;
5680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005681 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005682#endif /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005683}
5684
5685
5686#ifdef CONFIG_P2P
5687static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
5688{
5689 unsigned int timeout = atoi(cmd);
5690 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005691 u8 dev_id[ETH_ALEN], *_dev_id = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005692 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005693 char *pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005694 unsigned int search_delay;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005695 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005696 u8 seek_count = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005697 int freq = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005698 bool include_6ghz = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005699
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005700 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5701 wpa_dbg(wpa_s, MSG_INFO,
5702 "Reject P2P_FIND since interface is disabled");
5703 return -1;
5704 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08005705
5706 if (os_strstr(cmd, " include_6ghz"))
5707 include_6ghz = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005708 if (os_strstr(cmd, "type=social"))
5709 type = P2P_FIND_ONLY_SOCIAL;
5710 else if (os_strstr(cmd, "type=progressive"))
5711 type = P2P_FIND_PROGRESSIVE;
5712
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005713 pos = os_strstr(cmd, "dev_id=");
5714 if (pos) {
5715 pos += 7;
5716 if (hwaddr_aton(pos, dev_id))
5717 return -1;
5718 _dev_id = dev_id;
5719 }
5720
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005721 pos = os_strstr(cmd, "dev_type=");
5722 if (pos) {
5723 pos += 9;
5724 if (wps_dev_type_str2bin(pos, dev_type) < 0)
5725 return -1;
5726 _dev_type = dev_type;
5727 }
5728
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005729 pos = os_strstr(cmd, "delay=");
5730 if (pos) {
5731 pos += 6;
5732 search_delay = atoi(pos);
5733 } else
5734 search_delay = wpas_p2p_search_delay(wpa_s);
5735
Dmitry Shmidt41712582015-06-29 11:02:15 -07005736 pos = os_strstr(cmd, "freq=");
5737 if (pos) {
5738 pos += 5;
5739 freq = atoi(pos);
5740 if (freq <= 0)
5741 return -1;
5742 }
5743
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005744 /* Must be searched for last, because it adds nul termination */
5745 pos = os_strstr(cmd, " seek=");
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005746 if (pos)
5747 pos += 6;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005748 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
5749 char *term;
5750
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005751 _seek[seek_count++] = pos;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005752 seek = _seek;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005753 term = os_strchr(pos, ' ');
5754 if (!term)
5755 break;
5756 *term = '\0';
5757 pos = os_strstr(term + 1, "seek=");
5758 if (pos)
5759 pos += 5;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005760 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005761 if (seek_count > P2P_MAX_QUERY_HASH) {
5762 seek[0] = NULL;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005763 seek_count = 1;
5764 }
5765
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005766 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
Hai Shaloma20dcd72022-02-04 13:43:00 -08005767 _dev_id, search_delay, seek_count, seek, freq,
5768 include_6ghz);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005769}
5770
5771
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005772static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
5773{
5774 const char *last = NULL;
5775 const char *token;
5776 long int token_len;
5777 unsigned int i;
5778
5779 /* Expected predefined CPT names delimited by ':' */
5780 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
5781 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
5782 wpa_printf(MSG_ERROR,
5783 "P2PS: CPT name list is too long, expected up to %d names",
5784 P2PS_FEATURE_CAPAB_CPT_MAX);
5785 cpt[0] = 0;
5786 return -1;
5787 }
5788
5789 token_len = last - token;
5790
5791 if (token_len == 3 &&
5792 os_memcmp(token, "UDP", token_len) == 0) {
5793 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5794 } else if (token_len == 3 &&
5795 os_memcmp(token, "MAC", token_len) == 0) {
5796 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
5797 } else {
5798 wpa_printf(MSG_ERROR,
5799 "P2PS: Unsupported CPT name '%s'", token);
5800 cpt[0] = 0;
5801 return -1;
5802 }
5803
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005804 if (isblank((unsigned char) *last)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005805 i++;
5806 break;
5807 }
5808 }
5809 cpt[i] = 0;
5810 return 0;
5811}
5812
5813
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005814static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
5815{
5816 struct p2ps_provision *p2ps_prov;
5817 char *pos;
5818 size_t info_len = 0;
5819 char *info = NULL;
5820 u8 role = P2PS_SETUP_NONE;
5821 long long unsigned val;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005822 int i;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005823
5824 pos = os_strstr(cmd, "info=");
5825 if (pos) {
5826 pos += 5;
5827 info_len = os_strlen(pos);
5828
5829 if (info_len) {
5830 info = os_malloc(info_len + 1);
5831 if (info) {
5832 info_len = utf8_unescape(pos, info_len,
5833 info, info_len + 1);
5834 } else
5835 info_len = 0;
5836 }
5837 }
5838
5839 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
5840 if (p2ps_prov == NULL) {
5841 os_free(info);
5842 return NULL;
5843 }
5844
5845 if (info) {
5846 os_memcpy(p2ps_prov->info, info, info_len);
5847 p2ps_prov->info[info_len] = '\0';
5848 os_free(info);
5849 }
5850
5851 pos = os_strstr(cmd, "status=");
5852 if (pos)
5853 p2ps_prov->status = atoi(pos + 7);
5854 else
5855 p2ps_prov->status = -1;
5856
5857 pos = os_strstr(cmd, "adv_id=");
5858 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
5859 goto invalid_args;
5860 p2ps_prov->adv_id = val;
5861
5862 pos = os_strstr(cmd, "method=");
5863 if (pos)
5864 p2ps_prov->method = strtol(pos + 7, NULL, 16);
5865 else
5866 p2ps_prov->method = 0;
5867
5868 pos = os_strstr(cmd, "session=");
5869 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
5870 goto invalid_args;
5871 p2ps_prov->session_id = val;
5872
5873 pos = os_strstr(cmd, "adv_mac=");
5874 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
5875 goto invalid_args;
5876
5877 pos = os_strstr(cmd, "session_mac=");
5878 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
5879 goto invalid_args;
5880
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005881 pos = os_strstr(cmd, "cpt=");
5882 if (pos) {
5883 if (p2ps_ctrl_parse_cpt_priority(pos + 4,
5884 p2ps_prov->cpt_priority))
5885 goto invalid_args;
5886 } else {
5887 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
5888 }
5889
5890 for (i = 0; p2ps_prov->cpt_priority[i]; i++)
5891 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
5892
Hai Shaloma20dcd72022-02-04 13:43:00 -08005893 /* force conncap with tstCap (no validity checks) */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005894 pos = os_strstr(cmd, "tstCap=");
5895 if (pos) {
5896 role = strtol(pos + 7, NULL, 16);
5897 } else {
5898 pos = os_strstr(cmd, "role=");
5899 if (pos) {
5900 role = strtol(pos + 5, NULL, 16);
5901 if (role != P2PS_SETUP_CLIENT &&
5902 role != P2PS_SETUP_GROUP_OWNER)
5903 role = P2PS_SETUP_NONE;
5904 }
5905 }
5906 p2ps_prov->role = role;
5907
5908 return p2ps_prov;
5909
5910invalid_args:
5911 os_free(p2ps_prov);
5912 return NULL;
5913}
5914
5915
5916static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
5917{
5918 u8 addr[ETH_ALEN];
5919 struct p2ps_provision *p2ps_prov;
5920 char *pos;
5921
5922 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
5923
5924 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5925
5926 if (hwaddr_aton(cmd, addr))
5927 return -1;
5928
5929 pos = cmd + 17;
5930 if (*pos != ' ')
5931 return -1;
5932
5933 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5934 if (!p2ps_prov)
5935 return -1;
5936
5937 if (p2ps_prov->status < 0) {
5938 os_free(p2ps_prov);
5939 return -1;
5940 }
5941
5942 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5943 p2ps_prov);
5944}
5945
5946
5947static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
5948{
5949 u8 addr[ETH_ALEN];
5950 struct p2ps_provision *p2ps_prov;
5951 char *pos;
5952
5953 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
5954 * session=<ses_id> mac=<ses_mac> [info=<infodata>]
5955 */
5956
5957 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
5958 if (hwaddr_aton(cmd, addr))
5959 return -1;
5960
5961 pos = cmd + 17;
5962 if (*pos != ' ')
5963 return -1;
5964
5965 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
5966 if (!p2ps_prov)
5967 return -1;
5968
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005969 p2ps_prov->pd_seeker = 1;
5970
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005971 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
5972 p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005973}
5974
5975
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005976static int parse_freq(int chwidth, int freq2)
5977{
5978 if (freq2 < 0)
5979 return -1;
5980 if (freq2)
Hai Shalom81f62d82019-07-22 12:10:00 -07005981 return CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005982
5983 switch (chwidth) {
5984 case 0:
5985 case 20:
5986 case 40:
Hai Shalom81f62d82019-07-22 12:10:00 -07005987 return CHANWIDTH_USE_HT;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005988 case 80:
Hai Shalom81f62d82019-07-22 12:10:00 -07005989 return CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005990 case 160:
Hai Shalom81f62d82019-07-22 12:10:00 -07005991 return CHANWIDTH_160MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005992 default:
5993 wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
5994 chwidth);
5995 return -1;
5996 }
5997}
5998
5999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006000static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6001 char *buf, size_t buflen)
6002{
6003 u8 addr[ETH_ALEN];
6004 char *pos, *pos2;
6005 char *pin = NULL;
6006 enum p2p_wps_method wps_method;
6007 int new_pin;
6008 int ret;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006009 int persistent_group, persistent_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006010 int join;
6011 int auth;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006012 int automatic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006013 int go_intent = -1;
6014 int freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006015 int pd;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006016 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006017 int edmg;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006018 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6019 size_t group_ssid_len = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08006020 int he;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006021 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006022
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006023 if (!wpa_s->global->p2p_init_wpa_s)
6024 return -1;
6025 if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6026 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6027 wpa_s->global->p2p_init_wpa_s->ifname);
6028 wpa_s = wpa_s->global->p2p_init_wpa_s;
6029 }
6030
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006031 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
Dmitry Shmidt04949592012-07-19 12:16:46 -07006032 * [persistent|persistent=<network id>]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006033 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006034 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035
6036 if (hwaddr_aton(cmd, addr))
6037 return -1;
6038
6039 pos = cmd + 17;
6040 if (*pos != ' ')
6041 return -1;
6042 pos++;
6043
6044 persistent_group = os_strstr(pos, " persistent") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006045 pos2 = os_strstr(pos, " persistent=");
6046 if (pos2) {
6047 struct wpa_ssid *ssid;
6048 persistent_id = atoi(pos2 + 12);
6049 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6050 if (ssid == NULL || ssid->disabled != 2 ||
6051 ssid->mode != WPAS_MODE_P2P_GO) {
6052 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6053 "SSID id=%d for persistent P2P group (GO)",
6054 persistent_id);
6055 return -1;
6056 }
6057 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006058 join = os_strstr(pos, " join") != NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006059 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006060 auth = os_strstr(pos, " auth") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006061 automatic = os_strstr(pos, " auto") != NULL;
6062 pd = os_strstr(pos, " provdisc") != NULL;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006063 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6064 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6065 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006066 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006067 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006068
6069 pos2 = os_strstr(pos, " go_intent=");
6070 if (pos2) {
6071 pos2 += 11;
6072 go_intent = atoi(pos2);
6073 if (go_intent < 0 || go_intent > 15)
6074 return -1;
6075 }
6076
6077 pos2 = os_strstr(pos, " freq=");
6078 if (pos2) {
6079 pos2 += 6;
6080 freq = atoi(pos2);
6081 if (freq <= 0)
6082 return -1;
6083 }
6084
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006085 pos2 = os_strstr(pos, " freq2=");
6086 if (pos2)
6087 freq2 = atoi(pos2 + 7);
6088
6089 pos2 = os_strstr(pos, " max_oper_chwidth=");
6090 if (pos2)
6091 chwidth = atoi(pos2 + 18);
6092
6093 max_oper_chwidth = parse_freq(chwidth, freq2);
6094 if (max_oper_chwidth < 0)
6095 return -1;
6096
Hai Shaloma20dcd72022-02-04 13:43:00 -08006097 if (allow_6ghz && chwidth == 40)
6098 max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
6099
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006100 pos2 = os_strstr(pos, " ssid=");
6101 if (pos2) {
6102 char *end;
6103
6104 pos2 += 6;
6105 end = os_strchr(pos2, ' ');
6106 if (!end)
6107 group_ssid_len = os_strlen(pos2) / 2;
6108 else
6109 group_ssid_len = (end - pos2) / 2;
6110 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6111 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6112 return -1;
6113 group_ssid = _group_ssid;
6114 }
6115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006116 if (os_strncmp(pos, "pin", 3) == 0) {
6117 /* Request random PIN (to be displayed) and enable the PIN */
6118 wps_method = WPS_PIN_DISPLAY;
6119 } else if (os_strncmp(pos, "pbc", 3) == 0) {
6120 wps_method = WPS_PBC;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006121 } else if (os_strstr(pos, "p2ps") != NULL) {
6122 wps_method = WPS_P2PS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006123 } else {
6124 pin = pos;
6125 pos = os_strchr(pin, ' ');
6126 wps_method = WPS_PIN_KEYPAD;
6127 if (pos) {
6128 *pos++ = '\0';
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006129 if (os_strncmp(pos, "display", 7) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006130 wps_method = WPS_PIN_DISPLAY;
6131 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006132 if (!wps_pin_str_valid(pin)) {
6133 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6134 return 17;
6135 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006136 }
6137
6138 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
Dmitry Shmidt04949592012-07-19 12:16:46 -07006139 persistent_group, automatic, join,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006140 auth, go_intent, freq, freq2, persistent_id,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006141 pd, ht40, vht, max_oper_chwidth, he, edmg,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006142 group_ssid, group_ssid_len, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006143 if (new_pin == -2) {
6144 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6145 return 25;
6146 }
6147 if (new_pin == -3) {
6148 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6149 return 25;
6150 }
6151 if (new_pin < 0)
6152 return -1;
6153 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6154 ret = os_snprintf(buf, buflen, "%08d", new_pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006155 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006156 return -1;
6157 return ret;
6158 }
6159
6160 os_memcpy(buf, "OK\n", 3);
6161 return 3;
6162}
6163
6164
6165static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6166{
6167 unsigned int timeout = atoi(cmd);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006168 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6169 wpa_dbg(wpa_s, MSG_INFO,
6170 "Reject P2P_LISTEN since interface is disabled");
6171 return -1;
6172 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006173 return wpas_p2p_listen(wpa_s, timeout);
6174}
6175
6176
6177static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6178{
6179 u8 addr[ETH_ALEN];
6180 char *pos;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006181 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006182
Dmitry Shmidt04949592012-07-19 12:16:46 -07006183 /* <addr> <config method> [join|auto] */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006184
6185 if (hwaddr_aton(cmd, addr))
6186 return -1;
6187
6188 pos = cmd + 17;
6189 if (*pos != ' ')
6190 return -1;
6191 pos++;
6192
Dmitry Shmidt04949592012-07-19 12:16:46 -07006193 if (os_strstr(pos, " join") != NULL)
6194 use = WPAS_P2P_PD_FOR_JOIN;
6195 else if (os_strstr(pos, " auto") != NULL)
6196 use = WPAS_P2P_PD_AUTO;
6197
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006198 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006199}
6200
6201
6202static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6203 size_t buflen)
6204{
6205 struct wpa_ssid *ssid = wpa_s->current_ssid;
6206
6207 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6208 ssid->passphrase == NULL)
6209 return -1;
6210
6211 os_strlcpy(buf, ssid->passphrase, buflen);
6212 return os_strlen(buf);
6213}
6214
6215
6216static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6217 char *buf, size_t buflen)
6218{
6219 u64 ref;
6220 int res;
6221 u8 dst_buf[ETH_ALEN], *dst;
6222 struct wpabuf *tlvs;
6223 char *pos;
6224 size_t len;
6225
6226 if (hwaddr_aton(cmd, dst_buf))
6227 return -1;
6228 dst = dst_buf;
6229 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6230 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6231 dst = NULL;
6232 pos = cmd + 17;
6233 if (*pos != ' ')
6234 return -1;
6235 pos++;
6236
6237 if (os_strncmp(pos, "upnp ", 5) == 0) {
6238 u8 version;
6239 pos += 5;
6240 if (hexstr2bin(pos, &version, 1) < 0)
6241 return -1;
6242 pos += 2;
6243 if (*pos != ' ')
6244 return -1;
6245 pos++;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006246 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006247#ifdef CONFIG_WIFI_DISPLAY
6248 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6249 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6250#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006251 } else if (os_strncmp(pos, "asp ", 4) == 0) {
6252 char *svc_str;
6253 char *svc_info = NULL;
6254 u32 id;
6255
6256 pos += 4;
6257 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6258 return -1;
6259
6260 pos = os_strchr(pos, ' ');
6261 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6262 return -1;
6263
6264 svc_str = pos + 1;
6265
6266 pos = os_strchr(svc_str, ' ');
6267
6268 if (pos)
6269 *pos++ = '\0';
6270
6271 /* All remaining data is the svc_info string */
6272 if (pos && pos[0] && pos[0] != ' ') {
6273 len = os_strlen(pos);
6274
6275 /* Unescape in place */
6276 len = utf8_unescape(pos, len, pos, len);
6277 if (len > 0xff)
6278 return -1;
6279
6280 svc_info = pos;
6281 }
6282
6283 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6284 svc_str, svc_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006285 } else {
6286 len = os_strlen(pos);
6287 if (len & 1)
6288 return -1;
6289 len /= 2;
6290 tlvs = wpabuf_alloc(len);
6291 if (tlvs == NULL)
6292 return -1;
6293 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6294 wpabuf_free(tlvs);
6295 return -1;
6296 }
6297
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006298 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006299 wpabuf_free(tlvs);
6300 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006301 if (ref == 0)
6302 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006303 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006304 if (os_snprintf_error(buflen, res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006305 return -1;
6306 return res;
6307}
6308
6309
6310static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6311 char *cmd)
6312{
6313 long long unsigned val;
6314 u64 req;
6315 if (sscanf(cmd, "%llx", &val) != 1)
6316 return -1;
6317 req = val;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006318 return wpas_p2p_sd_cancel_request(wpa_s, req);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006319}
6320
6321
6322static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6323{
6324 int freq;
6325 u8 dst[ETH_ALEN];
6326 u8 dialog_token;
6327 struct wpabuf *resp_tlvs;
6328 char *pos, *pos2;
6329 size_t len;
6330
6331 pos = os_strchr(cmd, ' ');
6332 if (pos == NULL)
6333 return -1;
6334 *pos++ = '\0';
6335 freq = atoi(cmd);
6336 if (freq == 0)
6337 return -1;
6338
6339 if (hwaddr_aton(pos, dst))
6340 return -1;
6341 pos += 17;
6342 if (*pos != ' ')
6343 return -1;
6344 pos++;
6345
6346 pos2 = os_strchr(pos, ' ');
6347 if (pos2 == NULL)
6348 return -1;
6349 *pos2++ = '\0';
6350 dialog_token = atoi(pos);
6351
6352 len = os_strlen(pos2);
6353 if (len & 1)
6354 return -1;
6355 len /= 2;
6356 resp_tlvs = wpabuf_alloc(len);
6357 if (resp_tlvs == NULL)
6358 return -1;
6359 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6360 wpabuf_free(resp_tlvs);
6361 return -1;
6362 }
6363
6364 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6365 wpabuf_free(resp_tlvs);
6366 return 0;
6367}
6368
6369
6370static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6371 char *cmd)
6372{
Dmitry Shmidt04949592012-07-19 12:16:46 -07006373 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6374 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006375 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6376 return 0;
6377}
6378
6379
6380static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6381 char *cmd)
6382{
6383 char *pos;
6384 size_t len;
6385 struct wpabuf *query, *resp;
6386
6387 pos = os_strchr(cmd, ' ');
6388 if (pos == NULL)
6389 return -1;
6390 *pos++ = '\0';
6391
6392 len = os_strlen(cmd);
6393 if (len & 1)
6394 return -1;
6395 len /= 2;
6396 query = wpabuf_alloc(len);
6397 if (query == NULL)
6398 return -1;
6399 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6400 wpabuf_free(query);
6401 return -1;
6402 }
6403
6404 len = os_strlen(pos);
6405 if (len & 1) {
6406 wpabuf_free(query);
6407 return -1;
6408 }
6409 len /= 2;
6410 resp = wpabuf_alloc(len);
6411 if (resp == NULL) {
6412 wpabuf_free(query);
6413 return -1;
6414 }
6415 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
6416 wpabuf_free(query);
6417 wpabuf_free(resp);
6418 return -1;
6419 }
6420
6421 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
6422 wpabuf_free(query);
6423 wpabuf_free(resp);
6424 return -1;
6425 }
6426 return 0;
6427}
6428
6429
6430static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6431{
6432 char *pos;
6433 u8 version;
6434
6435 pos = os_strchr(cmd, ' ');
6436 if (pos == NULL)
6437 return -1;
6438 *pos++ = '\0';
6439
6440 if (hexstr2bin(cmd, &version, 1) < 0)
6441 return -1;
6442
6443 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6444}
6445
6446
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006447static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6448 u8 replace, char *cmd)
6449{
6450 char *pos;
6451 char *adv_str;
6452 u32 auto_accept, adv_id, svc_state, config_methods;
6453 char *svc_info = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006454 char *cpt_prio_str;
6455 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006456
6457 pos = os_strchr(cmd, ' ');
6458 if (pos == NULL)
6459 return -1;
6460 *pos++ = '\0';
6461
6462 /* Auto-Accept value is mandatory, and must be one of the
6463 * single values (0, 1, 2, 4) */
6464 auto_accept = atoi(cmd);
6465 switch (auto_accept) {
6466 case P2PS_SETUP_NONE: /* No auto-accept */
6467 case P2PS_SETUP_NEW:
6468 case P2PS_SETUP_CLIENT:
6469 case P2PS_SETUP_GROUP_OWNER:
6470 break;
6471 default:
6472 return -1;
6473 }
6474
6475 /* Advertisement ID is mandatory */
6476 cmd = pos;
6477 pos = os_strchr(cmd, ' ');
6478 if (pos == NULL)
6479 return -1;
6480 *pos++ = '\0';
6481
6482 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6483 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6484 return -1;
6485
6486 /* Only allow replacements if exist, and adds if not */
6487 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6488 if (!replace)
6489 return -1;
6490 } else {
6491 if (replace)
6492 return -1;
6493 }
6494
6495 /* svc_state between 0 - 0xff is mandatory */
6496 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6497 return -1;
6498
6499 pos = os_strchr(pos, ' ');
6500 if (pos == NULL)
6501 return -1;
6502
6503 /* config_methods is mandatory */
6504 pos++;
6505 if (sscanf(pos, "%x", &config_methods) != 1)
6506 return -1;
6507
6508 if (!(config_methods &
6509 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6510 return -1;
6511
6512 pos = os_strchr(pos, ' ');
6513 if (pos == NULL)
6514 return -1;
6515
6516 pos++;
6517 adv_str = pos;
6518
6519 /* Advertisement string is mandatory */
6520 if (!pos[0] || pos[0] == ' ')
6521 return -1;
6522
6523 /* Terminate svc string */
6524 pos = os_strchr(pos, ' ');
6525 if (pos != NULL)
6526 *pos++ = '\0';
6527
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006528 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6529 if (cpt_prio_str) {
6530 pos = os_strchr(pos, ' ');
6531 if (pos != NULL)
6532 *pos++ = '\0';
6533
6534 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6535 return -1;
6536 } else {
6537 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6538 cpt_prio[1] = 0;
6539 }
6540
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006541 /* Service and Response Information are optional */
6542 if (pos && pos[0]) {
6543 size_t len;
6544
6545 /* Note the bare ' included, which cannot exist legally
6546 * in unescaped string. */
6547 svc_info = os_strstr(pos, "svc_info='");
6548
6549 if (svc_info) {
6550 svc_info += 9;
6551 len = os_strlen(svc_info);
6552 utf8_unescape(svc_info, len, svc_info, len);
6553 }
6554 }
6555
6556 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6557 (u8) svc_state, (u16) config_methods,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006558 svc_info, cpt_prio);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006559}
6560
6561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006562static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6563{
6564 char *pos;
6565
6566 pos = os_strchr(cmd, ' ');
6567 if (pos == NULL)
6568 return -1;
6569 *pos++ = '\0';
6570
6571 if (os_strcmp(cmd, "bonjour") == 0)
6572 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6573 if (os_strcmp(cmd, "upnp") == 0)
6574 return p2p_ctrl_service_add_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006575 if (os_strcmp(cmd, "asp") == 0)
6576 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006577 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6578 return -1;
6579}
6580
6581
6582static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6583 char *cmd)
6584{
6585 size_t len;
6586 struct wpabuf *query;
6587 int ret;
6588
6589 len = os_strlen(cmd);
6590 if (len & 1)
6591 return -1;
6592 len /= 2;
6593 query = wpabuf_alloc(len);
6594 if (query == NULL)
6595 return -1;
6596 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6597 wpabuf_free(query);
6598 return -1;
6599 }
6600
6601 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6602 wpabuf_free(query);
6603 return ret;
6604}
6605
6606
6607static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6608{
6609 char *pos;
6610 u8 version;
6611
6612 pos = os_strchr(cmd, ' ');
6613 if (pos == NULL)
6614 return -1;
6615 *pos++ = '\0';
6616
6617 if (hexstr2bin(cmd, &version, 1) < 0)
6618 return -1;
6619
6620 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6621}
6622
6623
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006624static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6625{
6626 u32 adv_id;
6627
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07006628 if (os_strcmp(cmd, "all") == 0) {
6629 wpas_p2p_service_flush_asp(wpa_s);
6630 return 0;
6631 }
6632
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006633 if (sscanf(cmd, "%x", &adv_id) != 1)
6634 return -1;
6635
6636 return wpas_p2p_service_del_asp(wpa_s, adv_id);
6637}
6638
6639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006640static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6641{
6642 char *pos;
6643
6644 pos = os_strchr(cmd, ' ');
6645 if (pos == NULL)
6646 return -1;
6647 *pos++ = '\0';
6648
6649 if (os_strcmp(cmd, "bonjour") == 0)
6650 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
6651 if (os_strcmp(cmd, "upnp") == 0)
6652 return p2p_ctrl_service_del_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006653 if (os_strcmp(cmd, "asp") == 0)
6654 return p2p_ctrl_service_del_asp(wpa_s, pos);
6655 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6656 return -1;
6657}
6658
6659
6660static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
6661{
6662 char *pos;
6663
6664 pos = os_strchr(cmd, ' ');
6665 if (pos == NULL)
6666 return -1;
6667 *pos++ = '\0';
6668
6669 if (os_strcmp(cmd, "asp") == 0)
6670 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
6671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006672 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6673 return -1;
6674}
6675
6676
6677static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
6678{
6679 u8 addr[ETH_ALEN];
6680
6681 /* <addr> */
6682
6683 if (hwaddr_aton(cmd, addr))
6684 return -1;
6685
6686 return wpas_p2p_reject(wpa_s, addr);
6687}
6688
6689
6690static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
6691{
6692 char *pos;
6693 int id;
6694 struct wpa_ssid *ssid;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006695 u8 *_peer = NULL, peer[ETH_ALEN];
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08006696 int freq = 0, pref_freq = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08006697 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006698 int edmg;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006699 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006700
6701 id = atoi(cmd);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006702 pos = os_strstr(cmd, " peer=");
6703 if (pos) {
6704 pos += 6;
6705 if (hwaddr_aton(pos, peer))
6706 return -1;
6707 _peer = peer;
6708 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006709 ssid = wpa_config_get_network(wpa_s->conf, id);
6710 if (ssid == NULL || ssid->disabled != 2) {
6711 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6712 "for persistent P2P group",
6713 id);
6714 return -1;
6715 }
6716
Jouni Malinen31be0a42012-08-31 21:20:51 +03006717 pos = os_strstr(cmd, " freq=");
6718 if (pos) {
6719 pos += 6;
6720 freq = atoi(pos);
6721 if (freq <= 0)
6722 return -1;
6723 }
6724
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08006725 pos = os_strstr(cmd, " pref=");
6726 if (pos) {
6727 pos += 6;
6728 pref_freq = atoi(pos);
6729 if (pref_freq <= 0)
6730 return -1;
6731 }
6732
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006733 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6734 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6735 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006736 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006737 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Jouni Malinen31be0a42012-08-31 21:20:51 +03006738
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006739 pos = os_strstr(cmd, "freq2=");
6740 if (pos)
6741 freq2 = atoi(pos + 6);
6742
6743 pos = os_strstr(cmd, " max_oper_chwidth=");
6744 if (pos)
6745 chwidth = atoi(pos + 18);
6746
6747 max_oper_chwidth = parse_freq(chwidth, freq2);
6748 if (max_oper_chwidth < 0)
6749 return -1;
6750
Hai Shaloma20dcd72022-02-04 13:43:00 -08006751 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
6752
6753 if (allow_6ghz && chwidth == 40)
6754 max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
6755
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006756 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006757 max_oper_chwidth, pref_freq, he, edmg,
6758 allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006759}
6760
6761
6762static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
6763{
6764 char *pos;
6765 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006766 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006767
6768 pos = os_strstr(cmd, " peer=");
6769 if (!pos)
6770 return -1;
6771
6772 *pos = '\0';
6773 pos += 6;
6774 if (hwaddr_aton(pos, peer)) {
6775 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
6776 return -1;
6777 }
6778
Hai Shaloma20dcd72022-02-04 13:43:00 -08006779 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
6780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006781 pos = os_strstr(pos, " go_dev_addr=");
6782 if (pos) {
6783 pos += 13;
6784 if (hwaddr_aton(pos, go_dev_addr)) {
6785 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
6786 pos);
6787 return -1;
6788 }
6789 go_dev = go_dev_addr;
6790 }
6791
Hai Shaloma20dcd72022-02-04 13:43:00 -08006792 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006793}
6794
6795
6796static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
6797{
6798 if (os_strncmp(cmd, "persistent=", 11) == 0)
6799 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
6800 if (os_strncmp(cmd, "group=", 6) == 0)
6801 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
6802
6803 return -1;
6804}
6805
6806
6807static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006808 int id, int freq, int vht_center_freq2,
Hai Shalom74f70d42019-02-11 14:42:39 -08006809 int ht40, int vht, int vht_chwidth,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006810 int he, int edmg, bool allow_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006811{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006812 struct wpa_ssid *ssid;
6813
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006814 ssid = wpa_config_get_network(wpa_s->conf, id);
6815 if (ssid == NULL || ssid->disabled != 2) {
6816 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
6817 "for persistent P2P group",
6818 id);
6819 return -1;
6820 }
6821
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006822 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
6823 vht_center_freq2, 0, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006824 vht_chwidth, he, edmg,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006825 NULL, 0, 0, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006826}
6827
6828
6829static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
6830{
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006831 int freq = 0, persistent = 0, group_id = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006832 bool allow_6ghz = false;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006833 int vht = wpa_s->conf->p2p_go_vht;
6834 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006835 int he = wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006836 int edmg = wpa_s->conf->p2p_go_edmg;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006837 int max_oper_chwidth, chwidth = 0, freq2 = 0;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006838 char *token, *context = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006839#ifdef CONFIG_ACS
6840 int acs = 0;
6841#endif /* CONFIG_ACS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006842
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006843 while ((token = str_token(cmd, " ", &context))) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07006844 if (sscanf(token, "freq2=%d", &freq2) == 1 ||
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006845 sscanf(token, "persistent=%d", &group_id) == 1 ||
6846 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006847 continue;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006848#ifdef CONFIG_ACS
6849 } else if (os_strcmp(token, "freq=acs") == 0) {
6850 acs = 1;
6851#endif /* CONFIG_ACS */
6852 } else if (sscanf(token, "freq=%d", &freq) == 1) {
6853 continue;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006854 } else if (os_strcmp(token, "ht40") == 0) {
6855 ht40 = 1;
6856 } else if (os_strcmp(token, "vht") == 0) {
6857 vht = 1;
6858 ht40 = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08006859 } else if (os_strcmp(token, "he") == 0) {
6860 he = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006861 } else if (os_strcmp(token, "edmg") == 0) {
6862 edmg = 1;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006863 } else if (os_strcmp(token, "persistent") == 0) {
6864 persistent = 1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006865 } else if (os_strcmp(token, "allow_6ghz") == 0) {
6866 allow_6ghz = true;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006867 } else {
6868 wpa_printf(MSG_DEBUG,
6869 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
6870 token);
6871 return -1;
6872 }
6873 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006874
Roshan Pius3a1667e2018-07-03 15:17:14 -07006875#ifdef CONFIG_ACS
6876 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
6877 (acs || freq == 2 || freq == 5)) {
6878 if (freq == 2 && wpa_s->best_24_freq <= 0) {
6879 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
6880 wpa_s->p2p_go_do_acs = 1;
6881 freq = 0;
6882 } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
6883 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
6884 wpa_s->p2p_go_do_acs = 1;
6885 freq = 0;
6886 } else {
6887 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
6888 wpa_s->p2p_go_do_acs = 1;
6889 }
Hai Shalom021b0b52019-04-10 11:17:58 -07006890 } else {
6891 wpa_s->p2p_go_do_acs = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006892 }
6893#endif /* CONFIG_ACS */
6894
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006895 max_oper_chwidth = parse_freq(chwidth, freq2);
6896 if (max_oper_chwidth < 0)
6897 return -1;
6898
Hai Shaloma20dcd72022-02-04 13:43:00 -08006899 if (allow_6ghz && chwidth == 40)
6900 max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
6901
6902 /* Allow DFS to be used for Autonomous GO */
6903 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
6904 WPA_DRIVER_FLAGS_DFS_OFFLOAD);
6905
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006906 if (group_id >= 0)
6907 return p2p_ctrl_group_add_persistent(wpa_s, group_id,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006908 freq, freq2, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006909 max_oper_chwidth, he,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006910 edmg, allow_6ghz);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006911
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006912 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006913 max_oper_chwidth, he, edmg, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006914}
6915
6916
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006917static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
6918 char *buf, size_t buflen)
6919{
6920 u8 dev_addr[ETH_ALEN];
6921 struct wpa_ssid *ssid;
6922 int res;
6923 const u8 *iaddr;
6924
6925 ssid = wpa_s->current_ssid;
6926 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
6927 hwaddr_aton(cmd, dev_addr))
6928 return -1;
6929
6930 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
6931 if (!iaddr)
6932 return -1;
6933 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
6934 if (os_snprintf_error(buflen, res))
6935 return -1;
6936 return res;
6937}
6938
6939
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006940static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
6941 const u8 *p2p_dev_addr)
6942{
6943 struct wpa_supplicant *wpa_s;
6944
6945 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6946 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
6947 return 1;
6948 }
6949
6950 return 0;
6951}
6952
6953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
6955 char *buf, size_t buflen)
6956{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006957 u8 addr[ETH_ALEN], *addr_ptr, group_capab;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006958 int next, res;
6959 const struct p2p_peer_info *info;
6960 char *pos, *end;
6961 char devtype[WPS_DEV_TYPE_BUFSIZE];
6962 struct wpa_ssid *ssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006963 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006964
6965 if (!wpa_s->global->p2p)
6966 return -1;
6967
6968 if (os_strcmp(cmd, "FIRST") == 0) {
6969 addr_ptr = NULL;
6970 next = 0;
6971 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
6972 if (hwaddr_aton(cmd + 5, addr) < 0)
6973 return -1;
6974 addr_ptr = addr;
6975 next = 1;
6976 } else {
6977 if (hwaddr_aton(cmd, addr) < 0)
6978 return -1;
6979 addr_ptr = addr;
6980 next = 0;
6981 }
6982
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006983 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
6984 if (info == NULL)
6985 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006986 group_capab = info->group_capab;
6987
6988 if (group_capab &&
6989 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
6990 wpa_printf(MSG_DEBUG,
6991 "P2P: Could not find any BSS with p2p_dev_addr "
6992 MACSTR ", hence override group_capab from 0x%x to 0",
6993 MAC2STR(info->p2p_device_addr), group_capab);
6994 group_capab = 0;
6995 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006996
6997 pos = buf;
6998 end = buf + buflen;
6999
7000 res = os_snprintf(pos, end - pos, MACSTR "\n"
7001 "pri_dev_type=%s\n"
7002 "device_name=%s\n"
7003 "manufacturer=%s\n"
7004 "model_name=%s\n"
7005 "model_number=%s\n"
7006 "serial_number=%s\n"
7007 "config_methods=0x%x\n"
7008 "dev_capab=0x%x\n"
7009 "group_capab=0x%x\n"
7010 "level=%d\n",
7011 MAC2STR(info->p2p_device_addr),
7012 wps_dev_type_bin2str(info->pri_dev_type,
7013 devtype, sizeof(devtype)),
7014 info->device_name,
7015 info->manufacturer,
7016 info->model_name,
7017 info->model_number,
7018 info->serial_number,
7019 info->config_methods,
7020 info->dev_capab,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007021 group_capab,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007022 info->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007023 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007024 return pos - buf;
7025 pos += res;
7026
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007027 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7028 {
7029 const u8 *t;
7030 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7031 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7032 wps_dev_type_bin2str(t, devtype,
7033 sizeof(devtype)));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007034 if (os_snprintf_error(end - pos, res))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007035 return pos - buf;
7036 pos += res;
7037 }
7038
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007039 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007040 if (ssid) {
7041 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007042 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007043 return pos - buf;
7044 pos += res;
7045 }
7046
7047 res = p2p_get_peer_info_txt(info, pos, end - pos);
7048 if (res < 0)
7049 return pos - buf;
7050 pos += res;
7051
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007052 if (info->vendor_elems) {
7053 res = os_snprintf(pos, end - pos, "vendor_elems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007054 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007055 return pos - buf;
7056 pos += res;
7057
7058 pos += wpa_snprintf_hex(pos, end - pos,
7059 wpabuf_head(info->vendor_elems),
7060 wpabuf_len(info->vendor_elems));
7061
7062 res = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007063 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007064 return pos - buf;
7065 pos += res;
7066 }
7067
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007068 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007069}
7070
7071
Dmitry Shmidt04949592012-07-19 12:16:46 -07007072static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7073 const char *param)
7074{
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007075 unsigned int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007076
7077 if (wpa_s->global->p2p == NULL)
7078 return -1;
7079
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007080 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7081 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007082
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007083 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7084 struct wpa_freq_range *freq;
7085 freq = &wpa_s->global->p2p_disallow_freq.range[i];
Dmitry Shmidt04949592012-07-19 12:16:46 -07007086 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007087 freq->min, freq->max);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007088 }
7089
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007090 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007091 return 0;
7092}
7093
7094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007095static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7096{
7097 char *param;
7098
7099 if (wpa_s->global->p2p == NULL)
7100 return -1;
7101
7102 param = os_strchr(cmd, ' ');
7103 if (param == NULL)
7104 return -1;
7105 *param++ = '\0';
7106
7107 if (os_strcmp(cmd, "discoverability") == 0) {
7108 p2p_set_client_discoverability(wpa_s->global->p2p,
7109 atoi(param));
7110 return 0;
7111 }
7112
7113 if (os_strcmp(cmd, "managed") == 0) {
7114 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7115 return 0;
7116 }
7117
7118 if (os_strcmp(cmd, "listen_channel") == 0) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08007119 char *pos;
7120 u8 channel, op_class;
7121
7122 channel = atoi(param);
7123 pos = os_strchr(param, ' ');
7124 op_class = pos ? atoi(pos) : 81;
7125
7126 return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7127 channel, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007128 }
7129
7130 if (os_strcmp(cmd, "ssid_postfix") == 0) {
7131 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7132 os_strlen(param));
7133 }
7134
7135 if (os_strcmp(cmd, "noa") == 0) {
7136 char *pos;
7137 int count, start, duration;
7138 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
7139 count = atoi(param);
7140 pos = os_strchr(param, ',');
7141 if (pos == NULL)
7142 return -1;
7143 pos++;
7144 start = atoi(pos);
7145 pos = os_strchr(pos, ',');
7146 if (pos == NULL)
7147 return -1;
7148 pos++;
7149 duration = atoi(pos);
7150 if (count < 0 || count > 255 || start < 0 || duration < 0)
7151 return -1;
7152 if (count == 0 && duration > 0)
7153 return -1;
7154 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7155 "start=%d duration=%d", count, start, duration);
7156 return wpas_p2p_set_noa(wpa_s, count, start, duration);
7157 }
7158
7159 if (os_strcmp(cmd, "ps") == 0)
7160 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7161
7162 if (os_strcmp(cmd, "oppps") == 0)
7163 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7164
7165 if (os_strcmp(cmd, "ctwindow") == 0)
7166 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7167
7168 if (os_strcmp(cmd, "disabled") == 0) {
7169 wpa_s->global->p2p_disabled = atoi(param);
7170 wpa_printf(MSG_DEBUG, "P2P functionality %s",
7171 wpa_s->global->p2p_disabled ?
7172 "disabled" : "enabled");
7173 if (wpa_s->global->p2p_disabled) {
7174 wpas_p2p_stop_find(wpa_s);
7175 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7176 p2p_flush(wpa_s->global->p2p);
7177 }
7178 return 0;
7179 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007180
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007181 if (os_strcmp(cmd, "conc_pref") == 0) {
7182 if (os_strcmp(param, "sta") == 0)
7183 wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7184 else if (os_strcmp(param, "p2p") == 0)
7185 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007186 else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007187 wpa_printf(MSG_INFO, "Invalid conc_pref value");
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007188 return -1;
7189 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007190 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
Dmitry Shmidt04949592012-07-19 12:16:46 -07007191 "%s", param);
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007192 return 0;
7193 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007195 if (os_strcmp(cmd, "force_long_sd") == 0) {
7196 wpa_s->force_long_sd = atoi(param);
7197 return 0;
7198 }
7199
7200 if (os_strcmp(cmd, "peer_filter") == 0) {
7201 u8 addr[ETH_ALEN];
7202 if (hwaddr_aton(param, addr))
7203 return -1;
7204 p2p_set_peer_filter(wpa_s->global->p2p, addr);
7205 return 0;
7206 }
7207
7208 if (os_strcmp(cmd, "cross_connect") == 0)
7209 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7210
7211 if (os_strcmp(cmd, "go_apsd") == 0) {
7212 if (os_strcmp(param, "disable") == 0)
7213 wpa_s->set_ap_uapsd = 0;
7214 else {
7215 wpa_s->set_ap_uapsd = 1;
7216 wpa_s->ap_uapsd = atoi(param);
7217 }
7218 return 0;
7219 }
7220
7221 if (os_strcmp(cmd, "client_apsd") == 0) {
7222 if (os_strcmp(param, "disable") == 0)
7223 wpa_s->set_sta_uapsd = 0;
7224 else {
7225 int be, bk, vi, vo;
7226 char *pos;
7227 /* format: BE,BK,VI,VO;max SP Length */
7228 be = atoi(param);
7229 pos = os_strchr(param, ',');
7230 if (pos == NULL)
7231 return -1;
7232 pos++;
7233 bk = atoi(pos);
7234 pos = os_strchr(pos, ',');
7235 if (pos == NULL)
7236 return -1;
7237 pos++;
7238 vi = atoi(pos);
7239 pos = os_strchr(pos, ',');
7240 if (pos == NULL)
7241 return -1;
7242 pos++;
7243 vo = atoi(pos);
7244 /* ignore max SP Length for now */
7245
7246 wpa_s->set_sta_uapsd = 1;
7247 wpa_s->sta_uapsd = 0;
7248 if (be)
7249 wpa_s->sta_uapsd |= BIT(0);
7250 if (bk)
7251 wpa_s->sta_uapsd |= BIT(1);
7252 if (vi)
7253 wpa_s->sta_uapsd |= BIT(2);
7254 if (vo)
7255 wpa_s->sta_uapsd |= BIT(3);
7256 }
7257 return 0;
7258 }
7259
Dmitry Shmidt04949592012-07-19 12:16:46 -07007260 if (os_strcmp(cmd, "disallow_freq") == 0)
7261 return p2p_ctrl_disallow_freq(wpa_s, param);
7262
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007263 if (os_strcmp(cmd, "disc_int") == 0) {
7264 int min_disc_int, max_disc_int, max_disc_tu;
7265 char *pos;
7266
7267 pos = param;
7268
7269 min_disc_int = atoi(pos);
7270 pos = os_strchr(pos, ' ');
7271 if (pos == NULL)
7272 return -1;
7273 *pos++ = '\0';
7274
7275 max_disc_int = atoi(pos);
7276 pos = os_strchr(pos, ' ');
7277 if (pos == NULL)
7278 return -1;
7279 *pos++ = '\0';
7280
7281 max_disc_tu = atoi(pos);
7282
7283 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7284 max_disc_int, max_disc_tu);
7285 }
7286
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007287 if (os_strcmp(cmd, "per_sta_psk") == 0) {
7288 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7289 return 0;
7290 }
7291
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007292#ifdef CONFIG_WPS_NFC
7293 if (os_strcmp(cmd, "nfc_tag") == 0)
7294 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7295#endif /* CONFIG_WPS_NFC */
7296
7297 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7298 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7299 return 0;
7300 }
7301
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007302 if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7303 int op_class, chan;
7304
7305 op_class = atoi(param);
7306 param = os_strchr(param, ':');
7307 if (!param)
7308 return -1;
7309 param++;
7310 chan = atoi(param);
7311 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7312 chan);
7313 return 0;
7314 }
7315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007316 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7317 cmd);
7318
7319 return -1;
7320}
7321
7322
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007323static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7324{
7325 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7326 wpa_s->force_long_sd = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007327
7328#ifdef CONFIG_TESTING_OPTIONS
7329 os_free(wpa_s->get_pref_freq_list_override);
7330 wpa_s->get_pref_freq_list_override = NULL;
7331#endif /* CONFIG_TESTING_OPTIONS */
7332
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007333 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007334 wpa_s->parent->p2ps_method_config_any = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007335 if (wpa_s->global->p2p)
7336 p2p_flush(wpa_s->global->p2p);
7337}
7338
7339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007340static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7341{
7342 char *pos, *pos2;
7343 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7344
7345 if (cmd[0]) {
7346 pos = os_strchr(cmd, ' ');
7347 if (pos == NULL)
7348 return -1;
7349 *pos++ = '\0';
7350 dur1 = atoi(cmd);
7351
7352 pos2 = os_strchr(pos, ' ');
7353 if (pos2)
7354 *pos2++ = '\0';
7355 int1 = atoi(pos);
7356 } else
7357 pos2 = NULL;
7358
7359 if (pos2) {
7360 pos = os_strchr(pos2, ' ');
7361 if (pos == NULL)
7362 return -1;
7363 *pos++ = '\0';
7364 dur2 = atoi(pos2);
7365 int2 = atoi(pos);
7366 }
7367
7368 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7369}
7370
7371
7372static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7373{
7374 char *pos;
7375 unsigned int period = 0, interval = 0;
7376
7377 if (cmd[0]) {
7378 pos = os_strchr(cmd, ' ');
7379 if (pos == NULL)
7380 return -1;
7381 *pos++ = '\0';
7382 period = atoi(cmd);
7383 interval = atoi(pos);
7384 }
7385
7386 return wpas_p2p_ext_listen(wpa_s, period, interval);
7387}
7388
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007389
7390static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7391{
7392 const char *pos;
7393 u8 peer[ETH_ALEN];
7394 int iface_addr = 0;
7395
7396 pos = cmd;
7397 if (os_strncmp(pos, "iface=", 6) == 0) {
7398 iface_addr = 1;
7399 pos += 6;
7400 }
7401 if (hwaddr_aton(pos, peer))
7402 return -1;
7403
7404 wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7405 return 0;
7406}
7407
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07007408
7409static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7410{
7411 int freq = 0, period = 0, interval = 0, count = 0;
7412
7413 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7414 {
7415 wpa_printf(MSG_DEBUG,
7416 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7417 return -1;
7418 }
7419
7420 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7421}
7422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007423#endif /* CONFIG_P2P */
7424
7425
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007426static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7427{
7428 struct wpa_freq_range_list ranges;
7429 int *freqs = NULL;
7430 struct hostapd_hw_modes *mode;
7431 u16 i;
7432
7433 if (wpa_s->hw.modes == NULL)
7434 return NULL;
7435
7436 os_memset(&ranges, 0, sizeof(ranges));
7437 if (freq_range_list_parse(&ranges, val) < 0)
7438 return NULL;
7439
7440 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7441 int j;
7442
7443 mode = &wpa_s->hw.modes[i];
7444 for (j = 0; j < mode->num_channels; j++) {
7445 unsigned int freq;
7446
7447 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7448 continue;
7449
7450 freq = mode->channels[j].freq;
7451 if (!freq_range_list_includes(&ranges, freq))
7452 continue;
7453
7454 int_array_add_unique(&freqs, freq);
7455 }
7456 }
7457
7458 os_free(ranges.range);
7459 return freqs;
7460}
7461
7462
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007463#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007464
7465static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7466{
7467 int auto_sel = 0;
7468 int *freqs = NULL;
7469
7470 if (param) {
7471 char *pos;
7472
7473 auto_sel = os_strstr(param, "auto") != NULL;
7474
7475 pos = os_strstr(param, "freq=");
7476 if (pos) {
7477 freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7478 if (freqs == NULL)
7479 return -1;
7480 }
7481
7482 }
7483
7484 return interworking_select(wpa_s, auto_sel, freqs);
7485}
7486
7487
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007488static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7489 int only_add)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007490{
7491 u8 bssid[ETH_ALEN];
7492 struct wpa_bss *bss;
7493
7494 if (hwaddr_aton(dst, bssid)) {
7495 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7496 return -1;
7497 }
7498
Hai Shalomfdcde762020-04-02 11:19:20 -07007499 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007500 if (bss == NULL) {
7501 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7502 MAC2STR(bssid));
7503 return -1;
7504 }
7505
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007506 if (bss->ssid_len == 0) {
7507 int found = 0;
7508
7509 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7510 " does not have SSID information", MAC2STR(bssid));
7511
7512 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7513 list) {
7514 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
7515 bss->ssid_len > 0) {
7516 found = 1;
7517 break;
7518 }
7519 }
7520
7521 if (!found)
7522 return -1;
7523 wpa_printf(MSG_DEBUG,
7524 "Found another matching BSS entry with SSID");
7525 }
7526
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007527 return interworking_connect(wpa_s, bss, only_add);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007528}
7529
7530
7531static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7532{
7533 u8 dst_addr[ETH_ALEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07007534 int used, freq = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007535 char *pos;
7536#define MAX_ANQP_INFO_ID 100
7537 u16 id[MAX_ANQP_INFO_ID];
7538 size_t num_id = 0;
Dmitry Shmidt15907092014-03-25 10:42:57 -07007539 u32 subtypes = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007540 u32 mbo_subtypes = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007541
7542 used = hwaddr_aton2(dst, dst_addr);
7543 if (used < 0)
7544 return -1;
7545 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007546 if (*pos == ' ')
7547 pos++;
Hai Shalom899fcc72020-10-19 14:38:18 -07007548
7549 if (os_strncmp(pos, "freq=", 5) == 0) {
7550 freq = atoi(pos + 5);
7551 pos = os_strchr(pos, ' ');
7552 if (!pos)
7553 return -1;
7554 pos++;
7555 }
7556
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007557 while (num_id < MAX_ANQP_INFO_ID) {
Dmitry Shmidt15907092014-03-25 10:42:57 -07007558 if (os_strncmp(pos, "hs20:", 5) == 0) {
7559#ifdef CONFIG_HS20
7560 int num = atoi(pos + 5);
7561 if (num <= 0 || num > 31)
7562 return -1;
7563 subtypes |= BIT(num);
7564#else /* CONFIG_HS20 */
7565 return -1;
7566#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007567 } else if (os_strncmp(pos, "mbo:", 4) == 0) {
7568#ifdef CONFIG_MBO
7569 int num = atoi(pos + 4);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007570
7571 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007572 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007573 mbo_subtypes |= BIT(num);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007574#else /* CONFIG_MBO */
7575 return -1;
7576#endif /* CONFIG_MBO */
Dmitry Shmidt15907092014-03-25 10:42:57 -07007577 } else {
7578 id[num_id] = atoi(pos);
7579 if (id[num_id])
7580 num_id++;
7581 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007582 pos = os_strchr(pos + 1, ',');
7583 if (pos == NULL)
7584 break;
7585 pos++;
7586 }
7587
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007588 if (num_id == 0 && !subtypes && !mbo_subtypes)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007589 return -1;
7590
Hai Shalom899fcc72020-10-19 14:38:18 -07007591 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007592 mbo_subtypes);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007593}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007594
7595
7596static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
7597{
7598 u8 dst_addr[ETH_ALEN];
7599 struct wpabuf *advproto, *query = NULL;
7600 int used, ret = -1;
7601 char *pos, *end;
7602 size_t len;
7603
7604 used = hwaddr_aton2(cmd, dst_addr);
7605 if (used < 0)
7606 return -1;
7607
7608 pos = cmd + used;
7609 while (*pos == ' ')
7610 pos++;
7611
7612 /* Advertisement Protocol ID */
7613 end = os_strchr(pos, ' ');
7614 if (end)
7615 len = end - pos;
7616 else
7617 len = os_strlen(pos);
7618 if (len & 0x01)
7619 return -1;
7620 len /= 2;
7621 if (len == 0)
7622 return -1;
7623 advproto = wpabuf_alloc(len);
7624 if (advproto == NULL)
7625 return -1;
7626 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
7627 goto fail;
7628
7629 if (end) {
7630 /* Optional Query Request */
7631 pos = end + 1;
7632 while (*pos == ' ')
7633 pos++;
7634
7635 len = os_strlen(pos);
7636 if (len) {
7637 if (len & 0x01)
7638 goto fail;
7639 len /= 2;
7640 if (len == 0)
7641 goto fail;
7642 query = wpabuf_alloc(len);
7643 if (query == NULL)
7644 goto fail;
7645 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
7646 goto fail;
7647 }
7648 }
7649
7650 ret = gas_send_request(wpa_s, dst_addr, advproto, query);
7651
7652fail:
7653 wpabuf_free(advproto);
7654 wpabuf_free(query);
7655
7656 return ret;
7657}
7658
7659
7660static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
7661 size_t buflen)
7662{
7663 u8 addr[ETH_ALEN];
7664 int dialog_token;
7665 int used;
7666 char *pos;
7667 size_t resp_len, start, requested_len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007668 struct wpabuf *resp;
7669 int ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007670
7671 used = hwaddr_aton2(cmd, addr);
7672 if (used < 0)
7673 return -1;
7674
7675 pos = cmd + used;
7676 while (*pos == ' ')
7677 pos++;
7678 dialog_token = atoi(pos);
7679
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007680 if (wpa_s->last_gas_resp &&
7681 os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
7682 dialog_token == wpa_s->last_gas_dialog_token)
7683 resp = wpa_s->last_gas_resp;
7684 else if (wpa_s->prev_gas_resp &&
7685 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
7686 dialog_token == wpa_s->prev_gas_dialog_token)
7687 resp = wpa_s->prev_gas_resp;
7688 else
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007689 return -1;
7690
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007691 resp_len = wpabuf_len(resp);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007692 start = 0;
7693 requested_len = resp_len;
7694
7695 pos = os_strchr(pos, ' ');
7696 if (pos) {
7697 start = atoi(pos);
7698 if (start > resp_len)
7699 return os_snprintf(buf, buflen, "FAIL-Invalid range");
7700 pos = os_strchr(pos, ',');
7701 if (pos == NULL)
7702 return -1;
7703 pos++;
7704 requested_len = atoi(pos);
7705 if (start + requested_len > resp_len)
7706 return os_snprintf(buf, buflen, "FAIL-Invalid range");
7707 }
7708
7709 if (requested_len * 2 + 1 > buflen)
7710 return os_snprintf(buf, buflen, "FAIL-Too long response");
7711
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007712 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
7713 requested_len);
7714
7715 if (start + requested_len == resp_len) {
7716 /*
7717 * Free memory by dropping the response after it has been
7718 * fetched.
7719 */
7720 if (resp == wpa_s->prev_gas_resp) {
7721 wpabuf_free(wpa_s->prev_gas_resp);
7722 wpa_s->prev_gas_resp = NULL;
7723 } else {
7724 wpabuf_free(wpa_s->last_gas_resp);
7725 wpa_s->last_gas_resp = NULL;
7726 }
7727 }
7728
7729 return ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007730}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007731#endif /* CONFIG_INTERWORKING */
7732
7733
Dmitry Shmidt04949592012-07-19 12:16:46 -07007734#ifdef CONFIG_HS20
7735
7736static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
7737{
7738 u8 dst_addr[ETH_ALEN];
7739 int used;
7740 char *pos;
7741 u32 subtypes = 0;
7742
7743 used = hwaddr_aton2(dst, dst_addr);
7744 if (used < 0)
7745 return -1;
7746 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007747 if (*pos == ' ')
7748 pos++;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007749 for (;;) {
7750 int num = atoi(pos);
7751 if (num <= 0 || num > 31)
7752 return -1;
7753 subtypes |= BIT(num);
7754 pos = os_strchr(pos + 1, ',');
7755 if (pos == NULL)
7756 break;
7757 pos++;
7758 }
7759
7760 if (subtypes == 0)
7761 return -1;
7762
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007763 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007764}
7765
7766
7767static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7768 const u8 *addr, const char *realm)
7769{
7770 u8 *buf;
7771 size_t rlen, len;
7772 int ret;
7773
7774 rlen = os_strlen(realm);
7775 len = 3 + rlen;
7776 buf = os_malloc(len);
7777 if (buf == NULL)
7778 return -1;
7779 buf[0] = 1; /* NAI Home Realm Count */
7780 buf[1] = 0; /* Formatted in accordance with RFC 4282 */
7781 buf[2] = rlen;
7782 os_memcpy(buf + 3, realm, rlen);
7783
7784 ret = hs20_anqp_send_req(wpa_s, addr,
7785 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007786 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007787
7788 os_free(buf);
7789
7790 return ret;
7791}
7792
7793
7794static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
7795 char *dst)
7796{
7797 struct wpa_cred *cred = wpa_s->conf->cred;
7798 u8 dst_addr[ETH_ALEN];
7799 int used;
7800 u8 *buf;
7801 size_t len;
7802 int ret;
7803
7804 used = hwaddr_aton2(dst, dst_addr);
7805 if (used < 0)
7806 return -1;
7807
7808 while (dst[used] == ' ')
7809 used++;
7810 if (os_strncmp(dst + used, "realm=", 6) == 0)
7811 return hs20_nai_home_realm_list(wpa_s, dst_addr,
7812 dst + used + 6);
7813
7814 len = os_strlen(dst + used);
7815
7816 if (len == 0 && cred && cred->realm)
7817 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
7818
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07007819 if (len & 1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007820 return -1;
7821 len /= 2;
7822 buf = os_malloc(len);
7823 if (buf == NULL)
7824 return -1;
7825 if (hexstr2bin(dst + used, buf, len) < 0) {
7826 os_free(buf);
7827 return -1;
7828 }
7829
7830 ret = hs20_anqp_send_req(wpa_s, dst_addr,
7831 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007832 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007833 os_free(buf);
7834
7835 return ret;
7836}
7837
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007838
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007839static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
7840 int buflen)
7841{
7842 u8 dst_addr[ETH_ALEN];
7843 int used;
7844 char *ctx = NULL, *icon, *poffset, *psize;
7845
7846 used = hwaddr_aton2(cmd, dst_addr);
7847 if (used < 0)
7848 return -1;
7849 cmd += used;
7850
7851 icon = str_token(cmd, " ", &ctx);
7852 poffset = str_token(cmd, " ", &ctx);
7853 psize = str_token(cmd, " ", &ctx);
7854 if (!icon || !poffset || !psize)
7855 return -1;
7856
7857 wpa_s->fetch_osu_icon_in_progress = 0;
7858 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
7859 reply, buflen);
7860}
7861
7862
7863static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
7864{
7865 u8 dst_addr[ETH_ALEN];
7866 int used;
7867 char *icon;
7868
7869 if (!cmd[0])
7870 return hs20_del_icon(wpa_s, NULL, NULL);
7871
7872 used = hwaddr_aton2(cmd, dst_addr);
7873 if (used < 0)
7874 return -1;
7875
7876 while (cmd[used] == ' ')
7877 used++;
7878 icon = cmd[used] ? &cmd[used] : NULL;
7879
7880 return hs20_del_icon(wpa_s, dst_addr, icon);
7881}
7882
7883
7884static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007885{
7886 u8 dst_addr[ETH_ALEN];
7887 int used;
7888 char *icon;
7889
7890 used = hwaddr_aton2(cmd, dst_addr);
7891 if (used < 0)
7892 return -1;
7893
7894 while (cmd[used] == ' ')
7895 used++;
7896 icon = &cmd[used];
7897
7898 wpa_s->fetch_osu_icon_in_progress = 0;
7899 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007900 (u8 *) icon, os_strlen(icon), inmem);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007901}
7902
Dmitry Shmidt04949592012-07-19 12:16:46 -07007903#endif /* CONFIG_HS20 */
7904
7905
Dmitry Shmidt04949592012-07-19 12:16:46 -07007906#ifdef CONFIG_AUTOSCAN
7907
7908static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
7909 char *cmd)
7910{
7911 enum wpa_states state = wpa_s->wpa_state;
7912 char *new_params = NULL;
7913
7914 if (os_strlen(cmd) > 0) {
7915 new_params = os_strdup(cmd);
7916 if (new_params == NULL)
7917 return -1;
7918 }
7919
7920 os_free(wpa_s->conf->autoscan);
7921 wpa_s->conf->autoscan = new_params;
7922
7923 if (wpa_s->conf->autoscan == NULL)
7924 autoscan_deinit(wpa_s);
7925 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
7926 autoscan_init(wpa_s, 1);
7927 else if (state == WPA_SCANNING)
7928 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007929 else
7930 wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
7931 wpa_supplicant_state_txt(state));
Dmitry Shmidt04949592012-07-19 12:16:46 -07007932
7933 return 0;
7934}
7935
7936#endif /* CONFIG_AUTOSCAN */
7937
7938
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007939#ifdef CONFIG_WNM
7940
7941static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
7942{
7943 int enter;
7944 int intval = 0;
7945 char *pos;
7946 int ret;
7947 struct wpabuf *tfs_req = NULL;
7948
7949 if (os_strncmp(cmd, "enter", 5) == 0)
7950 enter = 1;
7951 else if (os_strncmp(cmd, "exit", 4) == 0)
7952 enter = 0;
7953 else
7954 return -1;
7955
7956 pos = os_strstr(cmd, " interval=");
7957 if (pos)
7958 intval = atoi(pos + 10);
7959
7960 pos = os_strstr(cmd, " tfs_req=");
7961 if (pos) {
7962 char *end;
7963 size_t len;
7964 pos += 9;
7965 end = os_strchr(pos, ' ');
7966 if (end)
7967 len = end - pos;
7968 else
7969 len = os_strlen(pos);
7970 if (len & 1)
7971 return -1;
7972 len /= 2;
7973 tfs_req = wpabuf_alloc(len);
7974 if (tfs_req == NULL)
7975 return -1;
7976 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
7977 wpabuf_free(tfs_req);
7978 return -1;
7979 }
7980 }
7981
7982 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
7983 WNM_SLEEP_MODE_EXIT, intval,
7984 tfs_req);
7985 wpabuf_free(tfs_req);
7986
7987 return ret;
7988}
7989
Dmitry Shmidt44c95782013-05-17 09:51:35 -07007990
7991static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
7992{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007993 int query_reason, list = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007994 char *btm_candidates = NULL;
Dmitry Shmidt44c95782013-05-17 09:51:35 -07007995
7996 query_reason = atoi(cmd);
7997
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007998 cmd = os_strchr(cmd, ' ');
7999 if (cmd) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008000 if (os_strncmp(cmd, " list", 5) == 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008001 list = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008002 else
8003 btm_candidates = cmd;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008004 }
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008005
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008006 wpa_printf(MSG_DEBUG,
8007 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8008 query_reason, list ? " candidate list" : "");
8009
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008010 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8011 btm_candidates,
8012 list);
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008013}
8014
Hai Shalom39ba6fc2019-01-22 12:40:38 -08008015
8016static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8017 char *cmd)
8018{
8019 struct wpabuf *elems;
8020 int ret;
8021
8022 elems = wpabuf_parse_bin(cmd);
8023 if (!elems)
8024 return -1;
8025
8026 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8027 wpabuf_free(elems);
8028 return ret;
8029}
8030
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008031#endif /* CONFIG_WNM */
8032
8033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008034static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8035 size_t buflen)
8036{
8037 struct wpa_signal_info si;
8038 int ret;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008039 char *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008040
8041 ret = wpa_drv_signal_poll(wpa_s, &si);
8042 if (ret)
8043 return -1;
8044
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008045 pos = buf;
8046 end = buf + buflen;
8047
8048 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008049 "NOISE=%d\nFREQUENCY=%u\n",
8050 si.current_signal, si.current_txrate / 1000,
8051 si.current_noise, si.frequency);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008052 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008053 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008054 pos += ret;
8055
8056 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8057 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008058 channel_width_to_string(si.chanwidth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008059 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008060 return -1;
8061 pos += ret;
8062 }
8063
Roshan Pius3a1667e2018-07-03 15:17:14 -07008064 if (si.center_frq1 > 0) {
8065 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8066 si.center_frq1);
8067 if (os_snprintf_error(end - pos, ret))
8068 return -1;
8069 pos += ret;
8070 }
8071
8072 if (si.center_frq2 > 0) {
8073 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8074 si.center_frq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008075 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008076 return -1;
8077 pos += ret;
8078 }
8079
8080 if (si.avg_signal) {
8081 ret = os_snprintf(pos, end - pos,
8082 "AVG_RSSI=%d\n", si.avg_signal);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008083 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008084 return -1;
8085 pos += ret;
8086 }
8087
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07008088 if (si.avg_beacon_signal) {
8089 ret = os_snprintf(pos, end - pos,
8090 "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
8091 if (os_snprintf_error(end - pos, ret))
8092 return -1;
8093 pos += ret;
8094 }
8095
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008096 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008097}
8098
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008099
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008100static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8101 const char *cmd)
8102{
8103 const char *pos;
8104 int threshold = 0;
8105 int hysteresis = 0;
8106
8107 if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8108 wpa_printf(MSG_DEBUG,
8109 "Reject SIGNAL_MONITOR command - bgscan is active");
8110 return -1;
8111 }
8112 pos = os_strstr(cmd, "THRESHOLD=");
8113 if (pos)
8114 threshold = atoi(pos + 10);
8115 pos = os_strstr(cmd, "HYSTERESIS=");
8116 if (pos)
8117 hysteresis = atoi(pos + 11);
8118 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8119}
8120
8121
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008122#ifdef CONFIG_TESTING_OPTIONS
8123int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8124 enum wpa_driver_if_type if_type,
8125 unsigned int *num,
8126 unsigned int *freq_list)
8127{
8128 char *pos = wpa_s->get_pref_freq_list_override;
8129 char *end;
8130 unsigned int count = 0;
8131
8132 /* Override string format:
8133 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8134
8135 while (pos) {
8136 if (atoi(pos) == (int) if_type)
8137 break;
8138 pos = os_strchr(pos, ' ');
8139 if (pos)
8140 pos++;
8141 }
8142 if (!pos)
8143 return -1;
8144 pos = os_strchr(pos, ':');
8145 if (!pos)
8146 return -1;
8147 pos++;
8148 end = os_strchr(pos, ' ');
8149 while (pos && (!end || pos < end) && count < *num) {
8150 freq_list[count++] = atoi(pos);
8151 pos = os_strchr(pos, ',');
8152 if (pos)
8153 pos++;
8154 }
8155
8156 *num = count;
8157 return 0;
8158}
8159#endif /* CONFIG_TESTING_OPTIONS */
8160
8161
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008162static int wpas_ctrl_iface_get_pref_freq_list(
8163 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8164{
8165 unsigned int freq_list[100], num = 100, i;
8166 int ret;
8167 enum wpa_driver_if_type iface_type;
8168 char *pos, *end;
8169
8170 pos = buf;
8171 end = buf + buflen;
8172
8173 /* buf: "<interface_type>" */
8174 if (os_strcmp(cmd, "STATION") == 0)
8175 iface_type = WPA_IF_STATION;
8176 else if (os_strcmp(cmd, "AP") == 0)
8177 iface_type = WPA_IF_AP_BSS;
8178 else if (os_strcmp(cmd, "P2P_GO") == 0)
8179 iface_type = WPA_IF_P2P_GO;
8180 else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8181 iface_type = WPA_IF_P2P_CLIENT;
8182 else if (os_strcmp(cmd, "IBSS") == 0)
8183 iface_type = WPA_IF_IBSS;
8184 else if (os_strcmp(cmd, "TDLS") == 0)
8185 iface_type = WPA_IF_TDLS;
8186 else
8187 return -1;
8188
8189 wpa_printf(MSG_DEBUG,
8190 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
Hai Shalom5f92bc92019-04-18 11:54:11 -07008191 iface_type, cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008192
8193 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8194 if (ret)
8195 return -1;
8196
8197 for (i = 0; i < num; i++) {
8198 ret = os_snprintf(pos, end - pos, "%s%u",
8199 i > 0 ? "," : "", freq_list[i]);
8200 if (os_snprintf_error(end - pos, ret))
8201 return -1;
8202 pos += ret;
8203 }
8204
8205 return pos - buf;
8206}
8207
8208
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008209static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8210 char *buf, size_t buflen)
8211{
8212 int ret, i;
8213 char *pos, *end;
8214
8215 ret = os_snprintf(buf, buflen, "%016llX:\n",
8216 (long long unsigned) wpa_s->drv_flags);
8217 if (os_snprintf_error(buflen, ret))
8218 return -1;
8219
8220 pos = buf + ret;
8221 end = buf + buflen;
8222
8223 for (i = 0; i < 64; i++) {
8224 if (wpa_s->drv_flags & (1LLU << i)) {
8225 ret = os_snprintf(pos, end - pos, "%s\n",
8226 driver_flag_to_string(1LLU << i));
8227 if (os_snprintf_error(end - pos, ret))
8228 return -1;
8229 pos += ret;
8230 }
8231 }
8232
8233 return pos - buf;
8234}
8235
8236
Hai Shalomb755a2a2020-04-23 21:49:02 -07008237static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8238 char *buf, size_t buflen)
8239{
8240 int ret, i;
8241 char *pos, *end;
8242
8243 ret = os_snprintf(buf, buflen, "%016llX:\n",
8244 (long long unsigned) wpa_s->drv_flags2);
8245 if (os_snprintf_error(buflen, ret))
8246 return -1;
8247
8248 pos = buf + ret;
8249 end = buf + buflen;
8250
8251 for (i = 0; i < 64; i++) {
8252 if (wpa_s->drv_flags2 & (1LLU << i)) {
8253 ret = os_snprintf(pos, end - pos, "%s\n",
8254 driver_flag2_to_string(1LLU << i));
8255 if (os_snprintf_error(end - pos, ret))
8256 return -1;
8257 pos += ret;
8258 }
8259 }
8260
8261 return pos - buf;
8262}
8263
8264
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008265static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8266 size_t buflen)
8267{
8268 struct hostap_sta_driver_data sta;
8269 int ret;
8270
8271 ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8272 if (ret)
8273 return -1;
8274
8275 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008276 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008277 if (os_snprintf_error(buflen, ret))
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008278 return -1;
8279 return ret;
8280}
8281
8282
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008283#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008284static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8285 char *buf, size_t buflen)
8286{
8287 int ret;
8288
8289 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008290 if (ret == 0) {
8291 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8292 struct p2p_data *p2p = wpa_s->global->p2p;
8293 if (p2p) {
8294 char country[3];
8295 country[0] = cmd[8];
8296 country[1] = cmd[9];
8297 country[2] = 0x04;
8298 p2p_set_country(p2p, country);
8299 }
8300 }
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008301 ret = os_snprintf(buf, buflen, "%s\n", "OK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008302 if (os_snprintf_error(buflen, ret))
8303 ret = -1;
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008304 }
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008305 return ret;
8306}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008307#endif /* ANDROID */
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008308
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07008309
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008310static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8311 char *buf, size_t buflen)
8312{
8313 int ret;
Hai Shalom60840252021-02-19 19:02:11 -08008314 char *pos, *temp = NULL;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008315 u8 *data = NULL;
8316 unsigned int vendor_id, subcmd;
Hai Shalom60840252021-02-19 19:02:11 -08008317 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008318 struct wpabuf *reply;
8319 size_t data_len = 0;
8320
Hai Shalom60840252021-02-19 19:02:11 -08008321 /**
8322 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8323 * [nested=<0|1>]
8324 */
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008325 vendor_id = strtoul(cmd, &pos, 16);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008326 if (!isblank((unsigned char) *pos))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008327 return -EINVAL;
8328
8329 subcmd = strtoul(pos, &pos, 10);
8330
8331 if (*pos != '\0') {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008332 if (!isblank((unsigned char) *pos++))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008333 return -EINVAL;
Hai Shalom60840252021-02-19 19:02:11 -08008334
8335 temp = os_strchr(pos, ' ');
8336 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008337 }
8338
8339 if (data_len) {
8340 data_len /= 2;
8341 data = os_malloc(data_len);
8342 if (!data)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008343 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008344
8345 if (hexstr2bin(pos, data, data_len)) {
8346 wpa_printf(MSG_DEBUG,
8347 "Vendor command: wrong parameter format");
8348 os_free(data);
8349 return -EINVAL;
8350 }
8351 }
8352
Hai Shalom60840252021-02-19 19:02:11 -08008353 pos = os_strstr(cmd, "nested=");
8354 if (pos)
8355 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8356 NESTED_ATTR_NOT_USED;
8357
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008358 reply = wpabuf_alloc((buflen - 1) / 2);
8359 if (!reply) {
8360 os_free(data);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008361 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008362 }
8363
8364 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
Hai Shalom60840252021-02-19 19:02:11 -08008365 nested_attr_flag, reply);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008366
8367 if (ret == 0)
8368 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8369 wpabuf_len(reply));
8370
8371 wpabuf_free(reply);
8372 os_free(data);
8373
8374 return ret;
8375}
8376
8377
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008378static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8379{
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008380#ifdef CONFIG_P2P
8381 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8382 wpa_s->global->p2p_init_wpa_s : wpa_s;
8383#endif /* CONFIG_P2P */
8384
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008385 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8386
Dmitry Shmidt29333592017-01-09 12:27:11 -08008387 if (wpas_abort_ongoing_scan(wpa_s) == 0)
8388 wpa_s->ignore_post_flush_scan_res = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008389
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008390 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8391 /*
8392 * Avoid possible auto connect re-connection on getting
8393 * disconnected due to state flush.
8394 */
8395 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8396 }
8397
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008398#ifdef CONFIG_P2P
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008399 wpas_p2p_group_remove(p2p_wpa_s, "*");
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008400 wpas_p2p_cancel(p2p_wpa_s);
8401 p2p_ctrl_flush(p2p_wpa_s);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008402 wpas_p2p_service_flush(p2p_wpa_s);
8403 p2p_wpa_s->global->p2p_disabled = 0;
8404 p2p_wpa_s->global->p2p_per_sta_psk = 0;
8405 p2p_wpa_s->conf->num_sec_device_types = 0;
8406 p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8407 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8408 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008409 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08008410 p2p_wpa_s->global->pending_p2ps_group = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008411 p2p_wpa_s->global->pending_p2ps_group_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008412#endif /* CONFIG_P2P */
8413
8414#ifdef CONFIG_WPS_TESTING
8415 wps_version_number = 0x20;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008416 wps_testing_stub_cred = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008417 wps_corrupt_pkhash = 0;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008418 wps_force_auth_types_in_use = 0;
8419 wps_force_encr_types_in_use = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008420#endif /* CONFIG_WPS_TESTING */
8421#ifdef CONFIG_WPS
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008422 wpa_s->wps_fragment_size = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008423 wpas_wps_cancel(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008424 wps_registrar_flush(wpa_s->wps->registrar);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008425#endif /* CONFIG_WPS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07008426 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008427 wpa_s->known_wps_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008428
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008429#ifdef CONFIG_DPP
8430 wpas_dpp_deinit(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07008431 wpa_s->dpp_init_max_tries = 0;
8432 wpa_s->dpp_init_retry_time = 0;
8433 wpa_s->dpp_resp_wait_time = 0;
8434 wpa_s->dpp_resp_max_tries = 0;
8435 wpa_s->dpp_resp_retry_time = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008436#ifdef CONFIG_DPP2
8437 wpas_dpp_chirp_stop(wpa_s);
8438 wpa_s->dpp_pfs_fallback = 0;
8439#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008440#ifdef CONFIG_TESTING_OPTIONS
8441 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8442 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8443 dpp_pkex_ephemeral_key_override_len = 0;
8444 dpp_protocol_key_override_len = 0;
8445 dpp_nonce_override_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008446#ifdef CONFIG_DPP3
8447 dpp_version_override = 3;
8448#elif defined(CONFIG_DPP2)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07008449 dpp_version_override = 2;
8450#else /* CONFIG_DPP2 */
8451 dpp_version_override = 1;
8452#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008453#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008454#endif /* CONFIG_DPP */
8455
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008456#ifdef CONFIG_TDLS
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008457#ifdef CONFIG_TDLS_TESTING
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008458 tdls_testing = 0;
8459#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008460 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8461 wpa_tdls_enable(wpa_s->wpa, 1);
8462#endif /* CONFIG_TDLS */
8463
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008464 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8465 wpa_supplicant_stop_countermeasures(wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07008466 wpa_s->last_michael_mic_error.sec = 0;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008467
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008468 wpa_s->no_keep_alive = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008469 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008470 wpa_s->own_reconnect_req = 0;
8471 wpa_s->deny_ptk0_rekey = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008472
8473 os_free(wpa_s->disallow_aps_bssid);
8474 wpa_s->disallow_aps_bssid = NULL;
8475 wpa_s->disallow_aps_bssid_count = 0;
8476 os_free(wpa_s->disallow_aps_ssid);
8477 wpa_s->disallow_aps_ssid = NULL;
8478 wpa_s->disallow_aps_ssid_count = 0;
8479
8480 wpa_s->set_sta_uapsd = 0;
8481 wpa_s->sta_uapsd = 0;
8482
Hai Shalom899fcc72020-10-19 14:38:18 -07008483 wpa_s->consecutive_conn_failures = 0;
8484
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008485 wpa_drv_radio_disable(wpa_s, 0);
Hai Shalom60840252021-02-19 19:02:11 -08008486 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008487 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8488 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
Dmitry Shmidt344abd32014-01-14 13:17:00 -08008489 wpa_config_flush_blobs(wpa_s->conf);
Dmitry Shmidt18463232014-01-24 12:29:41 -08008490 wpa_s->conf->auto_interworking = 0;
8491 wpa_s->conf->okc = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008492
Hai Shalom60840252021-02-19 19:02:11 -08008493 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008494 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8495 rsn_preauth_deinit(wpa_s->wpa);
8496
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008497 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8498 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8499 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
Hai Shalome21d4e82020-04-29 16:34:06 -07008500 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008501
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08008502 radio_remove_works(wpa_s, NULL, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008503 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008504
8505 wpa_s->next_ssid = NULL;
8506
8507#ifdef CONFIG_INTERWORKING
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008508#ifdef CONFIG_HS20
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008509 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008510 hs20_del_icon(wpa_s, NULL, NULL);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008511#endif /* CONFIG_HS20 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008512#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt818ea482014-03-10 13:15:21 -07008513
8514 wpa_s->ext_mgmt_frame_handling = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008515 wpa_s->ext_eapol_frame_io = 0;
8516#ifdef CONFIG_TESTING_OPTIONS
8517 wpa_s->extra_roc_dur = 0;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008518 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008519 wpa_s->p2p_go_csa_on_inv = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07008520 wpa_s->ignore_auth_resp = 0;
8521 wpa_s->ignore_assoc_disallow = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008522 wpa_s->disable_sa_query = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008523 wpa_s->testing_resend_assoc = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008524 wpa_s->ignore_sae_h2e_only = 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07008525 wpa_s->ft_rsnxe_used = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07008526 wpa_s->reject_btm_req_reason = 0;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008527 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008528 os_free(wpa_s->get_pref_freq_list_override);
8529 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008530 wpabuf_free(wpa_s->sae_commit_override);
8531 wpa_s->sae_commit_override = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008532 os_free(wpa_s->extra_sae_rejected_groups);
8533 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008534 wpabuf_free(wpa_s->rsne_override_eapol);
8535 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008536 wpabuf_free(wpa_s->rsnxe_override_assoc);
8537 wpa_s->rsnxe_override_assoc = NULL;
8538 wpabuf_free(wpa_s->rsnxe_override_eapol);
8539 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008540 wpas_clear_driver_signal_override(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08008541 wpa_s->disable_scs_support = 0;
8542 wpa_s->disable_mscs_support = 0;
8543 wpa_s->enable_dscp_policy_capa = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -07008544 wpa_s->oci_freq_override_eapol = 0;
8545 wpa_s->oci_freq_override_saquery_req = 0;
8546 wpa_s->oci_freq_override_saquery_resp = 0;
8547 wpa_s->oci_freq_override_eapol_g2 = 0;
8548 wpa_s->oci_freq_override_ft_assoc = 0;
8549 wpa_s->oci_freq_override_fils_assoc = 0;
8550 wpa_s->oci_freq_override_wnm_sleep = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07008551 wpa_s->disable_eapol_g2_tx = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008552#ifdef CONFIG_DPP
8553 os_free(wpa_s->dpp_config_obj_override);
8554 wpa_s->dpp_config_obj_override = NULL;
8555 os_free(wpa_s->dpp_discovery_override);
8556 wpa_s->dpp_discovery_override = NULL;
8557 os_free(wpa_s->dpp_groups_override);
8558 wpa_s->dpp_groups_override = NULL;
8559 dpp_test = DPP_TEST_DISABLED;
8560#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008561#endif /* CONFIG_TESTING_OPTIONS */
8562
8563 wpa_s->disconnected = 0;
8564 os_free(wpa_s->next_scan_freqs);
8565 wpa_s->next_scan_freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008566 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
8567 wpa_s->next_scan_bssid_wildcard_ssid = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008568 os_free(wpa_s->select_network_scan_freqs);
8569 wpa_s->select_network_scan_freqs = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07008570 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008571
8572 wpa_bss_flush(wpa_s);
8573 if (!dl_list_empty(&wpa_s->bss)) {
8574 wpa_printf(MSG_DEBUG,
8575 "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8576 MACSTR " pending_bssid=" MACSTR,
8577 dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8578 MAC2STR(wpa_s->bssid),
8579 MAC2STR(wpa_s->pending_bssid));
8580 }
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07008581
8582 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Dmitry Shmidtb70d0bb2015-11-16 10:43:06 -08008583 wpa_s->wnmsleep_used = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008584
8585#ifdef CONFIG_SME
8586 wpa_s->sme.last_unprot_disconnect.sec = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008587 wpa_s->sme.auth_alg = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008588#endif /* CONFIG_SME */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008589
8590 wpabuf_free(wpa_s->ric_ies);
8591 wpa_s->ric_ies = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08008592
8593 wpa_supplicant_update_channel_list(wpa_s, NULL);
8594
8595 free_bss_tmp_disallowed(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07008596
8597 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Hai Shalom60840252021-02-19 19:02:11 -08008598
8599#ifdef CONFIG_PASN
8600 wpas_pasn_auth_stop(wpa_s);
8601#endif /* CONFIG_PASN */
8602
8603 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
8604 wpas_restore_permanent_mac_addr(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07008605
8606 wpa_s->conf->ignore_old_scan_res = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008607}
8608
8609
8610static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
8611 char *buf, size_t buflen)
8612{
8613 struct wpa_radio_work *work;
8614 char *pos, *end;
8615 struct os_reltime now, diff;
8616
8617 pos = buf;
8618 end = buf + buflen;
8619
8620 os_get_reltime(&now);
8621
8622 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8623 {
8624 int ret;
8625
8626 os_reltime_sub(&now, &work->time, &diff);
8627 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
8628 work->type, work->wpa_s->ifname, work->freq,
8629 work->started, diff.sec, diff.usec);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008630 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008631 break;
8632 pos += ret;
8633 }
8634
8635 return pos - buf;
8636}
8637
8638
8639static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
8640{
8641 struct wpa_radio_work *work = eloop_ctx;
8642 struct wpa_external_work *ework = work->ctx;
8643
8644 wpa_dbg(work->wpa_s, MSG_DEBUG,
8645 "Timing out external radio work %u (%s)",
8646 ework->id, work->type);
8647 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008648 work->wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008649 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07008650 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008651}
8652
8653
8654static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
8655{
8656 struct wpa_external_work *ework = work->ctx;
8657
8658 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08008659 if (work->started)
8660 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8661 work, NULL);
8662
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008663 /*
8664 * work->type points to a buffer in ework, so need to replace
8665 * that here with a fixed string to avoid use of freed memory
8666 * in debug prints.
8667 */
8668 work->type = "freed-ext-work";
8669 work->ctx = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008670 os_free(ework);
8671 return;
8672 }
8673
8674 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
8675 ework->id, ework->type);
8676 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008677 work->wpa_s->ext_work_in_progress = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008678 if (!ework->timeout)
8679 ework->timeout = 10;
8680 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
8681 work, NULL);
8682}
8683
8684
8685static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
8686 char *buf, size_t buflen)
8687{
8688 struct wpa_external_work *ework;
8689 char *pos, *pos2;
8690 size_t type_len;
8691 int ret;
8692 unsigned int freq = 0;
8693
8694 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
8695
8696 ework = os_zalloc(sizeof(*ework));
8697 if (ework == NULL)
8698 return -1;
8699
8700 pos = os_strchr(cmd, ' ');
8701 if (pos) {
8702 type_len = pos - cmd;
8703 pos++;
8704
8705 pos2 = os_strstr(pos, "freq=");
8706 if (pos2)
8707 freq = atoi(pos2 + 5);
8708
8709 pos2 = os_strstr(pos, "timeout=");
8710 if (pos2)
8711 ework->timeout = atoi(pos2 + 8);
8712 } else {
8713 type_len = os_strlen(cmd);
8714 }
8715 if (4 + type_len >= sizeof(ework->type))
8716 type_len = sizeof(ework->type) - 4 - 1;
8717 os_strlcpy(ework->type, "ext:", sizeof(ework->type));
8718 os_memcpy(ework->type + 4, cmd, type_len);
8719 ework->type[4 + type_len] = '\0';
8720
8721 wpa_s->ext_work_id++;
8722 if (wpa_s->ext_work_id == 0)
8723 wpa_s->ext_work_id++;
8724 ework->id = wpa_s->ext_work_id;
8725
8726 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
8727 ework) < 0) {
8728 os_free(ework);
8729 return -1;
8730 }
8731
8732 ret = os_snprintf(buf, buflen, "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008733 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008734 return -1;
8735 return ret;
8736}
8737
8738
8739static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
8740{
8741 struct wpa_radio_work *work;
8742 unsigned int id = atoi(cmd);
8743
8744 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8745 {
8746 struct wpa_external_work *ework;
8747
8748 if (os_strncmp(work->type, "ext:", 4) != 0)
8749 continue;
8750 ework = work->ctx;
8751 if (id && ework->id != id)
8752 continue;
8753 wpa_dbg(wpa_s, MSG_DEBUG,
8754 "Completed external radio work %u (%s)",
8755 ework->id, ework->type);
8756 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008757 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008758 radio_work_done(work);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07008759 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008760 return 3; /* "OK\n" */
8761 }
8762
8763 return -1;
8764}
8765
8766
8767static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
8768 char *buf, size_t buflen)
8769{
8770 if (os_strcmp(cmd, "show") == 0)
8771 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
8772 if (os_strncmp(cmd, "add ", 4) == 0)
8773 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
8774 if (os_strncmp(cmd, "done ", 5) == 0)
8775 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
8776 return -1;
8777}
8778
8779
8780void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
8781{
8782 struct wpa_radio_work *work, *tmp;
8783
Dmitry Shmidt18463232014-01-24 12:29:41 -08008784 if (!wpa_s || !wpa_s->radio)
8785 return;
8786
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008787 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
8788 struct wpa_radio_work, list) {
8789 struct wpa_external_work *ework;
8790
8791 if (os_strncmp(work->type, "ext:", 4) != 0)
8792 continue;
8793 ework = work->ctx;
8794 wpa_dbg(wpa_s, MSG_DEBUG,
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07008795 "Flushing%s external radio work %u (%s)",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008796 work->started ? " started" : "", ework->id,
8797 ework->type);
8798 if (work->started)
8799 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
8800 work, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008801 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07008802 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008803 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008804}
8805
8806
Dmitry Shmidt051af732013-10-22 13:52:46 -07008807static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
8808{
8809 struct wpa_supplicant *wpa_s = eloop_ctx;
8810 eapol_sm_notify_ctrl_response(wpa_s->eapol);
8811}
8812
8813
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008814static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
8815 unsigned int *scan_id_count, int scan_id[])
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008816{
8817 const char *pos = value;
8818
8819 while (pos) {
8820 if (*pos == ' ' || *pos == '\0')
8821 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008822 if (*scan_id_count == MAX_SCAN_ID)
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008823 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008824 scan_id[(*scan_id_count)++] = atoi(pos);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008825 pos = os_strchr(pos, ',');
8826 if (pos)
8827 pos++;
8828 }
8829
8830 return 0;
8831}
8832
8833
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008834static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
8835 char *reply, int reply_size, int *reply_len)
8836{
8837 char *pos;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008838 unsigned int manual_scan_passive = 0;
8839 unsigned int manual_scan_use_id = 0;
8840 unsigned int manual_scan_only_new = 0;
8841 unsigned int scan_only = 0;
8842 unsigned int scan_id_count = 0;
8843 int scan_id[MAX_SCAN_ID];
8844 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
8845 struct wpa_scan_results *scan_res);
8846 int *manual_scan_freqs = NULL;
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07008847 struct wpa_ssid_value *ssid = NULL, *ns;
8848 unsigned int ssid_count = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008849
8850 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
8851 *reply_len = -1;
8852 return;
8853 }
8854
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008855 if (radio_work_pending(wpa_s, "scan")) {
8856 wpa_printf(MSG_DEBUG,
8857 "Pending scan scheduled - reject new request");
8858 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8859 return;
8860 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008861
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07008862#ifdef CONFIG_INTERWORKING
8863 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
8864 wpa_printf(MSG_DEBUG,
8865 "Interworking select in progress - reject new scan");
8866 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
8867 return;
8868 }
8869#endif /* CONFIG_INTERWORKING */
8870
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008871 if (params) {
8872 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008873 scan_only = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008874
8875 pos = os_strstr(params, "freq=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008876 if (pos) {
8877 manual_scan_freqs = freq_range_to_channel_list(wpa_s,
8878 pos + 5);
8879 if (manual_scan_freqs == NULL) {
8880 *reply_len = -1;
8881 goto done;
8882 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008883 }
8884
8885 pos = os_strstr(params, "passive=");
8886 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008887 manual_scan_passive = !!atoi(pos + 8);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008888
8889 pos = os_strstr(params, "use_id=");
8890 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008891 manual_scan_use_id = atoi(pos + 7);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008892
8893 pos = os_strstr(params, "only_new=1");
8894 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008895 manual_scan_only_new = 1;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008896
8897 pos = os_strstr(params, "scan_id=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008898 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
8899 scan_id) < 0) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008900 *reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008901 goto done;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008902 }
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07008903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008904 pos = os_strstr(params, "bssid=");
8905 if (pos) {
8906 u8 bssid[ETH_ALEN];
8907
8908 pos += 6;
8909 if (hwaddr_aton(pos, bssid)) {
8910 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
8911 *reply_len = -1;
8912 goto done;
8913 }
8914 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07008915
8916 wpa_s->next_scan_bssid_wildcard_ssid =
8917 os_strstr(params, "wildcard_ssid=1") != NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008918 }
8919
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07008920 pos = params;
8921 while (pos && *pos != '\0') {
8922 if (os_strncmp(pos, "ssid ", 5) == 0) {
8923 char *end;
8924
8925 pos += 5;
8926 end = pos;
8927 while (*end) {
8928 if (*end == '\0' || *end == ' ')
8929 break;
8930 end++;
8931 }
8932
8933 ns = os_realloc_array(
8934 ssid, ssid_count + 1,
8935 sizeof(struct wpa_ssid_value));
8936 if (ns == NULL) {
8937 *reply_len = -1;
8938 goto done;
8939 }
8940 ssid = ns;
8941
8942 if ((end - pos) & 0x01 ||
8943 end - pos > 2 * SSID_MAX_LEN ||
8944 hexstr2bin(pos, ssid[ssid_count].ssid,
8945 (end - pos) / 2) < 0) {
8946 wpa_printf(MSG_DEBUG,
8947 "Invalid SSID value '%s'",
8948 pos);
8949 *reply_len = -1;
8950 goto done;
8951 }
8952 ssid[ssid_count].ssid_len = (end - pos) / 2;
8953 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
8954 ssid[ssid_count].ssid,
8955 ssid[ssid_count].ssid_len);
8956 ssid_count++;
8957 pos = end;
8958 }
8959
8960 pos = os_strchr(pos, ' ');
8961 if (pos)
8962 pos++;
8963 }
8964 }
8965
8966 wpa_s->num_ssids_from_scan_req = ssid_count;
8967 os_free(wpa_s->ssids_from_scan_req);
8968 if (ssid_count) {
8969 wpa_s->ssids_from_scan_req = ssid;
8970 ssid = NULL;
8971 } else {
8972 wpa_s->ssids_from_scan_req = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008973 }
8974
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008975 if (scan_only)
8976 scan_res_handler = scan_only_handler;
8977 else if (wpa_s->scan_res_handler == scan_only_handler)
8978 scan_res_handler = NULL;
8979 else
8980 scan_res_handler = wpa_s->scan_res_handler;
8981
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008982 if (!wpa_s->sched_scanning && !wpa_s->scanning &&
8983 ((wpa_s->wpa_state <= WPA_SCANNING) ||
8984 (wpa_s->wpa_state == WPA_COMPLETED))) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008985 wpa_s->manual_scan_passive = manual_scan_passive;
8986 wpa_s->manual_scan_use_id = manual_scan_use_id;
8987 wpa_s->manual_scan_only_new = manual_scan_only_new;
8988 wpa_s->scan_id_count = scan_id_count;
8989 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
8990 wpa_s->scan_res_handler = scan_res_handler;
8991 os_free(wpa_s->manual_scan_freqs);
8992 wpa_s->manual_scan_freqs = manual_scan_freqs;
8993 manual_scan_freqs = NULL;
8994
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008995 wpa_s->normal_scans = 0;
8996 wpa_s->scan_req = MANUAL_SCAN_REQ;
8997 wpa_s->after_wps = 0;
8998 wpa_s->known_wps_freq = 0;
8999 wpa_supplicant_req_scan(wpa_s, 0, 0);
9000 if (wpa_s->manual_scan_use_id) {
9001 wpa_s->manual_scan_id++;
9002 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9003 wpa_s->manual_scan_id);
9004 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9005 wpa_s->manual_scan_id);
9006 }
9007 } else if (wpa_s->sched_scanning) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009008 wpa_s->manual_scan_passive = manual_scan_passive;
9009 wpa_s->manual_scan_use_id = manual_scan_use_id;
9010 wpa_s->manual_scan_only_new = manual_scan_only_new;
9011 wpa_s->scan_id_count = scan_id_count;
9012 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9013 wpa_s->scan_res_handler = scan_res_handler;
9014 os_free(wpa_s->manual_scan_freqs);
9015 wpa_s->manual_scan_freqs = manual_scan_freqs;
9016 manual_scan_freqs = NULL;
9017
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009018 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9019 wpa_supplicant_cancel_sched_scan(wpa_s);
9020 wpa_s->scan_req = MANUAL_SCAN_REQ;
9021 wpa_supplicant_req_scan(wpa_s, 0, 0);
9022 if (wpa_s->manual_scan_use_id) {
9023 wpa_s->manual_scan_id++;
9024 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9025 wpa_s->manual_scan_id);
9026 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9027 wpa_s->manual_scan_id);
9028 }
9029 } else {
9030 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9031 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9032 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009033
9034done:
9035 os_free(manual_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009036 os_free(ssid);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009037}
9038
9039
Dmitry Shmidt818ea482014-03-10 13:15:21 -07009040#ifdef CONFIG_TESTING_OPTIONS
9041
9042static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9043 unsigned int freq, const u8 *dst,
9044 const u8 *src, const u8 *bssid,
9045 const u8 *data, size_t data_len,
9046 enum offchannel_send_action_result
9047 result)
9048{
9049 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9050 " src=" MACSTR " bssid=" MACSTR " result=%s",
9051 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9052 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9053 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9054 "NO_ACK" : "FAILED"));
9055}
9056
9057
9058static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9059{
9060 char *pos, *param;
9061 size_t len;
9062 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9063 int res, used;
9064 int freq = 0, no_cck = 0, wait_time = 0;
9065
9066 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9067 * <action=Action frame payload> */
9068
9069 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9070
9071 pos = cmd;
9072 used = hwaddr_aton2(pos, da);
9073 if (used < 0)
9074 return -1;
9075 pos += used;
9076 while (*pos == ' ')
9077 pos++;
9078 used = hwaddr_aton2(pos, bssid);
9079 if (used < 0)
9080 return -1;
9081 pos += used;
9082
9083 param = os_strstr(pos, " freq=");
9084 if (param) {
9085 param += 6;
9086 freq = atoi(param);
9087 }
9088
9089 param = os_strstr(pos, " no_cck=");
9090 if (param) {
9091 param += 8;
9092 no_cck = atoi(param);
9093 }
9094
9095 param = os_strstr(pos, " wait_time=");
9096 if (param) {
9097 param += 11;
9098 wait_time = atoi(param);
9099 }
9100
9101 param = os_strstr(pos, " action=");
9102 if (param == NULL)
9103 return -1;
9104 param += 8;
9105
9106 len = os_strlen(param);
9107 if (len & 1)
9108 return -1;
9109 len /= 2;
9110
9111 buf = os_malloc(len);
9112 if (buf == NULL)
9113 return -1;
9114
9115 if (hexstr2bin(param, buf, len) < 0) {
9116 os_free(buf);
9117 return -1;
9118 }
9119
9120 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9121 buf, len, wait_time,
9122 wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9123 os_free(buf);
9124 return res;
9125}
9126
9127
9128static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9129{
9130 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9131 offchannel_send_action_done(wpa_s);
9132}
9133
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009134
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009135static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9136 char *cmd)
9137{
9138 char *pos, *param;
9139 size_t len;
9140 u8 *buf;
9141 int freq = 0, datarate = 0, ssi_signal = 0;
9142 union wpa_event_data event;
9143
9144 if (!wpa_s->ext_mgmt_frame_handling)
9145 return -1;
9146
9147 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9148
9149 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9150
9151 pos = cmd;
9152 param = os_strstr(pos, "freq=");
9153 if (param) {
9154 param += 5;
9155 freq = atoi(param);
9156 }
9157
9158 param = os_strstr(pos, " datarate=");
9159 if (param) {
9160 param += 10;
9161 datarate = atoi(param);
9162 }
9163
9164 param = os_strstr(pos, " ssi_signal=");
9165 if (param) {
9166 param += 12;
9167 ssi_signal = atoi(param);
9168 }
9169
9170 param = os_strstr(pos, " frame=");
9171 if (param == NULL)
9172 return -1;
9173 param += 7;
9174
9175 len = os_strlen(param);
9176 if (len & 1)
9177 return -1;
9178 len /= 2;
9179
9180 buf = os_malloc(len);
9181 if (buf == NULL)
9182 return -1;
9183
9184 if (hexstr2bin(param, buf, len) < 0) {
9185 os_free(buf);
9186 return -1;
9187 }
9188
9189 os_memset(&event, 0, sizeof(event));
9190 event.rx_mgmt.freq = freq;
9191 event.rx_mgmt.frame = buf;
9192 event.rx_mgmt.frame_len = len;
9193 event.rx_mgmt.ssi_signal = ssi_signal;
9194 event.rx_mgmt.datarate = datarate;
9195 wpa_s->ext_mgmt_frame_handling = 0;
9196 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9197 wpa_s->ext_mgmt_frame_handling = 1;
9198
9199 os_free(buf);
9200
9201 return 0;
9202}
9203
9204
Paul Stewart092955c2017-02-06 09:13:09 -08009205static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9206 char *param)
9207{
9208 struct wpa_scan_res *res;
9209 struct os_reltime now;
9210 char *pos, *end;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009211 int ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -08009212
9213 if (!param)
9214 return -1;
9215
9216 if (os_strcmp(param, "START") == 0) {
9217 wpa_bss_update_start(wpa_s);
9218 return 0;
9219 }
9220
9221 if (os_strcmp(param, "END") == 0) {
9222 wpa_bss_update_end(wpa_s, NULL, 1);
9223 return 0;
9224 }
9225
9226 if (os_strncmp(param, "BSS ", 4) != 0)
9227 return -1;
9228 param += 3;
9229
9230 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9231 if (!res)
9232 return -1;
9233
9234 pos = os_strstr(param, " flags=");
9235 if (pos)
9236 res->flags = strtol(pos + 7, NULL, 16);
9237
9238 pos = os_strstr(param, " bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009239 if (pos && hwaddr_aton(pos + 7, res->bssid))
9240 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009241
9242 pos = os_strstr(param, " freq=");
9243 if (pos)
9244 res->freq = atoi(pos + 6);
9245
9246 pos = os_strstr(param, " beacon_int=");
9247 if (pos)
9248 res->beacon_int = atoi(pos + 12);
9249
9250 pos = os_strstr(param, " caps=");
9251 if (pos)
9252 res->caps = strtol(pos + 6, NULL, 16);
9253
9254 pos = os_strstr(param, " qual=");
9255 if (pos)
9256 res->qual = atoi(pos + 6);
9257
9258 pos = os_strstr(param, " noise=");
9259 if (pos)
9260 res->noise = atoi(pos + 7);
9261
9262 pos = os_strstr(param, " level=");
9263 if (pos)
9264 res->level = atoi(pos + 7);
9265
9266 pos = os_strstr(param, " tsf=");
9267 if (pos)
9268 res->tsf = strtoll(pos + 5, NULL, 16);
9269
9270 pos = os_strstr(param, " age=");
9271 if (pos)
9272 res->age = atoi(pos + 5);
9273
9274 pos = os_strstr(param, " est_throughput=");
9275 if (pos)
9276 res->est_throughput = atoi(pos + 16);
9277
9278 pos = os_strstr(param, " snr=");
9279 if (pos)
9280 res->snr = atoi(pos + 5);
9281
9282 pos = os_strstr(param, " parent_tsf=");
9283 if (pos)
9284 res->parent_tsf = strtoll(pos + 7, NULL, 16);
9285
9286 pos = os_strstr(param, " tsf_bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009287 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9288 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009289
9290 pos = os_strstr(param, " ie=");
9291 if (pos) {
9292 pos += 4;
9293 end = os_strchr(pos, ' ');
9294 if (!end)
9295 end = pos + os_strlen(pos);
9296 res->ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009297 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9298 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009299 }
9300
9301 pos = os_strstr(param, " beacon_ie=");
9302 if (pos) {
9303 pos += 11;
9304 end = os_strchr(pos, ' ');
9305 if (!end)
9306 end = pos + os_strlen(pos);
9307 res->beacon_ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009308 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9309 res->beacon_ie_len))
9310 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009311 }
9312
9313 os_get_reltime(&now);
9314 wpa_bss_update_scan_res(wpa_s, res, &now);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009315 ret = 0;
9316fail:
Paul Stewart092955c2017-02-06 09:13:09 -08009317 os_free(res);
9318
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009319 return ret;
Paul Stewart092955c2017-02-06 09:13:09 -08009320}
9321
9322
Hai Shaloma20dcd72022-02-04 13:43:00 -08009323static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9324 char *param)
9325{
9326 union wpa_event_data event;
9327 struct assoc_info *ai;
9328 char *ctx = NULL;
9329 int ret = -1;
9330 struct wpabuf *req_ies = NULL;
9331 struct wpabuf *resp_ies = NULL;
9332 struct wpabuf *resp_frame = NULL;
9333 struct wpabuf *beacon_ies = NULL;
9334 struct wpabuf *key_replay_ctr = NULL;
9335 struct wpabuf *ptk_kck = NULL;
9336 struct wpabuf *ptk_kek = NULL;
9337 struct wpabuf *fils_pmk = NULL;
9338 char *str, *pos;
9339 u8 addr[ETH_ALEN];
9340 u8 fils_pmkid[PMKID_LEN];
9341
9342 os_memset(&event, 0, sizeof(event));
9343 ai = &event.assoc_info;
9344
9345 while ((str = str_token(param, " ", &ctx))) {
9346 pos = os_strchr(str, '=');
9347 if (!pos)
9348 goto fail;
9349 *pos++ = '\0';
9350
9351 if (os_strcmp(str, "reassoc") == 0) {
9352 ai->reassoc = atoi(pos);
9353 } else if (os_strcmp(str, "req_ies") == 0) {
9354 wpabuf_free(req_ies);
9355 req_ies = wpabuf_parse_bin(pos);
9356 if (!req_ies)
9357 goto fail;
9358 ai->req_ies = wpabuf_head(req_ies);
9359 ai->req_ies_len = wpabuf_len(req_ies);
9360 } else if (os_strcmp(str, "resp_ies") == 0) {
9361 wpabuf_free(resp_ies);
9362 resp_ies = wpabuf_parse_bin(pos);
9363 if (!resp_ies)
9364 goto fail;
9365 ai->resp_ies = wpabuf_head(resp_ies);
9366 ai->resp_ies_len = wpabuf_len(resp_ies);
9367 } else if (os_strcmp(str, "resp_frame") == 0) {
9368 wpabuf_free(resp_frame);
9369 resp_frame = wpabuf_parse_bin(pos);
9370 if (!resp_frame)
9371 goto fail;
9372 ai->resp_frame = wpabuf_head(resp_frame);
9373 ai->resp_frame_len = wpabuf_len(resp_frame);
9374 } else if (os_strcmp(str, "beacon_ies") == 0) {
9375 wpabuf_free(beacon_ies);
9376 beacon_ies = wpabuf_parse_bin(pos);
9377 if (!beacon_ies)
9378 goto fail;
9379 ai->beacon_ies = wpabuf_head(beacon_ies);
9380 ai->beacon_ies_len = wpabuf_len(beacon_ies);
9381 } else if (os_strcmp(str, "freq") == 0) {
9382 ai->freq = atoi(pos);
9383 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9384 ai->wmm_params.info_bitmap = atoi(pos);
9385 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9386 ai->wmm_params.uapsd_queues = atoi(pos);
9387 } else if (os_strcmp(str, "addr") == 0) {
9388 if (hwaddr_aton(pos, addr))
9389 goto fail;
9390 ai->addr = addr;
9391 } else if (os_strcmp(str, "authorized") == 0) {
9392 ai->authorized = atoi(pos);
9393 } else if (os_strcmp(str, "key_replay_ctr") == 0) {
9394 wpabuf_free(key_replay_ctr);
9395 key_replay_ctr = wpabuf_parse_bin(pos);
9396 if (!key_replay_ctr)
9397 goto fail;
9398 ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9399 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9400 } else if (os_strcmp(str, "ptk_kck") == 0) {
9401 wpabuf_free(ptk_kck);
9402 ptk_kck = wpabuf_parse_bin(pos);
9403 if (!ptk_kck)
9404 goto fail;
9405 ai->ptk_kck = wpabuf_head(ptk_kck);
9406 ai->ptk_kck_len = wpabuf_len(ptk_kck);
9407 } else if (os_strcmp(str, "ptk_kek") == 0) {
9408 wpabuf_free(ptk_kek);
9409 ptk_kek = wpabuf_parse_bin(pos);
9410 if (!ptk_kek)
9411 goto fail;
9412 ai->ptk_kek = wpabuf_head(ptk_kek);
9413 ai->ptk_kek_len = wpabuf_len(ptk_kek);
9414 } else if (os_strcmp(str, "subnet_status") == 0) {
9415 ai->subnet_status = atoi(pos);
9416 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9417 ai->fils_erp_next_seq_num = atoi(pos);
9418 } else if (os_strcmp(str, "fils_pmk") == 0) {
9419 wpabuf_free(fils_pmk);
9420 fils_pmk = wpabuf_parse_bin(pos);
9421 if (!fils_pmk)
9422 goto fail;
9423 ai->fils_pmk = wpabuf_head(fils_pmk);
9424 ai->fils_pmk_len = wpabuf_len(fils_pmk);
9425 } else if (os_strcmp(str, "fils_pmkid") == 0) {
9426 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9427 goto fail;
9428 ai->fils_pmkid = fils_pmkid;
9429 } else {
9430 goto fail;
9431 }
9432 }
9433
9434 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9435 ret = 0;
9436fail:
9437 wpabuf_free(req_ies);
9438 wpabuf_free(resp_ies);
9439 wpabuf_free(resp_frame);
9440 wpabuf_free(beacon_ies);
9441 wpabuf_free(key_replay_ctr);
9442 wpabuf_free(ptk_kck);
9443 wpabuf_free(ptk_kek);
9444 wpabuf_free(fils_pmk);
9445 return ret;
9446}
9447
9448
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009449static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9450{
9451 char *pos, *param;
9452 union wpa_event_data event;
9453 enum wpa_event_type ev;
9454
9455 /* <event name> [parameters..] */
9456
9457 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9458
9459 pos = cmd;
9460 param = os_strchr(pos, ' ');
9461 if (param)
9462 *param++ = '\0';
9463
9464 os_memset(&event, 0, sizeof(event));
9465
9466 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9467 ev = EVENT_INTERFACE_ENABLED;
9468 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9469 ev = EVENT_INTERFACE_DISABLED;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07009470 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9471 ev = EVENT_AVOID_FREQUENCIES;
9472 if (param == NULL)
9473 param = "";
9474 if (freq_range_list_parse(&event.freq_range, param) < 0)
9475 return -1;
9476 wpa_supplicant_event(wpa_s, ev, &event);
9477 os_free(event.freq_range.range);
9478 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -08009479 } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
9480 return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
Hai Shaloma20dcd72022-02-04 13:43:00 -08009481 } else if (os_strcmp(cmd, "ASSOC") == 0) {
9482 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009483 } else {
9484 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
9485 cmd);
9486 return -1;
9487 }
9488
9489 wpa_supplicant_event(wpa_s, ev, &event);
9490
9491 return 0;
9492}
9493
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009494
9495static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
9496{
9497 char *pos;
9498 u8 src[ETH_ALEN], *buf;
9499 int used;
9500 size_t len;
9501
9502 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
9503
9504 pos = cmd;
9505 used = hwaddr_aton2(pos, src);
9506 if (used < 0)
9507 return -1;
9508 pos += used;
9509 while (*pos == ' ')
9510 pos++;
9511
9512 len = os_strlen(pos);
9513 if (len & 1)
9514 return -1;
9515 len /= 2;
9516
9517 buf = os_malloc(len);
9518 if (buf == NULL)
9519 return -1;
9520
9521 if (hexstr2bin(pos, buf, len) < 0) {
9522 os_free(buf);
9523 return -1;
9524 }
9525
9526 wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
9527 os_free(buf);
9528
9529 return 0;
9530}
9531
9532
Hai Shaloma20dcd72022-02-04 13:43:00 -08009533static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
9534{
9535 char *pos;
9536 u8 dst[ETH_ALEN], *buf;
9537 int used, ret;
9538 size_t len;
9539 unsigned int prev;
9540
9541 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
9542
9543 pos = cmd;
9544 used = hwaddr_aton2(pos, dst);
9545 if (used < 0)
9546 return -1;
9547 pos += used;
9548 while (*pos == ' ')
9549 pos++;
9550
9551 len = os_strlen(pos);
9552 if (len & 1)
9553 return -1;
9554 len /= 2;
9555
9556 buf = os_malloc(len);
9557 if (!buf || hexstr2bin(pos, buf, len) < 0) {
9558 os_free(buf);
9559 return -1;
9560 }
9561
9562 prev = wpa_s->ext_eapol_frame_io;
9563 wpa_s->ext_eapol_frame_io = 0;
9564 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
9565 wpa_s->ext_eapol_frame_io = prev;
9566 os_free(buf);
9567
9568 return ret;
9569}
9570
9571
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009572static u16 ipv4_hdr_checksum(const void *buf, size_t len)
9573{
9574 size_t i;
9575 u32 sum = 0;
9576 const u16 *pos = buf;
9577
9578 for (i = 0; i < len / 2; i++)
9579 sum += *pos++;
9580
9581 while (sum >> 16)
9582 sum = (sum & 0xffff) + (sum >> 16);
9583
9584 return sum ^ 0xffff;
9585}
9586
9587
9588#define HWSIM_PACKETLEN 1500
9589#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
9590
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07009591static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
9592 size_t len)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009593{
9594 struct wpa_supplicant *wpa_s = ctx;
9595 const struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -07009596 struct ip ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009597 const u8 *pos;
9598 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -08009599 char extra[30];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009600
Hai Shalom74f70d42019-02-11 14:42:39 -08009601 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
9602 wpa_printf(MSG_DEBUG,
9603 "test data: RX - ignore unexpected length %d",
9604 (int) len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009605 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08009606 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009607
9608 eth = (const struct ether_header *) buf;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009609 os_memcpy(&ip, eth + 1, sizeof(ip));
9610 pos = &buf[sizeof(*eth) + sizeof(ip)];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009611
Hai Shalomfdcde762020-04-02 11:19:20 -07009612 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009613 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07009614 "test data: RX - ignore unexpected IP header");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009615 return;
Hai Shalom39bc25d2019-02-06 16:32:13 -08009616 }
Hai Shalombf6e0ba2019-02-11 12:01:50 -08009617
Hai Shalomfdcde762020-04-02 11:19:20 -07009618 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009619 if (*pos != (u8) i) {
9620 wpa_printf(MSG_DEBUG,
9621 "test data: RX - ignore mismatching payload");
9622 return;
9623 }
9624 pos++;
9625 }
9626 extra[0] = '\0';
Hai Shalomfdcde762020-04-02 11:19:20 -07009627 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
9628 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
Hai Shalom74f70d42019-02-11 14:42:39 -08009629 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
9630 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009631}
9632
9633
9634static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
9635 char *cmd)
9636{
9637 int enabled = atoi(cmd);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009638 char *pos;
9639 const char *ifname;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009640
9641 if (!enabled) {
9642 if (wpa_s->l2_test) {
9643 l2_packet_deinit(wpa_s->l2_test);
9644 wpa_s->l2_test = NULL;
9645 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
9646 }
9647 return 0;
9648 }
9649
9650 if (wpa_s->l2_test)
9651 return 0;
9652
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08009653 pos = os_strstr(cmd, " ifname=");
9654 if (pos)
9655 ifname = pos + 8;
9656 else
9657 ifname = wpa_s->ifname;
9658
9659 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009660 ETHERTYPE_IP, wpas_data_test_rx,
9661 wpa_s, 1);
9662 if (wpa_s->l2_test == NULL)
9663 return -1;
9664
9665 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
9666
9667 return 0;
9668}
9669
9670
9671static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
9672{
9673 u8 dst[ETH_ALEN], src[ETH_ALEN];
Hai Shalom74f70d42019-02-11 14:42:39 -08009674 char *pos, *pos2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009675 int used;
9676 long int val;
9677 u8 tos;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009678 u8 buf[2 + HWSIM_PACKETLEN];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009679 struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -07009680 struct ip *ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009681 u8 *dpos;
9682 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -08009683 size_t send_len = HWSIM_IP_LEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009684
9685 if (wpa_s->l2_test == NULL)
9686 return -1;
9687
Hai Shalom74f70d42019-02-11 14:42:39 -08009688 /* format: <dst> <src> <tos> [len=<length>] */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009689
9690 pos = cmd;
9691 used = hwaddr_aton2(pos, dst);
9692 if (used < 0)
9693 return -1;
9694 pos += used;
9695 while (*pos == ' ')
9696 pos++;
9697 used = hwaddr_aton2(pos, src);
9698 if (used < 0)
9699 return -1;
9700 pos += used;
9701
Hai Shalom74f70d42019-02-11 14:42:39 -08009702 val = strtol(pos, &pos2, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009703 if (val < 0 || val > 0xff)
9704 return -1;
9705 tos = val;
9706
Hai Shalom74f70d42019-02-11 14:42:39 -08009707 pos = os_strstr(pos2, " len=");
9708 if (pos) {
9709 i = atoi(pos + 5);
9710 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
9711 return -1;
9712 send_len = i;
9713 }
9714
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009715 eth = (struct ether_header *) &buf[2];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009716 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
9717 os_memcpy(eth->ether_shost, src, ETH_ALEN);
9718 eth->ether_type = htons(ETHERTYPE_IP);
Hai Shalomfdcde762020-04-02 11:19:20 -07009719 ip = (struct ip *) (eth + 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009720 os_memset(ip, 0, sizeof(*ip));
Hai Shalomfdcde762020-04-02 11:19:20 -07009721 ip->ip_hl = 5;
9722 ip->ip_v = 4;
9723 ip->ip_ttl = 64;
9724 ip->ip_tos = tos;
9725 ip->ip_len = htons(send_len);
9726 ip->ip_p = 1;
9727 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
9728 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
9729 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009730 dpos = (u8 *) (ip + 1);
Hai Shalom74f70d42019-02-11 14:42:39 -08009731 for (i = 0; i < send_len - sizeof(*ip); i++)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009732 *dpos++ = i;
9733
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009734 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
Hai Shalom74f70d42019-02-11 14:42:39 -08009735 sizeof(struct ether_header) + send_len) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009736 return -1;
9737
9738 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
9739 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
9740
9741 return 0;
9742}
9743
9744
9745static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
9746 char *cmd)
9747{
9748 u8 *buf;
9749 struct ether_header *eth;
9750 struct l2_packet_data *l2 = NULL;
9751 size_t len;
9752 u16 ethertype;
9753 int res = -1;
9754
9755 len = os_strlen(cmd);
9756 if (len & 1 || len < ETH_HLEN * 2)
9757 return -1;
9758 len /= 2;
9759
9760 buf = os_malloc(len);
9761 if (buf == NULL)
9762 return -1;
9763
9764 if (hexstr2bin(cmd, buf, len) < 0)
9765 goto done;
9766
9767 eth = (struct ether_header *) buf;
9768 ethertype = ntohs(eth->ether_type);
9769
9770 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
9771 wpas_data_test_rx, wpa_s, 1);
9772 if (l2 == NULL)
9773 goto done;
9774
9775 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
9776 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
9777done:
9778 if (l2)
9779 l2_packet_deinit(l2);
9780 os_free(buf);
9781
9782 return res < 0 ? -1 : 0;
9783}
9784
Dmitry Shmidtff787d52015-01-12 13:01:47 -08009785
9786static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
9787{
9788#ifdef WPA_TRACE_BFD
Dmitry Shmidtff787d52015-01-12 13:01:47 -08009789 char *pos;
9790
9791 wpa_trace_fail_after = atoi(cmd);
9792 pos = os_strchr(cmd, ':');
9793 if (pos) {
9794 pos++;
9795 os_strlcpy(wpa_trace_fail_func, pos,
9796 sizeof(wpa_trace_fail_func));
9797 } else {
9798 wpa_trace_fail_after = 0;
9799 }
9800 return 0;
9801#else /* WPA_TRACE_BFD */
9802 return -1;
9803#endif /* WPA_TRACE_BFD */
9804}
9805
9806
9807static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
9808 char *buf, size_t buflen)
9809{
9810#ifdef WPA_TRACE_BFD
Dmitry Shmidtff787d52015-01-12 13:01:47 -08009811 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
9812 wpa_trace_fail_func);
9813#else /* WPA_TRACE_BFD */
9814 return -1;
9815#endif /* WPA_TRACE_BFD */
9816}
9817
Jouni Malinenc4818362015-10-04 11:45:13 +03009818
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009819static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
9820{
9821#ifdef WPA_TRACE_BFD
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009822 char *pos;
9823
9824 wpa_trace_test_fail_after = atoi(cmd);
9825 pos = os_strchr(cmd, ':');
9826 if (pos) {
9827 pos++;
9828 os_strlcpy(wpa_trace_test_fail_func, pos,
9829 sizeof(wpa_trace_test_fail_func));
9830 } else {
9831 wpa_trace_test_fail_after = 0;
9832 }
9833 return 0;
9834#else /* WPA_TRACE_BFD */
9835 return -1;
9836#endif /* WPA_TRACE_BFD */
9837}
9838
9839
9840static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
9841 char *buf, size_t buflen)
9842{
9843#ifdef WPA_TRACE_BFD
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009844 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
9845 wpa_trace_test_fail_func);
9846#else /* WPA_TRACE_BFD */
9847 return -1;
9848#endif /* WPA_TRACE_BFD */
9849}
9850
9851
Jouni Malinenc4818362015-10-04 11:45:13 +03009852static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
9853{
9854 struct wpa_supplicant *wpa_s = eloop_ctx;
9855 int i, count = (intptr_t) timeout_ctx;
9856
9857 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
9858 count);
9859 for (i = 0; i < count; i++) {
9860 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
9861 i + 1, count);
9862 }
9863}
9864
9865
9866static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
9867{
9868 int count;
9869
9870 count = atoi(cmd);
9871 if (count <= 0)
9872 return -1;
9873
9874 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
9875 (void *) (intptr_t) count);
9876}
9877
Dmitry Shmidt818ea482014-03-10 13:15:21 -07009878
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009879static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
9880 const char *cmd)
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07009881{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009882 struct wpabuf *buf;
9883 size_t len;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07009884
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009885 len = os_strlen(cmd);
9886 if (len & 1)
9887 return -1;
9888 len /= 2;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07009889
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009890 if (len == 0) {
9891 buf = NULL;
9892 } else {
9893 buf = wpabuf_alloc(len);
9894 if (buf == NULL)
9895 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009896
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009897 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
9898 wpabuf_free(buf);
9899 return -1;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07009900 }
9901 }
9902
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009903 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
9904 return 0;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07009905}
9906
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009907
9908static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
9909{
9910 u8 zero[WPA_TK_MAX_LEN];
9911
9912 if (wpa_s->last_tk_alg == WPA_ALG_NONE)
9913 return -1;
9914
9915 wpa_printf(MSG_INFO, "TESTING: Reset PN");
9916 os_memset(zero, 0, sizeof(zero));
9917
9918 /* First, use a zero key to avoid any possible duplicate key avoidance
9919 * in the driver. */
9920 if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9921 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -07009922 zero, wpa_s->last_tk_len,
9923 KEY_FLAG_PAIRWISE_RX_TX) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009924 return -1;
9925
9926 /* Set the previously configured key to reset its TSC/RSC */
9927 return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
9928 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -07009929 wpa_s->last_tk, wpa_s->last_tk_len,
9930 KEY_FLAG_PAIRWISE_RX_TX);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009931}
9932
9933
9934static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
9935{
9936 const char *pos = cmd;
9937 int error, pairwise;
9938
9939 error = atoi(pos);
9940 pos = os_strchr(pos, ' ');
9941 if (!pos)
9942 return -1;
9943 pairwise = atoi(pos);
9944 wpa_sm_key_request(wpa_s->wpa, error, pairwise);
9945 return 0;
9946}
9947
9948
9949static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
9950{
9951#ifdef CONFIG_SME
9952 struct wpa_driver_associate_params params;
9953 int ret;
9954
9955 os_memset(&params, 0, sizeof(params));
9956 params.bssid = wpa_s->bssid;
9957 params.ssid = wpa_s->sme.ssid;
9958 params.ssid_len = wpa_s->sme.ssid_len;
9959 params.freq.freq = wpa_s->sme.freq;
9960 if (wpa_s->last_assoc_req_wpa_ie) {
9961 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
9962 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
9963 }
9964 params.pairwise_suite = wpa_s->pairwise_cipher;
9965 params.group_suite = wpa_s->group_cipher;
9966 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
9967 params.key_mgmt_suite = wpa_s->key_mgmt;
9968 params.wpa_proto = wpa_s->wpa_proto;
9969 params.mgmt_frame_protection = wpa_s->sme.mfp;
9970 params.rrm_used = wpa_s->rrm.rrm_used;
9971 if (wpa_s->sme.prev_bssid_set)
9972 params.prev_bssid = wpa_s->sme.prev_bssid;
9973 wpa_printf(MSG_INFO, "TESTING: Resend association request");
9974 ret = wpa_drv_associate(wpa_s, &params);
9975 wpa_s->testing_resend_assoc = 1;
9976 return ret;
9977#else /* CONFIG_SME */
9978 return -1;
9979#endif /* CONFIG_SME */
9980}
9981
Hai Shaloma20dcd72022-02-04 13:43:00 -08009982
9983static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
9984 const char *cmd)
9985{
9986 u8 dtok = 1;
9987 int exponent = 10;
9988 int mantissa = 8192;
9989 u8 min_twt = 255;
9990 unsigned long long twt = 0;
9991 bool requestor = true;
9992 int setup_cmd = 0;
9993 bool trigger = true;
9994 bool implicit = true;
9995 bool flow_type = true;
9996 int flow_id = 0;
9997 bool protection = false;
9998 u8 twt_channel = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07009999 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021,
10000 * Figure 9-687 - Control field format):
10001 * B4 = TWT Information Frame Disabled */
Hai Shaloma20dcd72022-02-04 13:43:00 -080010002 const char *tok_s;
10003
10004 tok_s = os_strstr(cmd, " dialog=");
10005 if (tok_s)
10006 dtok = atoi(tok_s + os_strlen(" dialog="));
10007
10008 tok_s = os_strstr(cmd, " exponent=");
10009 if (tok_s)
10010 exponent = atoi(tok_s + os_strlen(" exponent="));
10011
10012 tok_s = os_strstr(cmd, " mantissa=");
10013 if (tok_s)
10014 mantissa = atoi(tok_s + os_strlen(" mantissa="));
10015
10016 tok_s = os_strstr(cmd, " min_twt=");
10017 if (tok_s)
10018 min_twt = atoi(tok_s + os_strlen(" min_twt="));
10019
10020 tok_s = os_strstr(cmd, " setup_cmd=");
10021 if (tok_s)
10022 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10023
10024 tok_s = os_strstr(cmd, " twt=");
10025 if (tok_s)
10026 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt);
10027
10028 tok_s = os_strstr(cmd, " requestor=");
10029 if (tok_s)
10030 requestor = atoi(tok_s + os_strlen(" requestor="));
10031
10032 tok_s = os_strstr(cmd, " trigger=");
10033 if (tok_s)
10034 trigger = atoi(tok_s + os_strlen(" trigger="));
10035
10036 tok_s = os_strstr(cmd, " implicit=");
10037 if (tok_s)
10038 implicit = atoi(tok_s + os_strlen(" implicit="));
10039
10040 tok_s = os_strstr(cmd, " flow_type=");
10041 if (tok_s)
10042 flow_type = atoi(tok_s + os_strlen(" flow_type="));
10043
10044 tok_s = os_strstr(cmd, " flow_id=");
10045 if (tok_s)
10046 flow_id = atoi(tok_s + os_strlen(" flow_id="));
10047
10048 tok_s = os_strstr(cmd, " protection=");
10049 if (tok_s)
10050 protection = atoi(tok_s + os_strlen(" protection="));
10051
10052 tok_s = os_strstr(cmd, " twt_channel=");
10053 if (tok_s)
10054 twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10055
10056 tok_s = os_strstr(cmd, " control=");
10057 if (tok_s)
10058 control = atoi(tok_s + os_strlen(" control="));
10059
10060 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10061 setup_cmd, twt, requestor, trigger, implicit,
10062 flow_type, flow_id, protection, twt_channel,
10063 control);
10064}
10065
10066
10067static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10068 const char *cmd)
10069{
10070 u8 flags = 0x1;
10071 const char *tok_s;
10072
10073 tok_s = os_strstr(cmd, " flags=");
10074 if (tok_s)
10075 flags = atoi(tok_s + os_strlen(" flags="));
10076
10077 return wpas_twt_send_teardown(wpa_s, flags);
10078}
10079
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010080#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010081
10082
10083static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10084{
10085 char *pos = cmd;
10086 int frame;
10087 size_t len;
10088 struct wpabuf *buf;
10089 struct ieee802_11_elems elems;
10090
10091 frame = atoi(pos);
10092 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10093 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010094 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010095
10096 pos = os_strchr(pos, ' ');
10097 if (pos == NULL)
10098 return -1;
10099 pos++;
10100
10101 len = os_strlen(pos);
10102 if (len == 0)
10103 return 0;
10104 if (len & 1)
10105 return -1;
10106 len /= 2;
10107
10108 buf = wpabuf_alloc(len);
10109 if (buf == NULL)
10110 return -1;
10111
10112 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10113 wpabuf_free(buf);
10114 return -1;
10115 }
10116
10117 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10118 ParseFailed) {
10119 wpabuf_free(buf);
10120 return -1;
10121 }
10122
10123 if (wpa_s->vendor_elem[frame] == NULL) {
10124 wpa_s->vendor_elem[frame] = buf;
Hai Shalom60840252021-02-19 19:02:11 -080010125 goto update_ies;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010126 }
10127
10128 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10129 wpabuf_free(buf);
10130 return -1;
10131 }
10132
10133 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10134 wpabuf_free(buf);
Hai Shalom60840252021-02-19 19:02:11 -080010135
10136update_ies:
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010137 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010138
Hai Shalom60840252021-02-19 19:02:11 -080010139 if (frame == VENDOR_ELEM_PROBE_REQ ||
10140 frame == VENDOR_ELEM_PROBE_REQ_P2P)
10141 wpa_supplicant_set_default_scan_ies(wpa_s);
10142
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010143 return 0;
10144}
10145
10146
10147static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10148 char *buf, size_t buflen)
10149{
10150 int frame = atoi(cmd);
10151
10152 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10153 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010154 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010155
10156 if (wpa_s->vendor_elem[frame] == NULL)
10157 return 0;
10158
10159 return wpa_snprintf_hex(buf, buflen,
10160 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10161 wpabuf_len(wpa_s->vendor_elem[frame]));
10162}
10163
10164
10165static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10166{
10167 char *pos = cmd;
10168 int frame;
10169 size_t len;
10170 u8 *buf;
10171 struct ieee802_11_elems elems;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010172 int res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010173
10174 frame = atoi(pos);
10175 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10176 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010177 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010178
10179 pos = os_strchr(pos, ' ');
10180 if (pos == NULL)
10181 return -1;
10182 pos++;
10183
10184 if (*pos == '*') {
10185 wpabuf_free(wpa_s->vendor_elem[frame]);
10186 wpa_s->vendor_elem[frame] = NULL;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010187 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010188 return 0;
10189 }
10190
10191 if (wpa_s->vendor_elem[frame] == NULL)
10192 return -1;
10193
10194 len = os_strlen(pos);
10195 if (len == 0)
10196 return 0;
10197 if (len & 1)
10198 return -1;
10199 len /= 2;
10200
10201 buf = os_malloc(len);
10202 if (buf == NULL)
10203 return -1;
10204
10205 if (hexstr2bin(pos, buf, len) < 0) {
10206 os_free(buf);
10207 return -1;
10208 }
10209
10210 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10211 os_free(buf);
10212 return -1;
10213 }
10214
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010215 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010216 os_free(buf);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010217 return res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010218}
10219
10220
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010221static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10222{
10223 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010224 size_t len;
10225 const u8 *data;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010226
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010227 /*
10228 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10229 * BSSID[6]
10230 * BSSID Information[4]
10231 * Operating Class[1]
10232 * Channel Number[1]
10233 * PHY Type[1]
10234 * Optional Subelements[variable]
10235 */
10236#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10237
10238 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010239 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010240 goto out;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010241 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010242
10243 data = wpabuf_head_u8(neighbor_rep);
10244 len = wpabuf_len(neighbor_rep);
10245
10246 while (len >= 2 + NR_IE_MIN_LEN) {
10247 const u8 *nr;
10248 char lci[256 * 2 + 1];
10249 char civic[256 * 2 + 1];
10250 u8 nr_len = data[1];
10251 const u8 *pos = data, *end;
10252
10253 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
10254 nr_len < NR_IE_MIN_LEN) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010255 wpa_dbg(wpa_s, MSG_DEBUG,
10256 "CTRL: Invalid Neighbor Report element: id=%u len=%u",
10257 data[0], nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010258 goto out;
10259 }
10260
10261 if (2U + nr_len > len) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010262 wpa_dbg(wpa_s, MSG_DEBUG,
10263 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
10264 data[0], len, nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010265 goto out;
10266 }
10267 pos += 2;
10268 end = pos + nr_len;
10269
10270 nr = pos;
10271 pos += NR_IE_MIN_LEN;
10272
10273 lci[0] = '\0';
10274 civic[0] = '\0';
10275 while (end - pos > 2) {
10276 u8 s_id, s_len;
10277
10278 s_id = *pos++;
10279 s_len = *pos++;
10280 if (s_len > end - pos)
10281 goto out;
10282 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
10283 /* Measurement Token[1] */
10284 /* Measurement Report Mode[1] */
10285 /* Measurement Type[1] */
10286 /* Measurement Report[variable] */
10287 switch (pos[2]) {
10288 case MEASURE_TYPE_LCI:
10289 if (lci[0])
10290 break;
10291 wpa_snprintf_hex(lci, sizeof(lci),
10292 pos, s_len);
10293 break;
10294 case MEASURE_TYPE_LOCATION_CIVIC:
10295 if (civic[0])
10296 break;
10297 wpa_snprintf_hex(civic, sizeof(civic),
10298 pos, s_len);
10299 break;
10300 }
10301 }
10302
10303 pos += s_len;
10304 }
10305
10306 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10307 "bssid=" MACSTR
10308 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10309 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10310 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10311 nr[ETH_ALEN + 6],
10312 lci[0] ? " lci=" : "", lci,
10313 civic[0] ? " civic=" : "", civic);
10314
10315 data = end;
10316 len -= 2 + nr_len;
10317 }
10318
10319out:
10320 wpabuf_free(neighbor_rep);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010321}
10322
10323
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010324static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10325 char *cmd)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010326{
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010327 struct wpa_ssid_value ssid, *ssid_p = NULL;
10328 int ret, lci = 0, civic = 0;
10329 char *ssid_s;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010330
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010331 ssid_s = os_strstr(cmd, "ssid=");
10332 if (ssid_s) {
10333 if (ssid_parse(ssid_s + 5, &ssid)) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010334 wpa_msg(wpa_s, MSG_INFO,
10335 "CTRL: Send Neighbor Report: bad SSID");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010336 return -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010337 }
10338
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010339 ssid_p = &ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010340
10341 /*
10342 * Move cmd after the SSID text that may include "lci" or
10343 * "civic".
10344 */
10345 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10346 if (cmd)
10347 cmd++;
10348
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010349 }
10350
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010351 if (cmd && os_strstr(cmd, "lci"))
10352 lci = 1;
10353
10354 if (cmd && os_strstr(cmd, "civic"))
10355 civic = 1;
10356
10357 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010358 wpas_ctrl_neighbor_rep_cb,
10359 wpa_s);
10360
10361 return ret;
10362}
10363
10364
10365static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10366{
10367 eapol_sm_erp_flush(wpa_s->eapol);
10368 return 0;
10369}
10370
10371
10372static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10373 char *cmd)
10374{
10375 char *token, *context = NULL;
10376 unsigned int enable = ~0, type = 0;
10377 u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10378 u8 *addr = NULL, *mask = NULL;
10379
10380 while ((token = str_token(cmd, " ", &context))) {
10381 if (os_strcasecmp(token, "scan") == 0) {
10382 type |= MAC_ADDR_RAND_SCAN;
10383 } else if (os_strcasecmp(token, "sched") == 0) {
10384 type |= MAC_ADDR_RAND_SCHED_SCAN;
10385 } else if (os_strcasecmp(token, "pno") == 0) {
10386 type |= MAC_ADDR_RAND_PNO;
10387 } else if (os_strcasecmp(token, "all") == 0) {
10388 type = wpa_s->mac_addr_rand_supported;
10389 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
10390 enable = atoi(token + 7);
10391 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
10392 addr = _addr;
10393 if (hwaddr_aton(token + 5, addr)) {
10394 wpa_printf(MSG_INFO,
10395 "CTRL: Invalid MAC address: %s",
10396 token);
10397 return -1;
10398 }
10399 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
10400 mask = _mask;
10401 if (hwaddr_aton(token + 5, mask)) {
10402 wpa_printf(MSG_INFO,
10403 "CTRL: Invalid MAC address mask: %s",
10404 token);
10405 return -1;
10406 }
10407 } else {
10408 wpa_printf(MSG_INFO,
10409 "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10410 token);
10411 return -1;
10412 }
10413 }
10414
10415 if (!type) {
10416 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10417 return -1;
10418 }
10419
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010420 if (enable > 1) {
10421 wpa_printf(MSG_INFO,
10422 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10423 return -1;
10424 }
10425
Hai Shalom81f62d82019-07-22 12:10:00 -070010426 if (!enable)
10427 return wpas_disable_mac_addr_randomization(wpa_s, type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010428
Hai Shalom81f62d82019-07-22 12:10:00 -070010429 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010430}
10431
10432
Dmitry Shmidte4663042016-04-04 10:07:49 -070010433static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10434 char *buf, size_t buflen)
10435{
10436 size_t reply_len;
10437
10438 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10439#ifdef CONFIG_AP
10440 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10441 buflen - reply_len);
10442#endif /* CONFIG_AP */
10443 return reply_len;
10444}
10445
10446
10447static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10448{
Hai Shalom60840252021-02-19 19:02:11 -080010449 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidte4663042016-04-04 10:07:49 -070010450 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10451#ifdef CONFIG_AP
10452 wpas_ap_pmksa_cache_flush(wpa_s);
10453#endif /* CONFIG_AP */
10454}
10455
10456
Dmitry Shmidt29333592017-01-09 12:27:11 -080010457#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10458
10459static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
10460 const char *cmd, char *buf, size_t buflen)
10461{
10462 struct rsn_pmksa_cache_entry *entry;
10463 struct wpa_ssid *ssid;
10464 char *pos, *pos2, *end;
10465 int ret;
10466 struct os_reltime now;
10467
10468 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10469 if (!ssid)
10470 return -1;
10471
10472 pos = buf;
10473 end = buf + buflen;
10474
10475 os_get_reltime(&now);
10476
10477 /*
10478 * Entry format:
10479 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10480 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010481 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080010482 */
10483
10484 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
10485 entry = entry->next) {
10486 if (entry->network_ctx != ssid)
10487 continue;
10488
10489 pos2 = pos;
10490 ret = os_snprintf(pos2, end - pos2, MACSTR " ",
10491 MAC2STR(entry->aa));
10492 if (os_snprintf_error(end - pos2, ret))
10493 break;
10494 pos2 += ret;
10495
10496 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
10497 PMKID_LEN);
10498
10499 ret = os_snprintf(pos2, end - pos2, " ");
10500 if (os_snprintf_error(end - pos2, ret))
10501 break;
10502 pos2 += ret;
10503
10504 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
10505 entry->pmk_len);
10506
10507 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
10508 (int) (entry->reauth_time - now.sec),
10509 (int) (entry->expiration - now.sec),
10510 entry->akmp,
10511 entry->opportunistic);
10512 if (os_snprintf_error(end - pos2, ret))
10513 break;
10514 pos2 += ret;
10515
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010516 if (entry->fils_cache_id_set) {
10517 ret = os_snprintf(pos2, end - pos2, " %02x%02x",
10518 entry->fils_cache_id[0],
10519 entry->fils_cache_id[1]);
10520 if (os_snprintf_error(end - pos2, ret))
10521 break;
10522 pos2 += ret;
10523 }
10524
Dmitry Shmidt29333592017-01-09 12:27:11 -080010525 ret = os_snprintf(pos2, end - pos2, "\n");
10526 if (os_snprintf_error(end - pos2, ret))
10527 break;
10528 pos2 += ret;
10529
10530 pos = pos2;
10531 }
10532
10533 return pos - buf;
10534}
10535
10536
10537static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
10538 char *cmd)
10539{
10540 struct rsn_pmksa_cache_entry *entry;
10541 struct wpa_ssid *ssid;
10542 char *pos, *pos2;
10543 int ret = -1;
10544 struct os_reltime now;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010545 int reauth_time = 0, expiration = 0, i;
Dmitry Shmidt29333592017-01-09 12:27:11 -080010546
10547 /*
10548 * Entry format:
10549 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10550 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010551 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080010552 */
10553
10554 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10555 if (!ssid)
10556 return -1;
10557
10558 pos = os_strchr(cmd, ' ');
10559 if (!pos)
10560 return -1;
10561 pos++;
10562
10563 entry = os_zalloc(sizeof(*entry));
10564 if (!entry)
10565 return -1;
10566
10567 if (hwaddr_aton(pos, entry->aa))
10568 goto fail;
10569
10570 pos = os_strchr(pos, ' ');
10571 if (!pos)
10572 goto fail;
10573 pos++;
10574
10575 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
10576 goto fail;
10577
10578 pos = os_strchr(pos, ' ');
10579 if (!pos)
10580 goto fail;
10581 pos++;
10582
10583 pos2 = os_strchr(pos, ' ');
10584 if (!pos2)
10585 goto fail;
10586 entry->pmk_len = (pos2 - pos) / 2;
10587 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
10588 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
10589 goto fail;
10590
10591 pos = os_strchr(pos, ' ');
10592 if (!pos)
10593 goto fail;
10594 pos++;
10595
10596 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
10597 &entry->akmp, &entry->opportunistic) != 4)
10598 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -080010599 if (reauth_time > expiration)
10600 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010601 for (i = 0; i < 4; i++) {
10602 pos = os_strchr(pos, ' ');
10603 if (!pos) {
10604 if (i < 3)
10605 goto fail;
10606 break;
10607 }
10608 pos++;
10609 }
10610 if (pos) {
10611 if (hexstr2bin(pos, entry->fils_cache_id,
10612 FILS_CACHE_ID_LEN) < 0)
10613 goto fail;
10614 entry->fils_cache_id_set = 1;
10615 }
Dmitry Shmidt29333592017-01-09 12:27:11 -080010616 os_get_reltime(&now);
10617 entry->expiration = now.sec + expiration;
10618 entry->reauth_time = now.sec + reauth_time;
10619
10620 entry->network_ctx = ssid;
10621
Hai Shaloma20dcd72022-02-04 13:43:00 -080010622 entry->external = true;
10623
Dmitry Shmidt29333592017-01-09 12:27:11 -080010624 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
10625 entry = NULL;
10626 ret = 0;
10627fail:
10628 os_free(entry);
10629 return ret;
10630}
10631
Paul Stewart092955c2017-02-06 09:13:09 -080010632
10633#ifdef CONFIG_MESH
10634
10635static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
10636 const char *cmd, char *buf,
10637 size_t buflen)
10638{
10639 u8 spa[ETH_ALEN];
10640
10641 if (!wpa_s->ifmsh)
10642 return -1;
10643
10644 if (os_strcasecmp(cmd, "any") == 0)
10645 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
10646
10647 if (hwaddr_aton(cmd, spa))
10648 return -1;
10649
10650 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
10651}
10652
10653
10654static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
10655 char *cmd)
10656{
10657 /*
Hai Shalom60840252021-02-19 19:02:11 -080010658 * We do not check mesh interface existence because PMKSA should be
Paul Stewart092955c2017-02-06 09:13:09 -080010659 * stored before wpa_s->ifmsh creation to suppress commit message
10660 * creation.
10661 */
10662 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
10663}
10664
10665#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080010666#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
10667
10668
Paul Stewart092955c2017-02-06 09:13:09 -080010669#ifdef CONFIG_FILS
10670static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
10671 const char *cmd)
10672{
10673 struct fils_hlp_req *req;
10674 const char *pos;
10675
10676 /* format: <dst> <packet starting from ethertype> */
10677
10678 req = os_zalloc(sizeof(*req));
10679 if (!req)
10680 return -1;
10681
10682 if (hwaddr_aton(cmd, req->dst))
10683 goto fail;
10684
10685 pos = os_strchr(cmd, ' ');
10686 if (!pos)
10687 goto fail;
10688 pos++;
10689 req->pkt = wpabuf_parse_bin(pos);
10690 if (!req->pkt)
10691 goto fail;
10692
10693 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
10694 return 0;
10695fail:
10696 wpabuf_free(req->pkt);
10697 os_free(req);
10698 return -1;
10699}
10700#endif /* CONFIG_FILS */
10701
10702
Sunil Ravia04bd252022-05-02 22:54:18 -070010703int wpas_ctrl_cmd_debug_level(const char *cmd)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010704{
10705 if (os_strcmp(cmd, "PING") == 0 ||
10706 os_strncmp(cmd, "BSS ", 4) == 0 ||
10707 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
10708 os_strncmp(cmd, "STATUS", 6) == 0 ||
10709 os_strncmp(cmd, "STA ", 4) == 0 ||
10710 os_strncmp(cmd, "STA-", 4) == 0)
10711 return MSG_EXCESSIVE;
10712 return MSG_DEBUG;
10713}
10714
10715
Hai Shalom899fcc72020-10-19 14:38:18 -070010716static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
10717 const char *cmd)
10718{
10719 size_t frame_classifier_len;
10720 const char *pos, *end;
10721 struct robust_av_data *robust_av = &wpa_s->robust_av;
10722 int val;
10723
10724 /*
10725 * format:
10726 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
10727 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
10728 */
10729 os_memset(robust_av, 0, sizeof(struct robust_av_data));
10730 if (os_strncmp(cmd, "add ", 4) == 0) {
10731 robust_av->request_type = SCS_REQ_ADD;
10732 } else if (os_strcmp(cmd, "remove") == 0) {
10733 robust_av->request_type = SCS_REQ_REMOVE;
10734 robust_av->valid_config = false;
10735 return wpas_send_mscs_req(wpa_s);
10736 } else if (os_strncmp(cmd, "change ", 7) == 0) {
10737 robust_av->request_type = SCS_REQ_CHANGE;
10738 } else {
10739 return -1;
10740 }
10741
10742 pos = os_strstr(cmd, "up_bitmap=");
10743 if (!pos)
10744 return -1;
10745
10746 val = hex2byte(pos + 10);
10747 if (val < 0)
10748 return -1;
10749 robust_av->up_bitmap = val;
10750
10751 pos = os_strstr(cmd, "up_limit=");
10752 if (!pos)
10753 return -1;
10754
10755 robust_av->up_limit = atoi(pos + 9);
10756
10757 pos = os_strstr(cmd, "stream_timeout=");
10758 if (!pos)
10759 return -1;
10760
10761 robust_av->stream_timeout = atoi(pos + 15);
10762 if (robust_av->stream_timeout == 0)
10763 return -1;
10764
10765 pos = os_strstr(cmd, "frame_classifier=");
10766 if (!pos)
10767 return -1;
10768
10769 pos += 17;
10770 end = os_strchr(pos, ' ');
10771 if (!end)
10772 end = pos + os_strlen(pos);
10773
10774 frame_classifier_len = (end - pos) / 2;
10775 if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
10776 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
10777 return -1;
10778
10779 robust_av->frame_classifier_len = frame_classifier_len;
10780 robust_av->valid_config = true;
10781
10782 return wpas_send_mscs_req(wpa_s);
10783}
10784
10785
Hai Shalom60840252021-02-19 19:02:11 -080010786#ifdef CONFIG_PASN
10787static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
10788{
10789 char *token, *context = NULL;
10790 u8 bssid[ETH_ALEN];
10791 int akmp = -1, cipher = -1, got_bssid = 0;
10792 u16 group = 0xFFFF;
Hai Shaloma20dcd72022-02-04 13:43:00 -080010793 u8 *comeback = NULL;
10794 size_t comeback_len = 0;
10795 int id = 0, ret = -1;
Hai Shalom60840252021-02-19 19:02:11 -080010796
10797 /*
10798 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
Hai Shaloma20dcd72022-02-04 13:43:00 -080010799 * [comeback=<hexdump>]
Hai Shalom60840252021-02-19 19:02:11 -080010800 */
10801 while ((token = str_token(cmd, " ", &context))) {
10802 if (os_strncmp(token, "bssid=", 6) == 0) {
10803 if (hwaddr_aton(token + 6, bssid))
Hai Shaloma20dcd72022-02-04 13:43:00 -080010804 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080010805 got_bssid = 1;
10806 } else if (os_strcmp(token, "akmp=PASN") == 0) {
10807 akmp = WPA_KEY_MGMT_PASN;
10808#ifdef CONFIG_IEEE80211R
10809 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
10810 akmp = WPA_KEY_MGMT_FT_PSK;
10811 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
10812 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
10813 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
10814 akmp = WPA_KEY_MGMT_FT_IEEE8021X;
10815#endif /* CONFIG_IEEE80211R */
10816#ifdef CONFIG_SAE
10817 } else if (os_strcmp(token, "akmp=SAE") == 0) {
10818 akmp = WPA_KEY_MGMT_SAE;
10819#endif /* CONFIG_SAE */
10820#ifdef CONFIG_FILS
10821 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
10822 akmp = WPA_KEY_MGMT_FILS_SHA256;
10823 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
10824 akmp = WPA_KEY_MGMT_FILS_SHA384;
10825#endif /* CONFIG_FILS */
10826 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
10827 cipher = WPA_CIPHER_CCMP_256;
10828 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
10829 cipher = WPA_CIPHER_GCMP_256;
10830 } else if (os_strcmp(token, "cipher=CCMP") == 0) {
10831 cipher = WPA_CIPHER_CCMP;
10832 } else if (os_strcmp(token, "cipher=GCMP") == 0) {
10833 cipher = WPA_CIPHER_GCMP;
10834 } else if (os_strncmp(token, "group=", 6) == 0) {
10835 group = atoi(token + 6);
10836 } else if (os_strncmp(token, "nid=", 4) == 0) {
10837 id = atoi(token + 4);
Hai Shaloma20dcd72022-02-04 13:43:00 -080010838 } else if (os_strncmp(token, "comeback=", 9) == 0) {
10839 comeback_len = os_strlen(token + 9);
10840 if (comeback || !comeback_len || comeback_len % 2)
10841 goto out;
10842
10843 comeback_len /= 2;
10844 comeback = os_malloc(comeback_len);
10845 if (!comeback ||
10846 hexstr2bin(token + 9, comeback, comeback_len))
10847 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080010848 } else {
10849 wpa_printf(MSG_DEBUG,
10850 "CTRL: PASN Invalid parameter: '%s'",
10851 token);
Hai Shaloma20dcd72022-02-04 13:43:00 -080010852 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080010853 }
10854 }
10855
10856 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
10857 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
Hai Shaloma20dcd72022-02-04 13:43:00 -080010858 goto out;
10859 }
10860
10861 ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
10862 comeback, comeback_len);
10863out:
10864 os_free(comeback);
10865 return ret;
10866}
10867
10868
10869static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
10870 const char *cmd)
10871{
10872 u8 bssid[ETH_ALEN];
10873
10874 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
10875 wpa_printf(MSG_DEBUG,
10876 "CTRL: PASN_DEAUTH without valid BSSID");
Hai Shalom60840252021-02-19 19:02:11 -080010877 return -1;
10878 }
10879
Hai Shaloma20dcd72022-02-04 13:43:00 -080010880 return wpas_pasn_deauthenticate(wpa_s, bssid);
Hai Shalom60840252021-02-19 19:02:11 -080010881}
Hai Shaloma20dcd72022-02-04 13:43:00 -080010882
Hai Shalom60840252021-02-19 19:02:11 -080010883#endif /* CONFIG_PASN */
10884
10885
Hai Shaloma20dcd72022-02-04 13:43:00 -080010886static int set_type4_frame_classifier(const char *cmd,
10887 struct type4_params *param)
10888{
10889 const char *pos, *end;
10890 u8 classifier_mask = 0;
10891 int ret;
10892 char addr[INET6_ADDRSTRLEN];
10893 size_t alen;
10894
10895 if (os_strstr(cmd, "ip_version=ipv4")) {
10896 param->ip_version = IPV4;
10897 } else if (os_strstr(cmd, "ip_version=ipv6")) {
10898 param->ip_version = IPV6;
10899 } else {
10900 wpa_printf(MSG_ERROR, "IP version missing/invalid");
10901 return -1;
10902 }
10903
10904 classifier_mask |= BIT(0);
10905
10906 pos = os_strstr(cmd, "src_ip=");
10907 if (pos) {
10908 pos += 7;
10909 end = os_strchr(pos, ' ');
10910 if (!end)
10911 end = pos + os_strlen(pos);
10912
10913 alen = end - pos;
10914 if (alen >= INET6_ADDRSTRLEN)
10915 return -1;
10916 os_memcpy(addr, pos, alen);
10917 addr[alen] = '\0';
10918 if (param->ip_version == IPV4)
10919 ret = inet_pton(AF_INET, addr,
10920 &param->ip_params.v4.src_ip);
10921 else
10922 ret = inet_pton(AF_INET6, addr,
10923 &param->ip_params.v6.src_ip);
10924
10925 if (ret != 1) {
10926 wpa_printf(MSG_ERROR,
10927 "Error converting src IP address to binary ret=%d",
10928 ret);
10929 return -1;
10930 }
10931
10932 classifier_mask |= BIT(1);
10933 }
10934
10935 pos = os_strstr(cmd, "dst_ip=");
10936 if (pos) {
10937 pos += 7;
10938 end = os_strchr(pos, ' ');
10939 if (!end)
10940 end = pos + os_strlen(pos);
10941
10942 alen = end - pos;
10943 if (alen >= INET6_ADDRSTRLEN)
10944 return -1;
10945 os_memcpy(addr, pos, alen);
10946 addr[alen] = '\0';
10947 if (param->ip_version == IPV4)
10948 ret = inet_pton(AF_INET, addr,
10949 &param->ip_params.v4.dst_ip);
10950 else
10951 ret = inet_pton(AF_INET6, addr,
10952 &param->ip_params.v6.dst_ip);
10953
10954 if (ret != 1) {
10955 wpa_printf(MSG_ERROR,
10956 "Error converting dst IP address to binary ret=%d",
10957 ret);
10958 return -1;
10959 }
10960
10961 classifier_mask |= BIT(2);
10962 }
10963
10964 pos = os_strstr(cmd, "src_port=");
10965 if (pos && atoi(pos + 9) > 0) {
10966 if (param->ip_version == IPV4)
10967 param->ip_params.v4.src_port = atoi(pos + 9);
10968 else
10969 param->ip_params.v6.src_port = atoi(pos + 9);
10970 classifier_mask |= BIT(3);
10971 }
10972
10973 pos = os_strstr(cmd, "dst_port=");
10974 if (pos && atoi(pos + 9) > 0) {
10975 if (param->ip_version == IPV4)
10976 param->ip_params.v4.dst_port = atoi(pos + 9);
10977 else
10978 param->ip_params.v6.dst_port = atoi(pos + 9);
10979 classifier_mask |= BIT(4);
10980 }
10981
10982 pos = os_strstr(cmd, "dscp=");
10983 if (pos && atoi(pos + 5) > 0) {
10984 if (param->ip_version == IPV4)
10985 param->ip_params.v4.dscp = atoi(pos + 5);
10986 else
10987 param->ip_params.v6.dscp = atoi(pos + 5);
10988 classifier_mask |= BIT(5);
10989 }
10990
10991 if (param->ip_version == IPV4) {
10992 pos = os_strstr(cmd, "protocol=");
10993 if (pos) {
10994 if (os_strstr(pos, "udp")) {
10995 param->ip_params.v4.protocol = 17;
10996 } else if (os_strstr(pos, "tcp")) {
10997 param->ip_params.v4.protocol = 6;
10998 } else if (os_strstr(pos, "esp")) {
10999 param->ip_params.v4.protocol = 50;
11000 } else {
11001 wpa_printf(MSG_ERROR, "Invalid protocol");
11002 return -1;
11003 }
11004 classifier_mask |= BIT(6);
11005 }
11006 } else {
11007 pos = os_strstr(cmd, "next_header=");
11008 if (pos) {
11009 if (os_strstr(pos, "udp")) {
11010 param->ip_params.v6.next_header = 17;
11011 } else if (os_strstr(pos, "tcp")) {
11012 param->ip_params.v6.next_header = 6;
11013 } else if (os_strstr(pos, "esp")) {
11014 param->ip_params.v6.next_header = 50;
11015 } else {
11016 wpa_printf(MSG_ERROR, "Invalid next header");
11017 return -1;
11018 }
11019
11020 classifier_mask |= BIT(6);
11021 }
11022
11023 pos = os_strstr(cmd, "flow_label=");
11024 if (pos) {
11025 pos += 11;
11026 end = os_strchr(pos, ' ');
11027 if (!end)
11028 end = pos + os_strlen(pos);
11029
11030 if (end - pos != 6 ||
11031 hexstr2bin(pos, param->ip_params.v6.flow_label,
11032 3) ||
11033 param->ip_params.v6.flow_label[0] > 0x0F) {
11034 wpa_printf(MSG_ERROR, "Invalid flow label");
11035 return -1;
11036 }
11037
11038 classifier_mask |= BIT(7);
11039 }
11040 }
11041
11042 param->classifier_mask = classifier_mask;
11043 return 0;
11044}
11045
11046
11047static int set_type10_frame_classifier(const char *cmd,
11048 struct type10_params *param)
11049{
11050 const char *pos, *end;
11051 size_t filter_len;
11052
11053 pos = os_strstr(cmd, "prot_instance=");
11054 if (!pos) {
11055 wpa_printf(MSG_ERROR, "Protocol instance missing");
11056 return -1;
11057 }
11058 param->prot_instance = atoi(pos + 14);
11059
11060 pos = os_strstr(cmd, "prot_number=");
11061 if (!pos) {
11062 wpa_printf(MSG_ERROR, "Protocol number missing");
11063 return -1;
11064 }
11065 if (os_strstr(pos, "udp")) {
11066 param->prot_number = 17;
11067 } else if (os_strstr(pos, "tcp")) {
11068 param->prot_number = 6;
11069 } else if (os_strstr(pos, "esp")) {
11070 param->prot_number = 50;
11071 } else {
11072 wpa_printf(MSG_ERROR, "Invalid protocol number");
11073 return -1;
11074 }
11075
11076 pos = os_strstr(cmd, "filter_value=");
11077 if (!pos) {
11078 wpa_printf(MSG_ERROR,
11079 "Classifier parameter filter_value missing");
11080 return -1;
11081 }
11082
11083 pos += 13;
11084 end = os_strchr(pos, ' ');
11085 if (!end)
11086 end = pos + os_strlen(pos);
11087
11088 filter_len = (end - pos) / 2;
11089 param->filter_value = os_malloc(filter_len);
11090 if (!param->filter_value)
11091 return -1;
11092
11093 if (hexstr2bin(pos, param->filter_value, filter_len)) {
11094 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11095 goto free;
11096 }
11097
11098 pos = os_strstr(cmd, "filter_mask=");
11099 if (!pos) {
11100 wpa_printf(MSG_ERROR,
11101 "Classifier parameter filter_mask missing");
11102 goto free;
11103 }
11104
11105 pos += 12;
11106 end = os_strchr(pos, ' ');
11107 if (!end)
11108 end = pos + os_strlen(pos);
11109
11110 if (filter_len != (size_t) (end - pos) / 2) {
11111 wpa_printf(MSG_ERROR,
11112 "Filter mask length mismatch expected=%zu received=%zu",
11113 filter_len, (size_t) (end - pos) / 2);
11114 goto free;
11115 }
11116
11117 param->filter_mask = os_malloc(filter_len);
11118 if (!param->filter_mask)
11119 goto free;
11120
11121 if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11122 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11123 os_free(param->filter_mask);
11124 param->filter_mask = NULL;
11125 goto free;
11126 }
11127
11128 param->filter_len = filter_len;
11129 return 0;
11130free:
11131 os_free(param->filter_value);
11132 param->filter_value = NULL;
11133 return -1;
11134}
11135
11136
11137static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11138{
11139 struct type4_params type4_param = { 0 };
11140
11141 if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11142 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11143 return -1;
11144 }
11145
11146 os_memcpy(&elem->frame_classifier.type4_param,
11147 &type4_param, sizeof(struct type4_params));
11148 return 0;
11149}
11150
11151
11152static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11153{
11154 struct type10_params type10_param = { 0 };
11155
11156 if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11157 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11158 return -1;
11159 }
11160
11161 os_memcpy(&elem->frame_classifier.type10_param,
11162 &type10_param, sizeof(struct type10_params));
11163 return 0;
11164}
11165
11166
11167static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11168 char *cmd)
11169{
11170 char *pos1, *pos;
11171 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11172 struct scs_desc_elem desc_elem = { 0 };
11173 int val;
11174 unsigned int num_scs_desc = 0;
11175
11176 if (wpa_s->ongoing_scs_req) {
11177 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11178 __func__);
11179 return -1;
11180 }
11181
11182 /**
11183 * format:
11184 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11185 * [classifier_type=<4|10>]
11186 * [classifier params based on classifier type]
11187 * [tclas_processing=<0|1>] [scs_id=<decimal number>] ...
11188 */
11189 pos1 = os_strstr(cmd, "scs_id=");
11190 if (!pos1) {
11191 wpa_printf(MSG_ERROR, "SCSID not present");
11192 return -1;
11193 }
11194
11195 free_up_scs_desc(scs_data);
11196
11197 while (pos1) {
11198 struct scs_desc_elem *n1;
11199 struct active_scs_elem *active_scs_desc;
11200 char *next_scs_desc;
11201 unsigned int num_tclas_elem = 0;
11202 bool scsid_active = false;
11203
11204 desc_elem.scs_id = atoi(pos1 + 7);
11205 pos1 += 7;
11206
11207 next_scs_desc = os_strstr(pos1, "scs_id=");
11208 if (next_scs_desc) {
11209 char temp[20];
11210
11211 os_snprintf(temp, sizeof(temp), "scs_id=%d ",
11212 desc_elem.scs_id);
11213 if (os_strstr(next_scs_desc, temp)) {
11214 wpa_printf(MSG_ERROR,
11215 "Multiple SCS descriptors configured with same SCSID(=%d)",
11216 desc_elem.scs_id);
11217 goto free_scs_desc;
11218 }
11219 pos1[next_scs_desc - pos1 - 1] = '\0';
11220 }
11221
11222 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
11223 struct active_scs_elem, list) {
11224 if (desc_elem.scs_id == active_scs_desc->scs_id) {
11225 scsid_active = true;
11226 break;
11227 }
11228 }
11229
11230 if (os_strstr(pos1, "add ")) {
11231 desc_elem.request_type = SCS_REQ_ADD;
11232 if (scsid_active) {
11233 wpa_printf(MSG_ERROR, "SCSID %d already active",
11234 desc_elem.scs_id);
11235 return -1;
11236 }
11237 } else if (os_strstr(pos1, "remove")) {
11238 desc_elem.request_type = SCS_REQ_REMOVE;
11239 if (!scsid_active) {
11240 wpa_printf(MSG_ERROR, "SCSID %d not active",
11241 desc_elem.scs_id);
11242 return -1;
11243 }
11244 goto scs_desc_end;
11245 } else if (os_strstr(pos1, "change ")) {
11246 desc_elem.request_type = SCS_REQ_CHANGE;
11247 if (!scsid_active) {
11248 wpa_printf(MSG_ERROR, "SCSID %d not active",
11249 desc_elem.scs_id);
11250 return -1;
11251 }
11252 } else {
11253 wpa_printf(MSG_ERROR, "SCS Request type invalid");
11254 goto free_scs_desc;
11255 }
11256
11257 pos1 = os_strstr(pos1, "scs_up=");
11258 if (!pos1) {
11259 wpa_printf(MSG_ERROR,
11260 "Intra-Access user priority not present");
11261 goto free_scs_desc;
11262 }
11263
11264 val = atoi(pos1 + 7);
11265 if (val < 0 || val > 7) {
11266 wpa_printf(MSG_ERROR,
11267 "Intra-Access user priority invalid %d",
11268 val);
11269 goto free_scs_desc;
11270 }
11271
11272 desc_elem.intra_access_priority = val;
11273 desc_elem.scs_up_avail = true;
11274
11275 pos = os_strstr(pos1, "classifier_type=");
11276 if (!pos) {
11277 wpa_printf(MSG_ERROR, "classifier type empty");
11278 goto free_scs_desc;
11279 }
11280
11281 while (pos) {
11282 struct tclas_element elem = { 0 }, *n;
11283 char *next_tclas_elem;
11284
11285 val = atoi(pos + 16);
11286 if (val != 4 && val != 10) {
11287 wpa_printf(MSG_ERROR,
11288 "classifier type invalid %d", val);
11289 goto free_scs_desc;
11290 }
11291
11292 elem.classifier_type = val;
11293 pos += 16;
11294
11295 next_tclas_elem = os_strstr(pos, "classifier_type=");
11296 if (next_tclas_elem) {
11297 pos1 = next_tclas_elem;
11298 pos[next_tclas_elem - pos - 1] = '\0';
11299 }
11300
11301 switch (val) {
11302 case 4:
11303 if (scs_parse_type4(&elem, pos) < 0)
11304 goto free_scs_desc;
11305 break;
11306 case 10:
11307 if (scs_parse_type10(&elem, pos) < 0)
11308 goto free_scs_desc;
11309 break;
11310 }
11311
11312 n = os_realloc(desc_elem.tclas_elems,
11313 (num_tclas_elem + 1) * sizeof(elem));
11314 if (!n)
11315 goto free_scs_desc;
11316
11317 desc_elem.tclas_elems = n;
11318 os_memcpy((u8 *) desc_elem.tclas_elems +
11319 num_tclas_elem * sizeof(elem),
11320 &elem, sizeof(elem));
11321 num_tclas_elem++;
11322 desc_elem.num_tclas_elem = num_tclas_elem;
11323 pos = next_tclas_elem;
11324 }
11325
11326 if (desc_elem.num_tclas_elem > 1) {
11327 pos1 = os_strstr(pos1, "tclas_processing=");
11328 if (!pos1) {
11329 wpa_printf(MSG_ERROR, "tclas_processing empty");
11330 goto free_scs_desc;
11331 }
11332
11333 val = atoi(pos1 + 17);
11334 if (val != 0 && val != 1) {
11335 wpa_printf(MSG_ERROR,
11336 "tclas_processing invalid");
11337 goto free_scs_desc;
11338 }
11339
11340 desc_elem.tclas_processing = val;
11341 }
11342
11343scs_desc_end:
11344 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
11345 sizeof(struct scs_desc_elem));
11346 if (!n1)
11347 goto free_scs_desc;
11348
11349 scs_data->scs_desc_elems = n1;
11350 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
11351 sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
11352 num_scs_desc++;
11353 scs_data->num_scs_desc = num_scs_desc;
11354 pos1 = next_scs_desc;
11355 os_memset(&desc_elem, 0, sizeof(desc_elem));
11356 }
11357
11358 return wpas_send_scs_req(wpa_s);
11359
11360free_scs_desc:
11361 free_up_tclas_elem(&desc_elem);
11362 free_up_scs_desc(scs_data);
11363 return -1;
11364}
11365
11366
11367static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
11368 const char *cmd)
11369{
11370 char *pos;
11371 struct dscp_policy_status *policy = NULL, *n;
11372 int num_policies = 0, ret = -1;
11373 struct dscp_resp_data resp_data;
11374
11375 /*
11376 * format:
11377 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
11378 */
11379
11380 os_memset(&resp_data, 0, sizeof(resp_data));
11381
11382 resp_data.more = os_strstr(cmd, "more") != NULL;
11383
11384 if (os_strstr(cmd, "reset")) {
11385 resp_data.reset = true;
11386 resp_data.solicited = false;
11387 goto send_resp;
11388 }
11389
11390 resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
11391
11392 pos = os_strstr(cmd, "policy_id=");
11393 while (pos) {
11394 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
11395 if (!n)
11396 goto fail;
11397
11398 policy = n;
11399 pos += 10;
11400 policy[num_policies].id = atoi(pos);
11401 if (policy[num_policies].id == 0) {
11402 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
11403 goto fail;
11404 }
11405
11406 pos = os_strstr(pos, "status=");
11407 if (!pos) {
11408 wpa_printf(MSG_ERROR,
11409 "DSCP: Status is not found for a policy");
11410 goto fail;
11411 }
11412
11413 pos += 7;
11414 policy[num_policies].status = atoi(pos);
11415 num_policies++;
11416
11417 pos = os_strstr(pos, "policy_id");
11418 }
11419
11420 resp_data.policy = policy;
11421 resp_data.num_policies = num_policies;
11422send_resp:
11423 ret = wpas_send_dscp_response(wpa_s, &resp_data);
11424 if (ret)
11425 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
11426fail:
11427 os_free(policy);
11428 return ret;
11429}
11430
11431
11432static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
11433 const char *cmd)
11434{
11435 char *pos;
11436
11437 /*
11438 * format:
11439 * Wildcard DSCP query
11440 * <wildcard>
11441 *
11442 * DSCP query with a domain name attribute:
11443 * [domain_name=<string>]
11444 */
11445
11446 if (os_strstr(cmd, "wildcard")) {
11447 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
11448 return wpas_send_dscp_query(wpa_s, NULL, 0);
11449 }
11450
11451 pos = os_strstr(cmd, "domain_name=");
11452 if (!pos || !os_strlen(pos + 12)) {
11453 wpa_printf(MSG_ERROR, "QM: Domain name not preset");
11454 return -1;
11455 }
11456
11457 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
11458}
11459
11460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011461char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
11462 char *buf, size_t *resp_len)
11463{
11464 char *reply;
11465 const int reply_size = 4096;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011466 int reply_len;
11467
11468 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011469 os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
11470 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
11471 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011472 if (wpa_debug_show_keys)
11473 wpa_dbg(wpa_s, MSG_DEBUG,
11474 "Control interface command '%s'", buf);
11475 else
11476 wpa_dbg(wpa_s, MSG_DEBUG,
11477 "Control interface command '%s [REMOVED]'",
11478 os_strncmp(buf, WPA_CTRL_RSP,
11479 os_strlen(WPA_CTRL_RSP)) == 0 ?
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011480 WPA_CTRL_RSP :
11481 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
11482 "SET_NETWORK" : "key-add"));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011483 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
Dmitry Shmidt21de2142014-04-08 10:50:52 -070011484 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011485 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
11486 (const u8 *) buf, os_strlen(buf));
11487 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080011488 int level = wpas_ctrl_cmd_debug_level(buf);
Dmitry Shmidtaa532512012-09-24 10:35:31 -070011489 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011490 }
11491
11492 reply = os_malloc(reply_size);
11493 if (reply == NULL) {
11494 *resp_len = 1;
11495 return NULL;
11496 }
11497
11498 os_memcpy(reply, "OK\n", 3);
11499 reply_len = 3;
11500
11501 if (os_strcmp(buf, "PING") == 0) {
11502 os_memcpy(reply, "PONG\n", 5);
11503 reply_len = 5;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070011504 } else if (os_strcmp(buf, "IFNAME") == 0) {
11505 reply_len = os_strlen(wpa_s->ifname);
11506 os_memcpy(reply, wpa_s->ifname, reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011507 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
11508 if (wpa_debug_reopen_file() < 0)
11509 reply_len = -1;
11510 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
11511 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
11512 } else if (os_strcmp(buf, "MIB") == 0) {
11513 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
11514 if (reply_len >= 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080011515 reply_len += eapol_sm_get_mib(wpa_s->eapol,
11516 reply + reply_len,
11517 reply_size - reply_len);
Hai Shalom74f70d42019-02-11 14:42:39 -080011518#ifdef CONFIG_MACSEC
11519 reply_len += ieee802_1x_kay_get_mib(
11520 wpa_s->kay, reply + reply_len,
11521 reply_size - reply_len);
11522#endif /* CONFIG_MACSEC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011523 }
11524 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
11525 reply_len = wpa_supplicant_ctrl_iface_status(
11526 wpa_s, buf + 6, reply, reply_size);
11527 } else if (os_strcmp(buf, "PMKSA") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070011528 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070011529 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070011530 wpas_ctrl_iface_pmksa_flush(wpa_s);
Dmitry Shmidt29333592017-01-09 12:27:11 -080011531#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
11532 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
11533 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
11534 reply, reply_size);
11535 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
11536 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
11537 reply_len = -1;
Paul Stewart092955c2017-02-06 09:13:09 -080011538#ifdef CONFIG_MESH
11539 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
11540 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
11541 reply, reply_size);
11542 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
11543 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
11544 reply_len = -1;
11545#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080011546#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011547 } else if (os_strncmp(buf, "SET ", 4) == 0) {
11548 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
11549 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080011550 } else if (os_strncmp(buf, "DUMP", 4) == 0) {
11551 reply_len = wpa_config_dump_values(wpa_s->conf,
11552 reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011553 } else if (os_strncmp(buf, "GET ", 4) == 0) {
11554 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
11555 reply, reply_size);
11556 } else if (os_strcmp(buf, "LOGON") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070011557 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011558 } else if (os_strcmp(buf, "LOGOFF") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070011559 eapol_sm_notify_logoff(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011560 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
11561 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
11562 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080011563 else
11564 wpas_request_connection(wpa_s);
Dmitry Shmidt98660862014-03-11 17:26:21 -070011565 } else if (os_strcmp(buf, "REATTACH") == 0) {
11566 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
11567 !wpa_s->current_ssid)
11568 reply_len = -1;
11569 else {
11570 wpa_s->reattach = 1;
11571 wpas_request_connection(wpa_s);
11572 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011573 } else if (os_strcmp(buf, "RECONNECT") == 0) {
11574 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
11575 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080011576 else if (wpa_s->disconnected)
11577 wpas_request_connection(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011578#ifdef IEEE8021X_EAPOL
11579 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
11580 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
11581 reply_len = -1;
11582#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011583#ifdef CONFIG_IEEE80211R
11584 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
11585 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
11586 reply_len = -1;
11587#endif /* CONFIG_IEEE80211R */
11588#ifdef CONFIG_WPS
11589 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
11590 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
11591 if (res == -2) {
11592 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
11593 reply_len = 17;
11594 } else if (res)
11595 reply_len = -1;
11596 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
11597 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
11598 if (res == -2) {
11599 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
11600 reply_len = 17;
11601 } else if (res)
11602 reply_len = -1;
11603 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
11604 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
11605 reply,
11606 reply_size);
11607 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
11608 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
11609 wpa_s, buf + 14, reply, reply_size);
11610 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
11611 if (wpas_wps_cancel(wpa_s))
11612 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070011613#ifdef CONFIG_WPS_NFC
11614 } else if (os_strcmp(buf, "WPS_NFC") == 0) {
11615 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
11616 reply_len = -1;
11617 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
11618 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
11619 reply_len = -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -080011620 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
11621 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
11622 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070011623 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
11624 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
11625 wpa_s, buf + 14, reply, reply_size);
11626 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
11627 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
11628 buf + 17))
11629 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080011630 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
11631 reply_len = wpas_ctrl_nfc_get_handover_req(
11632 wpa_s, buf + 21, reply, reply_size);
11633 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
11634 reply_len = wpas_ctrl_nfc_get_handover_sel(
11635 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidtf8623282013-02-20 14:34:59 -080011636 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
11637 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
11638 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070011639#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011640 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
11641 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
11642 reply_len = -1;
11643#ifdef CONFIG_AP
11644 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
11645 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
11646 wpa_s, buf + 11, reply, reply_size);
11647#endif /* CONFIG_AP */
11648#ifdef CONFIG_WPS_ER
11649 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
11650 if (wpas_wps_er_start(wpa_s, NULL))
11651 reply_len = -1;
11652 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
11653 if (wpas_wps_er_start(wpa_s, buf + 13))
11654 reply_len = -1;
11655 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080011656 wpas_wps_er_stop(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011657 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
11658 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
11659 reply_len = -1;
11660 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
11661 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
11662 if (ret == -2) {
11663 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
11664 reply_len = 17;
11665 } else if (ret == -3) {
11666 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
11667 reply_len = 18;
11668 } else if (ret == -4) {
11669 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
11670 reply_len = 20;
11671 } else if (ret)
11672 reply_len = -1;
11673 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
11674 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
11675 reply_len = -1;
11676 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
11677 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
11678 buf + 18))
11679 reply_len = -1;
11680 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
11681 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
11682 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070011683#ifdef CONFIG_WPS_NFC
11684 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
11685 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
11686 wpa_s, buf + 24, reply, reply_size);
11687#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011688#endif /* CONFIG_WPS_ER */
11689#endif /* CONFIG_WPS */
11690#ifdef CONFIG_IBSS_RSN
11691 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
11692 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
11693 reply_len = -1;
11694#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080011695#ifdef CONFIG_MESH
11696 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
11697 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
11698 wpa_s, buf + 19, reply, reply_size);
11699 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
11700 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
11701 wpa_s, "", reply, reply_size);
11702 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
11703 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
11704 reply_len = -1;
11705 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
11706 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
11707 buf + 18))
11708 reply_len = -1;
Dmitry Shmidte4663042016-04-04 10:07:49 -070011709 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
11710 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
11711 reply_len = -1;
11712 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
11713 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
11714 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070011715 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
11716 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
11717 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080011718#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011719#ifdef CONFIG_P2P
11720 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -080011721 if (p2p_ctrl_find(wpa_s, buf + 8))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011722 reply_len = -1;
11723 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
11724 if (p2p_ctrl_find(wpa_s, ""))
11725 reply_len = -1;
11726 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
11727 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -080011728 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
11729 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
11730 reply_len = -1;
11731 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
11732 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
11733 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011734 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
11735 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
11736 reply_size);
11737 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
11738 if (p2p_ctrl_listen(wpa_s, buf + 11))
11739 reply_len = -1;
11740 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
11741 if (p2p_ctrl_listen(wpa_s, ""))
11742 reply_len = -1;
11743 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
11744 if (wpas_p2p_group_remove(wpa_s, buf + 17))
11745 reply_len = -1;
11746 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -070011747 if (p2p_ctrl_group_add(wpa_s, ""))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011748 reply_len = -1;
11749 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
11750 if (p2p_ctrl_group_add(wpa_s, buf + 14))
11751 reply_len = -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070011752 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
11753 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
11754 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011755 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
11756 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
11757 reply_len = -1;
11758 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
11759 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
11760 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
11761 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
11762 reply_size);
11763 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
11764 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
11765 reply_len = -1;
11766 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
11767 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
11768 reply_len = -1;
11769 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
11770 wpas_p2p_sd_service_update(wpa_s);
11771 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
11772 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
11773 reply_len = -1;
11774 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
11775 wpas_p2p_service_flush(wpa_s);
11776 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
11777 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
11778 reply_len = -1;
11779 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
11780 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
11781 reply_len = -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -080011782 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
11783 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
11784 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011785 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
11786 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
11787 reply_len = -1;
11788 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
11789 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
11790 reply_len = -1;
11791 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
11792 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
11793 reply_size);
11794 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
11795 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
11796 reply_len = -1;
11797 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
Dmitry Shmidt444d5672013-04-01 13:08:44 -070011798 p2p_ctrl_flush(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011799 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
11800 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
11801 reply_len = -1;
11802 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
11803 if (wpas_p2p_cancel(wpa_s))
11804 reply_len = -1;
11805 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
11806 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
11807 reply_len = -1;
11808 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
11809 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
11810 reply_len = -1;
11811 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
11812 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
11813 reply_len = -1;
11814 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
11815 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
11816 reply_len = -1;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070011817 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
11818 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
11819 reply_len = -1;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070011820 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
11821 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
11822 reply_len = -1;
11823 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
11824 if (wpas_p2p_lo_stop(wpa_s))
11825 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011826#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070011827#ifdef CONFIG_WIFI_DISPLAY
11828 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
11829 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
11830 reply_len = -1;
11831 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
11832 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
11833 reply, reply_size);
11834#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011835#ifdef CONFIG_INTERWORKING
11836 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
11837 if (interworking_fetch_anqp(wpa_s) < 0)
11838 reply_len = -1;
11839 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
11840 interworking_stop_fetch_anqp(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011841 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
11842 if (ctrl_interworking_select(wpa_s, NULL) < 0)
11843 reply_len = -1;
11844 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
11845 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011846 reply_len = -1;
11847 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -080011848 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011849 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080011850 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
11851 int id;
11852
11853 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
11854 if (id < 0)
11855 reply_len = -1;
11856 else {
11857 reply_len = os_snprintf(reply, reply_size, "%d\n", id);
11858 if (os_snprintf_error(reply_size, reply_len))
11859 reply_len = -1;
11860 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011861 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
11862 if (get_anqp(wpa_s, buf + 9) < 0)
11863 reply_len = -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070011864 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
11865 if (gas_request(wpa_s, buf + 12) < 0)
11866 reply_len = -1;
11867 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
11868 reply_len = gas_response_get(wpa_s, buf + 17, reply,
11869 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011870#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -070011871#ifdef CONFIG_HS20
11872 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
11873 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
11874 reply_len = -1;
11875 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
11876 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
11877 reply_len = -1;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080011878 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080011879 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
11880 reply_len = -1;
11881 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
11882 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
11883 reply_len = -1;
11884 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
11885 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
11886 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
11887 if (del_hs20_icon(wpa_s, buf + 14) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080011888 reply_len = -1;
11889 } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070011890 if (hs20_fetch_osu(wpa_s, 0) < 0)
11891 reply_len = -1;
11892 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
11893 if (hs20_fetch_osu(wpa_s, 1) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080011894 reply_len = -1;
11895 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
11896 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -070011897#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011898 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
11899 {
11900 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
11901 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
11902 reply_len = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -070011903 else {
11904 /*
11905 * Notify response from timeout to allow the control
11906 * interface response to be sent first.
11907 */
11908 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
11909 wpa_s, NULL);
11910 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011911 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
11912 if (wpa_supplicant_reload_configuration(wpa_s))
11913 reply_len = -1;
11914 } else if (os_strcmp(buf, "TERMINATE") == 0) {
11915 wpa_supplicant_terminate_proc(wpa_s->global);
11916 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
11917 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
11918 reply_len = -1;
Hai Shalom60840252021-02-19 19:02:11 -080011919 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
11920 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
11921 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidte19501d2011-03-16 14:32:18 -070011922 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -080011923 /* deprecated backwards compatibility alias for BSSID_IGNORE */
11924 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011925 wpa_s, buf + 9, reply, reply_size);
11926 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
11927 reply_len = wpa_supplicant_ctrl_iface_log_level(
11928 wpa_s, buf + 9, reply, reply_size);
Vinit Deshpandeda134e92014-12-02 10:59:29 -080011929 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
11930 reply_len = wpa_supplicant_ctrl_iface_list_networks(
11931 wpa_s, buf + 14, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011932 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
11933 reply_len = wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -080011934 wpa_s, NULL, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011935 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070011936 wpas_request_disconnection(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011937 } else if (os_strcmp(buf, "SCAN") == 0) {
11938 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
11939 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
11940 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011941 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
11942 reply_len = wpa_supplicant_ctrl_iface_scan_results(
11943 wpa_s, reply, reply_size);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080011944 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
11945 if (wpas_abort_ongoing_scan(wpa_s) < 0)
11946 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011947 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
11948 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
11949 reply_len = -1;
11950 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
11951 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
11952 reply_len = -1;
11953 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
11954 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
11955 reply_len = -1;
11956 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
11957 reply_len = wpa_supplicant_ctrl_iface_add_network(
11958 wpa_s, reply, reply_size);
11959 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
11960 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
11961 reply_len = -1;
11962 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
11963 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
11964 reply_len = -1;
11965 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
11966 reply_len = wpa_supplicant_ctrl_iface_get_network(
11967 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidt684785c2014-05-12 13:34:29 -070011968 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080011969 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
11970 wpa_s))
Dmitry Shmidt684785c2014-05-12 13:34:29 -070011971 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070011972 } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
11973 reply_len = wpa_supplicant_ctrl_iface_list_creds(
11974 wpa_s, reply, reply_size);
11975 } else if (os_strcmp(buf, "ADD_CRED") == 0) {
11976 reply_len = wpa_supplicant_ctrl_iface_add_cred(
11977 wpa_s, reply, reply_size);
11978 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
11979 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
11980 reply_len = -1;
11981 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
11982 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
11983 reply_len = -1;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -070011984 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
11985 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
11986 reply,
11987 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011988#ifndef CONFIG_NO_CONFIG_WRITE
11989 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
11990 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
11991 reply_len = -1;
11992#endif /* CONFIG_NO_CONFIG_WRITE */
11993 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
11994 reply_len = wpa_supplicant_ctrl_iface_get_capability(
11995 wpa_s, buf + 15, reply, reply_size);
11996 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
11997 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
11998 reply_len = -1;
11999 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
12000 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
12001 reply_len = -1;
12002 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
12003 reply_len = wpa_supplicant_global_iface_list(
12004 wpa_s->global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080012005 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012006 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080012007 wpa_s->global, buf + 10, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012008 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
12009 reply_len = wpa_supplicant_ctrl_iface_bss(
12010 wpa_s, buf + 4, reply, reply_size);
12011#ifdef CONFIG_AP
12012 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
12013 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
12014 } else if (os_strncmp(buf, "STA ", 4) == 0) {
12015 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
12016 reply_size);
12017 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
12018 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
12019 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070012020 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
12021 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
12022 reply_len = -1;
12023 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
12024 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
12025 reply_len = -1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012026 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
12027 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
12028 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080012029 } else if (os_strcmp(buf, "STOP_AP") == 0) {
12030 if (wpas_ap_stop_ap(wpa_s))
12031 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080012032 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
12033 if (wpas_ap_update_beacon(wpa_s))
12034 reply_len = -1;
Sunil Ravia04bd252022-05-02 22:54:18 -070012035 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
12036 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
12037 if (ap_ctrl_iface_acl_add_mac(wpa_s,
12038 DENY_UNLESS_ACCEPTED,
12039 buf + 19) ||
12040 ap_ctrl_iface_set_acl(wpa_s))
12041 reply_len = -1;
12042 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
12043 if (ap_ctrl_iface_acl_del_mac(wpa_s,
12044 DENY_UNLESS_ACCEPTED,
12045 buf + 19) ||
12046 ap_ctrl_iface_set_acl(wpa_s) ||
12047 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
12048 reply_len = -1;
12049 } else if (os_strcmp(buf + 11, "SHOW") == 0) {
12050 reply_len = ap_ctrl_iface_acl_show_mac(
12051 wpa_s, DENY_UNLESS_ACCEPTED,
12052 reply, reply_size);
12053 } else if (os_strcmp(buf + 11, "CLEAR") == 0) {
12054 ap_ctrl_iface_acl_clear_list(wpa_s,
12055 DENY_UNLESS_ACCEPTED);
12056 if (ap_ctrl_iface_set_acl(wpa_s) ||
12057 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
12058 reply_len = -1;
12059 } else {
12060 reply_len = -1;
12061 }
12062 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
12063 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
12064 if (ap_ctrl_iface_acl_add_mac(wpa_s,
12065 ACCEPT_UNLESS_DENIED,
12066 buf + 17) ||
12067 ap_ctrl_iface_set_acl(wpa_s) ||
12068 ap_ctrl_iface_disassoc_deny_mac(wpa_s))
12069 reply_len = -1;
12070 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
12071 if (ap_ctrl_iface_acl_del_mac(wpa_s,
12072 ACCEPT_UNLESS_DENIED,
12073 buf + 17) ||
12074 ap_ctrl_iface_set_acl(wpa_s))
12075 reply_len = -1;
12076 } else if (os_strcmp(buf + 9, "SHOW") == 0) {
12077 reply_len = ap_ctrl_iface_acl_show_mac(
12078 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size);
12079 } else if (os_strcmp(buf + 9, "CLEAR") == 0) {
12080 ap_ctrl_iface_acl_clear_list(wpa_s,
12081 ACCEPT_UNLESS_DENIED);
12082 if (ap_ctrl_iface_set_acl(wpa_s))
12083 reply_len = -1;
12084 } else {
12085 reply_len = -1;
12086 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012087#endif /* CONFIG_AP */
12088 } else if (os_strcmp(buf, "SUSPEND") == 0) {
12089 wpas_notify_suspend(wpa_s->global);
12090 } else if (os_strcmp(buf, "RESUME") == 0) {
12091 wpas_notify_resume(wpa_s->global);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070012092#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012093 } else if (os_strcmp(buf, "DROP_SA") == 0) {
12094 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070012095#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012096 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
12097 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
12098 reply_len = -1;
12099 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012100 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012101 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
12102 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
12103 reply_len = -1;
12104 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
12105 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
12106 buf + 17))
12107 reply_len = -1;
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -070012108 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012109 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012110#ifdef CONFIG_TDLS
12111 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
12112 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
12113 reply_len = -1;
12114 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
12115 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
12116 reply_len = -1;
12117 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
12118 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
12119 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012120 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
12121 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
12122 buf + 17))
12123 reply_len = -1;
12124 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
12125 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
12126 buf + 24))
12127 reply_len = -1;
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -070012128 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
12129 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
12130 wpa_s, buf + 17, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012131#endif /* CONFIG_TDLS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012132 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
12133 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
12134 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
12135 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
12136 reply_len = -1;
12137 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
12138 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
12139 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012140 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
12141 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
12142 reply_size);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080012143 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
12144 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
12145 reply_len = -1;
Yuhao Zhengfcd6f212012-07-27 10:37:52 -070012146 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
12147 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
12148 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070012149#ifdef CONFIG_AUTOSCAN
12150 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
12151 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
12152 reply_len = -1;
12153#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070012154 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
12155 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
12156 reply_size);
Hai Shalomb755a2a2020-04-23 21:49:02 -070012157 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
12158 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
12159 reply_size);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080012160#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -070012161 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
12162 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
12163 reply_size);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080012164#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080012165 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
12166 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
12167 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012168 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012169 pmksa_cache_clear_current(wpa_s->wpa);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012170 eapol_sm_request_reauth(wpa_s->eapol);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080012171#ifdef CONFIG_WNM
12172 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
12173 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
12174 reply_len = -1;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080012175 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
12176 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
Dmitry Shmidt44c95782013-05-17 09:51:35 -070012177 reply_len = -1;
Hai Shalom39ba6fc2019-01-22 12:40:38 -080012178 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
12179 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
12180 reply_len = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080012181#endif /* CONFIG_WNM */
Sunil Ravia04bd252022-05-02 22:54:18 -070012182#ifdef CONFIG_WNM_AP
12183 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
12184 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
12185 reply_len = -1;
12186 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
12187 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13))
12188 reply_len = -1;
12189 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
12190 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
12191 reply_len = -1;
12192#endif /* CONFIG_WNM_AP */
Dmitry Shmidt444d5672013-04-01 13:08:44 -070012193 } else if (os_strcmp(buf, "FLUSH") == 0) {
12194 wpa_supplicant_ctrl_iface_flush(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012195 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
12196 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
12197 reply_size);
Dmitry Shmidt818ea482014-03-10 13:15:21 -070012198#ifdef CONFIG_TESTING_OPTIONS
12199 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
12200 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
12201 reply_len = -1;
12202 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
12203 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070012204 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
12205 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
12206 reply_len = -1;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -070012207 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
12208 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
12209 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012210 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
12211 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
12212 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080012213 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
12214 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
12215 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012216 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
12217 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
12218 reply_len = -1;
12219 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
12220 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
12221 reply_len = -1;
12222 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
12223 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
12224 reply_len = -1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080012225 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
12226 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
12227 reply_len = -1;
12228 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
12229 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080012230 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
12231 if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0)
12232 reply_len = -1;
12233 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
12234 reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
Jouni Malinenc4818362015-10-04 11:45:13 +030012235 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
12236 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
12237 reply_len = -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080012238 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
12239 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
12240 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012241 } else if (os_strcmp(buf, "RESET_PN") == 0) {
12242 if (wpas_ctrl_reset_pn(wpa_s) < 0)
12243 reply_len = -1;
12244 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
12245 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
12246 reply_len = -1;
12247 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
12248 if (wpas_ctrl_resend_assoc(wpa_s) < 0)
12249 reply_len = -1;
Hai Shalom74f70d42019-02-11 14:42:39 -080012250 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
12251 sme_event_unprot_disconnect(
12252 wpa_s, wpa_s->bssid, NULL,
12253 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
Hai Shaloma20dcd72022-02-04 13:43:00 -080012254 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
12255 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
12256 reply_len = -1;
12257 } else if (os_strcmp(buf, "TWT_SETUP") == 0) {
12258 if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
12259 reply_len = -1;
12260 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
12261 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
12262 reply_len = -1;
12263 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
12264 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
12265 reply_len = -1;
Dmitry Shmidt818ea482014-03-10 13:15:21 -070012266#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070012267 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
12268 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
12269 reply_len = -1;
12270 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
12271 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
12272 reply_size);
12273 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
12274 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
12275 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012276 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
Dmitry Shmidt849734c2016-05-27 09:59:01 -070012277 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012278 reply_len = -1;
12279 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
12280 wpas_ctrl_iface_erp_flush(wpa_s);
12281 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
12282 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
12283 reply_len = -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080012284 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
12285 reply_len = wpas_ctrl_iface_get_pref_freq_list(
12286 wpa_s, buf + 19, reply, reply_size);
Paul Stewart092955c2017-02-06 09:13:09 -080012287#ifdef CONFIG_FILS
12288 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
12289 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
12290 reply_len = -1;
12291 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
12292 wpas_flush_fils_hlp_req(wpa_s);
12293#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012294#ifdef CONFIG_DPP
12295 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
12296 int res;
12297
12298 res = wpas_dpp_qr_code(wpa_s, buf + 12);
12299 if (res < 0) {
12300 reply_len = -1;
12301 } else {
12302 reply_len = os_snprintf(reply, reply_size, "%d", res);
12303 if (os_snprintf_error(reply_size, reply_len))
12304 reply_len = -1;
12305 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080012306 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
12307 int res;
12308
12309 res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
12310 if (res < 0) {
12311 reply_len = -1;
12312 } else {
12313 reply_len = os_snprintf(reply, reply_size, "%d", res);
12314 if (os_snprintf_error(reply_size, reply_len))
12315 reply_len = -1;
12316 }
Hai Shalomfdcde762020-04-02 11:19:20 -070012317 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
12318 int res;
12319
12320 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
12321 if (res < 0) {
12322 reply_len = -1;
12323 } else {
12324 reply_len = os_snprintf(reply, reply_size, "%d", res);
12325 if (os_snprintf_error(reply_size, reply_len))
12326 reply_len = -1;
12327 }
12328 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
12329 int res;
12330
12331 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
12332 if (res < 0) {
12333 reply_len = -1;
12334 } else {
12335 reply_len = os_snprintf(reply, reply_size, "%d", res);
12336 if (os_snprintf_error(reply_size, reply_len))
12337 reply_len = -1;
12338 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012339 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
12340 int res;
12341
Hai Shalom021b0b52019-04-10 11:17:58 -070012342 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012343 if (res < 0) {
12344 reply_len = -1;
12345 } else {
12346 reply_len = os_snprintf(reply, reply_size, "%d", res);
12347 if (os_snprintf_error(reply_size, reply_len))
12348 reply_len = -1;
12349 }
12350 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070012351 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012352 reply_len = -1;
12353 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
12354 const char *uri;
12355
Hai Shalom021b0b52019-04-10 11:17:58 -070012356 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012357 if (!uri) {
12358 reply_len = -1;
12359 } else {
12360 reply_len = os_snprintf(reply, reply_size, "%s", uri);
12361 if (os_snprintf_error(reply_size, reply_len))
12362 reply_len = -1;
12363 }
12364 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070012365 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
12366 reply, reply_size);
Hai Shalomfdcde762020-04-02 11:19:20 -070012367 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
12368 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
12369 os_strchr(buf + 18, ' ')) < 0)
12370 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012371 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
12372 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
12373 reply_len = -1;
12374 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
12375 if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
12376 reply_len = -1;
12377 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -070012378 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012379 wpas_dpp_listen_stop(wpa_s);
12380 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
12381 int res;
12382
Hai Shalom021b0b52019-04-10 11:17:58 -070012383 res = dpp_configurator_add(wpa_s->dpp, buf + 20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012384 if (res < 0) {
12385 reply_len = -1;
12386 } else {
12387 reply_len = os_snprintf(reply, reply_size, "%d", res);
12388 if (os_snprintf_error(reply_size, reply_len))
12389 reply_len = -1;
12390 }
Sunil Ravia04bd252022-05-02 22:54:18 -070012391 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
12392 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0)
12393 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012394 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070012395 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012396 reply_len = -1;
12397 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -080012398 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012399 reply_len = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -070012400 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070012401 reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
12402 atoi(buf + 25),
12403 reply, reply_size);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012404 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
12405 int res;
12406
12407 res = wpas_dpp_pkex_add(wpa_s, buf + 12);
12408 if (res < 0) {
12409 reply_len = -1;
12410 } else {
12411 reply_len = os_snprintf(reply, reply_size, "%d", res);
12412 if (os_snprintf_error(reply_size, reply_len))
12413 reply_len = -1;
12414 }
12415 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
12416 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
12417 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080012418 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
12419 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
12420 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070012421#ifdef CONFIG_DPP2
12422 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
12423 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
12424 reply_len = -1;
12425 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
12426 if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
12427 reply_len = -1;
12428 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
12429 dpp_controller_stop(wpa_s->dpp);
Hai Shalomfdcde762020-04-02 11:19:20 -070012430 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
12431 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
12432 reply_len = -1;
12433 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
12434 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070012435 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
Hai Shalom899fcc72020-10-19 14:38:18 -070012436 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
12437 reply_len = -1;
12438 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
12439 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -070012440 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070012441#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012442#endif /* CONFIG_DPP */
Hai Shalom899fcc72020-10-19 14:38:18 -070012443 } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
12444 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
12445 reply_len = -1;
Hai Shalom60840252021-02-19 19:02:11 -080012446#ifdef CONFIG_PASN
12447 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
12448 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
12449 reply_len = -1;
12450 } else if (os_strcmp(buf, "PASN_STOP") == 0) {
12451 wpas_pasn_auth_stop(wpa_s);
12452 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
12453 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
Hai Shaloma20dcd72022-02-04 13:43:00 -080012454 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
12455 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
12456 reply_len = -1;
Hai Shalom60840252021-02-19 19:02:11 -080012457#endif /* CONFIG_PASN */
Hai Shaloma20dcd72022-02-04 13:43:00 -080012458 } else if (os_strncmp(buf, "SCS ", 4) == 0) {
12459 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
12460 reply_len = -1;
12461 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
12462 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
12463 reply_len = -1;
12464 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
12465 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
12466 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012467 } else {
12468 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
12469 reply_len = 16;
12470 }
12471
12472 if (reply_len < 0) {
12473 os_memcpy(reply, "FAIL\n", 5);
12474 reply_len = 5;
12475 }
12476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012477 *resp_len = reply_len;
12478 return reply;
12479}
12480
12481
12482static int wpa_supplicant_global_iface_add(struct wpa_global *global,
12483 char *cmd)
12484{
12485 struct wpa_interface iface;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012486 char *pos, *extra;
12487 struct wpa_supplicant *wpa_s;
12488 unsigned int create_iface = 0;
12489 u8 mac_addr[ETH_ALEN];
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012490 enum wpa_driver_if_type type = WPA_IF_STATION;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012491
12492 /*
12493 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012494 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012495 */
12496 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
12497
12498 os_memset(&iface, 0, sizeof(iface));
12499
12500 do {
12501 iface.ifname = pos = cmd;
12502 pos = os_strchr(pos, '\t');
12503 if (pos)
12504 *pos++ = '\0';
12505 if (iface.ifname[0] == '\0')
12506 return -1;
12507 if (pos == NULL)
12508 break;
12509
12510 iface.confname = pos;
12511 pos = os_strchr(pos, '\t');
12512 if (pos)
12513 *pos++ = '\0';
12514 if (iface.confname[0] == '\0')
12515 iface.confname = NULL;
12516 if (pos == NULL)
12517 break;
12518
12519 iface.driver = pos;
12520 pos = os_strchr(pos, '\t');
12521 if (pos)
12522 *pos++ = '\0';
12523 if (iface.driver[0] == '\0')
12524 iface.driver = NULL;
12525 if (pos == NULL)
12526 break;
12527
12528 iface.ctrl_interface = pos;
12529 pos = os_strchr(pos, '\t');
12530 if (pos)
12531 *pos++ = '\0';
12532 if (iface.ctrl_interface[0] == '\0')
12533 iface.ctrl_interface = NULL;
12534 if (pos == NULL)
12535 break;
12536
12537 iface.driver_param = pos;
12538 pos = os_strchr(pos, '\t');
12539 if (pos)
12540 *pos++ = '\0';
12541 if (iface.driver_param[0] == '\0')
12542 iface.driver_param = NULL;
12543 if (pos == NULL)
12544 break;
12545
12546 iface.bridge_ifname = pos;
12547 pos = os_strchr(pos, '\t');
12548 if (pos)
12549 *pos++ = '\0';
12550 if (iface.bridge_ifname[0] == '\0')
12551 iface.bridge_ifname = NULL;
12552 if (pos == NULL)
12553 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012554
12555 extra = pos;
12556 pos = os_strchr(pos, '\t');
12557 if (pos)
12558 *pos++ = '\0';
Dmitry Shmidt83474442015-04-15 13:47:09 -070012559 if (!extra[0])
12560 break;
12561
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012562 if (os_strcmp(extra, "create") == 0) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012563 create_iface = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012564 if (!pos)
12565 break;
12566
12567 if (os_strcmp(pos, "sta") == 0) {
12568 type = WPA_IF_STATION;
12569 } else if (os_strcmp(pos, "ap") == 0) {
12570 type = WPA_IF_AP_BSS;
12571 } else {
12572 wpa_printf(MSG_DEBUG,
12573 "INTERFACE_ADD unsupported interface type: '%s'",
12574 pos);
12575 return -1;
12576 }
12577 } else {
Dmitry Shmidt83474442015-04-15 13:47:09 -070012578 wpa_printf(MSG_DEBUG,
12579 "INTERFACE_ADD unsupported extra parameter: '%s'",
12580 extra);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012581 return -1;
Dmitry Shmidt83474442015-04-15 13:47:09 -070012582 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012583 } while (0);
12584
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012585 if (create_iface) {
12586 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
12587 iface.ifname);
12588 if (!global->ifaces)
12589 return -1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012590 if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012591 NULL, NULL, NULL, mac_addr, NULL) < 0) {
12592 wpa_printf(MSG_ERROR,
12593 "CTRL_IFACE interface creation failed");
12594 return -1;
12595 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012596
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012597 wpa_printf(MSG_DEBUG,
12598 "CTRL_IFACE interface '%s' created with MAC addr: "
12599 MACSTR, iface.ifname, MAC2STR(mac_addr));
12600 }
12601
12602 if (wpa_supplicant_get_iface(global, iface.ifname))
12603 goto fail;
12604
12605 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
12606 if (!wpa_s)
12607 goto fail;
12608 wpa_s->added_vif = create_iface;
12609 return 0;
12610
12611fail:
12612 if (create_iface)
12613 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
12614 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012615}
12616
12617
12618static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
12619 char *cmd)
12620{
12621 struct wpa_supplicant *wpa_s;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012622 int ret;
12623 unsigned int delete_iface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012624
12625 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
12626
12627 wpa_s = wpa_supplicant_get_iface(global, cmd);
12628 if (wpa_s == NULL)
12629 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070012630 delete_iface = wpa_s->added_vif;
12631 ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
12632 if (!ret && delete_iface) {
12633 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
12634 cmd);
12635 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
12636 }
12637 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012638}
12639
12640
12641static void wpa_free_iface_info(struct wpa_interface_info *iface)
12642{
12643 struct wpa_interface_info *prev;
12644
12645 while (iface) {
12646 prev = iface;
12647 iface = iface->next;
12648
12649 os_free(prev->ifname);
12650 os_free(prev->desc);
12651 os_free(prev);
12652 }
12653}
12654
12655
12656static int wpa_supplicant_global_iface_list(struct wpa_global *global,
12657 char *buf, int len)
12658{
12659 int i, res;
12660 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
12661 char *pos, *end;
12662
12663 for (i = 0; wpa_drivers[i]; i++) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070012664 const struct wpa_driver_ops *drv = wpa_drivers[i];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012665 if (drv->get_interfaces == NULL)
12666 continue;
12667 tmp = drv->get_interfaces(global->drv_priv[i]);
12668 if (tmp == NULL)
12669 continue;
12670
12671 if (last == NULL)
12672 iface = last = tmp;
12673 else
12674 last->next = tmp;
12675 while (last->next)
12676 last = last->next;
12677 }
12678
12679 pos = buf;
12680 end = buf + len;
12681 for (tmp = iface; tmp; tmp = tmp->next) {
12682 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
12683 tmp->drv_name, tmp->ifname,
12684 tmp->desc ? tmp->desc : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012685 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012686 *pos = '\0';
12687 break;
12688 }
12689 pos += res;
12690 }
12691
12692 wpa_free_iface_info(iface);
12693
12694 return pos - buf;
12695}
12696
12697
12698static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080012699 const char *input,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012700 char *buf, int len)
12701{
12702 int res;
12703 char *pos, *end;
12704 struct wpa_supplicant *wpa_s;
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080012705 int show_ctrl = 0;
12706
12707 if (input)
12708 show_ctrl = !!os_strstr(input, "ctrl");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012709
12710 wpa_s = global->ifaces;
12711 pos = buf;
12712 end = buf + len;
12713
12714 while (wpa_s) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080012715 if (show_ctrl)
12716 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
12717 wpa_s->ifname,
12718 wpa_s->conf->ctrl_interface ?
12719 wpa_s->conf->ctrl_interface : "N/A");
12720 else
12721 res = os_snprintf(pos, end - pos, "%s\n",
12722 wpa_s->ifname);
12723
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012724 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012725 *pos = '\0';
12726 break;
12727 }
12728 pos += res;
12729 wpa_s = wpa_s->next;
12730 }
12731 return pos - buf;
12732}
12733
12734
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012735static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
12736 const char *ifname,
12737 char *cmd, size_t *resp_len)
12738{
12739 struct wpa_supplicant *wpa_s;
12740
12741 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
12742 if (os_strcmp(ifname, wpa_s->ifname) == 0)
12743 break;
12744 }
12745
12746 if (wpa_s == NULL) {
12747 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
12748 if (resp)
12749 *resp_len = os_strlen(resp);
12750 else
12751 *resp_len = 1;
12752 return resp;
12753 }
12754
12755 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
12756}
12757
12758
12759static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
12760 char *buf, size_t *resp_len)
12761{
12762#ifdef CONFIG_P2P
12763 static const char * cmd[] = {
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070012764 "LIST_NETWORKS",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012765 "P2P_FIND",
12766 "P2P_STOP_FIND",
12767 "P2P_LISTEN",
12768 "P2P_GROUP_ADD",
12769 "P2P_GET_PASSPHRASE",
12770 "P2P_SERVICE_UPDATE",
12771 "P2P_SERVICE_FLUSH",
12772 "P2P_FLUSH",
12773 "P2P_CANCEL",
12774 "P2P_PRESENCE_REQ",
12775 "P2P_EXT_LISTEN",
Paul Stewart092955c2017-02-06 09:13:09 -080012776#ifdef CONFIG_AP
12777 "STA-FIRST",
12778#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012779 NULL
12780 };
12781 static const char * prefix[] = {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080012782#ifdef ANDROID
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070012783 "DRIVER ",
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080012784#endif /* ANDROID */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012785 "GET_CAPABILITY ",
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070012786 "GET_NETWORK ",
12787 "REMOVE_NETWORK ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012788 "P2P_FIND ",
12789 "P2P_CONNECT ",
12790 "P2P_LISTEN ",
12791 "P2P_GROUP_REMOVE ",
12792 "P2P_GROUP_ADD ",
Dmitry Shmidt849734c2016-05-27 09:59:01 -070012793 "P2P_GROUP_MEMBER ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012794 "P2P_PROV_DISC ",
12795 "P2P_SERV_DISC_REQ ",
12796 "P2P_SERV_DISC_CANCEL_REQ ",
12797 "P2P_SERV_DISC_RESP ",
12798 "P2P_SERV_DISC_EXTERNAL ",
12799 "P2P_SERVICE_ADD ",
12800 "P2P_SERVICE_DEL ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012801 "P2P_SERVICE_REP ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012802 "P2P_REJECT ",
12803 "P2P_INVITE ",
12804 "P2P_PEER ",
12805 "P2P_SET ",
12806 "P2P_UNAUTHORIZE ",
12807 "P2P_PRESENCE_REQ ",
12808 "P2P_EXT_LISTEN ",
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070012809 "P2P_REMOVE_CLIENT ",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080012810 "WPS_NFC_TOKEN ",
12811 "WPS_NFC_TAG_READ ",
Dmitry Shmidt413dde72014-04-11 10:23:22 -070012812 "NFC_GET_HANDOVER_SEL ",
12813 "NFC_GET_HANDOVER_REQ ",
12814 "NFC_REPORT_HANDOVER ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012815 "P2P_ASP_PROVISION ",
12816 "P2P_ASP_PROVISION_RESP ",
Paul Stewart092955c2017-02-06 09:13:09 -080012817#ifdef CONFIG_AP
12818 "STA ",
12819 "STA-NEXT ",
12820#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070012821 NULL
12822 };
12823 int found = 0;
12824 int i;
12825
12826 if (global->p2p_init_wpa_s == NULL)
12827 return NULL;
12828
12829 for (i = 0; !found && cmd[i]; i++) {
12830 if (os_strcmp(buf, cmd[i]) == 0)
12831 found = 1;
12832 }
12833
12834 for (i = 0; !found && prefix[i]; i++) {
12835 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
12836 found = 1;
12837 }
12838
12839 if (found)
12840 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
12841 buf, resp_len);
12842#endif /* CONFIG_P2P */
12843 return NULL;
12844}
12845
12846
12847static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
12848 char *buf, size_t *resp_len)
12849{
12850#ifdef CONFIG_WIFI_DISPLAY
12851 if (global->p2p_init_wpa_s == NULL)
12852 return NULL;
12853 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
12854 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
12855 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
12856 buf, resp_len);
12857#endif /* CONFIG_WIFI_DISPLAY */
12858 return NULL;
12859}
12860
12861
12862static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
12863 char *buf, size_t *resp_len)
12864{
12865 char *ret;
12866
12867 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
12868 if (ret)
12869 return ret;
12870
12871 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
12872 if (ret)
12873 return ret;
12874
12875 return NULL;
12876}
12877
12878
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012879static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
12880{
12881 char *value;
12882
12883 value = os_strchr(cmd, ' ');
12884 if (value == NULL)
12885 return -1;
12886 *value++ = '\0';
12887
12888 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
12889
12890#ifdef CONFIG_WIFI_DISPLAY
12891 if (os_strcasecmp(cmd, "wifi_display") == 0) {
12892 wifi_display_enable(global, !!atoi(value));
12893 return 0;
12894 }
12895#endif /* CONFIG_WIFI_DISPLAY */
12896
Dmitry Shmidt61593f02014-04-21 16:27:35 -070012897 /* Restore cmd to its original value to allow redirection */
12898 value[-1] = ' ';
12899
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012900 return -1;
12901}
12902
12903
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080012904static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
12905 char *cmd)
12906{
12907 struct wpa_supplicant *wpa_s[2]; /* src, dst */
12908 char *p;
12909 unsigned int i;
12910
12911 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
12912 * <variable name> */
12913
12914 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
12915 p = os_strchr(cmd, ' ');
12916 if (p == NULL)
12917 return -1;
12918 *p = '\0';
12919
12920 wpa_s[i] = global->ifaces;
12921 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
12922 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
12923 break;
12924 }
12925
12926 if (!wpa_s[i]) {
12927 wpa_printf(MSG_DEBUG,
12928 "CTRL_IFACE: Could not find iface=%s", cmd);
12929 return -1;
12930 }
12931
12932 cmd = p + 1;
12933 }
12934
12935 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
12936}
12937
12938
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012939#ifndef CONFIG_NO_CONFIG_WRITE
12940static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
12941{
Dmitry Shmidt61593f02014-04-21 16:27:35 -070012942 int ret = 0, saved = 0;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012943 struct wpa_supplicant *wpa_s;
12944
12945 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
12946 if (!wpa_s->conf->update_config) {
12947 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
12948 continue;
12949 }
12950
12951 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
12952 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
12953 ret = 1;
12954 } else {
12955 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
Dmitry Shmidt61593f02014-04-21 16:27:35 -070012956 saved++;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012957 }
12958 }
12959
Dmitry Shmidt61593f02014-04-21 16:27:35 -070012960 if (!saved && !ret) {
12961 wpa_dbg(wpa_s, MSG_DEBUG,
12962 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
12963 ret = 1;
12964 }
12965
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012966 return ret;
12967}
12968#endif /* CONFIG_NO_CONFIG_WRITE */
12969
12970
12971static int wpas_global_ctrl_iface_status(struct wpa_global *global,
12972 char *buf, size_t buflen)
12973{
12974 char *pos, *end;
12975 int ret;
12976 struct wpa_supplicant *wpa_s;
12977
12978 pos = buf;
12979 end = buf + buflen;
12980
12981#ifdef CONFIG_P2P
12982 if (global->p2p && !global->p2p_disabled) {
12983 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
12984 "\n"
12985 "p2p_state=%s\n",
12986 MAC2STR(global->p2p_dev_addr),
12987 p2p_get_state_txt(global->p2p));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012988 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012989 return pos - buf;
12990 pos += ret;
12991 } else if (global->p2p) {
12992 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012993 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012994 return pos - buf;
12995 pos += ret;
12996 }
12997#endif /* CONFIG_P2P */
12998
12999#ifdef CONFIG_WIFI_DISPLAY
13000 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
13001 !!global->wifi_display);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013002 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013003 return pos - buf;
13004 pos += ret;
13005#endif /* CONFIG_WIFI_DISPLAY */
13006
13007 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13008 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
13009 "address=" MACSTR "\n",
13010 wpa_s->ifname, MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013011 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013012 return pos - buf;
13013 pos += ret;
13014 }
13015
13016 return pos - buf;
13017}
13018
13019
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013020#ifdef CONFIG_FST
13021
13022static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
13023 char *cmd, char *buf,
13024 size_t reply_size)
13025{
13026 char ifname[IFNAMSIZ + 1];
13027 struct fst_iface_cfg cfg;
13028 struct wpa_supplicant *wpa_s;
13029 struct fst_wpa_obj iface_obj;
13030
13031 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
13032 wpa_s = wpa_supplicant_get_iface(global, ifname);
13033 if (wpa_s) {
13034 if (wpa_s->fst) {
13035 wpa_printf(MSG_INFO, "FST: Already attached");
13036 return -1;
13037 }
13038 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
13039 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
13040 &iface_obj, &cfg);
13041 if (wpa_s->fst)
13042 return os_snprintf(buf, reply_size, "OK\n");
13043 }
13044 }
13045
13046 return -1;
13047}
13048
13049
13050static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
13051 char *cmd, char *buf,
13052 size_t reply_size)
13053{
13054 char ifname[IFNAMSIZ + 1];
13055 struct wpa_supplicant *wpa_s;
13056
13057 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
13058 wpa_s = wpa_supplicant_get_iface(global, ifname);
13059 if (wpa_s) {
13060 if (!fst_iface_detach(ifname)) {
13061 wpa_s->fst = NULL;
13062 return os_snprintf(buf, reply_size, "OK\n");
13063 }
13064 }
13065 }
13066
13067 return -1;
13068}
13069
13070#endif /* CONFIG_FST */
13071
13072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013073char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
13074 char *buf, size_t *resp_len)
13075{
13076 char *reply;
13077 const int reply_size = 2048;
13078 int reply_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013079 int level = MSG_DEBUG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013080
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013081 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
13082 char *pos = os_strchr(buf + 7, ' ');
13083 if (pos) {
13084 *pos++ = '\0';
13085 return wpas_global_ctrl_iface_ifname(global,
13086 buf + 7, pos,
13087 resp_len);
13088 }
13089 }
13090
13091 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
13092 if (reply)
13093 return reply;
13094
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013095 if (os_strcmp(buf, "PING") == 0)
13096 level = MSG_EXCESSIVE;
13097 wpa_hexdump_ascii(level, "RX global ctrl_iface",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013098 (const u8 *) buf, os_strlen(buf));
13099
13100 reply = os_malloc(reply_size);
13101 if (reply == NULL) {
13102 *resp_len = 1;
13103 return NULL;
13104 }
13105
13106 os_memcpy(reply, "OK\n", 3);
13107 reply_len = 3;
13108
13109 if (os_strcmp(buf, "PING") == 0) {
13110 os_memcpy(reply, "PONG\n", 5);
13111 reply_len = 5;
13112 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
13113 if (wpa_supplicant_global_iface_add(global, buf + 14))
13114 reply_len = -1;
13115 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
13116 if (wpa_supplicant_global_iface_remove(global, buf + 17))
13117 reply_len = -1;
13118 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
13119 reply_len = wpa_supplicant_global_iface_list(
13120 global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013121 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013122 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013123 global, buf + 10, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013124#ifdef CONFIG_FST
13125 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
13126 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
13127 reply,
13128 reply_size);
13129 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
13130 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
13131 reply,
13132 reply_size);
13133 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
13134 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
13135#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013136 } else if (os_strcmp(buf, "TERMINATE") == 0) {
13137 wpa_supplicant_terminate_proc(global);
13138 } else if (os_strcmp(buf, "SUSPEND") == 0) {
13139 wpas_notify_suspend(global);
13140 } else if (os_strcmp(buf, "RESUME") == 0) {
13141 wpas_notify_resume(global);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013142 } else if (os_strncmp(buf, "SET ", 4) == 0) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -070013143 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
13144#ifdef CONFIG_P2P
13145 if (global->p2p_init_wpa_s) {
13146 os_free(reply);
13147 /* Check if P2P redirection would work for this
13148 * command. */
13149 return wpa_supplicant_ctrl_iface_process(
13150 global->p2p_init_wpa_s,
13151 buf, resp_len);
13152 }
13153#endif /* CONFIG_P2P */
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013154 reply_len = -1;
Dmitry Shmidt61593f02014-04-21 16:27:35 -070013155 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013156 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
13157 if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
13158 reply_len = -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013159#ifndef CONFIG_NO_CONFIG_WRITE
13160 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
13161 if (wpas_global_ctrl_iface_save_config(global))
13162 reply_len = -1;
13163#endif /* CONFIG_NO_CONFIG_WRITE */
13164 } else if (os_strcmp(buf, "STATUS") == 0) {
13165 reply_len = wpas_global_ctrl_iface_status(global, reply,
13166 reply_size);
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080013167#ifdef CONFIG_MODULE_TESTS
13168 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080013169 if (wpas_module_tests() < 0)
13170 reply_len = -1;
13171#endif /* CONFIG_MODULE_TESTS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013172 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
13173 if (wpa_debug_reopen_file() < 0)
13174 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013175 } else {
13176 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13177 reply_len = 16;
13178 }
13179
13180 if (reply_len < 0) {
13181 os_memcpy(reply, "FAIL\n", 5);
13182 reply_len = 5;
13183 }
13184
13185 *resp_len = reply_len;
13186 return reply;
13187}