blob: d0fda4cd9eca82505ffe4e83f16e5a7d92caa0a7 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant / Control interface (shared code for all backends)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003 * Copyright (c) 2004-2024, 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 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000025#include "common/nan_de.h"
Hai Shalom60840252021-02-19 19:02:11 -080026#include "common/ptksa_cache.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080027#include "crypto/tls.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080028#include "ap/hostapd.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "eap_peer/eap.h"
30#include "eapol_supp/eapol_supp_sm.h"
31#include "rsn_supp/wpa.h"
32#include "rsn_supp/preauth.h"
33#include "rsn_supp/pmksa_cache.h"
34#include "l2_packet/l2_packet.h"
35#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080036#include "fst/fst.h"
37#include "fst/fst_ctrl_iface.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070038#include "config.h"
39#include "wpa_supplicant_i.h"
40#include "driver_i.h"
41#include "wps_supplicant.h"
42#include "ibss_rsn.h"
Hai Shaloma20dcd72022-02-04 13:43:00 -080043#include "wpas_glue.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "ap.h"
45#include "p2p_supplicant.h"
46#include "p2p/p2p.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070047#include "hs20_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070048#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "notify.h"
50#include "bss.h"
51#include "scan.h"
52#include "ctrl_iface.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "interworking.h"
Hai Shalom60840252021-02-19 19:02:11 -080054#include "bssid_ignore.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070055#include "autoscan.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080056#include "wnm_sta.h"
Dmitry Shmidt818ea482014-03-10 13:15:21 -070057#include "offchannel.h"
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070058#include "drivers/driver.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080059#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070060#include "dpp_supplicant.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080061#include "sme.h"
Sunil Ravib0ac25f2024-07-12 01:42:03 +000062#include "nan_usd.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070063
Hai Shalomc3565922019-10-28 11:58:20 -070064#ifdef __NetBSD__
65#include <net/if_ether.h>
66#elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS)
67#include <net/ethernet.h>
68#endif
69
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070static int wpa_supplicant_global_iface_list(struct wpa_global *global,
71 char *buf, int len);
72static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080073 const char *input,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074 char *buf, int len);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -070075static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
76 char *val);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070078
Dmitry Shmidt04949592012-07-19 12:16:46 -070079static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
80{
81 char *pos;
82 u8 addr[ETH_ALEN], *filter = NULL, *n;
83 size_t count = 0;
84
85 pos = val;
86 while (pos) {
87 if (*pos == '\0')
88 break;
89 if (hwaddr_aton(pos, addr)) {
90 os_free(filter);
91 return -1;
92 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070093 n = os_realloc_array(filter, count + 1, ETH_ALEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -070094 if (n == NULL) {
95 os_free(filter);
96 return -1;
97 }
98 filter = n;
99 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
100 count++;
101
102 pos = os_strchr(pos, ' ');
103 if (pos)
104 pos++;
105 }
106
107 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
108 os_free(wpa_s->bssid_filter);
109 wpa_s->bssid_filter = filter;
110 wpa_s->bssid_filter_count = count;
111
112 return 0;
113}
114
115
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800116static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
117{
118 char *pos;
119 u8 addr[ETH_ALEN], *bssid = NULL, *n;
120 struct wpa_ssid_value *ssid = NULL, *ns;
121 size_t count = 0, ssid_count = 0;
122 struct wpa_ssid *c;
123
124 /*
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800125 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800126 * SSID_SPEC ::= ssid <SSID_HEX>
127 * BSSID_SPEC ::= bssid <BSSID_HEX>
128 */
129
130 pos = val;
131 while (pos) {
132 if (*pos == '\0')
133 break;
134 if (os_strncmp(pos, "bssid ", 6) == 0) {
135 int res;
136 pos += 6;
137 res = hwaddr_aton2(pos, addr);
138 if (res < 0) {
139 os_free(ssid);
140 os_free(bssid);
141 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
142 "BSSID value '%s'", pos);
143 return -1;
144 }
145 pos += res;
146 n = os_realloc_array(bssid, count + 1, ETH_ALEN);
147 if (n == NULL) {
148 os_free(ssid);
149 os_free(bssid);
150 return -1;
151 }
152 bssid = n;
153 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
154 count++;
155 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
156 char *end;
157 pos += 5;
158
159 end = pos;
160 while (*end) {
161 if (*end == '\0' || *end == ' ')
162 break;
163 end++;
164 }
165
166 ns = os_realloc_array(ssid, ssid_count + 1,
167 sizeof(struct wpa_ssid_value));
168 if (ns == NULL) {
169 os_free(ssid);
170 os_free(bssid);
171 return -1;
172 }
173 ssid = ns;
174
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700175 if ((end - pos) & 0x01 ||
176 end - pos > 2 * SSID_MAX_LEN ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800177 hexstr2bin(pos, ssid[ssid_count].ssid,
178 (end - pos) / 2) < 0) {
179 os_free(ssid);
180 os_free(bssid);
181 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
182 "SSID value '%s'", pos);
183 return -1;
184 }
185 ssid[ssid_count].ssid_len = (end - pos) / 2;
186 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
187 ssid[ssid_count].ssid,
188 ssid[ssid_count].ssid_len);
189 ssid_count++;
190 pos = end;
191 } else {
192 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
193 "'%s'", pos);
194 os_free(ssid);
195 os_free(bssid);
196 return -1;
197 }
198
199 pos = os_strchr(pos, ' ');
200 if (pos)
201 pos++;
202 }
203
204 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
205 os_free(wpa_s->disallow_aps_bssid);
206 wpa_s->disallow_aps_bssid = bssid;
207 wpa_s->disallow_aps_bssid_count = count;
208
209 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
210 os_free(wpa_s->disallow_aps_ssid);
211 wpa_s->disallow_aps_ssid = ssid;
212 wpa_s->disallow_aps_ssid_count = ssid_count;
213
214 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
215 return 0;
216
217 c = wpa_s->current_ssid;
218 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
219 return 0;
220
221 if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
222 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
223 return 0;
224
225 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
226 "because current AP was marked disallowed");
227
228#ifdef CONFIG_SME
229 wpa_s->sme.prev_bssid_set = 0;
230#endif /* CONFIG_SME */
231 wpa_s->reassociate = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800232 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800233 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
234 wpa_supplicant_req_scan(wpa_s, 0, 0);
235
236 return 0;
237}
238
239
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700240#ifndef CONFIG_NO_CONFIG_BLOBS
241static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
242{
243 char *name = pos;
244 struct wpa_config_blob *blob;
245 size_t len;
246
247 pos = os_strchr(pos, ' ');
248 if (pos == NULL)
249 return -1;
250 *pos++ = '\0';
251 len = os_strlen(pos);
252 if (len & 1)
253 return -1;
254
255 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
256 blob = os_zalloc(sizeof(*blob));
257 if (blob == NULL)
258 return -1;
259 blob->name = os_strdup(name);
260 blob->data = os_malloc(len / 2);
261 if (blob->name == NULL || blob->data == NULL) {
262 wpa_config_free_blob(blob);
263 return -1;
264 }
265
266 if (hexstr2bin(pos, blob->data, len / 2) < 0) {
267 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
268 wpa_config_free_blob(blob);
269 return -1;
270 }
271 blob->len = len / 2;
272
273 wpa_config_set_blob(wpa_s->conf, blob);
274
275 return 0;
276}
277#endif /* CONFIG_NO_CONFIG_BLOBS */
278
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700279
280static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
281{
282 char *params;
283 char *pos;
284 int *freqs = NULL;
285 int ret;
286
287 if (atoi(cmd)) {
288 params = os_strchr(cmd, ' ');
289 os_free(wpa_s->manual_sched_scan_freqs);
290 if (params) {
291 params++;
292 pos = os_strstr(params, "freq=");
293 if (pos)
294 freqs = freq_range_to_channel_list(wpa_s,
295 pos + 5);
296 }
297 wpa_s->manual_sched_scan_freqs = freqs;
298 ret = wpas_start_pno(wpa_s);
299 } else {
300 ret = wpas_stop_pno(wpa_s);
301 }
302 return ret;
303}
304
305
Hai Shalom60840252021-02-19 19:02:11 -0800306static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
Ravi Joshie6ccb162015-07-16 17:45:41 -0700307{
308 union wpa_event_data event;
Hai Shalom60840252021-02-19 19:02:11 -0800309 u32 setband_mask = WPA_SETBAND_AUTO;
Ravi Joshie6ccb162015-07-16 17:45:41 -0700310
Hai Shalom60840252021-02-19 19:02:11 -0800311 /*
312 * For example:
313 * SET setband 2G,6G
314 * SET setband 5G
315 * SET setband AUTO
316 */
317 if (!os_strstr(bands, "AUTO")) {
318 if (os_strstr(bands, "5G"))
319 setband_mask |= WPA_SETBAND_5G;
320 if (os_strstr(bands, "6G"))
321 setband_mask |= WPA_SETBAND_6G;
322 if (os_strstr(bands, "2G"))
323 setband_mask |= WPA_SETBAND_2G;
324 if (setband_mask == WPA_SETBAND_AUTO)
325 return -1;
326 }
Ravi Joshie6ccb162015-07-16 17:45:41 -0700327
Hai Shalom60840252021-02-19 19:02:11 -0800328 wpa_s->setband_mask = setband_mask;
329 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
Ravi Joshie6ccb162015-07-16 17:45:41 -0700330 os_memset(&event, 0, sizeof(event));
331 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
332 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
333 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
334 }
335
336 return 0;
337}
338
339
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700340static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
341 const char *cmd)
342{
343 struct wpabuf *lci;
344
345 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
346 wpabuf_free(wpa_s->lci);
347 wpa_s->lci = NULL;
348 return 0;
349 }
350
351 lci = wpabuf_parse_bin(cmd);
352 if (!lci)
353 return -1;
354
355 if (os_get_reltime(&wpa_s->lci_time)) {
356 wpabuf_free(lci);
357 return -1;
358 }
359
360 wpabuf_free(wpa_s->lci);
361 wpa_s->lci = lci;
362
363 return 0;
364}
365
366
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800367static int
368wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
369{
370 int relative_rssi;
371
372 if (os_strcmp(cmd, "disable") == 0) {
373 wpa_s->srp.relative_rssi_set = 0;
374 return 0;
375 }
376
377 relative_rssi = atoi(cmd);
378 if (relative_rssi < 0 || relative_rssi > 100)
379 return -1;
380 wpa_s->srp.relative_rssi = relative_rssi;
381 wpa_s->srp.relative_rssi_set = 1;
382 return 0;
383}
384
385
386static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
387 const char *cmd)
388{
389 char *pos;
390 int adjust_rssi;
391
392 /* <band>:adjust_value */
393 pos = os_strchr(cmd, ':');
394 if (!pos)
395 return -1;
396 pos++;
397 adjust_rssi = atoi(pos);
398 if (adjust_rssi < -100 || adjust_rssi > 100)
399 return -1;
400
401 if (os_strncmp(cmd, "2G", 2) == 0)
402 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
403 else if (os_strncmp(cmd, "5G", 2) == 0)
404 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
405 else
406 return -1;
407
408 wpa_s->srp.relative_adjust_rssi = adjust_rssi;
409
410 return 0;
411}
412
413
414static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
415 const char *cmd)
416{
417 struct wpabuf *ric_ies;
418
419 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
420 wpabuf_free(wpa_s->ric_ies);
421 wpa_s->ric_ies = NULL;
422 return 0;
423 }
424
425 ric_ies = wpabuf_parse_bin(cmd);
426 if (!ric_ies)
427 return -1;
428
429 wpabuf_free(wpa_s->ric_ies);
430 wpa_s->ric_ies = ric_ies;
431
432 return 0;
433}
434
435
Hai Shalomfdcde762020-04-02 11:19:20 -0700436#ifdef CONFIG_TESTING_OPTIONS
437static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
438 const char *val)
439{
440 u8 bssid[ETH_ALEN];
441 const char *pos = val;
442 struct driver_signal_override *dso = NULL, *tmp, parsed;
443
444 if (hwaddr_aton(pos, bssid))
445 return -1;
446 pos = os_strchr(pos, ' ');
447
448 dl_list_for_each(tmp, &wpa_s->drv_signal_override,
449 struct driver_signal_override, list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000450 if (ether_addr_equal(bssid, tmp->bssid)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700451 dso = tmp;
452 break;
453 }
454 }
455
456 if (!pos) {
457 /* Remove existing entry */
458 if (dso) {
459 dl_list_del(&dso->list);
460 os_free(dso);
461 }
462 return 0;
463 }
464 pos++;
465
466 /* Update an existing entry or add a new one */
467 os_memset(&parsed, 0, sizeof(parsed));
468 if (sscanf(pos, "%d %d %d %d %d",
469 &parsed.si_current_signal,
470 &parsed.si_avg_signal,
471 &parsed.si_avg_beacon_signal,
472 &parsed.si_current_noise,
473 &parsed.scan_level) != 5)
474 return -1;
475
476 if (!dso) {
477 dso = os_zalloc(sizeof(*dso));
478 if (!dso)
479 return -1;
480 os_memcpy(dso->bssid, bssid, ETH_ALEN);
481 dl_list_add(&wpa_s->drv_signal_override, &dso->list);
482 }
483 dso->si_current_signal = parsed.si_current_signal;
484 dso->si_avg_signal = parsed.si_avg_signal;
485 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
486 dso->si_current_noise = parsed.si_current_noise;
487 dso->scan_level = parsed.scan_level;
488
489 return 0;
490}
491#endif /* CONFIG_TESTING_OPTIONS */
492
493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700494static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
495 char *cmd)
496{
497 char *value;
498 int ret = 0;
499
500 value = os_strchr(cmd, ' ');
501 if (value == NULL)
502 return -1;
503 *value++ = '\0';
504
505 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
506 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
507 eapol_sm_configure(wpa_s->eapol,
508 atoi(value), -1, -1, -1);
509 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
510 eapol_sm_configure(wpa_s->eapol,
511 -1, atoi(value), -1, -1);
512 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
513 eapol_sm_configure(wpa_s->eapol,
514 -1, -1, atoi(value), -1);
515 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
516 eapol_sm_configure(wpa_s->eapol,
517 -1, -1, -1, atoi(value));
Hai Shaloma20dcd72022-02-04 13:43:00 -0800518#ifdef CONFIG_TESTING_OPTIONS
519 } else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
520 if (os_strcmp(value, "Auto") == 0)
521 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
522 else if (os_strcmp(value, "ForceUnauthorized") == 0)
523 eapol_sm_notify_portControl(wpa_s->eapol,
524 ForceUnauthorized);
525 else if (os_strcmp(value, "ForceAuthorized") == 0)
526 eapol_sm_notify_portControl(wpa_s->eapol,
527 ForceAuthorized);
528 else
529 ret = -1;
530#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
532 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
Paul Stewart092955c2017-02-06 09:13:09 -0800533 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800535 } else {
536 value[-1] = '=';
537 wpa_config_process_global(wpa_s->conf, cmd, -1);
538 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
540 0) {
541 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
Paul Stewart092955c2017-02-06 09:13:09 -0800542 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700543 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800544 } else {
545 value[-1] = '=';
546 wpa_config_process_global(wpa_s->conf, cmd, -1);
547 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
Paul Stewart092955c2017-02-06 09:13:09 -0800549 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
550 atoi(value))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700551 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800552 } else {
553 value[-1] = '=';
554 wpa_config_process_global(wpa_s->conf, cmd, -1);
555 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
557 wpa_s->wps_fragment_size = atoi(value);
558#ifdef CONFIG_WPS_TESTING
559 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
560 long int val;
561 val = strtol(value, NULL, 0);
562 if (val < 0 || val > 0xff) {
563 ret = -1;
564 wpa_printf(MSG_DEBUG, "WPS: Invalid "
565 "wps_version_number %ld", val);
566 } else {
567 wps_version_number = val;
568 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
569 "version %u.%u",
570 (wps_version_number & 0xf0) >> 4,
571 wps_version_number & 0x0f);
572 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800573 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
574 wps_testing_stub_cred = atoi(value);
575 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
576 wps_testing_stub_cred);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800577 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
578 wps_corrupt_pkhash = atoi(value);
579 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
580 wps_corrupt_pkhash);
Dmitry Shmidtde47be72016-01-07 12:52:55 -0800581 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
582 if (value[0] == '\0') {
583 wps_force_auth_types_in_use = 0;
584 } else {
585 wps_force_auth_types = strtol(value, NULL, 0);
586 wps_force_auth_types_in_use = 1;
587 }
588 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
589 if (value[0] == '\0') {
590 wps_force_encr_types_in_use = 0;
591 } else {
592 wps_force_encr_types = strtol(value, NULL, 0);
593 wps_force_encr_types_in_use = 1;
594 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700595#endif /* CONFIG_WPS_TESTING */
596 } else if (os_strcasecmp(cmd, "ampdu") == 0) {
597 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
598 ret = -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800599#ifdef CONFIG_TDLS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700600#ifdef CONFIG_TDLS_TESTING
601 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 tdls_testing = strtol(value, NULL, 0);
603 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
604#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
606 int disabled = atoi(value);
607 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
608 if (disabled) {
609 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
610 ret = -1;
611 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
612 ret = -1;
613 wpa_tdls_enable(wpa_s->wpa, !disabled);
614#endif /* CONFIG_TDLS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800615 } else if (os_strcasecmp(cmd, "pno") == 0) {
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700616 ret = wpas_ctrl_pno(wpa_s, value);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700617 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
618 int disabled = atoi(value);
619 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
620 ret = -1;
621 else if (disabled)
622 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
623 } else if (os_strcasecmp(cmd, "uapsd") == 0) {
624 if (os_strcmp(value, "disable") == 0)
625 wpa_s->set_sta_uapsd = 0;
626 else {
627 int be, bk, vi, vo;
628 char *pos;
629 /* format: BE,BK,VI,VO;max SP Length */
630 be = atoi(value);
631 pos = os_strchr(value, ',');
632 if (pos == NULL)
633 return -1;
634 pos++;
635 bk = atoi(pos);
636 pos = os_strchr(pos, ',');
637 if (pos == NULL)
638 return -1;
639 pos++;
640 vi = atoi(pos);
641 pos = os_strchr(pos, ',');
642 if (pos == NULL)
643 return -1;
644 pos++;
645 vo = atoi(pos);
646 /* ignore max SP Length for now */
647
648 wpa_s->set_sta_uapsd = 1;
649 wpa_s->sta_uapsd = 0;
650 if (be)
651 wpa_s->sta_uapsd |= BIT(0);
652 if (bk)
653 wpa_s->sta_uapsd |= BIT(1);
654 if (vi)
655 wpa_s->sta_uapsd |= BIT(2);
656 if (vo)
657 wpa_s->sta_uapsd |= BIT(3);
658 }
Jouni Malinen21d6bc82012-04-10 16:17:59 -0700659 } else if (os_strcasecmp(cmd, "ps") == 0) {
660 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700661#ifdef CONFIG_WIFI_DISPLAY
662 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
Dmitry Shmidted003d22014-02-06 10:09:12 -0800663 int enabled = !!atoi(value);
664 if (enabled && !wpa_s->global->p2p)
665 ret = -1;
666 else
667 wifi_display_enable(wpa_s->global, enabled);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700668#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700669 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
670 ret = set_bssid_filter(wpa_s, value);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800671 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
672 ret = set_disallow_aps(wpa_s, value);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800673 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
674 wpa_s->no_keep_alive = !!atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700675#ifdef CONFIG_DPP
676 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
677 os_free(wpa_s->dpp_configurator_params);
678 wpa_s->dpp_configurator_params = os_strdup(value);
Sunil Ravia04bd252022-05-02 22:54:18 -0700679#ifdef CONFIG_DPP2
680 dpp_controller_set_params(wpa_s->dpp, value);
681#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700682 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
683 wpa_s->dpp_init_max_tries = atoi(value);
684 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
685 wpa_s->dpp_init_retry_time = atoi(value);
686 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
687 wpa_s->dpp_resp_wait_time = atoi(value);
688 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
689 wpa_s->dpp_resp_max_tries = atoi(value);
690 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
691 wpa_s->dpp_resp_retry_time = atoi(value);
692#ifdef CONFIG_TESTING_OPTIONS
693 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
694 if (hwaddr_aton(value, dpp_pkex_own_mac_override))
695 ret = -1;
696 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
697 if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
698 ret = -1;
699 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
700 size_t hex_len = os_strlen(value);
701
702 if (hex_len >
703 2 * sizeof(dpp_pkex_ephemeral_key_override))
704 ret = -1;
705 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
706 hex_len / 2))
707 ret = -1;
708 else
709 dpp_pkex_ephemeral_key_override_len = hex_len / 2;
710 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
711 size_t hex_len = os_strlen(value);
712
713 if (hex_len > 2 * sizeof(dpp_protocol_key_override))
714 ret = -1;
715 else if (hexstr2bin(value, dpp_protocol_key_override,
716 hex_len / 2))
717 ret = -1;
718 else
719 dpp_protocol_key_override_len = hex_len / 2;
720 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
721 size_t hex_len = os_strlen(value);
722
723 if (hex_len > 2 * sizeof(dpp_nonce_override))
724 ret = -1;
725 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
726 ret = -1;
727 else
728 dpp_nonce_override_len = hex_len / 2;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700729 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
730 dpp_version_override = atoi(value);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700731#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700732#endif /* CONFIG_DPP */
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700733#ifdef CONFIG_TESTING_OPTIONS
734 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
735 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800736 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
737 wpa_s->ext_eapol_frame_io = !!atoi(value);
738#ifdef CONFIG_AP
739 if (wpa_s->ap_iface) {
740 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
741 wpa_s->ext_eapol_frame_io;
742 }
743#endif /* CONFIG_AP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000744 } else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) {
745 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2,
746 !!atoi(value));
747 } else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) {
748 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4,
749 !!atoi(value));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800750 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
751 wpa_s->extra_roc_dur = atoi(value);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800752 } else if (os_strcasecmp(cmd, "test_failure") == 0) {
753 wpa_s->test_failure = atoi(value);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800754 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
755 wpa_s->p2p_go_csa_on_inv = !!atoi(value);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700756 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
757 wpa_s->ignore_auth_resp = !!atoi(value);
758 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
759 wpa_s->ignore_assoc_disallow = !!atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700760 wpa_drv_ignore_assoc_disallow(wpa_s,
761 wpa_s->ignore_assoc_disallow);
Hai Shalomfdcde762020-04-02 11:19:20 -0700762 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) {
763 wpa_s->disable_sa_query = !!atoi(value);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800764 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
765 wpa_s->ignore_sae_h2e_only = !!atoi(value);
766 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
767 char *pos;
768
769 os_free(wpa_s->extra_sae_rejected_groups);
770 wpa_s->extra_sae_rejected_groups = NULL;
771 pos = value;
772 while (pos && pos[0]) {
773 int group;
774
775 group = atoi(pos);
776 wpa_printf(MSG_DEBUG,
777 "TESTING: Extra rejection of SAE group %d",
778 group);
779 if (group)
780 int_array_add_unique(
781 &wpa_s->extra_sae_rejected_groups,
782 group);
783 pos = os_strchr(pos, ' ');
784 if (!pos)
785 break;
786 pos++;
787 }
Hai Shalomb755a2a2020-04-23 21:49:02 -0700788 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) {
789 wpa_s->ft_rsnxe_used = atoi(value);
Hai Shalom899fcc72020-10-19 14:38:18 -0700790 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) {
791 wpa_s->oci_freq_override_eapol = atoi(value);
792 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) {
793 wpa_s->oci_freq_override_saquery_req = atoi(value);
794 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) {
795 wpa_s->oci_freq_override_saquery_resp = atoi(value);
796 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) {
797 wpa_s->oci_freq_override_eapol_g2 = atoi(value);
798 /* Populate value to wpa_sm if already associated. */
799 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
800 wpa_s->oci_freq_override_eapol_g2);
801 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) {
802 wpa_s->oci_freq_override_ft_assoc = atoi(value);
803 /* Populate value to wpa_sm if already associated. */
804 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
805 wpa_s->oci_freq_override_ft_assoc);
806 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) {
807 wpa_s->oci_freq_override_fils_assoc = atoi(value);
808 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) {
809 wpa_s->oci_freq_override_wnm_sleep = atoi(value);
Hai Shalomfdcde762020-04-02 11:19:20 -0700810 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) {
811 wpabuf_free(wpa_s->rsne_override_eapol);
812 if (os_strcmp(value, "NULL") == 0)
813 wpa_s->rsne_override_eapol = NULL;
814 else
815 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800816 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
817 wpabuf_free(wpa_s->rsnxe_override_assoc);
818 if (os_strcmp(value, "NULL") == 0)
819 wpa_s->rsnxe_override_assoc = NULL;
820 else
821 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
822 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
823 wpabuf_free(wpa_s->rsnxe_override_eapol);
824 if (os_strcmp(value, "NULL") == 0)
825 wpa_s->rsnxe_override_eapol = NULL;
826 else
827 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700828 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
829 wpa_s->reject_btm_req_reason = atoi(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800830 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
831 os_free(wpa_s->get_pref_freq_list_override);
832 if (!value[0])
833 wpa_s->get_pref_freq_list_override = NULL;
834 else
835 wpa_s->get_pref_freq_list_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700836 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
837 wpabuf_free(wpa_s->sae_commit_override);
838 if (value[0] == '\0')
839 wpa_s->sae_commit_override = NULL;
840 else
841 wpa_s->sae_commit_override = wpabuf_parse_bin(value);
Hai Shalomfdcde762020-04-02 11:19:20 -0700842 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
843 ret = wpas_ctrl_iface_set_dso(wpa_s, value);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000844#ifndef CONFIG_NO_ROBUST_AV
Hai Shaloma20dcd72022-02-04 13:43:00 -0800845 } else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
846 wpa_s->disable_scs_support = !!atoi(value);
847 } else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
848 wpa_s->disable_mscs_support = !!atoi(value);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000849#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravia04bd252022-05-02 22:54:18 -0700850 } else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) {
851 wpa_s->disable_eapol_g2_tx = !!atoi(value);
852 /* Populate value to wpa_sm if already associated. */
853 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
854 wpa_s->disable_eapol_g2_tx);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000855 } else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) {
856 wpa_s->test_assoc_comeback_type = atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700857#ifdef CONFIG_DPP
858 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
859 os_free(wpa_s->dpp_config_obj_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700860 if (value[0] == '\0')
861 wpa_s->dpp_config_obj_override = NULL;
862 else
863 wpa_s->dpp_config_obj_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700864 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
865 os_free(wpa_s->dpp_discovery_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700866 if (value[0] == '\0')
867 wpa_s->dpp_discovery_override = NULL;
868 else
869 wpa_s->dpp_discovery_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700870 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
871 os_free(wpa_s->dpp_groups_override);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700872 if (value[0] == '\0')
873 wpa_s->dpp_groups_override = NULL;
874 else
875 wpa_s->dpp_groups_override = os_strdup(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700876 } else if (os_strcasecmp(cmd,
877 "dpp_ignore_netaccesskey_mismatch") == 0) {
878 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
Sunil8cd6f4d2022-06-28 18:40:46 +0000879 } else if (os_strcasecmp(cmd, "dpp_discard_public_action") == 0) {
880 wpa_s->dpp_discard_public_action = atoi(value);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700881 } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
882 dpp_test = atoi(value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700883#endif /* CONFIG_DPP */
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700884#endif /* CONFIG_TESTING_OPTIONS */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700885#ifdef CONFIG_FILS
886 } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
887 wpa_s->disable_fils = !!atoi(value);
888 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
889 wpa_supplicant_set_default_scan_ies(wpa_s);
890#endif /* CONFIG_FILS */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700891#ifndef CONFIG_NO_CONFIG_BLOBS
892 } else if (os_strcmp(cmd, "blob") == 0) {
893 ret = wpas_ctrl_set_blob(wpa_s, value);
894#endif /* CONFIG_NO_CONFIG_BLOBS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800895 } else if (os_strcasecmp(cmd, "setband") == 0) {
Ravi Joshie6ccb162015-07-16 17:45:41 -0700896 ret = wpas_ctrl_set_band(wpa_s, value);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800897#ifdef CONFIG_MBO
898 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
899 ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
Paul Stewart092955c2017-02-06 09:13:09 -0800900 if (ret == 0) {
901 value[-1] = '=';
902 wpa_config_process_global(wpa_s->conf, cmd, -1);
903 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800904 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
Sunil Ravi99c035e2024-07-12 01:42:03 +0000905 int val = atoi(value);
906
907 if (val < MBO_CELL_CAPA_AVAILABLE ||
908 val > MBO_CELL_CAPA_NOT_SUPPORTED)
909 return -1;
910
911 wpas_mbo_update_cell_capa(wpa_s, val);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700912 } else if (os_strcasecmp(cmd, "oce") == 0) {
Sunil Ravi99c035e2024-07-12 01:42:03 +0000913 int val = atoi(value);
914
915 if (val < 0 || val > 3)
916 return -1;
917
918 wpa_s->conf->oce = val;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700919 if (wpa_s->conf->oce) {
920 if ((wpa_s->conf->oce & OCE_STA) &&
921 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
922 wpa_s->enable_oce = OCE_STA;
923
924 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
925 (wpa_s->drv_flags &
926 WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
927 /* TODO: Need to add STA-CFON support */
928 wpa_printf(MSG_ERROR,
929 "OCE STA-CFON feature is not yet supported");
930 return -1;
931 }
932 } else {
933 wpa_s->enable_oce = 0;
934 }
935 wpa_supplicant_set_default_scan_ies(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800936#endif /* CONFIG_MBO */
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700937 } else if (os_strcasecmp(cmd, "lci") == 0) {
938 ret = wpas_ctrl_iface_set_lci(wpa_s, value);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800939 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
940 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800941 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
942 ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
943 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
944 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
945 } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
946 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700947 } else if (os_strcasecmp(cmd, "roaming") == 0) {
948 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800949#ifdef CONFIG_WNM
950 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
951 struct wpabuf *elems;
952
953 elems = wpabuf_parse_bin(value);
954 if (!elems)
955 return -1;
956 wnm_set_coloc_intf_elems(wpa_s, elems);
957#endif /* CONFIG_WNM */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000958#ifndef CONFIG_NO_ROBUST_AV
Hai Shaloma20dcd72022-02-04 13:43:00 -0800959 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
960 wpa_s->enable_dscp_policy_capa = !!atoi(value);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000961#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 } else {
963 value[-1] = '=';
964 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
965 if (ret == 0)
966 wpa_supplicant_update_config(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -0700967 else if (ret == 1)
968 ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700969 }
970
971 return ret;
972}
973
974
975static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
976 char *cmd, char *buf, size_t buflen)
977{
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700978 int res = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979
980 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
981
982 if (os_strcmp(cmd, "version") == 0) {
983 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700984 } else if (os_strcasecmp(cmd, "max_command_len") == 0) {
985 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700986 } else if (os_strcasecmp(cmd, "country") == 0) {
987 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
988 res = os_snprintf(buf, buflen, "%c%c",
989 wpa_s->conf->country[0],
990 wpa_s->conf->country[1]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700991#ifdef CONFIG_WIFI_DISPLAY
992 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
Dmitry Shmidted003d22014-02-06 10:09:12 -0800993 int enabled;
994 if (wpa_s->global->p2p == NULL ||
995 wpa_s->global->p2p_disabled)
996 enabled = 0;
997 else
998 enabled = wpa_s->global->wifi_display;
999 res = os_snprintf(buf, buflen, "%d", enabled);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001000#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001001#ifdef CONFIG_TESTING_GET_GTK
1002 } else if (os_strcmp(cmd, "gtk") == 0) {
1003 if (wpa_s->last_gtk_len == 0)
1004 return -1;
1005 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
1006 wpa_s->last_gtk_len);
1007 return res;
1008#endif /* CONFIG_TESTING_GET_GTK */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001009 } else if (os_strcmp(cmd, "tls_library") == 0) {
1010 res = tls_get_library_version(buf, buflen);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001011#ifdef CONFIG_TESTING_OPTIONS
1012 } else if (os_strcmp(cmd, "anonce") == 0) {
1013 return wpa_snprintf_hex(buf, buflen,
1014 wpa_sm_get_anonce(wpa_s->wpa),
1015 WPA_NONCE_LEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001016 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
1017 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001019 } else {
1020 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001021 }
1022
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001023 if (os_snprintf_error(buflen, res))
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -07001024 return -1;
1025 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026}
1027
1028
1029#ifdef IEEE8021X_EAPOL
1030static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1031 char *addr)
1032{
1033 u8 bssid[ETH_ALEN];
1034 struct wpa_ssid *ssid = wpa_s->current_ssid;
1035
1036 if (hwaddr_aton(addr, bssid)) {
1037 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1038 "'%s'", addr);
1039 return -1;
1040 }
1041
1042 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1043 rsn_preauth_deinit(wpa_s->wpa);
1044 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1045 return -1;
1046
1047 return 0;
1048}
1049#endif /* IEEE8021X_EAPOL */
1050
1051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052#ifdef CONFIG_TDLS
1053
1054static int wpa_supplicant_ctrl_iface_tdls_discover(
1055 struct wpa_supplicant *wpa_s, char *addr)
1056{
1057 u8 peer[ETH_ALEN];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001058 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001059
1060 if (hwaddr_aton(addr, peer)) {
1061 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1062 "address '%s'", addr);
1063 return -1;
1064 }
1065
1066 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1067 MAC2STR(peer));
1068
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001069 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1070 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1071 else
1072 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1073
1074 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075}
1076
1077
1078static int wpa_supplicant_ctrl_iface_tdls_setup(
1079 struct wpa_supplicant *wpa_s, char *addr)
1080{
1081 u8 peer[ETH_ALEN];
1082 int ret;
1083
1084 if (hwaddr_aton(addr, peer)) {
1085 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1086 "address '%s'", addr);
1087 return -1;
1088 }
1089
1090 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1091 MAC2STR(peer));
1092
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001093 if ((wpa_s->conf->tdls_external_control) &&
1094 wpa_tdls_is_external_setup(wpa_s->wpa))
1095 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1096
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001097 wpa_tdls_remove(wpa_s->wpa, peer);
1098
1099 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1100 ret = wpa_tdls_start(wpa_s->wpa, peer);
1101 else
1102 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 return ret;
1105}
1106
1107
1108static int wpa_supplicant_ctrl_iface_tdls_teardown(
1109 struct wpa_supplicant *wpa_s, char *addr)
1110{
1111 u8 peer[ETH_ALEN];
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001112 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001114 if (os_strcmp(addr, "*") == 0) {
1115 /* remove everyone */
1116 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1117 wpa_tdls_teardown_peers(wpa_s->wpa);
1118 return 0;
1119 }
1120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 if (hwaddr_aton(addr, peer)) {
1122 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1123 "address '%s'", addr);
1124 return -1;
1125 }
1126
1127 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1128 MAC2STR(peer));
1129
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001130 if ((wpa_s->conf->tdls_external_control) &&
1131 wpa_tdls_is_external_setup(wpa_s->wpa))
1132 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1133
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001134 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1135 ret = wpa_tdls_teardown_link(
1136 wpa_s->wpa, peer,
1137 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1138 else
1139 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1140
1141 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142}
1143
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001144
1145static int ctrl_iface_get_capability_tdls(
1146 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1147{
1148 int ret;
1149
1150 ret = os_snprintf(buf, buflen, "%s\n",
1151 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1152 (wpa_s->drv_flags &
1153 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1154 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001156 return -1;
1157 return ret;
1158}
1159
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001160
1161static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1162 struct wpa_supplicant *wpa_s, char *cmd)
1163{
1164 u8 peer[ETH_ALEN];
1165 struct hostapd_freq_params freq_params;
1166 u8 oper_class;
1167 char *pos, *end;
1168
1169 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1170 wpa_printf(MSG_INFO,
1171 "tdls_chanswitch: Only supported with external setup");
1172 return -1;
1173 }
1174
1175 os_memset(&freq_params, 0, sizeof(freq_params));
1176
1177 pos = os_strchr(cmd, ' ');
1178 if (pos == NULL)
1179 return -1;
1180 *pos++ = '\0';
1181
1182 oper_class = strtol(pos, &end, 10);
1183 if (pos == end) {
1184 wpa_printf(MSG_INFO,
1185 "tdls_chanswitch: Invalid op class provided");
1186 return -1;
1187 }
1188
1189 pos = end;
1190 freq_params.freq = atoi(pos);
1191 if (freq_params.freq == 0) {
1192 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1193 return -1;
1194 }
1195
1196#define SET_FREQ_SETTING(str) \
1197 do { \
1198 const char *pos2 = os_strstr(pos, " " #str "="); \
1199 if (pos2) { \
1200 pos2 += sizeof(" " #str "=") - 1; \
1201 freq_params.str = atoi(pos2); \
1202 } \
1203 } while (0)
1204
1205 SET_FREQ_SETTING(center_freq1);
1206 SET_FREQ_SETTING(center_freq2);
1207 SET_FREQ_SETTING(bandwidth);
1208 SET_FREQ_SETTING(sec_channel_offset);
1209#undef SET_FREQ_SETTING
1210
1211 freq_params.ht_enabled = !!os_strstr(pos, " ht");
1212 freq_params.vht_enabled = !!os_strstr(pos, " vht");
1213
1214 if (hwaddr_aton(cmd, peer)) {
1215 wpa_printf(MSG_DEBUG,
1216 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1217 cmd);
1218 return -1;
1219 }
1220
1221 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1222 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1223 MAC2STR(peer), oper_class, freq_params.freq,
1224 freq_params.center_freq1, freq_params.center_freq2,
1225 freq_params.bandwidth, freq_params.sec_channel_offset,
1226 freq_params.ht_enabled ? " HT" : "",
1227 freq_params.vht_enabled ? " VHT" : "");
1228
1229 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1230 &freq_params);
1231}
1232
1233
1234static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1235 struct wpa_supplicant *wpa_s, char *cmd)
1236{
1237 u8 peer[ETH_ALEN];
1238
1239 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1240 wpa_printf(MSG_INFO,
1241 "tdls_chanswitch: Only supported with external setup");
1242 return -1;
1243 }
1244
1245 if (hwaddr_aton(cmd, peer)) {
1246 wpa_printf(MSG_DEBUG,
1247 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1248 cmd);
1249 return -1;
1250 }
1251
1252 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1253 MAC2STR(peer));
1254
1255 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1256}
1257
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07001258
1259static int wpa_supplicant_ctrl_iface_tdls_link_status(
1260 struct wpa_supplicant *wpa_s, const char *addr,
1261 char *buf, size_t buflen)
1262{
1263 u8 peer[ETH_ALEN];
1264 const char *tdls_status;
1265 int ret;
1266
1267 if (hwaddr_aton(addr, peer)) {
1268 wpa_printf(MSG_DEBUG,
1269 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1270 addr);
1271 return -1;
1272 }
1273 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1274 MAC2STR(peer));
1275
1276 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1277 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1278 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1279 if (os_snprintf_error(buflen, ret))
1280 return -1;
1281
1282 return ret;
1283}
1284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285#endif /* CONFIG_TDLS */
1286
1287
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001288#ifndef CONFIG_NO_WMM_AC
1289
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001290static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1291{
1292 char *token, *context = NULL;
1293 struct wmm_ac_ts_setup_params params = {
1294 .tsid = 0xff,
1295 .direction = 0xff,
1296 };
1297
1298 while ((token = str_token(cmd, " ", &context))) {
1299 if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1300 sscanf(token, "up=%i", &params.user_priority) == 1 ||
1301 sscanf(token, "nominal_msdu_size=%i",
1302 &params.nominal_msdu_size) == 1 ||
1303 sscanf(token, "mean_data_rate=%i",
1304 &params.mean_data_rate) == 1 ||
1305 sscanf(token, "min_phy_rate=%i",
1306 &params.minimum_phy_rate) == 1 ||
1307 sscanf(token, "sba=%i",
1308 &params.surplus_bandwidth_allowance) == 1)
1309 continue;
1310
1311 if (os_strcasecmp(token, "downlink") == 0) {
1312 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1313 } else if (os_strcasecmp(token, "uplink") == 0) {
1314 params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1315 } else if (os_strcasecmp(token, "bidi") == 0) {
1316 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1317 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1318 params.fixed_nominal_msdu = 1;
1319 } else {
1320 wpa_printf(MSG_DEBUG,
1321 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1322 token);
1323 return -1;
1324 }
1325
1326 }
1327
1328 return wpas_wmm_ac_addts(wpa_s, &params);
1329}
1330
1331
1332static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1333{
1334 u8 tsid = atoi(cmd);
1335
1336 return wpas_wmm_ac_delts(wpa_s, tsid);
1337}
1338
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001339#endif /* CONFIG_NO_WMM_AC */
1340
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001342#ifdef CONFIG_IEEE80211R
1343static int wpa_supplicant_ctrl_iface_ft_ds(
1344 struct wpa_supplicant *wpa_s, char *addr)
1345{
1346 u8 target_ap[ETH_ALEN];
1347 struct wpa_bss *bss;
1348 const u8 *mdie;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001349 bool force = os_strstr(addr, " force") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350
1351 if (hwaddr_aton(addr, target_ap)) {
1352 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1353 "address '%s'", addr);
1354 return -1;
1355 }
1356
1357 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1358
1359 bss = wpa_bss_get_bssid(wpa_s, target_ap);
1360 if (bss)
1361 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1362 else
1363 mdie = NULL;
1364
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001365 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366}
1367#endif /* CONFIG_IEEE80211R */
1368
1369
1370#ifdef CONFIG_WPS
1371static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1372 char *cmd)
1373{
1374 u8 bssid[ETH_ALEN], *_bssid = bssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001375#ifdef CONFIG_P2P
1376 u8 p2p_dev_addr[ETH_ALEN];
1377#endif /* CONFIG_P2P */
1378#ifdef CONFIG_AP
1379 u8 *_p2p_dev_addr = NULL;
1380#endif /* CONFIG_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001381 char *pos;
1382 int multi_ap = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001383
Hai Shalom021b0b52019-04-10 11:17:58 -07001384 if (!cmd || os_strcmp(cmd, "any") == 0 ||
1385 os_strncmp(cmd, "any ", 4) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 _bssid = NULL;
1387#ifdef CONFIG_P2P
1388 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1389 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1390 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1391 "P2P Device Address '%s'",
1392 cmd + 13);
1393 return -1;
1394 }
1395 _p2p_dev_addr = p2p_dev_addr;
1396#endif /* CONFIG_P2P */
Hai Shalom021b0b52019-04-10 11:17:58 -07001397 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1398 _bssid = NULL;
1399 multi_ap = atoi(cmd + 9);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001400 } else if (hwaddr_aton(cmd, bssid)) {
1401 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1402 cmd);
1403 return -1;
1404 }
1405
Hai Shalom021b0b52019-04-10 11:17:58 -07001406 if (cmd) {
1407 pos = os_strstr(cmd, " multi_ap=");
1408 if (pos) {
1409 pos += 10;
1410 multi_ap = atoi(pos);
1411 }
1412 }
1413
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001414#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 if (wpa_s->ap_iface)
1416 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1417#endif /* CONFIG_AP */
1418
Hai Shalom021b0b52019-04-10 11:17:58 -07001419 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420}
1421
1422
1423static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1424 char *cmd, char *buf,
1425 size_t buflen)
1426{
1427 u8 bssid[ETH_ALEN], *_bssid = bssid;
1428 char *pin;
1429 int ret;
1430
1431 pin = os_strchr(cmd, ' ');
1432 if (pin)
1433 *pin++ = '\0';
1434
1435 if (os_strcmp(cmd, "any") == 0)
1436 _bssid = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001437 else if (os_strcmp(cmd, "get") == 0) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001438 if (wps_generate_pin((unsigned int *) &ret) < 0)
1439 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001440 goto done;
1441 } else if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1443 cmd);
1444 return -1;
1445 }
1446
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001447#ifdef CONFIG_AP
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001448 if (wpa_s->ap_iface) {
1449 int timeout = 0;
1450 char *pos;
1451
1452 if (pin) {
1453 pos = os_strchr(pin, ' ');
1454 if (pos) {
1455 *pos++ = '\0';
1456 timeout = atoi(pos);
1457 }
1458 }
1459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001460 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001461 buf, buflen, timeout);
1462 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001463#endif /* CONFIG_AP */
1464
1465 if (pin) {
1466 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1467 DEV_PW_DEFAULT);
1468 if (ret < 0)
1469 return -1;
1470 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001471 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472 return -1;
1473 return ret;
1474 }
1475
1476 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1477 if (ret < 0)
1478 return -1;
1479
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001480done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001481 /* Return the generated PIN */
1482 ret = os_snprintf(buf, buflen, "%08d", ret);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001483 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001484 return -1;
1485 return ret;
1486}
1487
1488
1489static int wpa_supplicant_ctrl_iface_wps_check_pin(
1490 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1491{
1492 char pin[9];
1493 size_t len;
1494 char *pos;
1495 int ret;
1496
1497 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1498 (u8 *) cmd, os_strlen(cmd));
1499 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1500 if (*pos < '0' || *pos > '9')
1501 continue;
1502 pin[len++] = *pos;
1503 if (len == 9) {
1504 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1505 return -1;
1506 }
1507 }
1508 if (len != 4 && len != 8) {
1509 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1510 return -1;
1511 }
1512 pin[len] = '\0';
1513
1514 if (len == 8) {
1515 unsigned int pin_val;
1516 pin_val = atoi(pin);
1517 if (!wps_pin_valid(pin_val)) {
1518 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1519 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001520 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 return -1;
1522 return ret;
1523 }
1524 }
1525
1526 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001527 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528 return -1;
1529
1530 return ret;
1531}
1532
1533
Dmitry Shmidt04949592012-07-19 12:16:46 -07001534#ifdef CONFIG_WPS_NFC
1535
1536static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1537 char *cmd)
1538{
1539 u8 bssid[ETH_ALEN], *_bssid = bssid;
1540
1541 if (cmd == NULL || cmd[0] == '\0')
1542 _bssid = NULL;
1543 else if (hwaddr_aton(cmd, bssid))
1544 return -1;
1545
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001546 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1547 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001548}
1549
1550
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001551static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1552 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1553{
1554 int ndef;
1555 struct wpabuf *buf;
1556 int res;
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001557 char *pos;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001558
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001559 pos = os_strchr(cmd, ' ');
1560 if (pos)
1561 *pos++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001562 if (os_strcmp(cmd, "WPS") == 0)
1563 ndef = 0;
1564 else if (os_strcmp(cmd, "NDEF") == 0)
1565 ndef = 1;
1566 else
1567 return -1;
1568
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001569 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001570 if (buf == NULL)
1571 return -1;
1572
1573 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1574 wpabuf_len(buf));
1575 reply[res++] = '\n';
1576 reply[res] = '\0';
1577
1578 wpabuf_free(buf);
1579
1580 return res;
1581}
1582
1583
Dmitry Shmidt04949592012-07-19 12:16:46 -07001584static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1585 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1586{
1587 int ndef;
1588 struct wpabuf *buf;
1589 int res;
1590
1591 if (os_strcmp(cmd, "WPS") == 0)
1592 ndef = 0;
1593 else if (os_strcmp(cmd, "NDEF") == 0)
1594 ndef = 1;
1595 else
1596 return -1;
1597
1598 buf = wpas_wps_nfc_token(wpa_s, ndef);
1599 if (buf == NULL)
1600 return -1;
1601
1602 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1603 wpabuf_len(buf));
1604 reply[res++] = '\n';
1605 reply[res] = '\0';
1606
1607 wpabuf_free(buf);
1608
1609 return res;
1610}
1611
1612
1613static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1614 struct wpa_supplicant *wpa_s, char *pos)
1615{
1616 size_t len;
1617 struct wpabuf *buf;
1618 int ret;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001619 char *freq;
1620 int forced_freq = 0;
1621
1622 freq = strstr(pos, " freq=");
1623 if (freq) {
1624 *freq = '\0';
1625 freq += 6;
1626 forced_freq = atoi(freq);
1627 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001628
1629 len = os_strlen(pos);
1630 if (len & 0x01)
1631 return -1;
1632 len /= 2;
1633
1634 buf = wpabuf_alloc(len);
1635 if (buf == NULL)
1636 return -1;
1637 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1638 wpabuf_free(buf);
1639 return -1;
1640 }
1641
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001642 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001643 wpabuf_free(buf);
1644
1645 return ret;
1646}
1647
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001648
1649static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001650 char *reply, size_t max_len,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001651 int ndef)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001652{
1653 struct wpabuf *buf;
1654 int res;
1655
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001656 buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001657 if (buf == NULL)
1658 return -1;
1659
1660 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1661 wpabuf_len(buf));
1662 reply[res++] = '\n';
1663 reply[res] = '\0';
1664
1665 wpabuf_free(buf);
1666
1667 return res;
1668}
1669
1670
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001671#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001672static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1673 char *reply, size_t max_len,
1674 int ndef)
1675{
1676 struct wpabuf *buf;
1677 int res;
1678
1679 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1680 if (buf == NULL) {
1681 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1682 return -1;
1683 }
1684
1685 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1686 wpabuf_len(buf));
1687 reply[res++] = '\n';
1688 reply[res] = '\0';
1689
1690 wpabuf_free(buf);
1691
1692 return res;
1693}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001694#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001695
1696
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001697static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1698 char *cmd, char *reply,
1699 size_t max_len)
1700{
1701 char *pos;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001702 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001703
1704 pos = os_strchr(cmd, ' ');
1705 if (pos == NULL)
1706 return -1;
1707 *pos++ = '\0';
1708
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001709 if (os_strcmp(cmd, "WPS") == 0)
1710 ndef = 0;
1711 else if (os_strcmp(cmd, "NDEF") == 0)
1712 ndef = 1;
1713 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001714 return -1;
1715
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001716 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001717 if (!ndef)
1718 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001719 return wpas_ctrl_nfc_get_handover_req_wps(
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001720 wpa_s, reply, max_len, ndef);
1721 }
1722
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001723#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001724 if (os_strcmp(pos, "P2P-CR") == 0) {
1725 return wpas_ctrl_nfc_get_handover_req_p2p(
1726 wpa_s, reply, max_len, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001727 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001728#endif /* CONFIG_P2P */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001729
1730 return -1;
1731}
1732
1733
1734static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001735 char *reply, size_t max_len,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001736 int ndef, int cr, char *uuid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001737{
1738 struct wpabuf *buf;
1739 int res;
1740
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001741 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001742 if (buf == NULL)
1743 return -1;
1744
1745 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1746 wpabuf_len(buf));
1747 reply[res++] = '\n';
1748 reply[res] = '\0';
1749
1750 wpabuf_free(buf);
1751
1752 return res;
1753}
1754
1755
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001756#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001757static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1758 char *reply, size_t max_len,
1759 int ndef, int tag)
1760{
1761 struct wpabuf *buf;
1762 int res;
1763
1764 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1765 if (buf == NULL)
1766 return -1;
1767
1768 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1769 wpabuf_len(buf));
1770 reply[res++] = '\n';
1771 reply[res] = '\0';
1772
1773 wpabuf_free(buf);
1774
1775 return res;
1776}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001777#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001778
1779
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001780static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1781 char *cmd, char *reply,
1782 size_t max_len)
1783{
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001784 char *pos, *pos2;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001785 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001786
1787 pos = os_strchr(cmd, ' ');
1788 if (pos == NULL)
1789 return -1;
1790 *pos++ = '\0';
1791
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001792 if (os_strcmp(cmd, "WPS") == 0)
1793 ndef = 0;
1794 else if (os_strcmp(cmd, "NDEF") == 0)
1795 ndef = 1;
1796 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001797 return -1;
1798
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001799 pos2 = os_strchr(pos, ' ');
1800 if (pos2)
1801 *pos2++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001802 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001803 if (!ndef)
1804 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001805 return wpas_ctrl_nfc_get_handover_sel_wps(
1806 wpa_s, reply, max_len, ndef,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001807 os_strcmp(pos, "WPS-CR") == 0, pos2);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001808 }
1809
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001810#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001811 if (os_strcmp(pos, "P2P-CR") == 0) {
1812 return wpas_ctrl_nfc_get_handover_sel_p2p(
1813 wpa_s, reply, max_len, ndef, 0);
1814 }
1815
1816 if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1817 return wpas_ctrl_nfc_get_handover_sel_p2p(
1818 wpa_s, reply, max_len, ndef, 1);
1819 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001820#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001821
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001822 return -1;
1823}
1824
1825
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001826static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1827 char *cmd)
1828{
1829 size_t len;
1830 struct wpabuf *req, *sel;
1831 int ret;
1832 char *pos, *role, *type, *pos2;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001833#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001834 char *freq;
1835 int forced_freq = 0;
1836
1837 freq = strstr(cmd, " freq=");
1838 if (freq) {
1839 *freq = '\0';
1840 freq += 6;
1841 forced_freq = atoi(freq);
1842 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001843#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001844
1845 role = cmd;
1846 pos = os_strchr(role, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001847 if (pos == NULL) {
1848 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001849 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001850 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001851 *pos++ = '\0';
1852
1853 type = pos;
1854 pos = os_strchr(type, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001855 if (pos == NULL) {
1856 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001857 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001858 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001859 *pos++ = '\0';
1860
1861 pos2 = os_strchr(pos, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001862 if (pos2 == NULL) {
1863 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001864 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001865 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001866 *pos2++ = '\0';
1867
1868 len = os_strlen(pos);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001869 if (len & 0x01) {
1870 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001871 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001872 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001873 len /= 2;
1874
1875 req = wpabuf_alloc(len);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001876 if (req == NULL) {
1877 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001878 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001879 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001880 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001881 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001882 wpabuf_free(req);
1883 return -1;
1884 }
1885
1886 len = os_strlen(pos2);
1887 if (len & 0x01) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001888 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001889 wpabuf_free(req);
1890 return -1;
1891 }
1892 len /= 2;
1893
1894 sel = wpabuf_alloc(len);
1895 if (sel == NULL) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001896 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001897 wpabuf_free(req);
1898 return -1;
1899 }
1900 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001901 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001902 wpabuf_free(req);
1903 wpabuf_free(sel);
1904 return -1;
1905 }
1906
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001907 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1908 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1909
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001910 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1911 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001912#ifdef CONFIG_AP
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001913 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1914 {
1915 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1916 if (ret < 0)
1917 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001918#endif /* CONFIG_AP */
1919#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001920 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1921 {
1922 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1923 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1924 {
1925 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1926 forced_freq);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001927#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001928 } else {
1929 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1930 "reported: role=%s type=%s", role, type);
1931 ret = -1;
1932 }
1933 wpabuf_free(req);
1934 wpabuf_free(sel);
1935
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001936 if (ret)
1937 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1938
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001939 return ret;
1940}
1941
Dmitry Shmidt04949592012-07-19 12:16:46 -07001942#endif /* CONFIG_WPS_NFC */
1943
1944
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1946 char *cmd)
1947{
1948 u8 bssid[ETH_ALEN];
1949 char *pin;
1950 char *new_ssid;
1951 char *new_auth;
1952 char *new_encr;
1953 char *new_key;
1954 struct wps_new_ap_settings ap;
1955
1956 pin = os_strchr(cmd, ' ');
1957 if (pin == NULL)
1958 return -1;
1959 *pin++ = '\0';
1960
1961 if (hwaddr_aton(cmd, bssid)) {
1962 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1963 cmd);
1964 return -1;
1965 }
1966
1967 new_ssid = os_strchr(pin, ' ');
1968 if (new_ssid == NULL)
1969 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1970 *new_ssid++ = '\0';
1971
1972 new_auth = os_strchr(new_ssid, ' ');
1973 if (new_auth == NULL)
1974 return -1;
1975 *new_auth++ = '\0';
1976
1977 new_encr = os_strchr(new_auth, ' ');
1978 if (new_encr == NULL)
1979 return -1;
1980 *new_encr++ = '\0';
1981
1982 new_key = os_strchr(new_encr, ' ');
1983 if (new_key == NULL)
1984 return -1;
1985 *new_key++ = '\0';
1986
1987 os_memset(&ap, 0, sizeof(ap));
1988 ap.ssid_hex = new_ssid;
1989 ap.auth = new_auth;
1990 ap.encr = new_encr;
1991 ap.key_hex = new_key;
1992 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1993}
1994
1995
1996#ifdef CONFIG_AP
1997static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1998 char *cmd, char *buf,
1999 size_t buflen)
2000{
2001 int timeout = 300;
2002 char *pos;
2003 const char *pin_txt;
2004
2005 if (!wpa_s->ap_iface)
2006 return -1;
2007
2008 pos = os_strchr(cmd, ' ');
2009 if (pos)
2010 *pos++ = '\0';
2011
2012 if (os_strcmp(cmd, "disable") == 0) {
2013 wpas_wps_ap_pin_disable(wpa_s);
2014 return os_snprintf(buf, buflen, "OK\n");
2015 }
2016
2017 if (os_strcmp(cmd, "random") == 0) {
2018 if (pos)
2019 timeout = atoi(pos);
2020 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
2021 if (pin_txt == NULL)
2022 return -1;
2023 return os_snprintf(buf, buflen, "%s", pin_txt);
2024 }
2025
2026 if (os_strcmp(cmd, "get") == 0) {
2027 pin_txt = wpas_wps_ap_pin_get(wpa_s);
2028 if (pin_txt == NULL)
2029 return -1;
2030 return os_snprintf(buf, buflen, "%s", pin_txt);
2031 }
2032
2033 if (os_strcmp(cmd, "set") == 0) {
2034 char *pin;
2035 if (pos == NULL)
2036 return -1;
2037 pin = pos;
2038 pos = os_strchr(pos, ' ');
2039 if (pos) {
2040 *pos++ = '\0';
2041 timeout = atoi(pos);
2042 }
2043 if (os_strlen(pin) > buflen)
2044 return -1;
2045 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2046 return -1;
2047 return os_snprintf(buf, buflen, "%s", pin);
2048 }
2049
2050 return -1;
2051}
2052#endif /* CONFIG_AP */
2053
2054
2055#ifdef CONFIG_WPS_ER
2056static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2057 char *cmd)
2058{
2059 char *uuid = cmd, *pin, *pos;
2060 u8 addr_buf[ETH_ALEN], *addr = NULL;
2061 pin = os_strchr(uuid, ' ');
2062 if (pin == NULL)
2063 return -1;
2064 *pin++ = '\0';
2065 pos = os_strchr(pin, ' ');
2066 if (pos) {
2067 *pos++ = '\0';
2068 if (hwaddr_aton(pos, addr_buf) == 0)
2069 addr = addr_buf;
2070 }
2071 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2072}
2073
2074
2075static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2076 char *cmd)
2077{
2078 char *uuid = cmd, *pin;
2079 pin = os_strchr(uuid, ' ');
2080 if (pin == NULL)
2081 return -1;
2082 *pin++ = '\0';
2083 return wpas_wps_er_learn(wpa_s, uuid, pin);
2084}
2085
2086
2087static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2088 struct wpa_supplicant *wpa_s, char *cmd)
2089{
2090 char *uuid = cmd, *id;
2091 id = os_strchr(uuid, ' ');
2092 if (id == NULL)
2093 return -1;
2094 *id++ = '\0';
2095 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2096}
2097
2098
2099static int wpa_supplicant_ctrl_iface_wps_er_config(
2100 struct wpa_supplicant *wpa_s, char *cmd)
2101{
2102 char *pin;
2103 char *new_ssid;
2104 char *new_auth;
2105 char *new_encr;
2106 char *new_key;
2107 struct wps_new_ap_settings ap;
2108
2109 pin = os_strchr(cmd, ' ');
2110 if (pin == NULL)
2111 return -1;
2112 *pin++ = '\0';
2113
2114 new_ssid = os_strchr(pin, ' ');
2115 if (new_ssid == NULL)
2116 return -1;
2117 *new_ssid++ = '\0';
2118
2119 new_auth = os_strchr(new_ssid, ' ');
2120 if (new_auth == NULL)
2121 return -1;
2122 *new_auth++ = '\0';
2123
2124 new_encr = os_strchr(new_auth, ' ');
2125 if (new_encr == NULL)
2126 return -1;
2127 *new_encr++ = '\0';
2128
2129 new_key = os_strchr(new_encr, ' ');
2130 if (new_key == NULL)
2131 return -1;
2132 *new_key++ = '\0';
2133
2134 os_memset(&ap, 0, sizeof(ap));
2135 ap.ssid_hex = new_ssid;
2136 ap.auth = new_auth;
2137 ap.encr = new_encr;
2138 ap.key_hex = new_key;
2139 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2140}
Dmitry Shmidt04949592012-07-19 12:16:46 -07002141
2142
2143#ifdef CONFIG_WPS_NFC
2144static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2145 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2146{
2147 int ndef;
2148 struct wpabuf *buf;
2149 int res;
2150 char *uuid;
2151
2152 uuid = os_strchr(cmd, ' ');
2153 if (uuid == NULL)
2154 return -1;
2155 *uuid++ = '\0';
2156
2157 if (os_strcmp(cmd, "WPS") == 0)
2158 ndef = 0;
2159 else if (os_strcmp(cmd, "NDEF") == 0)
2160 ndef = 1;
2161 else
2162 return -1;
2163
2164 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2165 if (buf == NULL)
2166 return -1;
2167
2168 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2169 wpabuf_len(buf));
2170 reply[res++] = '\n';
2171 reply[res] = '\0';
2172
2173 wpabuf_free(buf);
2174
2175 return res;
2176}
2177#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178#endif /* CONFIG_WPS_ER */
2179
2180#endif /* CONFIG_WPS */
2181
2182
2183#ifdef CONFIG_IBSS_RSN
2184static int wpa_supplicant_ctrl_iface_ibss_rsn(
2185 struct wpa_supplicant *wpa_s, char *addr)
2186{
2187 u8 peer[ETH_ALEN];
2188
2189 if (hwaddr_aton(addr, peer)) {
2190 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2191 "address '%s'", addr);
2192 return -1;
2193 }
2194
2195 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2196 MAC2STR(peer));
2197
2198 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2199}
2200#endif /* CONFIG_IBSS_RSN */
2201
2202
2203static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2204 char *rsp)
2205{
2206#ifdef IEEE8021X_EAPOL
2207 char *pos, *id_pos;
2208 int id;
2209 struct wpa_ssid *ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002210
2211 pos = os_strchr(rsp, '-');
2212 if (pos == NULL)
2213 return -1;
2214 *pos++ = '\0';
2215 id_pos = pos;
2216 pos = os_strchr(pos, ':');
2217 if (pos == NULL)
2218 return -1;
2219 *pos++ = '\0';
2220 id = atoi(id_pos);
2221 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2222 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2223 (u8 *) pos, os_strlen(pos));
2224
2225 ssid = wpa_config_get_network(wpa_s->conf, id);
2226 if (ssid == NULL) {
2227 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2228 "to update", id);
2229 return -1;
2230 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002232 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2233 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234#else /* IEEE8021X_EAPOL */
2235 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2236 return -1;
2237#endif /* IEEE8021X_EAPOL */
2238}
2239
2240
2241static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2242 const char *params,
2243 char *buf, size_t buflen)
2244{
2245 char *pos, *end, tmp[30];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002246 int res, verbose, wps, ret;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002247#ifdef CONFIG_HS20
2248 const u8 *hs20;
2249#endif /* CONFIG_HS20 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002250 const u8 *sess_id;
2251 size_t sess_id_len;
Dmitry Shmidt44da0252011-08-23 12:30:30 -07002252
Dmitry Shmidt56052862013-10-04 10:23:25 -07002253 if (os_strcmp(params, "-DRIVER") == 0)
2254 return wpa_drv_status(wpa_s, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255 verbose = os_strcmp(params, "-VERBOSE") == 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002256 wps = os_strcmp(params, "-WPS") == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 pos = buf;
2258 end = buf + buflen;
2259 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2260 struct wpa_ssid *ssid = wpa_s->current_ssid;
2261 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2262 MAC2STR(wpa_s->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002263 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 return pos - buf;
2265 pos += ret;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002266 ret = os_snprintf(pos, end - pos, "freq=%u\n",
2267 wpa_s->assoc_freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002268 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002269 return pos - buf;
2270 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 if (ssid) {
2272 u8 *_ssid = ssid->ssid;
2273 size_t ssid_len = ssid->ssid_len;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002274 u8 ssid_buf[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002275 if (ssid_len == 0) {
2276 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2277 if (_res < 0)
2278 ssid_len = 0;
2279 else
2280 ssid_len = _res;
2281 _ssid = ssid_buf;
2282 }
2283 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2284 wpa_ssid_txt(_ssid, ssid_len),
2285 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002286 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002287 return pos - buf;
2288 pos += ret;
2289
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002290 if (wps && ssid->passphrase &&
2291 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2292 (ssid->mode == WPAS_MODE_AP ||
2293 ssid->mode == WPAS_MODE_P2P_GO)) {
2294 ret = os_snprintf(pos, end - pos,
2295 "passphrase=%s\n",
2296 ssid->passphrase);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002297 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002298 return pos - buf;
2299 pos += ret;
2300 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301 if (ssid->id_str) {
2302 ret = os_snprintf(pos, end - pos,
2303 "id_str=%s\n",
2304 ssid->id_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002305 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 return pos - buf;
2307 pos += ret;
2308 }
2309
2310 switch (ssid->mode) {
2311 case WPAS_MODE_INFRA:
2312 ret = os_snprintf(pos, end - pos,
2313 "mode=station\n");
2314 break;
2315 case WPAS_MODE_IBSS:
2316 ret = os_snprintf(pos, end - pos,
2317 "mode=IBSS\n");
2318 break;
2319 case WPAS_MODE_AP:
2320 ret = os_snprintf(pos, end - pos,
2321 "mode=AP\n");
2322 break;
2323 case WPAS_MODE_P2P_GO:
2324 ret = os_snprintf(pos, end - pos,
2325 "mode=P2P GO\n");
2326 break;
2327 case WPAS_MODE_P2P_GROUP_FORMATION:
2328 ret = os_snprintf(pos, end - pos,
2329 "mode=P2P GO - group "
2330 "formation\n");
2331 break;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002332 case WPAS_MODE_MESH:
2333 ret = os_snprintf(pos, end - pos,
2334 "mode=mesh\n");
2335 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002336 default:
2337 ret = 0;
2338 break;
2339 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002340 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002341 return pos - buf;
2342 pos += ret;
2343 }
2344
Hai Shalom021b0b52019-04-10 11:17:58 -07002345 if (wpa_s->connection_set &&
2346 (wpa_s->connection_ht || wpa_s->connection_vht ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002347 wpa_s->connection_he || wpa_s->connection_eht)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002348 ret = os_snprintf(pos, end - pos,
2349 "wifi_generation=%u\n",
Sunil Ravia04bd252022-05-02 22:54:18 -07002350 wpa_s->connection_eht ? 7 :
2351 (wpa_s->connection_he ? 6 :
2352 (wpa_s->connection_vht ? 5 : 4)));
Hai Shalom021b0b52019-04-10 11:17:58 -07002353 if (os_snprintf_error(end - pos, ret))
2354 return pos - buf;
2355 pos += ret;
2356 }
2357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358#ifdef CONFIG_AP
2359 if (wpa_s->ap_iface) {
2360 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2361 end - pos,
2362 verbose);
2363 } else
2364#endif /* CONFIG_AP */
2365 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2366 }
Paul Stewart092955c2017-02-06 09:13:09 -08002367#ifdef CONFIG_SME
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002368#ifdef CONFIG_SAE
2369 if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002370#ifdef CONFIG_AP
2371 !wpa_s->ap_iface &&
2372#endif /* CONFIG_AP */
2373 wpa_s->sme.sae.state == SAE_ACCEPTED) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002374 ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2375 "sae_h2e=%d\n"
2376 "sae_pk=%d\n",
2377 wpa_s->sme.sae.group,
2378 wpa_s->sme.sae.h2e,
2379 wpa_s->sme.sae.pk);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002380 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002381 return pos - buf;
2382 pos += ret;
2383 }
2384#endif /* CONFIG_SAE */
Paul Stewart092955c2017-02-06 09:13:09 -08002385#endif /* CONFIG_SME */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2387 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002388 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 return pos - buf;
2390 pos += ret;
2391
2392 if (wpa_s->l2 &&
2393 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2394 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002395 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 return pos - buf;
2397 pos += ret;
2398 }
2399
2400#ifdef CONFIG_P2P
2401 if (wpa_s->global->p2p) {
2402 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2403 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002404 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 return pos - buf;
2406 pos += ret;
2407 }
2408#endif /* CONFIG_P2P */
2409
2410 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2411 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002412 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413 return pos - buf;
2414 pos += ret;
2415
Sunil Ravi89eba102022-09-13 21:04:37 -07002416 if (wpa_s->valid_links) {
2417 ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n",
2418 MAC2STR(wpa_s->ap_mld_addr));
2419 if (os_snprintf_error(end - pos, ret))
2420 return pos - buf;
2421 pos += ret;
2422 }
2423
Dmitry Shmidt04949592012-07-19 12:16:46 -07002424#ifdef CONFIG_HS20
2425 if (wpa_s->current_bss &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002426 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2427 HS20_IE_VENDOR_TYPE)) &&
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428 wpa_s->wpa_proto == WPA_PROTO_RSN &&
2429 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002430 int release = 1;
2431 if (hs20[1] >= 5) {
2432 u8 rel_num = (hs20[6] & 0xf0) >> 4;
2433 release = rel_num + 1;
2434 }
2435 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002436 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07002437 return pos - buf;
2438 pos += ret;
2439 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002440
2441 if (wpa_s->current_ssid) {
2442 struct wpa_cred *cred;
2443 char *type;
2444
2445 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002446 size_t i;
2447
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002448 if (wpa_s->current_ssid->parent_cred != cred)
2449 continue;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002450
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002451 if (cred->provisioning_sp) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002452 ret = os_snprintf(pos, end - pos,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002453 "provisioning_sp=%s\n",
2454 cred->provisioning_sp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002455 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt051af732013-10-22 13:52:46 -07002456 return pos - buf;
2457 pos += ret;
2458 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002459
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002460 if (!cred->domain)
2461 goto no_domain;
2462
2463 i = 0;
2464 if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2465 struct wpabuf *names =
2466 wpa_s->current_bss->anqp->domain_name;
2467 for (i = 0; names && i < cred->num_domain; i++)
2468 {
2469 if (domain_name_list_contains(
2470 names, cred->domain[i], 1))
2471 break;
2472 }
2473 if (i == cred->num_domain)
2474 i = 0; /* show first entry by default */
2475 }
2476 ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2477 cred->domain[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002478 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002479 return pos - buf;
2480 pos += ret;
2481
2482 no_domain:
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002483 if (wpa_s->current_bss == NULL ||
2484 wpa_s->current_bss->anqp == NULL)
2485 res = -1;
2486 else
2487 res = interworking_home_sp_cred(
2488 wpa_s, cred,
2489 wpa_s->current_bss->anqp->domain_name);
2490 if (res > 0)
2491 type = "home";
2492 else if (res == 0)
2493 type = "roaming";
2494 else
2495 type = "unknown";
2496
2497 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002498 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002499 return pos - buf;
2500 pos += ret;
2501
2502 break;
2503 }
2504 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002505#endif /* CONFIG_HS20 */
2506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2508 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2509 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2510 verbose);
2511 if (res >= 0)
2512 pos += res;
2513 }
2514
Dmitry Shmidt29333592017-01-09 12:27:11 -08002515#ifdef CONFIG_MACSEC
2516 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2517 if (res > 0)
2518 pos += res;
2519#endif /* CONFIG_MACSEC */
2520
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002521 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2522 if (sess_id) {
2523 char *start = pos;
2524
2525 ret = os_snprintf(pos, end - pos, "eap_session_id=");
2526 if (os_snprintf_error(end - pos, ret))
2527 return start - buf;
2528 pos += ret;
2529 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2530 if (ret <= 0)
2531 return start - buf;
2532 pos += ret;
2533 ret = os_snprintf(pos, end - pos, "\n");
2534 if (os_snprintf_error(end - pos, ret))
2535 return start - buf;
2536 pos += ret;
2537 }
2538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2540 if (res >= 0)
2541 pos += res;
2542
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002543#ifdef CONFIG_WPS
2544 {
2545 char uuid_str[100];
2546 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2547 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002548 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002549 return pos - buf;
2550 pos += ret;
2551 }
2552#endif /* CONFIG_WPS */
2553
Roshan Pius3a1667e2018-07-03 15:17:14 -07002554 if (wpa_s->ieee80211ac) {
2555 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2556 if (os_snprintf_error(end - pos, ret))
2557 return pos - buf;
2558 pos += ret;
2559 }
2560
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002561#ifdef ANDROID
vandwalleffc70182014-09-11 11:40:14 -07002562 /*
2563 * Allow using the STATUS command with default behavior, say for debug,
2564 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2565 * events with STATUS-NO_EVENTS.
2566 */
2567 if (os_strcmp(params, "-NO_EVENTS")) {
2568 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2569 "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2570 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2571 wpa_s->wpa_state,
2572 MAC2STR(wpa_s->bssid),
2573 wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2574 wpa_ssid_txt(wpa_s->current_ssid->ssid,
2575 wpa_s->current_ssid->ssid_len) : "");
2576 if (wpa_s->wpa_state == WPA_COMPLETED) {
2577 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi89eba102022-09-13 21:04:37 -07002578 char mld_addr[50];
2579
2580 mld_addr[0] = '\0';
2581 if (wpa_s->valid_links)
2582 os_snprintf(mld_addr, sizeof(mld_addr),
2583 " ap_mld_addr=" MACSTR,
2584 MAC2STR(wpa_s->ap_mld_addr));
2585
vandwalleffc70182014-09-11 11:40:14 -07002586 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2587 "- connection to " MACSTR
Sunil Ravi89eba102022-09-13 21:04:37 -07002588 " completed %s [id=%d id_str=%s]%s",
vandwalleffc70182014-09-11 11:40:14 -07002589 MAC2STR(wpa_s->bssid), "(auth)",
2590 ssid ? ssid->id : -1,
Sunil Ravi89eba102022-09-13 21:04:37 -07002591 ssid && ssid->id_str ? ssid->id_str : "",
2592 mld_addr);
vandwalleffc70182014-09-11 11:40:14 -07002593 }
Irfan Sheriffbf5edf42012-01-11 16:54:57 -08002594 }
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002595#endif /* ANDROID */
2596
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 return pos - buf;
2598}
2599
2600
2601static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2602 char *cmd)
2603{
2604 char *pos;
2605 int id;
2606 struct wpa_ssid *ssid;
2607 u8 bssid[ETH_ALEN];
2608
2609 /* cmd: "<network id> <BSSID>" */
2610 pos = os_strchr(cmd, ' ');
2611 if (pos == NULL)
2612 return -1;
2613 *pos++ = '\0';
2614 id = atoi(cmd);
2615 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2616 if (hwaddr_aton(pos, bssid)) {
2617 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2618 return -1;
2619 }
2620
2621 ssid = wpa_config_get_network(wpa_s->conf, id);
2622 if (ssid == NULL) {
2623 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2624 "to update", id);
2625 return -1;
2626 }
2627
2628 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2629 ssid->bssid_set = !is_zero_ether_addr(bssid);
2630
2631 return 0;
2632}
2633
2634
Hai Shalom60840252021-02-19 19:02:11 -08002635static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2636 char *cmd, char *buf,
2637 size_t buflen)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002638{
2639 u8 bssid[ETH_ALEN];
Hai Shalom60840252021-02-19 19:02:11 -08002640 struct wpa_bssid_ignore *e;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002641 char *pos, *end;
2642 int ret;
2643
Hai Shalom60840252021-02-19 19:02:11 -08002644 /* cmd: "BSSID_IGNORE [<BSSID>]" */
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002645 if (*cmd == '\0') {
2646 pos = buf;
2647 end = buf + buflen;
Hai Shalom60840252021-02-19 19:02:11 -08002648 e = wpa_s->bssid_ignore;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002649 while (e) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002650 ret = os_snprintf(pos, end - pos, MACSTR "\n",
2651 MAC2STR(e->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002652 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002653 return pos - buf;
2654 pos += ret;
2655 e = e->next;
2656 }
2657 return pos - buf;
2658 }
2659
2660 cmd++;
2661 if (os_strncmp(cmd, "clear", 5) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -08002662 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002663 os_memcpy(buf, "OK\n", 3);
2664 return 3;
2665 }
2666
Hai Shalom60840252021-02-19 19:02:11 -08002667 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002668 if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002669 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002670 return -1;
2671 }
2672
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002673 /*
2674 * Add the BSSID twice, so its count will be 2, causing it to be
2675 * skipped when processing scan results.
2676 */
Hai Shalom60840252021-02-19 19:02:11 -08002677 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002678 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002679 return -1;
Hai Shalom60840252021-02-19 19:02:11 -08002680 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002681 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002682 return -1;
2683 os_memcpy(buf, "OK\n", 3);
2684 return 3;
2685}
2686
2687
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002688static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2689 char *cmd, char *buf,
2690 size_t buflen)
2691{
2692 char *pos, *end, *stamp;
2693 int ret;
2694
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002695 /* cmd: "LOG_LEVEL [<level>]" */
2696 if (*cmd == '\0') {
2697 pos = buf;
2698 end = buf + buflen;
2699 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2700 "Timestamp: %d\n",
2701 debug_level_str(wpa_debug_level),
2702 wpa_debug_timestamp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002703 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002704 ret = 0;
2705
2706 return ret;
2707 }
2708
2709 while (*cmd == ' ')
2710 cmd++;
2711
2712 stamp = os_strchr(cmd, ' ');
2713 if (stamp) {
2714 *stamp++ = '\0';
2715 while (*stamp == ' ') {
2716 stamp++;
2717 }
2718 }
2719
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002720 if (os_strlen(cmd)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002721 int level = str_to_debug_level(cmd);
2722 if (level < 0)
2723 return -1;
2724 wpa_debug_level = level;
2725 }
2726
2727 if (stamp && os_strlen(stamp))
2728 wpa_debug_timestamp = atoi(stamp);
2729
2730 os_memcpy(buf, "OK\n", 3);
2731 return 3;
2732}
2733
2734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735static int wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002736 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002737{
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002738 char *pos, *end, *prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739 struct wpa_ssid *ssid;
2740 int ret;
2741
2742 pos = buf;
2743 end = buf + buflen;
2744 ret = os_snprintf(pos, end - pos,
2745 "network id / ssid / bssid / flags\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002746 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 return pos - buf;
2748 pos += ret;
2749
2750 ssid = wpa_s->conf->ssid;
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002751
2752 /* skip over ssids until we find next one */
2753 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2754 int last_id = atoi(cmd + 8);
2755 if (last_id != -1) {
2756 while (ssid != NULL && ssid->id <= last_id) {
2757 ssid = ssid->next;
2758 }
2759 }
2760 }
2761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 while (ssid) {
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002763 prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 ret = os_snprintf(pos, end - pos, "%d\t%s",
2765 ssid->id,
2766 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002767 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002768 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 pos += ret;
2770 if (ssid->bssid_set) {
2771 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2772 MAC2STR(ssid->bssid));
2773 } else {
2774 ret = os_snprintf(pos, end - pos, "\tany");
2775 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002776 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002777 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 pos += ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 ssid == wpa_s->current_ssid ?
2781 "[CURRENT]" : "",
2782 ssid->disabled ? "[DISABLED]" : "",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783 ssid->disabled_until.sec ?
2784 "[TEMP-DISABLED]" : "",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002785 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2786 "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002787 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002788 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 pos += ret;
2790 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002791 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002792 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 pos += ret;
2794
2795 ssid = ssid->next;
2796 }
2797
2798 return pos - buf;
2799}
2800
2801
2802static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2803{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002804 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805 ret = os_snprintf(pos, end - pos, "-");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002806 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002807 return pos;
2808 pos += ret;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002809 ret = wpa_write_ciphers(pos, end, cipher, "+");
2810 if (ret < 0)
2811 return pos;
2812 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813 return pos;
2814}
2815
2816
2817static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2818 const u8 *ie, size_t ie_len)
2819{
2820 struct wpa_ie_data data;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002821 char *start;
2822 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002823
2824 ret = os_snprintf(pos, end - pos, "[%s-", proto);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002825 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 return pos;
2827 pos += ret;
2828
2829 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2830 ret = os_snprintf(pos, end - pos, "?]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002831 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 return pos;
2833 pos += ret;
2834 return pos;
2835 }
2836
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002837 start = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002839 ret = os_snprintf(pos, end - pos, "%sEAP",
2840 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002841 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 return pos;
2843 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002844 }
2845 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002846 ret = os_snprintf(pos, end - pos, "%sPSK",
2847 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002848 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849 return pos;
2850 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002851 }
2852 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002853 ret = os_snprintf(pos, end - pos, "%sNone",
2854 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002855 if (os_snprintf_error(end - pos, ret))
2856 return pos;
2857 pos += ret;
2858 }
2859 if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2860 ret = os_snprintf(pos, end - pos, "%sSAE",
2861 pos == start ? "" : "+");
2862 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 return pos;
2864 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002866 if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
2867 ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY",
2868 pos == start ? "" : "+");
2869 if (os_snprintf_error(end - pos, ret))
2870 return pos;
2871 pos += ret;
2872 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002873#ifdef CONFIG_IEEE80211R
2874 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2875 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002876 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002877 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002878 return pos;
2879 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 }
2881 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2882 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002883 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002884 if (os_snprintf_error(end - pos, ret))
2885 return pos;
2886 pos += ret;
2887 }
2888 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2889 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2890 pos == start ? "" : "+");
2891 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002892 return pos;
2893 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002894 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002895 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
2896 ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY",
2897 pos == start ? "" : "+");
2898 if (os_snprintf_error(end - pos, ret))
2899 return pos;
2900 pos += ret;
2901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002902#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002903 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2904 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002905 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002906 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002907 return pos;
2908 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909 }
2910 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2911 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002912 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002913 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002914 return pos;
2915 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002918#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002919 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2920 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2921 pos == start ? "" : "+");
2922 if (os_snprintf_error(end - pos, ret))
2923 return pos;
2924 pos += ret;
2925 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002926#endif /* CONFIG_SUITEB */
2927
2928#ifdef CONFIG_SUITEB192
2929 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2930 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2931 pos == start ? "" : "+");
2932 if (os_snprintf_error(end - pos, ret))
2933 return pos;
2934 pos += ret;
2935 }
2936#endif /* CONFIG_SUITEB192 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002937
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002938#ifdef CONFIG_FILS
2939 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2940 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2941 pos == start ? "" : "+");
2942 if (os_snprintf_error(end - pos, ret))
2943 return pos;
2944 pos += ret;
2945 }
2946 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2947 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2948 pos == start ? "" : "+");
2949 if (os_snprintf_error(end - pos, ret))
2950 return pos;
2951 pos += ret;
2952 }
2953#ifdef CONFIG_IEEE80211R
2954 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2955 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2956 pos == start ? "" : "+");
2957 if (os_snprintf_error(end - pos, ret))
2958 return pos;
2959 pos += ret;
2960 }
2961 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2962 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2963 pos == start ? "" : "+");
2964 if (os_snprintf_error(end - pos, ret))
2965 return pos;
2966 pos += ret;
2967 }
2968#endif /* CONFIG_IEEE80211R */
2969#endif /* CONFIG_FILS */
2970
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002971#ifdef CONFIG_OWE
2972 if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2973 ret = os_snprintf(pos, end - pos, "%sOWE",
2974 pos == start ? "" : "+");
2975 if (os_snprintf_error(end - pos, ret))
2976 return pos;
2977 pos += ret;
2978 }
2979#endif /* CONFIG_OWE */
2980
2981#ifdef CONFIG_DPP
2982 if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
2983 ret = os_snprintf(pos, end - pos, "%sDPP",
2984 pos == start ? "" : "+");
2985 if (os_snprintf_error(end - pos, ret))
2986 return pos;
2987 pos += ret;
2988 }
2989#endif /* CONFIG_DPP */
2990
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002991 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
2992 ret = os_snprintf(pos, end - pos, "%sOSEN",
2993 pos == start ? "" : "+");
2994 if (os_snprintf_error(end - pos, ret))
2995 return pos;
2996 pos += ret;
2997 }
2998
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002999#ifdef CONFIG_SHA384
3000 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
3001 ret = os_snprintf(pos, end - pos, "%sEAP-SHA384",
3002 pos == start ? "" : "+");
3003 if (os_snprintf_error(end - pos, ret))
3004 return pos;
3005 pos += ret;
3006 }
3007#endif /* CONFIG_SHA384 */
3008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003009 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
3010
3011 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
3012 ret = os_snprintf(pos, end - pos, "-preauth");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003013 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 return pos;
3015 pos += ret;
3016 }
3017
3018 ret = os_snprintf(pos, end - pos, "]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003019 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003020 return pos;
3021 pos += ret;
3022
3023 return pos;
3024}
3025
3026
3027#ifdef CONFIG_WPS
3028static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
3029 char *pos, char *end,
3030 struct wpabuf *wps_ie)
3031{
3032 int ret;
3033 const char *txt;
3034
3035 if (wps_ie == NULL)
3036 return pos;
3037 if (wps_is_selected_pbc_registrar(wps_ie))
3038 txt = "[WPS-PBC]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003039 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
3040 txt = "[WPS-AUTH]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 else if (wps_is_selected_pin_registrar(wps_ie))
3042 txt = "[WPS-PIN]";
3043 else
3044 txt = "[WPS]";
3045
3046 ret = os_snprintf(pos, end - pos, "%s", txt);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003047 if (!os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 pos += ret;
3049 wpabuf_free(wps_ie);
3050 return pos;
3051}
3052#endif /* CONFIG_WPS */
3053
3054
3055static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
3056 char *pos, char *end,
3057 const struct wpa_bss *bss)
3058{
3059#ifdef CONFIG_WPS
3060 struct wpabuf *wps_ie;
3061 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
3062 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
3063#else /* CONFIG_WPS */
3064 return pos;
3065#endif /* CONFIG_WPS */
3066}
3067
3068
3069/* Format one result on one text line into a buffer. */
3070static int wpa_supplicant_ctrl_iface_scan_result(
3071 struct wpa_supplicant *wpa_s,
3072 const struct wpa_bss *bss, char *buf, size_t buflen)
3073{
3074 char *pos, *end;
3075 int ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003076 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003077
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003078 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003079 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt96571392013-10-14 12:54:46 -07003080 if (!p2p)
3081 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3083 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3084 0)
3085 return 0; /* Do not show P2P listen discovery results here */
3086
3087 pos = buf;
3088 end = buf + buflen;
3089
3090 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3091 MAC2STR(bss->bssid), bss->freq, bss->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003092 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003093 return -1;
3094 pos += ret;
3095 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3096 if (ie)
3097 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
3098 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003099 if (ie2) {
3100 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3101 ie2, 2 + ie2[1]);
3102 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003103 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003104 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3105 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3106 if (os_snprintf_error(end - pos, ret))
3107 return -1;
3108 pos += ret;
3109 }
3110 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3111 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3112 if (os_snprintf_error(end - pos, ret))
3113 return -1;
3114 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003115 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003116 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3117 if (osen_ie)
3118 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3119 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003120 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3121 if (owe) {
3122 ret = os_snprintf(pos, end - pos,
3123 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3124 if (os_snprintf_error(end - pos, ret))
3125 return -1;
3126 pos += ret;
3127 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003129 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003130 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003131 if (os_snprintf_error(end - pos, ret))
3132 return -1;
3133 pos += ret;
3134 }
3135 if (mesh) {
3136 ret = os_snprintf(pos, end - pos, "[MESH]");
3137 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003138 return -1;
3139 pos += ret;
3140 }
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003141 if (bss_is_dmg(bss)) {
3142 const char *s;
Hai Shalomc3565922019-10-28 11:58:20 -07003143
Hai Shalom60840252021-02-19 19:02:11 -08003144 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
Hai Shalomc3565922019-10-28 11:58:20 -07003145 ret = os_snprintf(pos, end - pos, "[EDMG]");
3146 if (os_snprintf_error(end - pos, ret))
3147 return -1;
3148 pos += ret;
3149 }
3150
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003151 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003152 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003153 return -1;
3154 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003155 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3156 case IEEE80211_CAP_DMG_IBSS:
3157 s = "[IBSS]";
3158 break;
3159 case IEEE80211_CAP_DMG_AP:
3160 s = "[ESS]";
3161 break;
3162 case IEEE80211_CAP_DMG_PBSS:
3163 s = "[PBSS]";
3164 break;
3165 default:
3166 s = "";
3167 break;
3168 }
3169 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003170 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003171 return -1;
3172 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003173 } else {
3174 if (bss->caps & IEEE80211_CAP_IBSS) {
3175 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003176 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003177 return -1;
3178 pos += ret;
3179 }
3180 if (bss->caps & IEEE80211_CAP_ESS) {
3181 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003182 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003183 return -1;
3184 pos += ret;
3185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003186 }
3187 if (p2p) {
3188 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003189 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003190 return -1;
3191 pos += ret;
3192 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003193#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003194 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003195 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003196 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003197 return -1;
3198 pos += ret;
3199 }
3200#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003201#ifdef CONFIG_FILS
3202 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3203 ret = os_snprintf(pos, end - pos, "[FILS]");
3204 if (os_snprintf_error(end - pos, ret))
3205 return -1;
3206 pos += ret;
3207 }
3208#endif /* CONFIG_FILS */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003209#ifdef CONFIG_FST
3210 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3211 ret = os_snprintf(pos, end - pos, "[FST]");
3212 if (os_snprintf_error(end - pos, ret))
3213 return -1;
3214 pos += ret;
3215 }
3216#endif /* CONFIG_FST */
Hai Shalom74f70d42019-02-11 14:42:39 -08003217 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3218 ret = os_snprintf(pos, end - pos, "[UTF-8]");
3219 if (os_snprintf_error(end - pos, ret))
3220 return -1;
3221 pos += ret;
3222 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223
3224 ret = os_snprintf(pos, end - pos, "\t%s",
3225 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003226 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003227 return -1;
3228 pos += ret;
3229
3230 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003231 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003232 return -1;
3233 pos += ret;
3234
3235 return pos - buf;
3236}
3237
3238
3239static int wpa_supplicant_ctrl_iface_scan_results(
3240 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3241{
3242 char *pos, *end;
3243 struct wpa_bss *bss;
3244 int ret;
3245
3246 pos = buf;
3247 end = buf + buflen;
3248 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3249 "flags / ssid\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003250 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003251 return pos - buf;
3252 pos += ret;
3253
3254 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3255 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3256 end - pos);
3257 if (ret < 0 || ret >= end - pos)
3258 return pos - buf;
3259 pos += ret;
3260 }
3261
3262 return pos - buf;
3263}
3264
3265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003266#ifdef CONFIG_MESH
3267
3268static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3269 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3270{
3271 char *pos, ifname[IFNAMSIZ + 1];
3272
3273 ifname[0] = '\0';
3274
3275 pos = os_strstr(cmd, "ifname=");
3276 if (pos) {
3277 pos += 7;
3278 os_strlcpy(ifname, pos, sizeof(ifname));
3279 }
3280
3281 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3282 return -1;
3283
3284 os_strlcpy(reply, ifname, max_len);
3285 return os_strlen(ifname);
3286}
3287
3288
3289static int wpa_supplicant_ctrl_iface_mesh_group_add(
3290 struct wpa_supplicant *wpa_s, char *cmd)
3291{
3292 int id;
3293 struct wpa_ssid *ssid;
3294
3295 id = atoi(cmd);
3296 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3297
3298 ssid = wpa_config_get_network(wpa_s->conf, id);
3299 if (ssid == NULL) {
3300 wpa_printf(MSG_DEBUG,
3301 "CTRL_IFACE: Could not find network id=%d", id);
3302 return -1;
3303 }
3304 if (ssid->mode != WPAS_MODE_MESH) {
3305 wpa_printf(MSG_DEBUG,
3306 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3307 return -1;
3308 }
3309 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
Sunil Ravi89eba102022-09-13 21:04:37 -07003310 ssid->key_mgmt != WPA_KEY_MGMT_SAE &&
3311 ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003312 wpa_printf(MSG_ERROR,
3313 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3314 return -1;
3315 }
3316
3317 /*
3318 * TODO: If necessary write our own group_add function,
3319 * for now we can reuse select_network
3320 */
3321 wpa_supplicant_select_network(wpa_s, ssid);
3322
3323 return 0;
3324}
3325
3326
3327static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3328 struct wpa_supplicant *wpa_s, char *cmd)
3329{
3330 struct wpa_supplicant *orig;
3331 struct wpa_global *global;
3332 int found = 0;
3333
3334 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3335
3336 global = wpa_s->global;
3337 orig = wpa_s;
3338
3339 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3340 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3341 found = 1;
3342 break;
3343 }
3344 }
3345 if (!found) {
3346 wpa_printf(MSG_ERROR,
3347 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3348 cmd);
3349 return -1;
3350 }
3351 if (wpa_s->mesh_if_created && wpa_s == orig) {
3352 wpa_printf(MSG_ERROR,
3353 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3354 return -1;
3355 }
3356
3357 wpa_s->reassociate = 0;
3358 wpa_s->disconnected = 1;
3359 wpa_supplicant_cancel_sched_scan(wpa_s);
3360 wpa_supplicant_cancel_scan(wpa_s);
3361
3362 /*
3363 * TODO: If necessary write our own group_remove function,
3364 * for now we can reuse deauthenticate
3365 */
3366 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3367
3368 if (wpa_s->mesh_if_created)
3369 wpa_supplicant_remove_iface(global, wpa_s, 0);
3370
3371 return 0;
3372}
3373
Dmitry Shmidte4663042016-04-04 10:07:49 -07003374
3375static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3376 struct wpa_supplicant *wpa_s, char *cmd)
3377{
3378 u8 addr[ETH_ALEN];
3379
3380 if (hwaddr_aton(cmd, addr) < 0)
3381 return -1;
3382
3383 return wpas_mesh_peer_remove(wpa_s, addr);
3384}
3385
3386
3387static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3388 struct wpa_supplicant *wpa_s, char *cmd)
3389{
3390 u8 addr[ETH_ALEN];
3391 int duration;
3392 char *pos;
3393
3394 pos = os_strstr(cmd, " duration=");
3395 if (pos) {
3396 *pos = '\0';
3397 duration = atoi(pos + 10);
3398 } else {
3399 duration = -1;
3400 }
3401
3402 if (hwaddr_aton(cmd, addr))
3403 return -1;
3404
3405 return wpas_mesh_peer_add(wpa_s, addr, duration);
3406}
3407
Hai Shalom81f62d82019-07-22 12:10:00 -07003408
3409static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3410 struct wpa_supplicant *wpa_s, char *cmd)
3411{
3412 struct ether_header *eth;
3413 u8 addr[ETH_ALEN];
3414 u8 *buf;
3415 char *pos;
3416 size_t payload_len = 0, len;
3417 int ret = -1;
3418
3419 if (hwaddr_aton(cmd, addr))
3420 return -1;
3421
3422 pos = os_strstr(cmd, " payload=");
3423 if (pos) {
3424 pos = pos + 9;
3425 payload_len = os_strlen(pos);
3426 if (payload_len & 1)
3427 return -1;
3428
3429 payload_len /= 2;
3430 }
3431
3432 len = ETH_HLEN + payload_len;
3433 buf = os_malloc(len);
3434 if (!buf)
3435 return -1;
3436
3437 eth = (struct ether_header *) buf;
3438 os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3439 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3440 eth->ether_type = htons(ETH_P_802_3);
3441
3442 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3443 goto fail;
3444
3445 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3446fail:
3447 os_free(buf);
3448 return -ret;
3449}
3450
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003451#endif /* CONFIG_MESH */
3452
3453
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454static int wpa_supplicant_ctrl_iface_select_network(
3455 struct wpa_supplicant *wpa_s, char *cmd)
3456{
3457 int id;
3458 struct wpa_ssid *ssid;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003459 char *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460
3461 /* cmd: "<network id>" or "any" */
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003462 if (os_strncmp(cmd, "any", 3) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3464 ssid = NULL;
3465 } else {
3466 id = atoi(cmd);
3467 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3468
3469 ssid = wpa_config_get_network(wpa_s->conf, id);
3470 if (ssid == NULL) {
3471 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3472 "network id=%d", id);
3473 return -1;
3474 }
3475 if (ssid->disabled == 2) {
3476 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3477 "SELECT_NETWORK with persistent P2P group");
3478 return -1;
3479 }
3480 }
3481
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003482 pos = os_strstr(cmd, " freq=");
3483 if (pos) {
3484 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3485 if (freqs) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003486 os_free(wpa_s->select_network_scan_freqs);
3487 wpa_s->select_network_scan_freqs = freqs;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003488 }
3489 }
3490
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003491 wpa_s->scan_min_time.sec = 0;
3492 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 wpa_supplicant_select_network(wpa_s, ssid);
3494
3495 return 0;
3496}
3497
3498
3499static int wpa_supplicant_ctrl_iface_enable_network(
3500 struct wpa_supplicant *wpa_s, char *cmd)
3501{
3502 int id;
3503 struct wpa_ssid *ssid;
3504
3505 /* cmd: "<network id>" or "all" */
3506 if (os_strcmp(cmd, "all") == 0) {
3507 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3508 ssid = NULL;
3509 } else {
3510 id = atoi(cmd);
3511 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3512
3513 ssid = wpa_config_get_network(wpa_s->conf, id);
3514 if (ssid == NULL) {
3515 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3516 "network id=%d", id);
3517 return -1;
3518 }
3519 if (ssid->disabled == 2) {
3520 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3521 "ENABLE_NETWORK with persistent P2P group");
3522 return -1;
3523 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003524
3525 if (os_strstr(cmd, " no-connect")) {
3526 ssid->disabled = 0;
3527 return 0;
3528 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003529 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003530 wpa_s->scan_min_time.sec = 0;
3531 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003532 wpa_supplicant_enable_network(wpa_s, ssid);
3533
3534 return 0;
3535}
3536
3537
3538static int wpa_supplicant_ctrl_iface_disable_network(
3539 struct wpa_supplicant *wpa_s, char *cmd)
3540{
3541 int id;
3542 struct wpa_ssid *ssid;
3543
3544 /* cmd: "<network id>" or "all" */
3545 if (os_strcmp(cmd, "all") == 0) {
3546 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3547 ssid = NULL;
3548 } else {
3549 id = atoi(cmd);
3550 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3551
3552 ssid = wpa_config_get_network(wpa_s->conf, id);
3553 if (ssid == NULL) {
3554 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3555 "network id=%d", id);
3556 return -1;
3557 }
3558 if (ssid->disabled == 2) {
3559 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3560 "DISABLE_NETWORK with persistent P2P "
3561 "group");
3562 return -1;
3563 }
3564 }
3565 wpa_supplicant_disable_network(wpa_s, ssid);
3566
3567 return 0;
3568}
3569
3570
3571static int wpa_supplicant_ctrl_iface_add_network(
3572 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3573{
3574 struct wpa_ssid *ssid;
3575 int ret;
3576
3577 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3578
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003579 ssid = wpa_supplicant_add_network(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003580 if (ssid == NULL)
3581 return -1;
3582
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003583 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003584 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003585 return -1;
3586 return ret;
3587}
3588
3589
3590static int wpa_supplicant_ctrl_iface_remove_network(
3591 struct wpa_supplicant *wpa_s, char *cmd)
3592{
3593 int id;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003594 int result;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595
3596 /* cmd: "<network id>" or "all" */
3597 if (os_strcmp(cmd, "all") == 0) {
3598 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
Hai Shalom899fcc72020-10-19 14:38:18 -07003599 return wpa_supplicant_remove_all_networks(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003600 }
3601
3602 id = atoi(cmd);
3603 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3604
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003605 result = wpa_supplicant_remove_network(wpa_s, id);
3606 if (result == -1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3608 "id=%d", id);
3609 return -1;
3610 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003611 if (result == -2) {
Deepthi Gowria831d782012-09-03 11:55:38 +03003612 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3613 "network id=%d", id);
3614 return -1;
3615 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003616 return 0;
3617}
3618
3619
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003620static int wpa_supplicant_ctrl_iface_update_network(
3621 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3622 char *name, char *value)
3623{
Dmitry Shmidte4663042016-04-04 10:07:49 -07003624 int ret;
3625
3626 ret = wpa_config_set(ssid, name, value, 0);
3627 if (ret < 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003628 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3629 "variable '%s'", name);
3630 return -1;
3631 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07003632 if (ret == 1)
3633 return 0; /* No change to the previously configured value */
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003634
Hai Shalom899fcc72020-10-19 14:38:18 -07003635#ifdef CONFIG_BGSCAN
3636 if (os_strcmp(name, "bgscan") == 0) {
3637 /*
3638 * Reset the bgscan parameters for the current network and
3639 * return. There's no need to flush caches for bgscan parameter
3640 * changes.
3641 */
3642 if (wpa_s->current_ssid == ssid &&
3643 wpa_s->wpa_state == WPA_COMPLETED)
3644 wpa_supplicant_reset_bgscan(wpa_s);
3645 return 0;
3646 }
3647#endif /* CONFIG_BGSCAN */
3648
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003649 if (os_strcmp(name, "bssid") != 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003650 os_strncmp(name, "bssid_", 6) != 0 &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003651 os_strcmp(name, "scan_freq") != 0 &&
Dmitry Shmidte4663042016-04-04 10:07:49 -07003652 os_strcmp(name, "priority") != 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003653 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3654
Dmitry Shmidte4663042016-04-04 10:07:49 -07003655 if (wpa_s->current_ssid == ssid ||
3656 wpa_s->current_ssid == NULL) {
3657 /*
3658 * Invalidate the EAP session cache if anything in the
3659 * current or previously used configuration changes.
3660 */
3661 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3662 }
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003663 }
3664
3665 if ((os_strcmp(name, "psk") == 0 &&
3666 value[0] == '"' && ssid->ssid_len) ||
3667 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3668 wpa_config_update_psk(ssid);
3669 else if (os_strcmp(name, "priority") == 0)
3670 wpa_config_update_prio_list(wpa_s->conf);
3671
3672 return 0;
3673}
3674
3675
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676static int wpa_supplicant_ctrl_iface_set_network(
3677 struct wpa_supplicant *wpa_s, char *cmd)
3678{
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003679 int id, ret, prev_bssid_set, prev_disabled;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003680 struct wpa_ssid *ssid;
3681 char *name, *value;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003682 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003683
3684 /* cmd: "<network id> <variable name> <value>" */
3685 name = os_strchr(cmd, ' ');
3686 if (name == NULL)
3687 return -1;
3688 *name++ = '\0';
3689
3690 value = os_strchr(name, ' ');
3691 if (value == NULL)
3692 return -1;
3693 *value++ = '\0';
3694
3695 id = atoi(cmd);
3696 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3697 id, name);
3698 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3699 (u8 *) value, os_strlen(value));
3700
3701 ssid = wpa_config_get_network(wpa_s->conf, id);
3702 if (ssid == NULL) {
3703 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3704 "id=%d", id);
3705 return -1;
3706 }
3707
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003708 prev_bssid_set = ssid->bssid_set;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003709 prev_disabled = ssid->disabled;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003710 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3711 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3712 value);
3713 if (ret == 0 &&
3714 (ssid->bssid_set != prev_bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003715 !ether_addr_equal(ssid->bssid, prev_bssid)))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003716 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003717
3718 if (prev_disabled != ssid->disabled &&
3719 (prev_disabled == 2 || ssid->disabled == 2))
3720 wpas_notify_network_type_changed(wpa_s, ssid);
3721
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003722 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003723}
3724
3725
3726static int wpa_supplicant_ctrl_iface_get_network(
3727 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3728{
3729 int id;
3730 size_t res;
3731 struct wpa_ssid *ssid;
3732 char *name, *value;
3733
3734 /* cmd: "<network id> <variable name>" */
3735 name = os_strchr(cmd, ' ');
3736 if (name == NULL || buflen == 0)
3737 return -1;
3738 *name++ = '\0';
3739
3740 id = atoi(cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003741 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003742 id, name);
3743
3744 ssid = wpa_config_get_network(wpa_s->conf, id);
3745 if (ssid == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003746 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 "id=%d", id);
3748 return -1;
3749 }
3750
3751 value = wpa_config_get_no_key(ssid, name);
3752 if (value == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003753 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754 "variable '%s'", name);
3755 return -1;
3756 }
3757
3758 res = os_strlcpy(buf, value, buflen);
3759 if (res >= buflen) {
3760 os_free(value);
3761 return -1;
3762 }
3763
3764 os_free(value);
3765
3766 return res;
3767}
3768
3769
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003770static int wpa_supplicant_ctrl_iface_dup_network(
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003771 struct wpa_supplicant *wpa_s, char *cmd,
3772 struct wpa_supplicant *dst_wpa_s)
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003773{
3774 struct wpa_ssid *ssid_s, *ssid_d;
3775 char *name, *id, *value;
3776 int id_s, id_d, ret;
3777
3778 /* cmd: "<src network id> <dst network id> <variable name>" */
3779 id = os_strchr(cmd, ' ');
3780 if (id == NULL)
3781 return -1;
3782 *id++ = '\0';
3783
3784 name = os_strchr(id, ' ');
3785 if (name == NULL)
3786 return -1;
3787 *name++ = '\0';
3788
3789 id_s = atoi(cmd);
3790 id_d = atoi(id);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003791
3792 wpa_printf(MSG_DEBUG,
3793 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3794 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003795
3796 ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3797 if (ssid_s == NULL) {
3798 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3799 "network id=%d", id_s);
3800 return -1;
3801 }
3802
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003803 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003804 if (ssid_d == NULL) {
3805 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003806 "network id=%d", id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003807 return -1;
3808 }
3809
3810 value = wpa_config_get(ssid_s, name);
3811 if (value == NULL) {
3812 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3813 "variable '%s'", name);
3814 return -1;
3815 }
3816
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003817 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003818 value);
3819
3820 os_free(value);
3821
3822 return ret;
3823}
3824
3825
Dmitry Shmidt04949592012-07-19 12:16:46 -07003826static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3827 char *buf, size_t buflen)
3828{
3829 char *pos, *end;
3830 struct wpa_cred *cred;
3831 int ret;
3832
3833 pos = buf;
3834 end = buf + buflen;
3835 ret = os_snprintf(pos, end - pos,
3836 "cred id / realm / username / domain / imsi\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003837 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003838 return pos - buf;
3839 pos += ret;
3840
3841 cred = wpa_s->conf->cred;
3842 while (cred) {
3843 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3844 cred->id, cred->realm ? cred->realm : "",
3845 cred->username ? cred->username : "",
Dmitry Shmidt051af732013-10-22 13:52:46 -07003846 cred->domain ? cred->domain[0] : "",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003847 cred->imsi ? cred->imsi : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003848 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003849 return pos - buf;
3850 pos += ret;
3851
3852 cred = cred->next;
3853 }
3854
3855 return pos - buf;
3856}
3857
3858
3859static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3860 char *buf, size_t buflen)
3861{
3862 struct wpa_cred *cred;
3863 int ret;
3864
3865 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3866
3867 cred = wpa_config_add_cred(wpa_s->conf);
3868 if (cred == NULL)
3869 return -1;
3870
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003871 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3872
Dmitry Shmidt04949592012-07-19 12:16:46 -07003873 ret = os_snprintf(buf, buflen, "%d\n", cred->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003874 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003875 return -1;
3876 return ret;
3877}
3878
3879
3880static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3881 char *cmd)
3882{
3883 int id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003884 struct wpa_cred *cred, *prev;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003885
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003886 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3887 * "provisioning_sp=<FQDN> */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003888 if (os_strcmp(cmd, "all") == 0) {
3889 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003890 return wpas_remove_all_creds(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003891 }
3892
3893 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3894 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3895 cmd + 8);
3896 cred = wpa_s->conf->cred;
3897 while (cred) {
3898 prev = cred;
3899 cred = cred->next;
Dmitry Shmidt051af732013-10-22 13:52:46 -07003900 if (prev->domain) {
3901 size_t i;
3902 for (i = 0; i < prev->num_domain; i++) {
3903 if (os_strcmp(prev->domain[i], cmd + 8)
3904 != 0)
3905 continue;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003906 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidt051af732013-10-22 13:52:46 -07003907 break;
3908 }
3909 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003910 }
3911 return 0;
3912 }
3913
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003914 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3915 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3916 cmd + 16);
3917 cred = wpa_s->conf->cred;
3918 while (cred) {
3919 prev = cred;
3920 cred = cred->next;
3921 if (prev->provisioning_sp &&
3922 os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
Hai Shaloma20dcd72022-02-04 13:43:00 -08003923 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003924 }
3925 return 0;
3926 }
3927
Dmitry Shmidt04949592012-07-19 12:16:46 -07003928 id = atoi(cmd);
3929 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3930
3931 cred = wpa_config_get_cred(wpa_s->conf, id);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003932 return wpas_remove_cred(wpa_s, cred);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003933}
3934
3935
3936static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3937 char *cmd)
3938{
3939 int id;
3940 struct wpa_cred *cred;
3941 char *name, *value;
3942
3943 /* cmd: "<cred id> <variable name> <value>" */
3944 name = os_strchr(cmd, ' ');
3945 if (name == NULL)
3946 return -1;
3947 *name++ = '\0';
3948
3949 value = os_strchr(name, ' ');
3950 if (value == NULL)
3951 return -1;
3952 *value++ = '\0';
3953
3954 id = atoi(cmd);
3955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3956 id, name);
3957 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3958 (u8 *) value, os_strlen(value));
3959
3960 cred = wpa_config_get_cred(wpa_s->conf, id);
3961 if (cred == NULL) {
3962 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3963 id);
3964 return -1;
3965 }
3966
3967 if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3968 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3969 "variable '%s'", name);
3970 return -1;
3971 }
3972
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003973 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3974
Dmitry Shmidt04949592012-07-19 12:16:46 -07003975 return 0;
3976}
3977
3978
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003979static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3980 char *cmd, char *buf,
3981 size_t buflen)
3982{
3983 int id;
3984 size_t res;
3985 struct wpa_cred *cred;
3986 char *name, *value;
3987
3988 /* cmd: "<cred id> <variable name>" */
3989 name = os_strchr(cmd, ' ');
3990 if (name == NULL)
3991 return -1;
3992 *name++ = '\0';
3993
3994 id = atoi(cmd);
3995 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3996 id, name);
3997
3998 cred = wpa_config_get_cred(wpa_s->conf, id);
3999 if (cred == NULL) {
4000 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4001 id);
4002 return -1;
4003 }
4004
4005 value = wpa_config_get_cred_no_key(cred, name);
4006 if (value == NULL) {
4007 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
4008 name);
4009 return -1;
4010 }
4011
4012 res = os_strlcpy(buf, value, buflen);
4013 if (res >= buflen) {
4014 os_free(value);
4015 return -1;
4016 }
4017
4018 os_free(value);
4019
4020 return res;
4021}
4022
4023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024#ifndef CONFIG_NO_CONFIG_WRITE
4025static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
4026{
4027 int ret;
4028
4029 if (!wpa_s->conf->update_config) {
4030 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
4031 "to update configuration (update_config=0)");
4032 return -1;
4033 }
4034
4035 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
4036 if (ret) {
4037 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
4038 "update configuration");
4039 } else {
4040 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
4041 " updated");
4042 }
4043
4044 return ret;
4045}
4046#endif /* CONFIG_NO_CONFIG_WRITE */
4047
4048
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004049struct cipher_info {
4050 unsigned int capa;
4051 const char *name;
4052 int group_only;
4053};
4054
4055static const struct cipher_info ciphers[] = {
4056 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4057 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4058 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4059 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07004060#ifndef CONFIG_NO_TKIP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004061 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07004062#endif /* CONFIG_NO_TKIP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004063 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
Hai Shalomfdcde762020-04-02 11:19:20 -07004064#ifdef CONFIG_WEP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004065 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4066 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004067#endif /* CONFIG_WEP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004068};
4069
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004070static const struct cipher_info ciphers_group_mgmt[] = {
4071 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4072 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4073 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4074 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4075};
4076
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004077
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004078static int ctrl_iface_get_capability_pairwise(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004079 struct wpa_driver_capa *capa,
4080 char *buf, size_t buflen)
4081{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004082 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 char *pos, *end;
4084 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004085 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004086
4087 pos = buf;
4088 end = pos + buflen;
4089
4090 if (res < 0) {
4091 if (strict)
4092 return 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07004093#ifdef CONFIG_NO_TKIP
4094 len = os_strlcpy(buf, "CCMP NONE", buflen);
4095#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004096 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004097#endif /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 if (len >= buflen)
4099 return -1;
4100 return len;
4101 }
4102
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004103 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4104 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4105 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004106 pos == buf ? "" : " ",
4107 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004108 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004109 return pos - buf;
4110 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004111 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 }
4113
4114 return pos - buf;
4115}
4116
4117
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004118static int ctrl_iface_get_capability_group(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119 struct wpa_driver_capa *capa,
4120 char *buf, size_t buflen)
4121{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004122 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004123 char *pos, *end;
4124 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004125 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126
4127 pos = buf;
4128 end = pos + buflen;
4129
4130 if (res < 0) {
4131 if (strict)
4132 return 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004133#ifdef CONFIG_WEP
Hai Shalomb755a2a2020-04-23 21:49:02 -07004134#ifdef CONFIG_NO_TKIP
4135 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4136#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004137 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004138#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004139#else /* CONFIG_WEP */
Hai Shalomb755a2a2020-04-23 21:49:02 -07004140#ifdef CONFIG_NO_TKIP
4141 len = os_strlcpy(buf, "CCMP", buflen);
4142#else /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004143 len = os_strlcpy(buf, "CCMP TKIP", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004144#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004145#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 if (len >= buflen)
4147 return -1;
4148 return len;
4149 }
4150
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004151 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4152 if (capa->enc & ciphers[i].capa) {
4153 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004154 pos == buf ? "" : " ",
4155 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004156 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004157 return pos - buf;
4158 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004159 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 }
4161
4162 return pos - buf;
4163}
4164
4165
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004166static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004167 struct wpa_driver_capa *capa,
4168 char *buf, size_t buflen)
4169{
4170 int ret;
4171 char *pos, *end;
4172 unsigned int i;
4173
4174 pos = buf;
4175 end = pos + buflen;
4176
4177 if (res < 0)
4178 return 0;
4179
4180 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4181 if (capa->enc & ciphers_group_mgmt[i].capa) {
4182 ret = os_snprintf(pos, end - pos, "%s%s",
4183 pos == buf ? "" : " ",
4184 ciphers_group_mgmt[i].name);
4185 if (os_snprintf_error(end - pos, ret))
4186 return pos - buf;
4187 pos += ret;
4188 }
4189 }
4190
4191 return pos - buf;
4192}
4193
4194
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004195static int iftype_str_to_index(const char *iftype_str)
4196{
4197 if (!iftype_str)
4198 return WPA_IF_MAX;
4199
4200 if (os_strcmp(iftype_str, "STATION") == 0)
4201 return WPA_IF_STATION;
4202
4203 if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4204 return WPA_IF_AP_VLAN;
4205
4206 if (os_strcmp(iftype_str, "AP") == 0)
4207 return WPA_IF_AP_BSS;
4208
4209 if (os_strcmp(iftype_str, "P2P_GO") == 0)
4210 return WPA_IF_P2P_GO;
4211
4212 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4213 return WPA_IF_P2P_CLIENT;
4214
4215 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4216 return WPA_IF_P2P_DEVICE;
4217
4218 if (os_strcmp(iftype_str, "MESH") == 0)
4219 return WPA_IF_MESH;
4220
4221 if (os_strcmp(iftype_str, "IBSS") == 0)
4222 return WPA_IF_IBSS;
4223
4224 if (os_strcmp(iftype_str, "NAN") == 0)
4225 return WPA_IF_NAN;
4226
4227 return WPA_IF_MAX;
4228}
4229
4230
4231static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004232 struct wpa_driver_capa *capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004233 const char *iftype_str,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 char *buf, size_t buflen)
4235{
4236 int ret;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004237 unsigned int key_mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004238 char *pos, *end;
4239 size_t len;
4240
4241 pos = buf;
4242 end = pos + buflen;
4243
4244 if (res < 0) {
4245 if (strict)
4246 return 0;
4247 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4248 "NONE", buflen);
4249 if (len >= buflen)
4250 return -1;
4251 return len;
4252 }
4253
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004254 if (iftype_str) {
4255 enum wpa_driver_if_type iftype;
4256
4257 iftype = iftype_str_to_index(iftype_str);
4258 if (iftype == WPA_IF_MAX)
4259 return -1;
4260 key_mgmt = capa->key_mgmt_iftype[iftype];
4261 } else {
4262 key_mgmt = capa->key_mgmt;
4263 }
4264
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004265 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004266 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004267 return pos - buf;
4268 pos += ret;
4269
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004270 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4271 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272 ret = os_snprintf(pos, end - pos, " WPA-EAP");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004273 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274 return pos - buf;
4275 pos += ret;
4276 }
4277
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004278 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4279 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004280 ret = os_snprintf(pos, end - pos, " WPA-PSK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004281 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282 return pos - buf;
4283 pos += ret;
4284 }
4285
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004286 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287 ret = os_snprintf(pos, end - pos, " WPA-NONE");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004288 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004289 return pos - buf;
4290 pos += ret;
4291 }
4292
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304293 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4294 ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4295 if (os_snprintf_error(end - pos, ret))
4296 return pos - buf;
4297 pos += ret;
4298 }
4299
4300 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4301 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4302 if (os_snprintf_error(end - pos, ret))
4303 return pos - buf;
4304 pos += ret;
4305 }
4306
4307 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4308 ret = os_snprintf(pos, end - pos, " CCKM");
4309 if (os_snprintf_error(end - pos, ret))
4310 return pos - buf;
4311 pos += ret;
4312 }
4313
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004314#ifdef CONFIG_SUITEB
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004315 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004316 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4317 if (os_snprintf_error(end - pos, ret))
4318 return pos - buf;
4319 pos += ret;
4320 }
4321#endif /* CONFIG_SUITEB */
4322#ifdef CONFIG_SUITEB192
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004323 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004324 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4325 if (os_snprintf_error(end - pos, ret))
4326 return pos - buf;
4327 pos += ret;
4328 }
4329#endif /* CONFIG_SUITEB192 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004330#ifdef CONFIG_OWE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004331 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004332 ret = os_snprintf(pos, end - pos, " OWE");
4333 if (os_snprintf_error(end - pos, ret))
4334 return pos - buf;
4335 pos += ret;
4336 }
4337#endif /* CONFIG_OWE */
4338#ifdef CONFIG_DPP
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004339 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004340 ret = os_snprintf(pos, end - pos, " DPP");
4341 if (os_snprintf_error(end - pos, ret))
4342 return pos - buf;
4343 pos += ret;
4344 }
4345#endif /* CONFIG_DPP */
4346#ifdef CONFIG_FILS
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004347 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004348 ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4349 if (os_snprintf_error(end - pos, ret))
4350 return pos - buf;
4351 pos += ret;
4352 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004353 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004354 ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4355 if (os_snprintf_error(end - pos, ret))
4356 return pos - buf;
4357 pos += ret;
4358 }
4359#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004360 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004361 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4362 if (os_snprintf_error(end - pos, ret))
4363 return pos - buf;
4364 pos += ret;
4365 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004366 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004367 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4368 if (os_snprintf_error(end - pos, ret))
4369 return pos - buf;
4370 pos += ret;
4371 }
4372#endif /* CONFIG_IEEE80211R */
4373#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08004374#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004375 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004376 ret = os_snprintf(pos, end - pos, " FT-PSK");
4377 if (os_snprintf_error(end - pos, ret))
4378 return pos - buf;
4379 pos += ret;
4380 }
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304381 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4382 ret = os_snprintf(pos, end - pos, " FT-EAP");
4383 if (os_snprintf_error(end - pos, ret))
4384 return pos - buf;
4385 pos += ret;
4386 }
4387#ifdef CONFIG_SAE
4388 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4389 ret = os_snprintf(pos, end - pos, " FT-SAE");
4390 if (os_snprintf_error(end - pos, ret))
4391 return pos - buf;
4392 pos += ret;
4393 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004394 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) {
4395 ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY");
4396 if (os_snprintf_error(end - pos, ret))
4397 return pos - buf;
4398 pos += ret;
4399 }
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304400#endif /* CONFIG_SAE */
4401#ifdef CONFIG_SHA384
4402 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4403 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4404 if (os_snprintf_error(end - pos, ret))
4405 return pos - buf;
4406 pos += ret;
4407 }
4408#endif /* CONFIG_SHA384 */
Hai Shalom74f70d42019-02-11 14:42:39 -08004409#endif /* CONFIG_IEEE80211R */
4410#ifdef CONFIG_SAE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004411 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004412 ret = os_snprintf(pos, end - pos, " SAE");
4413 if (os_snprintf_error(end - pos, ret))
4414 return pos - buf;
4415 pos += ret;
4416 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004417 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) {
4418 ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY");
4419 if (os_snprintf_error(end - pos, ret))
4420 return pos - buf;
4421 pos += ret;
4422 }
Hai Shalom74f70d42019-02-11 14:42:39 -08004423#endif /* CONFIG_SAE */
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304424#ifdef CONFIG_SHA256
4425 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4426 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4427 if (os_snprintf_error(end - pos, ret))
4428 return pos - buf;
4429 pos += ret;
4430 }
4431
4432 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4433 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4434 if (os_snprintf_error(end - pos, ret))
4435 return pos - buf;
4436 pos += ret;
4437 }
4438#endif /* CONFIG_SHA256 */
4439#ifdef CONFIG_HS20
4440 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4441 ret = os_snprintf(pos, end - pos, " OSEN");
4442 if (os_snprintf_error(end - pos, ret))
4443 return pos - buf;
4444 pos += ret;
4445 }
4446#endif /* CONFIG_HS20 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004447
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004448 return pos - buf;
4449}
4450
4451
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004452static int ctrl_iface_get_capability_proto(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004453 struct wpa_driver_capa *capa,
4454 char *buf, size_t buflen)
4455{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004456 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457 char *pos, *end;
4458 size_t len;
4459
4460 pos = buf;
4461 end = pos + buflen;
4462
4463 if (res < 0) {
4464 if (strict)
4465 return 0;
4466 len = os_strlcpy(buf, "RSN WPA", buflen);
4467 if (len >= buflen)
4468 return -1;
4469 return len;
4470 }
4471
4472 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4473 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004474 ret = os_snprintf(pos, end - pos, "%sRSN",
4475 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004476 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004477 return pos - buf;
4478 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 }
4480
4481 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4482 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004483 ret = os_snprintf(pos, end - pos, "%sWPA",
4484 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004485 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004486 return pos - buf;
4487 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004488 }
4489
4490 return pos - buf;
4491}
4492
4493
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004494static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004495 int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004496 struct wpa_driver_capa *capa,
4497 char *buf, size_t buflen)
4498{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004499 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 char *pos, *end;
4501 size_t len;
4502
4503 pos = buf;
4504 end = pos + buflen;
4505
4506 if (res < 0) {
4507 if (strict)
4508 return 0;
4509 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4510 if (len >= buflen)
4511 return -1;
4512 return len;
4513 }
4514
4515 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004516 ret = os_snprintf(pos, end - pos, "%sOPEN",
4517 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004518 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519 return pos - buf;
4520 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004521 }
4522
4523 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4524 ret = os_snprintf(pos, end - pos, "%sSHARED",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004525 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004526 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004527 return pos - buf;
4528 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529 }
4530
4531 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004532 ret = os_snprintf(pos, end - pos, "%sLEAP",
4533 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004534 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004535 return pos - buf;
4536 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537 }
4538
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004539#ifdef CONFIG_SAE
4540 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4541 ret = os_snprintf(pos, end - pos, "%sSAE",
4542 pos == buf ? "" : " ");
4543 if (os_snprintf_error(end - pos, ret))
4544 return pos - buf;
4545 pos += ret;
4546 }
4547#endif /* CONFIG_SAE */
4548
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004549#ifdef CONFIG_FILS
4550 if (wpa_is_fils_supported(wpa_s)) {
4551 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4552 pos == buf ? "" : " ");
4553 if (os_snprintf_error(end - pos, ret))
4554 return pos - buf;
4555 pos += ret;
4556 }
4557
4558#ifdef CONFIG_FILS_SK_PFS
4559 if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4560 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4561 pos == buf ? "" : " ");
4562 if (os_snprintf_error(end - pos, ret))
4563 return pos - buf;
4564 pos += ret;
4565 }
4566#endif /* CONFIG_FILS_SK_PFS */
4567#endif /* CONFIG_FILS */
4568
Hai Shalom60840252021-02-19 19:02:11 -08004569#ifdef CONFIG_PASN
4570 ret = os_snprintf(pos, end - pos, "%sPASN",
4571 pos == buf ? "" : " ");
4572 if (os_snprintf_error(end - pos, ret))
4573 return pos - buf;
4574 pos += ret;
4575
4576#endif /* CONFIG_PASN */
4577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004578 return pos - buf;
4579}
4580
4581
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004582static int ctrl_iface_get_capability_modes(int res, bool strict,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004583 struct wpa_driver_capa *capa,
4584 char *buf, size_t buflen)
4585{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004586 int ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004587 char *pos, *end;
4588 size_t len;
4589
4590 pos = buf;
4591 end = pos + buflen;
4592
4593 if (res < 0) {
4594 if (strict)
4595 return 0;
4596 len = os_strlcpy(buf, "IBSS AP", buflen);
4597 if (len >= buflen)
4598 return -1;
4599 return len;
4600 }
4601
4602 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004603 ret = os_snprintf(pos, end - pos, "%sIBSS",
4604 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004605 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004606 return pos - buf;
4607 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004608 }
4609
4610 if (capa->flags & WPA_DRIVER_FLAGS_AP) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004611 ret = os_snprintf(pos, end - pos, "%sAP",
4612 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004613 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004614 return pos - buf;
4615 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004616 }
4617
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004618#ifdef CONFIG_MESH
4619 if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4620 ret = os_snprintf(pos, end - pos, "%sMESH",
4621 pos == buf ? "" : " ");
4622 if (os_snprintf_error(end - pos, ret))
4623 return pos - buf;
4624 pos += ret;
4625 }
4626#endif /* CONFIG_MESH */
4627
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004628 return pos - buf;
4629}
4630
4631
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004632static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4633 char *buf, size_t buflen)
4634{
4635 struct hostapd_channel_data *chnl;
4636 int ret, i, j;
4637 char *pos, *end, *hmode;
4638
4639 pos = buf;
4640 end = pos + buflen;
4641
4642 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4643 switch (wpa_s->hw.modes[j].mode) {
4644 case HOSTAPD_MODE_IEEE80211B:
4645 hmode = "B";
4646 break;
4647 case HOSTAPD_MODE_IEEE80211G:
4648 hmode = "G";
4649 break;
4650 case HOSTAPD_MODE_IEEE80211A:
4651 hmode = "A";
4652 break;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004653 case HOSTAPD_MODE_IEEE80211AD:
4654 hmode = "AD";
4655 break;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004656 default:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004657 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004658 }
4659 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004660 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004661 return pos - buf;
4662 pos += ret;
4663 chnl = wpa_s->hw.modes[j].channels;
4664 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004665 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4666 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004667 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004668 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004669 return pos - buf;
4670 pos += ret;
4671 }
4672 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004673 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004674 return pos - buf;
4675 pos += ret;
4676 }
4677
4678 return pos - buf;
4679}
4680
4681
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004682static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4683 char *buf, size_t buflen)
4684{
4685 struct hostapd_channel_data *chnl;
4686 int ret, i, j;
4687 char *pos, *end, *hmode;
4688
4689 pos = buf;
4690 end = pos + buflen;
4691
4692 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4693 switch (wpa_s->hw.modes[j].mode) {
4694 case HOSTAPD_MODE_IEEE80211B:
4695 hmode = "B";
4696 break;
4697 case HOSTAPD_MODE_IEEE80211G:
4698 hmode = "G";
4699 break;
4700 case HOSTAPD_MODE_IEEE80211A:
4701 hmode = "A";
4702 break;
4703 case HOSTAPD_MODE_IEEE80211AD:
4704 hmode = "AD";
4705 break;
4706 default:
4707 continue;
4708 }
4709 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4710 hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004711 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004712 return pos - buf;
4713 pos += ret;
4714 chnl = wpa_s->hw.modes[j].channels;
4715 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4716 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4717 continue;
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004718 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004719 chnl[i].chan, chnl[i].freq,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004720 chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4721 " (NO_IR)" : "",
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004722 chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4723 " (DFS)" : "");
4724
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004725 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004726 return pos - buf;
4727 pos += ret;
4728 }
4729 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004730 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004731 return pos - buf;
4732 pos += ret;
4733 }
4734
4735 return pos - buf;
4736}
4737
4738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004739static int wpa_supplicant_ctrl_iface_get_capability(
4740 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4741 size_t buflen)
4742{
4743 struct wpa_driver_capa capa;
4744 int res;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004745 char *next_param, *curr_param, *iftype = NULL;
4746 bool strict = false;
4747 char field[50];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 size_t len;
4749
4750 /* Determine whether or not strict checking was requested */
4751 len = os_strlcpy(field, _field, sizeof(field));
4752 if (len >= sizeof(field))
4753 return -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004754
4755 next_param = os_strchr(field, ' ');
4756 while (next_param) {
4757 *next_param++ = '\0';
4758 curr_param = next_param;
4759 next_param = os_strchr(next_param, ' ');
4760
4761 if (next_param)
4762 *next_param = '\0';
4763
4764 if (os_strcmp(curr_param, "strict") == 0)
4765 strict = true;
4766 else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4767 iftype = curr_param + 7;
4768 else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004769 return -1;
4770 }
4771
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004772 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4773 field, iftype ? " iftype=" : "", iftype ? iftype : "",
4774 strict ? " strict" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004775
4776 if (os_strcmp(field, "eap") == 0) {
4777 return eap_get_names(buf, buflen);
4778 }
4779
4780 res = wpa_drv_get_capa(wpa_s, &capa);
4781
4782 if (os_strcmp(field, "pairwise") == 0)
4783 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4784 buf, buflen);
4785
4786 if (os_strcmp(field, "group") == 0)
4787 return ctrl_iface_get_capability_group(res, strict, &capa,
4788 buf, buflen);
4789
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004790 if (os_strcmp(field, "group_mgmt") == 0)
4791 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4792 buf, buflen);
4793
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004794 if (os_strcmp(field, "key_mgmt") == 0)
4795 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004796 iftype, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797
4798 if (os_strcmp(field, "proto") == 0)
4799 return ctrl_iface_get_capability_proto(res, strict, &capa,
4800 buf, buflen);
4801
4802 if (os_strcmp(field, "auth_alg") == 0)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004803 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4804 &capa, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004805
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004806 if (os_strcmp(field, "modes") == 0)
4807 return ctrl_iface_get_capability_modes(res, strict, &capa,
4808 buf, buflen);
4809
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004810 if (os_strcmp(field, "channels") == 0)
4811 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4812
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004813 if (os_strcmp(field, "freq") == 0)
4814 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4815
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004816#ifdef CONFIG_TDLS
4817 if (os_strcmp(field, "tdls") == 0)
4818 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4819#endif /* CONFIG_TDLS */
4820
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004821#ifdef CONFIG_ERP
4822 if (os_strcmp(field, "erp") == 0) {
4823 res = os_snprintf(buf, buflen, "ERP");
4824 if (os_snprintf_error(buflen, res))
4825 return -1;
4826 return res;
4827 }
4828#endif /* CONFIG_EPR */
4829
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004830#ifdef CONFIG_FIPS
4831 if (os_strcmp(field, "fips") == 0) {
4832 res = os_snprintf(buf, buflen, "FIPS");
4833 if (os_snprintf_error(buflen, res))
4834 return -1;
4835 return res;
4836 }
4837#endif /* CONFIG_FIPS */
4838
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08004839#ifdef CONFIG_ACS
4840 if (os_strcmp(field, "acs") == 0) {
4841 res = os_snprintf(buf, buflen, "ACS");
4842 if (os_snprintf_error(buflen, res))
4843 return -1;
4844 return res;
4845 }
4846#endif /* CONFIG_ACS */
4847
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004848#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004849 if (os_strcmp(field, "fils") == 0) {
4850#ifdef CONFIG_FILS_SK_PFS
4851 if (wpa_is_fils_supported(wpa_s) &&
4852 wpa_is_fils_sk_pfs_supported(wpa_s)) {
4853 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4854 if (os_snprintf_error(buflen, res))
4855 return -1;
4856 return res;
4857 }
4858#endif /* CONFIG_FILS_SK_PFS */
4859
4860 if (wpa_is_fils_supported(wpa_s)) {
4861 res = os_snprintf(buf, buflen, "FILS");
4862 if (os_snprintf_error(buflen, res))
4863 return -1;
4864 return res;
4865 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004866 }
4867#endif /* CONFIG_FILS */
4868
Hai Shalom74f70d42019-02-11 14:42:39 -08004869 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4870 res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4871 if (os_snprintf_error(buflen, res))
4872 return -1;
4873 return res;
4874 }
4875
Hai Shalom021b0b52019-04-10 11:17:58 -07004876#ifdef CONFIG_DPP
4877 if (os_strcmp(field, "dpp") == 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004878#ifdef CONFIG_DPP3
4879 res = os_snprintf(buf, buflen, "DPP=3");
4880#elif defined(CONFIG_DPP2)
Hai Shalom021b0b52019-04-10 11:17:58 -07004881 res = os_snprintf(buf, buflen, "DPP=2");
4882#else /* CONFIG_DPP2 */
4883 res = os_snprintf(buf, buflen, "DPP=1");
4884#endif /* CONFIG_DPP2 */
4885 if (os_snprintf_error(buflen, res))
4886 return -1;
4887 return res;
4888 }
4889#endif /* CONFIG_DPP */
4890
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004891#ifdef CONFIG_NAN_USD
4892 if (os_strcmp(field, "nan") == 0) {
4893 res = os_snprintf(buf, buflen, "USD");
4894 if (os_snprintf_error(buflen, res))
4895 return -1;
4896 return res;
4897 }
4898#endif /* CONFIG_NAN_USD */
4899
Hai Shalom899fcc72020-10-19 14:38:18 -07004900#ifdef CONFIG_SAE
4901 if (os_strcmp(field, "sae") == 0 &&
4902 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4903#ifdef CONFIG_SAE_PK
4904 res = os_snprintf(buf, buflen, "H2E PK");
4905#else /* CONFIG_SAE_PK */
4906 res = os_snprintf(buf, buflen, "H2E");
4907#endif /* CONFIG_SAE_PK */
4908 if (os_snprintf_error(buflen, res))
4909 return -1;
4910 return res;
4911 }
4912#endif /* CONFIG_SAE */
4913
Hai Shalom60840252021-02-19 19:02:11 -08004914#ifdef CONFIG_OCV
4915 if (os_strcmp(field, "ocv") == 0) {
4916 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4917 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4918 res = os_snprintf(buf, buflen, "supported");
4919 else
4920 res = os_snprintf(buf, buflen, "not supported");
4921 if (os_snprintf_error(buflen, res))
4922 return -1;
4923 return res;
4924 }
4925#endif /* CONFIG_OCV */
4926
4927 if (os_strcmp(field, "beacon_prot") == 0) {
4928 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4929 (wpa_s->drv_flags2 &
4930 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4931 res = os_snprintf(buf, buflen, "supported");
4932 else
4933 res = os_snprintf(buf, buflen, "not supported");
4934 if (os_snprintf_error(buflen, res))
4935 return -1;
4936 return res;
4937 }
4938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004939 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4940 field);
4941
4942 return -1;
4943}
4944
4945
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004946#ifdef CONFIG_INTERWORKING
4947static char * anqp_add_hex(char *pos, char *end, const char *title,
4948 struct wpabuf *data)
4949{
4950 char *start = pos;
4951 size_t i;
4952 int ret;
4953 const u8 *d;
4954
4955 if (data == NULL)
4956 return start;
4957
4958 ret = os_snprintf(pos, end - pos, "%s=", title);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004959 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004960 return start;
4961 pos += ret;
4962
4963 d = wpabuf_head_u8(data);
4964 for (i = 0; i < wpabuf_len(data); i++) {
4965 ret = os_snprintf(pos, end - pos, "%02x", *d++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004966 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004967 return start;
4968 pos += ret;
4969 }
4970
4971 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004972 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004973 return start;
4974 pos += ret;
4975
4976 return pos;
4977}
4978#endif /* CONFIG_INTERWORKING */
4979
4980
Dmitry Shmidt29333592017-01-09 12:27:11 -08004981#ifdef CONFIG_FILS
4982static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
4983{
4984 char *start = pos;
4985 const u8 *ie, *ie_end;
4986 u16 info, realms;
4987 int ret;
4988
4989 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
4990 if (!ie)
4991 return 0;
4992 ie_end = ie + 2 + ie[1];
4993 ie += 2;
4994 if (ie_end - ie < 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004995 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08004996
4997 info = WPA_GET_LE16(ie);
4998 ie += 2;
4999 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
5000 if (os_snprintf_error(end - pos, ret))
5001 return 0;
5002 pos += ret;
5003
5004 if (info & BIT(7)) {
5005 /* Cache Identifier Included */
5006 if (ie_end - ie < 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005007 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005008 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
5009 ie[0], ie[1]);
5010 if (os_snprintf_error(end - pos, ret))
5011 return 0;
5012 pos += ret;
5013 ie += 2;
5014 }
5015
5016 if (info & BIT(8)) {
5017 /* HESSID Included */
5018 if (ie_end - ie < ETH_ALEN)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005019 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005020 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
5021 MAC2STR(ie));
5022 if (os_snprintf_error(end - pos, ret))
5023 return 0;
5024 pos += ret;
5025 ie += ETH_ALEN;
5026 }
5027
5028 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
5029 if (realms) {
5030 if (ie_end - ie < realms * 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005031 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005032 ret = os_snprintf(pos, end - pos, "fils_realms=");
5033 if (os_snprintf_error(end - pos, ret))
5034 return 0;
5035 pos += ret;
5036
5037 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
5038 if (ret <= 0)
5039 return 0;
5040 pos += ret;
5041 ie += realms * 2;
5042 ret = os_snprintf(pos, end - pos, "\n");
5043 if (os_snprintf_error(end - pos, ret))
5044 return 0;
5045 pos += ret;
5046 }
5047
5048 return pos - start;
5049}
5050#endif /* CONFIG_FILS */
5051
5052
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005053static int print_rnr(struct wpa_bss *bss, char *pos, char *end)
5054{
5055 char *start = pos;
5056 const u8 *ie, *ie_end;
5057 unsigned int n = 0;
5058 int ret;
5059
5060 ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
5061 if (!ie)
5062 return 0;
5063
5064 ie_end = ie + 2 + ie[1];
5065 ie += 2;
5066
5067 while (ie < ie_end) {
5068 const struct ieee80211_neighbor_ap_info *info =
5069 (const struct ieee80211_neighbor_ap_info *) ie;
5070 const u8 *tbtt_start;
5071 size_t left = ie_end - ie;
5072
5073 if (left < sizeof(struct ieee80211_neighbor_ap_info))
5074 return 0;
5075
5076 left -= sizeof(struct ieee80211_neighbor_ap_info);
5077 if (left < info->tbtt_info_len)
5078 return 0;
5079
5080 ret = os_snprintf(pos, end - pos,
5081 "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ",
5082 n, *ie, info->tbtt_info_len,
5083 info->op_class, info->channel);
5084 if (os_snprintf_error(end - pos, ret))
5085 return 0;
5086 pos += ret;
5087
5088 ie += sizeof(struct ieee80211_neighbor_ap_info);
5089 tbtt_start = ie;
5090 if (info->tbtt_info_len >= 1) {
5091 ret = os_snprintf(pos, end - pos,
5092 "tbtt_offset=%u, ", *ie);
5093 if (os_snprintf_error(end - pos, ret))
5094 return 0;
5095
5096 ie++;
5097 pos += ret;
5098 }
5099
5100 if (info->tbtt_info_len >= 7) {
5101 ret = os_snprintf(pos, end - pos,
5102 "bssid=" MACSTR ", ",
5103 MAC2STR(ie));
5104 if (os_snprintf_error(end - pos, ret))
5105 return 0;
5106
5107 ie += ETH_ALEN;
5108 pos += ret;
5109 }
5110
5111 if (info->tbtt_info_len >= 11) {
5112 ret = os_snprintf(pos, end - pos,
5113 "short SSID=0x%x, ",
5114 WPA_GET_LE32(ie));
5115 if (os_snprintf_error(end - pos, ret))
5116 return 0;
5117
5118 ie += 4;
5119 pos += ret;
5120 }
5121
5122 if (info->tbtt_info_len >= 12) {
5123 ret = os_snprintf(pos, end - pos,
5124 "bss_params=0x%x, ", *ie);
5125 if (os_snprintf_error(end - pos, ret))
5126 return 0;
5127
5128 ie++;
5129 pos += ret;
5130 }
5131
5132 if (info->tbtt_info_len >= 13) {
5133 ret = os_snprintf(pos, end - pos,
5134 "PSD=0x%x, ", *ie);
5135 if (os_snprintf_error(end - pos, ret))
5136 return 0;
5137
5138 ie++;
5139 pos += ret;
5140 }
5141
5142 if (info->tbtt_info_len >= 16) {
5143 ret = os_snprintf(pos, end - pos,
5144 "mld ID=%u, link ID=%u",
5145 *ie, *(ie + 1) & 0xF);
5146 if (os_snprintf_error(end - pos, ret))
5147 return 0;
5148
5149 ie += 3;
5150 pos += ret;
5151 }
5152
5153 ie = tbtt_start + info->tbtt_info_len;
5154
5155 ret = os_snprintf(pos, end - pos, "\n");
5156 if (os_snprintf_error(end - pos, ret))
5157 return 0;
5158 pos += ret;
5159
5160 n++;
5161 }
5162
5163 return pos - start;
5164}
5165
5166
5167static int print_ml(struct wpa_bss *bss, char *pos, char *end)
5168{
5169 const struct ieee80211_eht_ml *ml;
5170 char *start = pos;
5171 const u8 *ie, *ie_end;
5172 u16 ml_control;
5173 u8 common_info_length;
5174 int ret;
5175
5176 ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len,
5177 MULTI_LINK_CONTROL_TYPE_BASIC);
5178 if (!ie)
5179 return 0;
5180
5181 ie_end = ie + 2 + ie[1];
5182 ie += 3;
5183 ml = (const struct ieee80211_eht_ml *) ie;
5184
5185 /* control + common info length + MLD MAC Address */
5186 if (ie_end - ie < 2 + 1 + ETH_ALEN)
5187 return 0;
5188
5189 ml_control = le_to_host16(ml->ml_control);
5190
5191 common_info_length = *(ie + 2);
5192 ret = os_snprintf(pos, end - pos,
5193 "multi-link: control=0x%x, common info len=%u",
5194 ml_control, common_info_length);
5195 if (os_snprintf_error(end - pos, ret))
5196 return 0;
5197 pos += ret;
5198
5199 ie += 2;
5200 if (ie_end - ie < common_info_length)
5201 return 0;
5202
5203 ie++;
5204 common_info_length--;
5205
5206 if (common_info_length < ETH_ALEN)
5207 return 0;
5208
5209 ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie));
5210 if (os_snprintf_error(end - pos, ret))
5211 return 0;
5212 pos += ret;
5213
5214 ie += ETH_ALEN;
5215 common_info_length -= ETH_ALEN;
5216
5217 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
5218 if (common_info_length < 1)
5219 return 0;
5220
5221 ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f);
5222 if (os_snprintf_error(end - pos, ret))
5223 return 0;
5224 pos += ret;
5225 ie++;
5226 common_info_length--;
5227 }
5228
5229 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
5230 if (common_info_length < 1)
5231 return 0;
5232
5233 ret = os_snprintf(pos, end - pos,
5234 ", BSS change parameters=0x%x", *ie);
5235 if (os_snprintf_error(end - pos, ret))
5236 return 0;
5237 pos += ret;
5238 ie++;
5239 common_info_length--;
5240 }
5241
5242 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
5243 if (common_info_length < 2)
5244 return 0;
5245
5246 ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x",
5247 WPA_GET_LE16(ie));
5248 if (os_snprintf_error(end - pos, ret))
5249 return 0;
5250 pos += ret;
5251 ie += 2;
5252 common_info_length -= 2;
5253 }
5254
5255 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
5256 if (common_info_length < 2)
5257 return 0;
5258
5259 ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x",
5260 WPA_GET_LE16(ie));
5261 if (os_snprintf_error(end - pos, ret))
5262 return 0;
5263 pos += ret;
5264 ie += 2;
5265 common_info_length -= 2;
5266 }
5267
5268 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
5269 if (common_info_length < 2)
5270 return 0;
5271
5272 ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x",
5273 WPA_GET_LE16(ie));
5274 if (os_snprintf_error(end - pos, ret))
5275 return 0;
5276 pos += ret;
5277 ie += 2;
5278 common_info_length -= 2;
5279 }
5280
5281 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
5282 if (common_info_length < 1)
5283 return 0;
5284
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005285 ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005286 if (os_snprintf_error(end - pos, ret))
5287 return 0;
5288 pos += ret;
5289 ie += 1;
5290 common_info_length--;
5291 }
5292
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005293 ret = os_snprintf(pos, end - pos, "\n");
5294 if (os_snprintf_error(end - pos, ret))
5295 return 0;
5296 pos += ret;
5297
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005298 return pos - start;
5299}
5300
5301
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005302static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5303 unsigned long mask, char *buf, size_t buflen)
5304{
5305 size_t i;
5306 int ret;
5307 char *pos, *end;
Hai Shalom899fcc72020-10-19 14:38:18 -07005308 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005309
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005310 pos = buf;
5311 end = buf + buflen;
5312
5313 if (mask & WPA_BSS_MASK_ID) {
5314 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005315 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005316 return 0;
5317 pos += ret;
5318 }
5319
5320 if (mask & WPA_BSS_MASK_BSSID) {
5321 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
5322 MAC2STR(bss->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005323 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005324 return 0;
5325 pos += ret;
5326 }
5327
5328 if (mask & WPA_BSS_MASK_FREQ) {
5329 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005330 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005331 return 0;
5332 pos += ret;
5333 }
5334
5335 if (mask & WPA_BSS_MASK_BEACON_INT) {
5336 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5337 bss->beacon_int);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005338 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005339 return 0;
5340 pos += ret;
5341 }
5342
5343 if (mask & WPA_BSS_MASK_CAPABILITIES) {
5344 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5345 bss->caps);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005346 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005347 return 0;
5348 pos += ret;
5349 }
5350
5351 if (mask & WPA_BSS_MASK_QUAL) {
5352 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005353 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005354 return 0;
5355 pos += ret;
5356 }
5357
5358 if (mask & WPA_BSS_MASK_NOISE) {
5359 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005360 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005361 return 0;
5362 pos += ret;
5363 }
5364
5365 if (mask & WPA_BSS_MASK_LEVEL) {
5366 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005367 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005368 return 0;
5369 pos += ret;
5370 }
5371
5372 if (mask & WPA_BSS_MASK_TSF) {
5373 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5374 (unsigned long long) bss->tsf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005375 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005376 return 0;
5377 pos += ret;
5378 }
5379
5380 if (mask & WPA_BSS_MASK_AGE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005381 struct os_reltime now;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005382
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005383 os_get_reltime(&now);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005384 ret = os_snprintf(pos, end - pos, "age=%d\n",
5385 (int) (now.sec - bss->last_update.sec));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005386 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005387 return 0;
5388 pos += ret;
5389 }
5390
5391 if (mask & WPA_BSS_MASK_IE) {
5392 ret = os_snprintf(pos, end - pos, "ie=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005393 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005394 return 0;
5395 pos += ret;
5396
Hai Shalom60840252021-02-19 19:02:11 -08005397 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005398 for (i = 0; i < bss->ie_len; i++) {
5399 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005400 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005401 return 0;
5402 pos += ret;
5403 }
5404
5405 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005406 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005407 return 0;
5408 pos += ret;
5409 }
5410
5411 if (mask & WPA_BSS_MASK_FLAGS) {
5412 ret = os_snprintf(pos, end - pos, "flags=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005413 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005414 return 0;
5415 pos += ret;
5416
Dmitry Shmidt29333592017-01-09 12:27:11 -08005417 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5418
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005419 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5420 if (ie)
5421 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5422 2 + ie[1]);
5423 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
5424 if (ie2)
Dmitry Shmidt29333592017-01-09 12:27:11 -08005425 pos = wpa_supplicant_ie_txt(pos, end,
5426 mesh ? "RSN" : "WPA2", ie2,
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005427 2 + ie2[1]);
Hai Shalom899fcc72020-10-19 14:38:18 -07005428 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Hai Shaloma20dcd72022-02-04 13:43:00 -08005429 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5430 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5431 if (os_snprintf_error(end - pos, ret))
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005432 return 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005433 pos += ret;
5434 }
5435 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5436 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5437 if (os_snprintf_error(end - pos, ret))
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005438 return 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005439 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07005440 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005441 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5442 if (osen_ie)
5443 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5444 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005445 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5446 if (owe) {
5447 ret = os_snprintf(
5448 pos, end - pos,
5449 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5450 if (os_snprintf_error(end - pos, ret))
5451 return 0;
5452 pos += ret;
5453 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005454 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005455 if (!ie && !ie2 && !osen_ie &&
5456 (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005457 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005458 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005459 return 0;
5460 pos += ret;
5461 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005462
5463 if (mesh) {
5464 ret = os_snprintf(pos, end - pos, "[MESH]");
5465 if (os_snprintf_error(end - pos, ret))
5466 return 0;
5467 pos += ret;
5468 }
5469
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005470 if (bss_is_dmg(bss)) {
5471 const char *s;
5472 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005473 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005474 return 0;
5475 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005476 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5477 case IEEE80211_CAP_DMG_IBSS:
5478 s = "[IBSS]";
5479 break;
5480 case IEEE80211_CAP_DMG_AP:
5481 s = "[ESS]";
5482 break;
5483 case IEEE80211_CAP_DMG_PBSS:
5484 s = "[PBSS]";
5485 break;
5486 default:
5487 s = "";
5488 break;
5489 }
5490 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005491 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005492 return 0;
5493 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005494 } else {
5495 if (bss->caps & IEEE80211_CAP_IBSS) {
5496 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005497 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005498 return 0;
5499 pos += ret;
5500 }
5501 if (bss->caps & IEEE80211_CAP_ESS) {
5502 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005503 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005504 return 0;
5505 pos += ret;
5506 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005507 }
Dmitry Shmidt96571392013-10-14 12:54:46 -07005508 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5509 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005510 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005511 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005512 return 0;
5513 pos += ret;
5514 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005515#ifdef CONFIG_HS20
5516 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5517 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005518 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005519 return 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005520 pos += ret;
5521 }
5522#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005523#ifdef CONFIG_FILS
5524 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5525 ret = os_snprintf(pos, end - pos, "[FILS]");
5526 if (os_snprintf_error(end - pos, ret))
5527 return 0;
5528 pos += ret;
5529 }
5530#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08005531#ifdef CONFIG_FST
5532 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5533 ret = os_snprintf(pos, end - pos, "[FST]");
5534 if (os_snprintf_error(end - pos, ret))
5535 return 0;
5536 pos += ret;
5537 }
5538#endif /* CONFIG_FST */
5539 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5540 ret = os_snprintf(pos, end - pos, "[UTF-8]");
5541 if (os_snprintf_error(end - pos, ret))
5542 return 0;
5543 pos += ret;
5544 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005545
5546 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005547 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005548 return 0;
5549 pos += ret;
5550 }
5551
5552 if (mask & WPA_BSS_MASK_SSID) {
5553 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5554 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005555 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005556 return 0;
5557 pos += ret;
5558 }
5559
5560#ifdef CONFIG_WPS
5561 if (mask & WPA_BSS_MASK_WPS_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005562 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005563 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005564 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005565 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005566 if (ret > 0)
5567 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005568 }
5569#endif /* CONFIG_WPS */
5570
5571#ifdef CONFIG_P2P
5572 if (mask & WPA_BSS_MASK_P2P_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005573 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005574 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005575 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005576 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005577 if (ret > 0)
5578 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005579 }
5580#endif /* CONFIG_P2P */
5581
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005582#ifdef CONFIG_WIFI_DISPLAY
5583 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5584 struct wpabuf *wfd;
Hai Shalom60840252021-02-19 19:02:11 -08005585
5586 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005587 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5588 WFD_IE_VENDOR_TYPE);
5589 if (wfd) {
5590 ret = os_snprintf(pos, end - pos, "wfd_subelems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005591 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005592 wpabuf_free(wfd);
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005593 return 0;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005594 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005595 pos += ret;
5596
5597 pos += wpa_snprintf_hex(pos, end - pos,
5598 wpabuf_head(wfd),
5599 wpabuf_len(wfd));
5600 wpabuf_free(wfd);
5601
5602 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005603 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005604 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005605 pos += ret;
5606 }
5607 }
5608#endif /* CONFIG_WIFI_DISPLAY */
5609
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005610#ifdef CONFIG_INTERWORKING
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005611 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5612 struct wpa_bss_anqp *anqp = bss->anqp;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005613 struct wpa_bss_anqp_elem *elem;
5614
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005615 pos = anqp_add_hex(pos, end, "anqp_capability_list",
5616 anqp->capability_list);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005617 pos = anqp_add_hex(pos, end, "anqp_venue_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005618 anqp->venue_name);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005619 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005620 anqp->network_auth_type);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005621 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005622 anqp->roaming_consortium);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005623 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005624 anqp->ip_addr_type_availability);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005625 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005626 anqp->nai_realm);
5627 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005628 pos = anqp_add_hex(pos, end, "anqp_domain_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005629 anqp->domain_name);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005630 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5631 anqp->fils_realm_info);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005632#ifdef CONFIG_HS20
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005633 pos = anqp_add_hex(pos, end, "hs20_capability_list",
5634 anqp->hs20_capability_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005635 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005636 anqp->hs20_operator_friendly_name);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005637 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005638 anqp->hs20_wan_metrics);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005639 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005640 anqp->hs20_connection_capability);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005641 pos = anqp_add_hex(pos, end, "hs20_operating_class",
5642 anqp->hs20_operating_class);
5643 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5644 anqp->hs20_osu_providers_list);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005645 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5646 anqp->hs20_operator_icon_metadata);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005647 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5648 anqp->hs20_osu_providers_nai_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005649#endif /* CONFIG_HS20 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005650
5651 dl_list_for_each(elem, &anqp->anqp_elems,
5652 struct wpa_bss_anqp_elem, list) {
5653 char title[20];
5654
5655 os_snprintf(title, sizeof(title), "anqp[%u]",
5656 elem->infoid);
5657 pos = anqp_add_hex(pos, end, title, elem->payload);
Hai Shalom60840252021-02-19 19:02:11 -08005658 if (elem->protected_response) {
5659 ret = os_snprintf(pos, end - pos,
5660 "protected-anqp-info[%u]=1\n",
5661 elem->infoid);
5662 if (os_snprintf_error(end - pos, ret))
5663 return 0;
5664 pos += ret;
5665 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005666 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005667 }
5668#endif /* CONFIG_INTERWORKING */
5669
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005670#ifdef CONFIG_MESH
5671 if (mask & WPA_BSS_MASK_MESH_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005672 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005673 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005674 if (ret >= end - pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005675 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005676 if (ret > 0)
5677 pos += ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005678 }
5679#endif /* CONFIG_MESH */
5680
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005681 if (mask & WPA_BSS_MASK_SNR) {
5682 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5683 if (os_snprintf_error(end - pos, ret))
5684 return 0;
5685 pos += ret;
5686 }
5687
5688 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5689 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5690 bss->est_throughput);
5691 if (os_snprintf_error(end - pos, ret))
5692 return 0;
5693 pos += ret;
5694 }
5695
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005696#ifdef CONFIG_FST
5697 if (mask & WPA_BSS_MASK_FST) {
5698 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5699 if (ret < 0 || ret >= end - pos)
5700 return 0;
5701 pos += ret;
5702 }
5703#endif /* CONFIG_FST */
5704
Dmitry Shmidt29333592017-01-09 12:27:11 -08005705 if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5706 ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5707 bss->last_update_idx);
5708 if (os_snprintf_error(end - pos, ret))
5709 return 0;
5710 pos += ret;
5711 }
5712
5713 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5714 ret = os_snprintf(pos, end - pos, "beacon_ie=");
5715 if (os_snprintf_error(end - pos, ret))
5716 return 0;
5717 pos += ret;
5718
Hai Shalom60840252021-02-19 19:02:11 -08005719 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005720 ie += bss->ie_len;
5721 for (i = 0; i < bss->beacon_ie_len; i++) {
5722 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5723 if (os_snprintf_error(end - pos, ret))
5724 return 0;
5725 pos += ret;
5726 }
5727
5728 ret = os_snprintf(pos, end - pos, "\n");
5729 if (os_snprintf_error(end - pos, ret))
5730 return 0;
5731 pos += ret;
5732 }
5733
5734#ifdef CONFIG_FILS
5735 if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5736 ret = print_fils_indication(bss, pos, end);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005737 pos += ret;
5738 }
5739#endif /* CONFIG_FILS */
5740
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005741 if (!is_zero_ether_addr(bss->mld_addr) &&
5742 (mask & WPA_BSS_MASK_AP_MLD_ADDR)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07005743 ret = os_snprintf(pos, end - pos,
5744 "ap_mld_addr=" MACSTR "\n",
5745 MAC2STR(bss->mld_addr));
5746 if (os_snprintf_error(end - pos, ret))
5747 return 0;
5748 pos += ret;
5749 }
5750
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005751 if (mask & WPA_BSS_MASK_RNR)
5752 pos += print_rnr(bss, pos, end);
5753
5754 if (mask & WPA_BSS_MASK_ML)
5755 pos += print_ml(bss, pos, end);
5756
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005757 if (mask & WPA_BSS_MASK_DELIM) {
5758 ret = os_snprintf(pos, end - pos, "====\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005759 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005760 return 0;
5761 pos += ret;
5762 }
Irfan Sheriffe2ea0082012-08-13 10:56:16 -07005763
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005764 return pos - buf;
5765}
5766
Dmitry Shmidt04949592012-07-19 12:16:46 -07005767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005768static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5769 const char *cmd, char *buf,
5770 size_t buflen)
5771{
5772 u8 bssid[ETH_ALEN];
5773 size_t i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005774 struct wpa_bss *bss;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005775 struct wpa_bss *bsslast = NULL;
5776 struct dl_list *next;
5777 int ret = 0;
5778 int len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005779 char *ctmp, *end = buf + buflen;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005780 unsigned long mask = WPA_BSS_MASK_ALL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005781
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005782 if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5783 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5784 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005785 list_id);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005786 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5787 list_id);
5788 } else { /* N1-N2 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005789 unsigned int id1, id2;
5790
5791 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5792 wpa_printf(MSG_INFO, "Wrong BSS range "
5793 "format");
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005794 return 0;
5795 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005796
Dmitry Shmidtf8623282013-02-20 14:34:59 -08005797 if (*(cmd + 6) == '-')
5798 id1 = 0;
5799 else
5800 id1 = atoi(cmd + 6);
5801 ctmp++;
5802 if (*ctmp >= '0' && *ctmp <= '9')
5803 id2 = atoi(ctmp);
5804 else
5805 id2 = (unsigned int) -1;
5806 bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5807 if (id2 == (unsigned int) -1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005808 bsslast = dl_list_last(&wpa_s->bss_id,
5809 struct wpa_bss,
5810 list_id);
5811 else {
5812 bsslast = wpa_bss_get_id(wpa_s, id2);
5813 if (bsslast == NULL && bss && id2 > id1) {
5814 struct wpa_bss *tmp = bss;
5815 for (;;) {
5816 next = tmp->list_id.next;
5817 if (next == &wpa_s->bss_id)
5818 break;
5819 tmp = dl_list_entry(
5820 next, struct wpa_bss,
5821 list_id);
5822 if (tmp->id > id2)
5823 break;
5824 bsslast = tmp;
5825 }
5826 }
5827 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005828 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005829 } else if (os_strncmp(cmd, "FIRST", 5) == 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005830 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005831 else if (os_strncmp(cmd, "LAST", 4) == 0)
5832 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833 else if (os_strncmp(cmd, "ID-", 3) == 0) {
5834 i = atoi(cmd + 3);
5835 bss = wpa_bss_get_id(wpa_s, i);
5836 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5837 i = atoi(cmd + 5);
5838 bss = wpa_bss_get_id(wpa_s, i);
5839 if (bss) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005840 next = bss->list_id.next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005841 if (next == &wpa_s->bss_id)
5842 bss = NULL;
5843 else
5844 bss = dl_list_entry(next, struct wpa_bss,
5845 list_id);
5846 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005847 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5848 bss = wpa_s->current_bss;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005849#ifdef CONFIG_P2P
5850 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5851 if (hwaddr_aton(cmd + 13, bssid) == 0)
5852 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5853 else
5854 bss = NULL;
5855#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856 } else if (hwaddr_aton(cmd, bssid) == 0)
5857 bss = wpa_bss_get_bssid(wpa_s, bssid);
5858 else {
5859 struct wpa_bss *tmp;
5860 i = atoi(cmd);
5861 bss = NULL;
5862 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5863 {
Hai Shalom021b0b52019-04-10 11:17:58 -07005864 if (i == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005865 bss = tmp;
5866 break;
5867 }
Hai Shalom021b0b52019-04-10 11:17:58 -07005868 i--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005869 }
5870 }
5871
Dmitry Shmidt04949592012-07-19 12:16:46 -07005872 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5873 mask = strtoul(ctmp + 5, NULL, 0x10);
5874 if (mask == 0)
5875 mask = WPA_BSS_MASK_ALL;
5876 }
5877
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005878 if (bss == NULL)
5879 return 0;
5880
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005881 if (bsslast == NULL)
5882 bsslast = bss;
5883 do {
5884 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5885 ret += len;
5886 buf += len;
5887 buflen -= len;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005888 if (bss == bsslast) {
5889 if ((mask & WPA_BSS_MASK_DELIM) && len &&
5890 (bss == dl_list_last(&wpa_s->bss_id,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005891 struct wpa_bss, list_id))) {
5892 int res;
5893
5894 res = os_snprintf(buf - 5, end - buf + 5,
5895 "####\n");
5896 if (os_snprintf_error(end - buf + 5, res)) {
5897 wpa_printf(MSG_DEBUG,
5898 "Could not add end delim");
5899 }
5900 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005901 break;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005902 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005903 next = bss->list_id.next;
5904 if (next == &wpa_s->bss_id)
5905 break;
5906 bss = dl_list_entry(next, struct wpa_bss, list_id);
5907 } while (bss && len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005909 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005910}
5911
5912
5913static int wpa_supplicant_ctrl_iface_ap_scan(
5914 struct wpa_supplicant *wpa_s, char *cmd)
5915{
5916 int ap_scan = atoi(cmd);
5917 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5918}
5919
5920
5921static int wpa_supplicant_ctrl_iface_scan_interval(
5922 struct wpa_supplicant *wpa_s, char *cmd)
5923{
5924 int scan_int = atoi(cmd);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005925 return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005926}
5927
5928
5929static int wpa_supplicant_ctrl_iface_bss_expire_age(
5930 struct wpa_supplicant *wpa_s, char *cmd)
5931{
5932 int expire_age = atoi(cmd);
5933 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5934}
5935
5936
5937static int wpa_supplicant_ctrl_iface_bss_expire_count(
5938 struct wpa_supplicant *wpa_s, char *cmd)
5939{
5940 int expire_count = atoi(cmd);
5941 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5942}
5943
5944
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005945static void wpa_supplicant_ctrl_iface_bss_flush(
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005946 struct wpa_supplicant *wpa_s, char *cmd)
5947{
5948 int flush_age = atoi(cmd);
5949
5950 if (flush_age == 0)
5951 wpa_bss_flush(wpa_s);
5952 else
5953 wpa_bss_flush_by_age(wpa_s, flush_age);
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005954}
5955
5956
Dmitry Shmidt21de2142014-04-08 10:50:52 -07005957#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005958static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5959{
5960 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5961 /* MLME-DELETEKEYS.request */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005962 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005963 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005964 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005965 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005966 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005967 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005968 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005969 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005970 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005971 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005972 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005973 0, KEY_FLAG_GROUP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005974
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005975 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0,
5976 NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -07005977 if (wpa_sm_ext_key_id(wpa_s->wpa))
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005978 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07005979 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005980 /* MLME-SETPROTECTION.request(None) */
5981 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
5982 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
5983 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5984 wpa_sm_drop_sa(wpa_s->wpa);
5985}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07005986#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005987
5988
5989static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
5990 char *addr)
5991{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005992#ifdef CONFIG_NO_SCAN_PROCESSING
5993 return -1;
5994#else /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005995 u8 bssid[ETH_ALEN];
5996 struct wpa_bss *bss;
5997 struct wpa_ssid *ssid = wpa_s->current_ssid;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005998 struct wpa_radio_work *already_connecting;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005999
6000 if (hwaddr_aton(addr, bssid)) {
6001 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
6002 "address '%s'", addr);
6003 return -1;
6004 }
6005
6006 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
6007
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006008 if (!ssid) {
6009 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
6010 "configuration known for the target AP");
6011 return -1;
6012 }
6013
6014 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006015 if (!bss) {
6016 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
6017 "from BSS table");
6018 return -1;
6019 }
6020
6021 /*
6022 * TODO: Find best network configuration block from configuration to
6023 * allow roaming to other networks
6024 */
6025
Hai Shaloma20dcd72022-02-04 13:43:00 -08006026 already_connecting = radio_work_pending(wpa_s, "sme-connect");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006027 wpa_s->reassociate = 1;
6028 wpa_supplicant_connect(wpa_s, bss, ssid);
6029
Hai Shaloma20dcd72022-02-04 13:43:00 -08006030 /*
6031 * Indicate that an explicitly requested roam is in progress so scan
6032 * results that come in before the 'sme-connect' radio work gets
6033 * executed do not override the original connection attempt.
6034 */
6035 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
6036 wpa_s->roam_in_progress = true;
6037
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006038 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006039#endif /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006040}
6041
6042
6043#ifdef CONFIG_P2P
6044static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
6045{
6046 unsigned int timeout = atoi(cmd);
6047 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006048 u8 dev_id[ETH_ALEN], *_dev_id = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006049 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006050 char *pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006051 unsigned int search_delay;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006052 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006053 u8 seek_count = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006054 int freq = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006055 bool include_6ghz = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006056
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006057 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6058 wpa_dbg(wpa_s, MSG_INFO,
6059 "Reject P2P_FIND since interface is disabled");
6060 return -1;
6061 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08006062
6063 if (os_strstr(cmd, " include_6ghz"))
6064 include_6ghz = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006065 if (os_strstr(cmd, "type=social"))
6066 type = P2P_FIND_ONLY_SOCIAL;
6067 else if (os_strstr(cmd, "type=progressive"))
6068 type = P2P_FIND_PROGRESSIVE;
6069
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006070 pos = os_strstr(cmd, "dev_id=");
6071 if (pos) {
6072 pos += 7;
6073 if (hwaddr_aton(pos, dev_id))
6074 return -1;
6075 _dev_id = dev_id;
6076 }
6077
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006078 pos = os_strstr(cmd, "dev_type=");
6079 if (pos) {
6080 pos += 9;
6081 if (wps_dev_type_str2bin(pos, dev_type) < 0)
6082 return -1;
6083 _dev_type = dev_type;
6084 }
6085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006086 pos = os_strstr(cmd, "delay=");
6087 if (pos) {
6088 pos += 6;
6089 search_delay = atoi(pos);
6090 } else
6091 search_delay = wpas_p2p_search_delay(wpa_s);
6092
Dmitry Shmidt41712582015-06-29 11:02:15 -07006093 pos = os_strstr(cmd, "freq=");
6094 if (pos) {
6095 pos += 5;
6096 freq = atoi(pos);
6097 if (freq <= 0)
6098 return -1;
6099 }
6100
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006101 /* Must be searched for last, because it adds nul termination */
6102 pos = os_strstr(cmd, " seek=");
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006103 if (pos)
6104 pos += 6;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006105 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
6106 char *term;
6107
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006108 _seek[seek_count++] = pos;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006109 seek = _seek;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006110 term = os_strchr(pos, ' ');
6111 if (!term)
6112 break;
6113 *term = '\0';
6114 pos = os_strstr(term + 1, "seek=");
6115 if (pos)
6116 pos += 5;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006117 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006118 if (seek_count > P2P_MAX_QUERY_HASH) {
6119 seek[0] = NULL;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006120 seek_count = 1;
6121 }
6122
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006123 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006124 _dev_id, search_delay, seek_count, seek, freq,
6125 include_6ghz);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006126}
6127
6128
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006129static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
6130{
6131 const char *last = NULL;
6132 const char *token;
6133 long int token_len;
6134 unsigned int i;
6135
6136 /* Expected predefined CPT names delimited by ':' */
6137 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
6138 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
6139 wpa_printf(MSG_ERROR,
6140 "P2PS: CPT name list is too long, expected up to %d names",
6141 P2PS_FEATURE_CAPAB_CPT_MAX);
6142 cpt[0] = 0;
6143 return -1;
6144 }
6145
6146 token_len = last - token;
6147
6148 if (token_len == 3 &&
6149 os_memcmp(token, "UDP", token_len) == 0) {
6150 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6151 } else if (token_len == 3 &&
6152 os_memcmp(token, "MAC", token_len) == 0) {
6153 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
6154 } else {
6155 wpa_printf(MSG_ERROR,
6156 "P2PS: Unsupported CPT name '%s'", token);
6157 cpt[0] = 0;
6158 return -1;
6159 }
6160
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006161 if (isblank((unsigned char) *last)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006162 i++;
6163 break;
6164 }
6165 }
6166 cpt[i] = 0;
6167 return 0;
6168}
6169
6170
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006171static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
6172{
6173 struct p2ps_provision *p2ps_prov;
6174 char *pos;
6175 size_t info_len = 0;
6176 char *info = NULL;
6177 u8 role = P2PS_SETUP_NONE;
6178 long long unsigned val;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006179 int i;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006180
6181 pos = os_strstr(cmd, "info=");
6182 if (pos) {
6183 pos += 5;
6184 info_len = os_strlen(pos);
6185
6186 if (info_len) {
6187 info = os_malloc(info_len + 1);
6188 if (info) {
6189 info_len = utf8_unescape(pos, info_len,
6190 info, info_len + 1);
6191 } else
6192 info_len = 0;
6193 }
6194 }
6195
6196 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
6197 if (p2ps_prov == NULL) {
6198 os_free(info);
6199 return NULL;
6200 }
6201
6202 if (info) {
6203 os_memcpy(p2ps_prov->info, info, info_len);
6204 p2ps_prov->info[info_len] = '\0';
6205 os_free(info);
6206 }
6207
6208 pos = os_strstr(cmd, "status=");
6209 if (pos)
6210 p2ps_prov->status = atoi(pos + 7);
6211 else
6212 p2ps_prov->status = -1;
6213
6214 pos = os_strstr(cmd, "adv_id=");
6215 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
6216 goto invalid_args;
6217 p2ps_prov->adv_id = val;
6218
6219 pos = os_strstr(cmd, "method=");
6220 if (pos)
6221 p2ps_prov->method = strtol(pos + 7, NULL, 16);
6222 else
6223 p2ps_prov->method = 0;
6224
6225 pos = os_strstr(cmd, "session=");
6226 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
6227 goto invalid_args;
6228 p2ps_prov->session_id = val;
6229
6230 pos = os_strstr(cmd, "adv_mac=");
6231 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
6232 goto invalid_args;
6233
6234 pos = os_strstr(cmd, "session_mac=");
6235 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
6236 goto invalid_args;
6237
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006238 pos = os_strstr(cmd, "cpt=");
6239 if (pos) {
6240 if (p2ps_ctrl_parse_cpt_priority(pos + 4,
6241 p2ps_prov->cpt_priority))
6242 goto invalid_args;
6243 } else {
6244 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6245 }
6246
6247 for (i = 0; p2ps_prov->cpt_priority[i]; i++)
6248 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
6249
Hai Shaloma20dcd72022-02-04 13:43:00 -08006250 /* force conncap with tstCap (no validity checks) */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006251 pos = os_strstr(cmd, "tstCap=");
6252 if (pos) {
6253 role = strtol(pos + 7, NULL, 16);
6254 } else {
6255 pos = os_strstr(cmd, "role=");
6256 if (pos) {
6257 role = strtol(pos + 5, NULL, 16);
6258 if (role != P2PS_SETUP_CLIENT &&
6259 role != P2PS_SETUP_GROUP_OWNER)
6260 role = P2PS_SETUP_NONE;
6261 }
6262 }
6263 p2ps_prov->role = role;
6264
6265 return p2ps_prov;
6266
6267invalid_args:
6268 os_free(p2ps_prov);
6269 return NULL;
6270}
6271
6272
6273static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
6274{
6275 u8 addr[ETH_ALEN];
6276 struct p2ps_provision *p2ps_prov;
6277 char *pos;
6278
6279 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
6280
6281 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6282
6283 if (hwaddr_aton(cmd, addr))
6284 return -1;
6285
6286 pos = cmd + 17;
6287 if (*pos != ' ')
6288 return -1;
6289
6290 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6291 if (!p2ps_prov)
6292 return -1;
6293
6294 if (p2ps_prov->status < 0) {
6295 os_free(p2ps_prov);
6296 return -1;
6297 }
6298
6299 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6300 p2ps_prov);
6301}
6302
6303
6304static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
6305{
6306 u8 addr[ETH_ALEN];
6307 struct p2ps_provision *p2ps_prov;
6308 char *pos;
6309
6310 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
6311 * session=<ses_id> mac=<ses_mac> [info=<infodata>]
6312 */
6313
6314 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6315 if (hwaddr_aton(cmd, addr))
6316 return -1;
6317
6318 pos = cmd + 17;
6319 if (*pos != ' ')
6320 return -1;
6321
6322 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6323 if (!p2ps_prov)
6324 return -1;
6325
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006326 p2ps_prov->pd_seeker = 1;
6327
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006328 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6329 p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006330}
6331
6332
6333static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6334 char *buf, size_t buflen)
6335{
6336 u8 addr[ETH_ALEN];
6337 char *pos, *pos2;
6338 char *pin = NULL;
6339 enum p2p_wps_method wps_method;
6340 int new_pin;
6341 int ret;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006342 int persistent_group, persistent_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006343 int join;
6344 int auth;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006345 int automatic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346 int go_intent = -1;
6347 int freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006348 int pd;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006349 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006350 int edmg;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006351 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6352 size_t group_ssid_len = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08006353 int he;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006354 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006355
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006356 if (!wpa_s->global->p2p_init_wpa_s)
6357 return -1;
6358 if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6359 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6360 wpa_s->global->p2p_init_wpa_s->ifname);
6361 wpa_s = wpa_s->global->p2p_init_wpa_s;
6362 }
6363
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006364 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
Dmitry Shmidt04949592012-07-19 12:16:46 -07006365 * [persistent|persistent=<network id>]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006366 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006367 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006368
6369 if (hwaddr_aton(cmd, addr))
6370 return -1;
6371
6372 pos = cmd + 17;
6373 if (*pos != ' ')
6374 return -1;
6375 pos++;
6376
6377 persistent_group = os_strstr(pos, " persistent") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006378 pos2 = os_strstr(pos, " persistent=");
6379 if (pos2) {
6380 struct wpa_ssid *ssid;
6381 persistent_id = atoi(pos2 + 12);
6382 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6383 if (ssid == NULL || ssid->disabled != 2 ||
6384 ssid->mode != WPAS_MODE_P2P_GO) {
6385 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6386 "SSID id=%d for persistent P2P group (GO)",
6387 persistent_id);
6388 return -1;
6389 }
6390 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006391 join = os_strstr(pos, " join") != NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006392 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006393 auth = os_strstr(pos, " auth") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006394 automatic = os_strstr(pos, " auto") != NULL;
6395 pd = os_strstr(pos, " provdisc") != NULL;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006396 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6397 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6398 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006399 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006400 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006401
6402 pos2 = os_strstr(pos, " go_intent=");
6403 if (pos2) {
6404 pos2 += 11;
6405 go_intent = atoi(pos2);
6406 if (go_intent < 0 || go_intent > 15)
6407 return -1;
6408 }
6409
6410 pos2 = os_strstr(pos, " freq=");
6411 if (pos2) {
6412 pos2 += 6;
6413 freq = atoi(pos2);
6414 if (freq <= 0)
6415 return -1;
6416 }
6417
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006418 pos2 = os_strstr(pos, " freq2=");
6419 if (pos2)
6420 freq2 = atoi(pos2 + 7);
6421
6422 pos2 = os_strstr(pos, " max_oper_chwidth=");
6423 if (pos2)
6424 chwidth = atoi(pos2 + 18);
6425
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006426 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006427 if (max_oper_chwidth < 0)
6428 return -1;
6429
Hai Shaloma20dcd72022-02-04 13:43:00 -08006430 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00006431 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006432
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006433 pos2 = os_strstr(pos, " ssid=");
6434 if (pos2) {
6435 char *end;
6436
6437 pos2 += 6;
6438 end = os_strchr(pos2, ' ');
6439 if (!end)
6440 group_ssid_len = os_strlen(pos2) / 2;
6441 else
6442 group_ssid_len = (end - pos2) / 2;
6443 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6444 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6445 return -1;
6446 group_ssid = _group_ssid;
6447 }
6448
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006449 if (os_strncmp(pos, "pin", 3) == 0) {
6450 /* Request random PIN (to be displayed) and enable the PIN */
6451 wps_method = WPS_PIN_DISPLAY;
6452 } else if (os_strncmp(pos, "pbc", 3) == 0) {
6453 wps_method = WPS_PBC;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006454 } else if (os_strstr(pos, "p2ps") != NULL) {
6455 wps_method = WPS_P2PS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006456 } else {
6457 pin = pos;
6458 pos = os_strchr(pin, ' ');
6459 wps_method = WPS_PIN_KEYPAD;
6460 if (pos) {
6461 *pos++ = '\0';
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006462 if (os_strncmp(pos, "display", 7) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006463 wps_method = WPS_PIN_DISPLAY;
6464 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006465 if (!wps_pin_str_valid(pin)) {
6466 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6467 return 17;
6468 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006469 }
6470
6471 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
Dmitry Shmidt04949592012-07-19 12:16:46 -07006472 persistent_group, automatic, join,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006473 auth, go_intent, freq, freq2, persistent_id,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006474 pd, ht40, vht, max_oper_chwidth, he, edmg,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006475 group_ssid, group_ssid_len, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006476 if (new_pin == -2) {
6477 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6478 return 25;
6479 }
6480 if (new_pin == -3) {
6481 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6482 return 25;
6483 }
6484 if (new_pin < 0)
6485 return -1;
6486 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6487 ret = os_snprintf(buf, buflen, "%08d", new_pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006488 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006489 return -1;
6490 return ret;
6491 }
6492
6493 os_memcpy(buf, "OK\n", 3);
6494 return 3;
6495}
6496
6497
6498static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6499{
6500 unsigned int timeout = atoi(cmd);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006501 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6502 wpa_dbg(wpa_s, MSG_INFO,
6503 "Reject P2P_LISTEN since interface is disabled");
6504 return -1;
6505 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006506 return wpas_p2p_listen(wpa_s, timeout);
6507}
6508
6509
6510static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6511{
6512 u8 addr[ETH_ALEN];
6513 char *pos;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006514 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006515
Dmitry Shmidt04949592012-07-19 12:16:46 -07006516 /* <addr> <config method> [join|auto] */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006517
6518 if (hwaddr_aton(cmd, addr))
6519 return -1;
6520
6521 pos = cmd + 17;
6522 if (*pos != ' ')
6523 return -1;
6524 pos++;
6525
Dmitry Shmidt04949592012-07-19 12:16:46 -07006526 if (os_strstr(pos, " join") != NULL)
6527 use = WPAS_P2P_PD_FOR_JOIN;
6528 else if (os_strstr(pos, " auto") != NULL)
6529 use = WPAS_P2P_PD_AUTO;
6530
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006531 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006532}
6533
6534
6535static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6536 size_t buflen)
6537{
6538 struct wpa_ssid *ssid = wpa_s->current_ssid;
6539
6540 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6541 ssid->passphrase == NULL)
6542 return -1;
6543
6544 os_strlcpy(buf, ssid->passphrase, buflen);
6545 return os_strlen(buf);
6546}
6547
6548
6549static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6550 char *buf, size_t buflen)
6551{
6552 u64 ref;
6553 int res;
6554 u8 dst_buf[ETH_ALEN], *dst;
6555 struct wpabuf *tlvs;
6556 char *pos;
6557 size_t len;
6558
6559 if (hwaddr_aton(cmd, dst_buf))
6560 return -1;
6561 dst = dst_buf;
6562 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6563 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6564 dst = NULL;
6565 pos = cmd + 17;
6566 if (*pos != ' ')
6567 return -1;
6568 pos++;
6569
6570 if (os_strncmp(pos, "upnp ", 5) == 0) {
6571 u8 version;
6572 pos += 5;
6573 if (hexstr2bin(pos, &version, 1) < 0)
6574 return -1;
6575 pos += 2;
6576 if (*pos != ' ')
6577 return -1;
6578 pos++;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006579 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006580#ifdef CONFIG_WIFI_DISPLAY
6581 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6582 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6583#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006584 } else if (os_strncmp(pos, "asp ", 4) == 0) {
6585 char *svc_str;
6586 char *svc_info = NULL;
6587 u32 id;
6588
6589 pos += 4;
6590 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6591 return -1;
6592
6593 pos = os_strchr(pos, ' ');
6594 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6595 return -1;
6596
6597 svc_str = pos + 1;
6598
6599 pos = os_strchr(svc_str, ' ');
6600
6601 if (pos)
6602 *pos++ = '\0';
6603
6604 /* All remaining data is the svc_info string */
6605 if (pos && pos[0] && pos[0] != ' ') {
6606 len = os_strlen(pos);
6607
6608 /* Unescape in place */
6609 len = utf8_unescape(pos, len, pos, len);
6610 if (len > 0xff)
6611 return -1;
6612
6613 svc_info = pos;
6614 }
6615
6616 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6617 svc_str, svc_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006618 } else {
6619 len = os_strlen(pos);
6620 if (len & 1)
6621 return -1;
6622 len /= 2;
6623 tlvs = wpabuf_alloc(len);
6624 if (tlvs == NULL)
6625 return -1;
6626 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6627 wpabuf_free(tlvs);
6628 return -1;
6629 }
6630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006631 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006632 wpabuf_free(tlvs);
6633 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006634 if (ref == 0)
6635 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006636 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006637 if (os_snprintf_error(buflen, res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006638 return -1;
6639 return res;
6640}
6641
6642
6643static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6644 char *cmd)
6645{
6646 long long unsigned val;
6647 u64 req;
6648 if (sscanf(cmd, "%llx", &val) != 1)
6649 return -1;
6650 req = val;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006651 return wpas_p2p_sd_cancel_request(wpa_s, req);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006652}
6653
6654
6655static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6656{
6657 int freq;
6658 u8 dst[ETH_ALEN];
6659 u8 dialog_token;
6660 struct wpabuf *resp_tlvs;
6661 char *pos, *pos2;
6662 size_t len;
6663
6664 pos = os_strchr(cmd, ' ');
6665 if (pos == NULL)
6666 return -1;
6667 *pos++ = '\0';
6668 freq = atoi(cmd);
6669 if (freq == 0)
6670 return -1;
6671
6672 if (hwaddr_aton(pos, dst))
6673 return -1;
6674 pos += 17;
6675 if (*pos != ' ')
6676 return -1;
6677 pos++;
6678
6679 pos2 = os_strchr(pos, ' ');
6680 if (pos2 == NULL)
6681 return -1;
6682 *pos2++ = '\0';
6683 dialog_token = atoi(pos);
6684
6685 len = os_strlen(pos2);
6686 if (len & 1)
6687 return -1;
6688 len /= 2;
6689 resp_tlvs = wpabuf_alloc(len);
6690 if (resp_tlvs == NULL)
6691 return -1;
6692 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6693 wpabuf_free(resp_tlvs);
6694 return -1;
6695 }
6696
6697 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6698 wpabuf_free(resp_tlvs);
6699 return 0;
6700}
6701
6702
6703static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6704 char *cmd)
6705{
Dmitry Shmidt04949592012-07-19 12:16:46 -07006706 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6707 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006708 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6709 return 0;
6710}
6711
6712
6713static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6714 char *cmd)
6715{
6716 char *pos;
6717 size_t len;
6718 struct wpabuf *query, *resp;
6719
6720 pos = os_strchr(cmd, ' ');
6721 if (pos == NULL)
6722 return -1;
6723 *pos++ = '\0';
6724
6725 len = os_strlen(cmd);
6726 if (len & 1)
6727 return -1;
6728 len /= 2;
6729 query = wpabuf_alloc(len);
6730 if (query == NULL)
6731 return -1;
6732 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6733 wpabuf_free(query);
6734 return -1;
6735 }
6736
6737 len = os_strlen(pos);
6738 if (len & 1) {
6739 wpabuf_free(query);
6740 return -1;
6741 }
6742 len /= 2;
6743 resp = wpabuf_alloc(len);
6744 if (resp == NULL) {
6745 wpabuf_free(query);
6746 return -1;
6747 }
6748 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
6749 wpabuf_free(query);
6750 wpabuf_free(resp);
6751 return -1;
6752 }
6753
6754 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
6755 wpabuf_free(query);
6756 wpabuf_free(resp);
6757 return -1;
6758 }
6759 return 0;
6760}
6761
6762
6763static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6764{
6765 char *pos;
6766 u8 version;
6767
6768 pos = os_strchr(cmd, ' ');
6769 if (pos == NULL)
6770 return -1;
6771 *pos++ = '\0';
6772
6773 if (hexstr2bin(cmd, &version, 1) < 0)
6774 return -1;
6775
6776 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6777}
6778
6779
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006780static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6781 u8 replace, char *cmd)
6782{
6783 char *pos;
6784 char *adv_str;
6785 u32 auto_accept, adv_id, svc_state, config_methods;
6786 char *svc_info = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006787 char *cpt_prio_str;
6788 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006789
6790 pos = os_strchr(cmd, ' ');
6791 if (pos == NULL)
6792 return -1;
6793 *pos++ = '\0';
6794
6795 /* Auto-Accept value is mandatory, and must be one of the
6796 * single values (0, 1, 2, 4) */
6797 auto_accept = atoi(cmd);
6798 switch (auto_accept) {
6799 case P2PS_SETUP_NONE: /* No auto-accept */
6800 case P2PS_SETUP_NEW:
6801 case P2PS_SETUP_CLIENT:
6802 case P2PS_SETUP_GROUP_OWNER:
6803 break;
6804 default:
6805 return -1;
6806 }
6807
6808 /* Advertisement ID is mandatory */
6809 cmd = pos;
6810 pos = os_strchr(cmd, ' ');
6811 if (pos == NULL)
6812 return -1;
6813 *pos++ = '\0';
6814
6815 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6816 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6817 return -1;
6818
6819 /* Only allow replacements if exist, and adds if not */
6820 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6821 if (!replace)
6822 return -1;
6823 } else {
6824 if (replace)
6825 return -1;
6826 }
6827
6828 /* svc_state between 0 - 0xff is mandatory */
6829 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6830 return -1;
6831
6832 pos = os_strchr(pos, ' ');
6833 if (pos == NULL)
6834 return -1;
6835
6836 /* config_methods is mandatory */
6837 pos++;
6838 if (sscanf(pos, "%x", &config_methods) != 1)
6839 return -1;
6840
6841 if (!(config_methods &
6842 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6843 return -1;
6844
6845 pos = os_strchr(pos, ' ');
6846 if (pos == NULL)
6847 return -1;
6848
6849 pos++;
6850 adv_str = pos;
6851
6852 /* Advertisement string is mandatory */
6853 if (!pos[0] || pos[0] == ' ')
6854 return -1;
6855
6856 /* Terminate svc string */
6857 pos = os_strchr(pos, ' ');
6858 if (pos != NULL)
6859 *pos++ = '\0';
6860
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006861 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6862 if (cpt_prio_str) {
6863 pos = os_strchr(pos, ' ');
6864 if (pos != NULL)
6865 *pos++ = '\0';
6866
6867 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6868 return -1;
6869 } else {
6870 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6871 cpt_prio[1] = 0;
6872 }
6873
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006874 /* Service and Response Information are optional */
6875 if (pos && pos[0]) {
6876 size_t len;
6877
6878 /* Note the bare ' included, which cannot exist legally
6879 * in unescaped string. */
6880 svc_info = os_strstr(pos, "svc_info='");
6881
6882 if (svc_info) {
6883 svc_info += 9;
6884 len = os_strlen(svc_info);
6885 utf8_unescape(svc_info, len, svc_info, len);
6886 }
6887 }
6888
6889 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6890 (u8) svc_state, (u16) config_methods,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006891 svc_info, cpt_prio);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006892}
6893
6894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006895static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6896{
6897 char *pos;
6898
6899 pos = os_strchr(cmd, ' ');
6900 if (pos == NULL)
6901 return -1;
6902 *pos++ = '\0';
6903
6904 if (os_strcmp(cmd, "bonjour") == 0)
6905 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6906 if (os_strcmp(cmd, "upnp") == 0)
6907 return p2p_ctrl_service_add_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006908 if (os_strcmp(cmd, "asp") == 0)
6909 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006910 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6911 return -1;
6912}
6913
6914
6915static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6916 char *cmd)
6917{
6918 size_t len;
6919 struct wpabuf *query;
6920 int ret;
6921
6922 len = os_strlen(cmd);
6923 if (len & 1)
6924 return -1;
6925 len /= 2;
6926 query = wpabuf_alloc(len);
6927 if (query == NULL)
6928 return -1;
6929 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
6930 wpabuf_free(query);
6931 return -1;
6932 }
6933
6934 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
6935 wpabuf_free(query);
6936 return ret;
6937}
6938
6939
6940static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6941{
6942 char *pos;
6943 u8 version;
6944
6945 pos = os_strchr(cmd, ' ');
6946 if (pos == NULL)
6947 return -1;
6948 *pos++ = '\0';
6949
6950 if (hexstr2bin(cmd, &version, 1) < 0)
6951 return -1;
6952
6953 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
6954}
6955
6956
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006957static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
6958{
6959 u32 adv_id;
6960
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07006961 if (os_strcmp(cmd, "all") == 0) {
6962 wpas_p2p_service_flush_asp(wpa_s);
6963 return 0;
6964 }
6965
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006966 if (sscanf(cmd, "%x", &adv_id) != 1)
6967 return -1;
6968
6969 return wpas_p2p_service_del_asp(wpa_s, adv_id);
6970}
6971
6972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006973static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
6974{
6975 char *pos;
6976
6977 pos = os_strchr(cmd, ' ');
6978 if (pos == NULL)
6979 return -1;
6980 *pos++ = '\0';
6981
6982 if (os_strcmp(cmd, "bonjour") == 0)
6983 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
6984 if (os_strcmp(cmd, "upnp") == 0)
6985 return p2p_ctrl_service_del_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006986 if (os_strcmp(cmd, "asp") == 0)
6987 return p2p_ctrl_service_del_asp(wpa_s, pos);
6988 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6989 return -1;
6990}
6991
6992
6993static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
6994{
6995 char *pos;
6996
6997 pos = os_strchr(cmd, ' ');
6998 if (pos == NULL)
6999 return -1;
7000 *pos++ = '\0';
7001
7002 if (os_strcmp(cmd, "asp") == 0)
7003 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
7004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007005 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7006 return -1;
7007}
7008
7009
7010static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
7011{
7012 u8 addr[ETH_ALEN];
7013
7014 /* <addr> */
7015
7016 if (hwaddr_aton(cmd, addr))
7017 return -1;
7018
7019 return wpas_p2p_reject(wpa_s, addr);
7020}
7021
7022
7023static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
7024{
7025 char *pos;
7026 int id;
7027 struct wpa_ssid *ssid;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07007028 u8 *_peer = NULL, peer[ETH_ALEN];
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007029 int freq = 0, pref_freq = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08007030 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007031 int edmg;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007032 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007033
7034 id = atoi(cmd);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07007035 pos = os_strstr(cmd, " peer=");
7036 if (pos) {
7037 pos += 6;
7038 if (hwaddr_aton(pos, peer))
7039 return -1;
7040 _peer = peer;
7041 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007042 ssid = wpa_config_get_network(wpa_s->conf, id);
7043 if (ssid == NULL || ssid->disabled != 2) {
7044 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7045 "for persistent P2P group",
7046 id);
7047 return -1;
7048 }
7049
Jouni Malinen31be0a42012-08-31 21:20:51 +03007050 pos = os_strstr(cmd, " freq=");
7051 if (pos) {
7052 pos += 6;
7053 freq = atoi(pos);
7054 if (freq <= 0)
7055 return -1;
7056 }
7057
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007058 pos = os_strstr(cmd, " pref=");
7059 if (pos) {
7060 pos += 6;
7061 pref_freq = atoi(pos);
7062 if (pref_freq <= 0)
7063 return -1;
7064 }
7065
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007066 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
7067 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
7068 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08007069 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007070 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Jouni Malinen31be0a42012-08-31 21:20:51 +03007071
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007072 pos = os_strstr(cmd, "freq2=");
7073 if (pos)
7074 freq2 = atoi(pos + 6);
7075
7076 pos = os_strstr(cmd, " max_oper_chwidth=");
7077 if (pos)
7078 chwidth = atoi(pos + 18);
7079
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007080 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007081 if (max_oper_chwidth < 0)
7082 return -1;
7083
Hai Shaloma20dcd72022-02-04 13:43:00 -08007084 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
7085
7086 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00007087 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007088
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007089 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
Hai Shaloma20dcd72022-02-04 13:43:00 -08007090 max_oper_chwidth, pref_freq, he, edmg,
7091 allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007092}
7093
7094
7095static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
7096{
7097 char *pos;
7098 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007099 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007100
7101 pos = os_strstr(cmd, " peer=");
7102 if (!pos)
7103 return -1;
7104
7105 *pos = '\0';
7106 pos += 6;
7107 if (hwaddr_aton(pos, peer)) {
7108 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
7109 return -1;
7110 }
7111
Hai Shaloma20dcd72022-02-04 13:43:00 -08007112 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
7113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007114 pos = os_strstr(pos, " go_dev_addr=");
7115 if (pos) {
7116 pos += 13;
7117 if (hwaddr_aton(pos, go_dev_addr)) {
7118 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
7119 pos);
7120 return -1;
7121 }
7122 go_dev = go_dev_addr;
7123 }
7124
Hai Shaloma20dcd72022-02-04 13:43:00 -08007125 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007126}
7127
7128
7129static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
7130{
7131 if (os_strncmp(cmd, "persistent=", 11) == 0)
7132 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
7133 if (os_strncmp(cmd, "group=", 6) == 0)
7134 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
7135
7136 return -1;
7137}
7138
7139
7140static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007141 int id, int freq, int vht_center_freq2,
Hai Shalom74f70d42019-02-11 14:42:39 -08007142 int ht40, int vht, int vht_chwidth,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007143 int he, int edmg, bool allow_6ghz,
7144 const u8 *go_bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007146 struct wpa_ssid *ssid;
7147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007148 ssid = wpa_config_get_network(wpa_s->conf, id);
7149 if (ssid == NULL || ssid->disabled != 2) {
7150 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7151 "for persistent P2P group",
7152 id);
7153 return -1;
7154 }
7155
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007156 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
7157 vht_center_freq2, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007158 vht_chwidth, he, edmg,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007159 NULL, 0, 0, allow_6ghz, 0,
7160 go_bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007161}
7162
7163
7164static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
7165{
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007166 int freq = 0, persistent = 0, group_id = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007167 bool allow_6ghz = false;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007168 int vht = wpa_s->conf->p2p_go_vht;
7169 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08007170 int he = wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007171 int edmg = wpa_s->conf->p2p_go_edmg;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007172 int max_oper_chwidth, chwidth = 0, freq2 = 0;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007173 char *token, *context = NULL;
Sunil Raviaf8751c2023-03-29 11:35:17 -07007174 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007175#ifdef CONFIG_ACS
7176 int acs = 0;
7177#endif /* CONFIG_ACS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007178
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007179 while ((token = str_token(cmd, " ", &context))) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007180 if (sscanf(token, "freq2=%d", &freq2) == 1 ||
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007181 sscanf(token, "persistent=%d", &group_id) == 1 ||
7182 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007183 continue;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007184#ifdef CONFIG_ACS
7185 } else if (os_strcmp(token, "freq=acs") == 0) {
7186 acs = 1;
7187#endif /* CONFIG_ACS */
7188 } else if (sscanf(token, "freq=%d", &freq) == 1) {
7189 continue;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007190 } else if (os_strcmp(token, "ht40") == 0) {
7191 ht40 = 1;
7192 } else if (os_strcmp(token, "vht") == 0) {
7193 vht = 1;
7194 ht40 = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08007195 } else if (os_strcmp(token, "he") == 0) {
7196 he = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007197 } else if (os_strcmp(token, "edmg") == 0) {
7198 edmg = 1;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007199 } else if (os_strcmp(token, "persistent") == 0) {
7200 persistent = 1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007201 } else if (os_strcmp(token, "allow_6ghz") == 0) {
7202 allow_6ghz = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07007203 } else if (os_strncmp(token, "go_bssid=", 9) == 0) {
7204 if (hwaddr_aton(token + 9, go_bssid_buf))
7205 return -1;
7206 go_bssid = go_bssid_buf;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007207 } else {
7208 wpa_printf(MSG_DEBUG,
7209 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
7210 token);
7211 return -1;
7212 }
7213 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007214
Roshan Pius3a1667e2018-07-03 15:17:14 -07007215#ifdef CONFIG_ACS
7216 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
7217 (acs || freq == 2 || freq == 5)) {
7218 if (freq == 2 && wpa_s->best_24_freq <= 0) {
7219 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
7220 wpa_s->p2p_go_do_acs = 1;
7221 freq = 0;
7222 } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
7223 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
7224 wpa_s->p2p_go_do_acs = 1;
7225 freq = 0;
7226 } else {
7227 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
7228 wpa_s->p2p_go_do_acs = 1;
7229 }
Hai Shalom021b0b52019-04-10 11:17:58 -07007230 } else {
7231 wpa_s->p2p_go_do_acs = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007232 }
7233#endif /* CONFIG_ACS */
7234
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007235 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007236 if (max_oper_chwidth < 0)
7237 return -1;
7238
Hai Shaloma20dcd72022-02-04 13:43:00 -08007239 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00007240 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007241
7242 /* Allow DFS to be used for Autonomous GO */
7243 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
7244 WPA_DRIVER_FLAGS_DFS_OFFLOAD);
7245
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007246 if (group_id >= 0)
7247 return p2p_ctrl_group_add_persistent(wpa_s, group_id,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007248 freq, freq2, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007249 max_oper_chwidth, he,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007250 edmg, allow_6ghz,
7251 go_bssid);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007252
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007253 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
Hai Shaloma20dcd72022-02-04 13:43:00 -08007254 max_oper_chwidth, he, edmg, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007255}
7256
7257
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007258static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
7259 char *buf, size_t buflen)
7260{
7261 u8 dev_addr[ETH_ALEN];
7262 struct wpa_ssid *ssid;
7263 int res;
7264 const u8 *iaddr;
7265
7266 ssid = wpa_s->current_ssid;
7267 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
7268 hwaddr_aton(cmd, dev_addr))
7269 return -1;
7270
7271 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
7272 if (!iaddr)
7273 return -1;
7274 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
7275 if (os_snprintf_error(buflen, res))
7276 return -1;
7277 return res;
7278}
7279
7280
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007281static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
7282 const u8 *p2p_dev_addr)
7283{
7284 struct wpa_supplicant *wpa_s;
7285
7286 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7287 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
7288 return 1;
7289 }
7290
7291 return 0;
7292}
7293
7294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7296 char *buf, size_t buflen)
7297{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007298 u8 addr[ETH_ALEN], *addr_ptr, group_capab;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007299 int next, res;
7300 const struct p2p_peer_info *info;
7301 char *pos, *end;
7302 char devtype[WPS_DEV_TYPE_BUFSIZE];
7303 struct wpa_ssid *ssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007304 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007305
7306 if (!wpa_s->global->p2p)
7307 return -1;
7308
7309 if (os_strcmp(cmd, "FIRST") == 0) {
7310 addr_ptr = NULL;
7311 next = 0;
7312 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
7313 if (hwaddr_aton(cmd + 5, addr) < 0)
7314 return -1;
7315 addr_ptr = addr;
7316 next = 1;
7317 } else {
7318 if (hwaddr_aton(cmd, addr) < 0)
7319 return -1;
7320 addr_ptr = addr;
7321 next = 0;
7322 }
7323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007324 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7325 if (info == NULL)
7326 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007327 group_capab = info->group_capab;
7328
7329 if (group_capab &&
7330 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
7331 wpa_printf(MSG_DEBUG,
7332 "P2P: Could not find any BSS with p2p_dev_addr "
7333 MACSTR ", hence override group_capab from 0x%x to 0",
7334 MAC2STR(info->p2p_device_addr), group_capab);
7335 group_capab = 0;
7336 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007337
7338 pos = buf;
7339 end = buf + buflen;
7340
7341 res = os_snprintf(pos, end - pos, MACSTR "\n"
7342 "pri_dev_type=%s\n"
7343 "device_name=%s\n"
7344 "manufacturer=%s\n"
7345 "model_name=%s\n"
7346 "model_number=%s\n"
7347 "serial_number=%s\n"
7348 "config_methods=0x%x\n"
7349 "dev_capab=0x%x\n"
7350 "group_capab=0x%x\n"
7351 "level=%d\n",
7352 MAC2STR(info->p2p_device_addr),
7353 wps_dev_type_bin2str(info->pri_dev_type,
7354 devtype, sizeof(devtype)),
7355 info->device_name,
7356 info->manufacturer,
7357 info->model_name,
7358 info->model_number,
7359 info->serial_number,
7360 info->config_methods,
7361 info->dev_capab,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007362 group_capab,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007363 info->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007364 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007365 return pos - buf;
7366 pos += res;
7367
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007368 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7369 {
7370 const u8 *t;
7371 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7372 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7373 wps_dev_type_bin2str(t, devtype,
7374 sizeof(devtype)));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007375 if (os_snprintf_error(end - pos, res))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007376 return pos - buf;
7377 pos += res;
7378 }
7379
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007380 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007381 if (ssid) {
7382 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007383 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007384 return pos - buf;
7385 pos += res;
7386 }
7387
7388 res = p2p_get_peer_info_txt(info, pos, end - pos);
7389 if (res < 0)
7390 return pos - buf;
7391 pos += res;
7392
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007393 if (info->vendor_elems) {
7394 res = os_snprintf(pos, end - pos, "vendor_elems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007395 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007396 return pos - buf;
7397 pos += res;
7398
7399 pos += wpa_snprintf_hex(pos, end - pos,
7400 wpabuf_head(info->vendor_elems),
7401 wpabuf_len(info->vendor_elems));
7402
7403 res = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007404 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007405 return pos - buf;
7406 pos += res;
7407 }
7408
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007409 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007410}
7411
7412
Dmitry Shmidt04949592012-07-19 12:16:46 -07007413static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7414 const char *param)
7415{
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007416 unsigned int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007417
7418 if (wpa_s->global->p2p == NULL)
7419 return -1;
7420
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007421 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7422 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007423
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007424 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7425 struct wpa_freq_range *freq;
7426 freq = &wpa_s->global->p2p_disallow_freq.range[i];
Dmitry Shmidt04949592012-07-19 12:16:46 -07007427 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007428 freq->min, freq->max);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007429 }
7430
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007431 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007432 return 0;
7433}
7434
7435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007436static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7437{
7438 char *param;
7439
7440 if (wpa_s->global->p2p == NULL)
7441 return -1;
7442
7443 param = os_strchr(cmd, ' ');
7444 if (param == NULL)
7445 return -1;
7446 *param++ = '\0';
7447
7448 if (os_strcmp(cmd, "discoverability") == 0) {
7449 p2p_set_client_discoverability(wpa_s->global->p2p,
7450 atoi(param));
7451 return 0;
7452 }
7453
7454 if (os_strcmp(cmd, "managed") == 0) {
7455 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7456 return 0;
7457 }
7458
7459 if (os_strcmp(cmd, "listen_channel") == 0) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08007460 char *pos;
7461 u8 channel, op_class;
7462
7463 channel = atoi(param);
7464 pos = os_strchr(param, ' ');
7465 op_class = pos ? atoi(pos) : 81;
7466
7467 return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7468 channel, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007469 }
7470
7471 if (os_strcmp(cmd, "ssid_postfix") == 0) {
7472 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7473 os_strlen(param));
7474 }
7475
7476 if (os_strcmp(cmd, "noa") == 0) {
7477 char *pos;
7478 int count, start, duration;
7479 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
7480 count = atoi(param);
7481 pos = os_strchr(param, ',');
7482 if (pos == NULL)
7483 return -1;
7484 pos++;
7485 start = atoi(pos);
7486 pos = os_strchr(pos, ',');
7487 if (pos == NULL)
7488 return -1;
7489 pos++;
7490 duration = atoi(pos);
7491 if (count < 0 || count > 255 || start < 0 || duration < 0)
7492 return -1;
7493 if (count == 0 && duration > 0)
7494 return -1;
7495 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7496 "start=%d duration=%d", count, start, duration);
7497 return wpas_p2p_set_noa(wpa_s, count, start, duration);
7498 }
7499
7500 if (os_strcmp(cmd, "ps") == 0)
7501 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7502
7503 if (os_strcmp(cmd, "oppps") == 0)
7504 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7505
7506 if (os_strcmp(cmd, "ctwindow") == 0)
7507 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7508
7509 if (os_strcmp(cmd, "disabled") == 0) {
7510 wpa_s->global->p2p_disabled = atoi(param);
7511 wpa_printf(MSG_DEBUG, "P2P functionality %s",
7512 wpa_s->global->p2p_disabled ?
7513 "disabled" : "enabled");
7514 if (wpa_s->global->p2p_disabled) {
7515 wpas_p2p_stop_find(wpa_s);
7516 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7517 p2p_flush(wpa_s->global->p2p);
7518 }
7519 return 0;
7520 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007521
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007522 if (os_strcmp(cmd, "conc_pref") == 0) {
7523 if (os_strcmp(param, "sta") == 0)
7524 wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7525 else if (os_strcmp(param, "p2p") == 0)
7526 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007527 else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007528 wpa_printf(MSG_INFO, "Invalid conc_pref value");
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007529 return -1;
7530 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007531 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
Dmitry Shmidt04949592012-07-19 12:16:46 -07007532 "%s", param);
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007533 return 0;
7534 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007536 if (os_strcmp(cmd, "force_long_sd") == 0) {
7537 wpa_s->force_long_sd = atoi(param);
7538 return 0;
7539 }
7540
7541 if (os_strcmp(cmd, "peer_filter") == 0) {
7542 u8 addr[ETH_ALEN];
7543 if (hwaddr_aton(param, addr))
7544 return -1;
7545 p2p_set_peer_filter(wpa_s->global->p2p, addr);
7546 return 0;
7547 }
7548
7549 if (os_strcmp(cmd, "cross_connect") == 0)
7550 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7551
7552 if (os_strcmp(cmd, "go_apsd") == 0) {
7553 if (os_strcmp(param, "disable") == 0)
7554 wpa_s->set_ap_uapsd = 0;
7555 else {
7556 wpa_s->set_ap_uapsd = 1;
7557 wpa_s->ap_uapsd = atoi(param);
7558 }
7559 return 0;
7560 }
7561
7562 if (os_strcmp(cmd, "client_apsd") == 0) {
7563 if (os_strcmp(param, "disable") == 0)
7564 wpa_s->set_sta_uapsd = 0;
7565 else {
7566 int be, bk, vi, vo;
7567 char *pos;
7568 /* format: BE,BK,VI,VO;max SP Length */
7569 be = atoi(param);
7570 pos = os_strchr(param, ',');
7571 if (pos == NULL)
7572 return -1;
7573 pos++;
7574 bk = atoi(pos);
7575 pos = os_strchr(pos, ',');
7576 if (pos == NULL)
7577 return -1;
7578 pos++;
7579 vi = atoi(pos);
7580 pos = os_strchr(pos, ',');
7581 if (pos == NULL)
7582 return -1;
7583 pos++;
7584 vo = atoi(pos);
7585 /* ignore max SP Length for now */
7586
7587 wpa_s->set_sta_uapsd = 1;
7588 wpa_s->sta_uapsd = 0;
7589 if (be)
7590 wpa_s->sta_uapsd |= BIT(0);
7591 if (bk)
7592 wpa_s->sta_uapsd |= BIT(1);
7593 if (vi)
7594 wpa_s->sta_uapsd |= BIT(2);
7595 if (vo)
7596 wpa_s->sta_uapsd |= BIT(3);
7597 }
7598 return 0;
7599 }
7600
Dmitry Shmidt04949592012-07-19 12:16:46 -07007601 if (os_strcmp(cmd, "disallow_freq") == 0)
7602 return p2p_ctrl_disallow_freq(wpa_s, param);
7603
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007604 if (os_strcmp(cmd, "disc_int") == 0) {
7605 int min_disc_int, max_disc_int, max_disc_tu;
7606 char *pos;
7607
7608 pos = param;
7609
7610 min_disc_int = atoi(pos);
7611 pos = os_strchr(pos, ' ');
7612 if (pos == NULL)
7613 return -1;
7614 *pos++ = '\0';
7615
7616 max_disc_int = atoi(pos);
7617 pos = os_strchr(pos, ' ');
7618 if (pos == NULL)
7619 return -1;
7620 *pos++ = '\0';
7621
7622 max_disc_tu = atoi(pos);
7623
7624 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7625 max_disc_int, max_disc_tu);
7626 }
7627
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007628 if (os_strcmp(cmd, "per_sta_psk") == 0) {
7629 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7630 return 0;
7631 }
7632
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007633#ifdef CONFIG_WPS_NFC
7634 if (os_strcmp(cmd, "nfc_tag") == 0)
7635 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7636#endif /* CONFIG_WPS_NFC */
7637
7638 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7639 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7640 return 0;
7641 }
7642
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007643 if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7644 int op_class, chan;
7645
7646 op_class = atoi(param);
7647 param = os_strchr(param, ':');
7648 if (!param)
7649 return -1;
7650 param++;
7651 chan = atoi(param);
7652 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7653 chan);
7654 return 0;
7655 }
7656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007657 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7658 cmd);
7659
7660 return -1;
7661}
7662
7663
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007664static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7665{
7666 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7667 wpa_s->force_long_sd = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007668
7669#ifdef CONFIG_TESTING_OPTIONS
7670 os_free(wpa_s->get_pref_freq_list_override);
7671 wpa_s->get_pref_freq_list_override = NULL;
7672#endif /* CONFIG_TESTING_OPTIONS */
7673
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007674 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007675 wpa_s->parent->p2ps_method_config_any = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007676 if (wpa_s->global->p2p)
7677 p2p_flush(wpa_s->global->p2p);
7678}
7679
7680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007681static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7682{
7683 char *pos, *pos2;
7684 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7685
7686 if (cmd[0]) {
7687 pos = os_strchr(cmd, ' ');
7688 if (pos == NULL)
7689 return -1;
7690 *pos++ = '\0';
7691 dur1 = atoi(cmd);
7692
7693 pos2 = os_strchr(pos, ' ');
7694 if (pos2)
7695 *pos2++ = '\0';
7696 int1 = atoi(pos);
7697 } else
7698 pos2 = NULL;
7699
7700 if (pos2) {
7701 pos = os_strchr(pos2, ' ');
7702 if (pos == NULL)
7703 return -1;
7704 *pos++ = '\0';
7705 dur2 = atoi(pos2);
7706 int2 = atoi(pos);
7707 }
7708
7709 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7710}
7711
7712
7713static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7714{
7715 char *pos;
7716 unsigned int period = 0, interval = 0;
7717
7718 if (cmd[0]) {
7719 pos = os_strchr(cmd, ' ');
7720 if (pos == NULL)
7721 return -1;
7722 *pos++ = '\0';
7723 period = atoi(cmd);
7724 interval = atoi(pos);
7725 }
7726
7727 return wpas_p2p_ext_listen(wpa_s, period, interval);
7728}
7729
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007730
7731static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7732{
7733 const char *pos;
7734 u8 peer[ETH_ALEN];
7735 int iface_addr = 0;
7736
7737 pos = cmd;
7738 if (os_strncmp(pos, "iface=", 6) == 0) {
7739 iface_addr = 1;
7740 pos += 6;
7741 }
7742 if (hwaddr_aton(pos, peer))
7743 return -1;
7744
7745 wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7746 return 0;
7747}
7748
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07007749
7750static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7751{
7752 int freq = 0, period = 0, interval = 0, count = 0;
7753
7754 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7755 {
7756 wpa_printf(MSG_DEBUG,
7757 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7758 return -1;
7759 }
7760
7761 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7762}
7763
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007764#endif /* CONFIG_P2P */
7765
7766
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007767static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7768{
7769 struct wpa_freq_range_list ranges;
7770 int *freqs = NULL;
7771 struct hostapd_hw_modes *mode;
7772 u16 i;
7773
7774 if (wpa_s->hw.modes == NULL)
7775 return NULL;
7776
7777 os_memset(&ranges, 0, sizeof(ranges));
7778 if (freq_range_list_parse(&ranges, val) < 0)
7779 return NULL;
7780
7781 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7782 int j;
7783
7784 mode = &wpa_s->hw.modes[i];
7785 for (j = 0; j < mode->num_channels; j++) {
7786 unsigned int freq;
7787
7788 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7789 continue;
7790
7791 freq = mode->channels[j].freq;
7792 if (!freq_range_list_includes(&ranges, freq))
7793 continue;
7794
7795 int_array_add_unique(&freqs, freq);
7796 }
7797 }
7798
7799 os_free(ranges.range);
7800 return freqs;
7801}
7802
7803
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007804#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007805
7806static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7807{
7808 int auto_sel = 0;
7809 int *freqs = NULL;
7810
7811 if (param) {
7812 char *pos;
7813
7814 auto_sel = os_strstr(param, "auto") != NULL;
7815
7816 pos = os_strstr(param, "freq=");
7817 if (pos) {
7818 freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7819 if (freqs == NULL)
7820 return -1;
7821 }
7822
7823 }
7824
7825 return interworking_select(wpa_s, auto_sel, freqs);
7826}
7827
7828
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007829static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7830 int only_add)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007831{
7832 u8 bssid[ETH_ALEN];
7833 struct wpa_bss *bss;
7834
7835 if (hwaddr_aton(dst, bssid)) {
7836 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7837 return -1;
7838 }
7839
Hai Shalomfdcde762020-04-02 11:19:20 -07007840 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007841 if (bss == NULL) {
7842 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
7843 MAC2STR(bssid));
7844 return -1;
7845 }
7846
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007847 if (bss->ssid_len == 0) {
7848 int found = 0;
7849
7850 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
7851 " does not have SSID information", MAC2STR(bssid));
7852
7853 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
7854 list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007855 if (ether_addr_equal(bss->bssid, bssid) &&
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007856 bss->ssid_len > 0) {
7857 found = 1;
7858 break;
7859 }
7860 }
7861
7862 if (!found)
7863 return -1;
7864 wpa_printf(MSG_DEBUG,
7865 "Found another matching BSS entry with SSID");
7866 }
7867
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007868 return interworking_connect(wpa_s, bss, only_add);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007869}
7870
7871
7872static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
7873{
7874 u8 dst_addr[ETH_ALEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07007875 int used, freq = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007876 char *pos;
7877#define MAX_ANQP_INFO_ID 100
7878 u16 id[MAX_ANQP_INFO_ID];
7879 size_t num_id = 0;
Dmitry Shmidt15907092014-03-25 10:42:57 -07007880 u32 subtypes = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007881 u32 mbo_subtypes = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007882
7883 used = hwaddr_aton2(dst, dst_addr);
7884 if (used < 0)
7885 return -1;
7886 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007887 if (*pos == ' ')
7888 pos++;
Hai Shalom899fcc72020-10-19 14:38:18 -07007889
7890 if (os_strncmp(pos, "freq=", 5) == 0) {
7891 freq = atoi(pos + 5);
7892 pos = os_strchr(pos, ' ');
7893 if (!pos)
7894 return -1;
7895 pos++;
7896 }
7897
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007898 while (num_id < MAX_ANQP_INFO_ID) {
Dmitry Shmidt15907092014-03-25 10:42:57 -07007899 if (os_strncmp(pos, "hs20:", 5) == 0) {
7900#ifdef CONFIG_HS20
7901 int num = atoi(pos + 5);
7902 if (num <= 0 || num > 31)
7903 return -1;
7904 subtypes |= BIT(num);
7905#else /* CONFIG_HS20 */
7906 return -1;
7907#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007908 } else if (os_strncmp(pos, "mbo:", 4) == 0) {
7909#ifdef CONFIG_MBO
7910 int num = atoi(pos + 4);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007911
7912 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007913 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007914 mbo_subtypes |= BIT(num);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08007915#else /* CONFIG_MBO */
7916 return -1;
7917#endif /* CONFIG_MBO */
Dmitry Shmidt15907092014-03-25 10:42:57 -07007918 } else {
7919 id[num_id] = atoi(pos);
7920 if (id[num_id])
7921 num_id++;
7922 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007923 pos = os_strchr(pos + 1, ',');
7924 if (pos == NULL)
7925 break;
7926 pos++;
7927 }
7928
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007929 if (num_id == 0 && !subtypes && !mbo_subtypes)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007930 return -1;
7931
Hai Shalom899fcc72020-10-19 14:38:18 -07007932 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007933 mbo_subtypes);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007934}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007935
7936
7937static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
7938{
7939 u8 dst_addr[ETH_ALEN];
7940 struct wpabuf *advproto, *query = NULL;
7941 int used, ret = -1;
7942 char *pos, *end;
7943 size_t len;
7944
7945 used = hwaddr_aton2(cmd, dst_addr);
7946 if (used < 0)
7947 return -1;
7948
7949 pos = cmd + used;
7950 while (*pos == ' ')
7951 pos++;
7952
7953 /* Advertisement Protocol ID */
7954 end = os_strchr(pos, ' ');
7955 if (end)
7956 len = end - pos;
7957 else
7958 len = os_strlen(pos);
7959 if (len & 0x01)
7960 return -1;
7961 len /= 2;
7962 if (len == 0)
7963 return -1;
7964 advproto = wpabuf_alloc(len);
7965 if (advproto == NULL)
7966 return -1;
7967 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
7968 goto fail;
7969
7970 if (end) {
7971 /* Optional Query Request */
7972 pos = end + 1;
7973 while (*pos == ' ')
7974 pos++;
7975
7976 len = os_strlen(pos);
7977 if (len) {
7978 if (len & 0x01)
7979 goto fail;
7980 len /= 2;
7981 if (len == 0)
7982 goto fail;
7983 query = wpabuf_alloc(len);
7984 if (query == NULL)
7985 goto fail;
7986 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
7987 goto fail;
7988 }
7989 }
7990
7991 ret = gas_send_request(wpa_s, dst_addr, advproto, query);
7992
7993fail:
7994 wpabuf_free(advproto);
7995 wpabuf_free(query);
7996
7997 return ret;
7998}
7999
8000
8001static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
8002 size_t buflen)
8003{
8004 u8 addr[ETH_ALEN];
8005 int dialog_token;
8006 int used;
8007 char *pos;
8008 size_t resp_len, start, requested_len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008009 struct wpabuf *resp;
8010 int ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008011
8012 used = hwaddr_aton2(cmd, addr);
8013 if (used < 0)
8014 return -1;
8015
8016 pos = cmd + used;
8017 while (*pos == ' ')
8018 pos++;
8019 dialog_token = atoi(pos);
8020
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008021 if (wpa_s->last_gas_resp &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008022 ether_addr_equal(addr, wpa_s->last_gas_addr) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008023 dialog_token == wpa_s->last_gas_dialog_token)
8024 resp = wpa_s->last_gas_resp;
8025 else if (wpa_s->prev_gas_resp &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008026 ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008027 dialog_token == wpa_s->prev_gas_dialog_token)
8028 resp = wpa_s->prev_gas_resp;
8029 else
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008030 return -1;
8031
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008032 resp_len = wpabuf_len(resp);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008033 start = 0;
8034 requested_len = resp_len;
8035
8036 pos = os_strchr(pos, ' ');
8037 if (pos) {
8038 start = atoi(pos);
8039 if (start > resp_len)
8040 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8041 pos = os_strchr(pos, ',');
8042 if (pos == NULL)
8043 return -1;
8044 pos++;
8045 requested_len = atoi(pos);
8046 if (start + requested_len > resp_len)
8047 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8048 }
8049
8050 if (requested_len * 2 + 1 > buflen)
8051 return os_snprintf(buf, buflen, "FAIL-Too long response");
8052
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008053 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
8054 requested_len);
8055
8056 if (start + requested_len == resp_len) {
8057 /*
8058 * Free memory by dropping the response after it has been
8059 * fetched.
8060 */
8061 if (resp == wpa_s->prev_gas_resp) {
8062 wpabuf_free(wpa_s->prev_gas_resp);
8063 wpa_s->prev_gas_resp = NULL;
8064 } else {
8065 wpabuf_free(wpa_s->last_gas_resp);
8066 wpa_s->last_gas_resp = NULL;
8067 }
8068 }
8069
8070 return ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008071}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008072#endif /* CONFIG_INTERWORKING */
8073
8074
Dmitry Shmidt04949592012-07-19 12:16:46 -07008075#ifdef CONFIG_HS20
8076
8077static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
8078{
8079 u8 dst_addr[ETH_ALEN];
8080 int used;
8081 char *pos;
8082 u32 subtypes = 0;
8083
8084 used = hwaddr_aton2(dst, dst_addr);
8085 if (used < 0)
8086 return -1;
8087 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008088 if (*pos == ' ')
8089 pos++;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008090 for (;;) {
8091 int num = atoi(pos);
8092 if (num <= 0 || num > 31)
8093 return -1;
8094 subtypes |= BIT(num);
8095 pos = os_strchr(pos + 1, ',');
8096 if (pos == NULL)
8097 break;
8098 pos++;
8099 }
8100
8101 if (subtypes == 0)
8102 return -1;
8103
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008104 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008105}
8106
8107
8108static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8109 const u8 *addr, const char *realm)
8110{
8111 u8 *buf;
8112 size_t rlen, len;
8113 int ret;
8114
8115 rlen = os_strlen(realm);
8116 len = 3 + rlen;
8117 buf = os_malloc(len);
8118 if (buf == NULL)
8119 return -1;
8120 buf[0] = 1; /* NAI Home Realm Count */
8121 buf[1] = 0; /* Formatted in accordance with RFC 4282 */
8122 buf[2] = rlen;
8123 os_memcpy(buf + 3, realm, rlen);
8124
8125 ret = hs20_anqp_send_req(wpa_s, addr,
8126 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008127 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008128
8129 os_free(buf);
8130
8131 return ret;
8132}
8133
8134
8135static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8136 char *dst)
8137{
8138 struct wpa_cred *cred = wpa_s->conf->cred;
8139 u8 dst_addr[ETH_ALEN];
8140 int used;
8141 u8 *buf;
8142 size_t len;
8143 int ret;
8144
8145 used = hwaddr_aton2(dst, dst_addr);
8146 if (used < 0)
8147 return -1;
8148
8149 while (dst[used] == ' ')
8150 used++;
8151 if (os_strncmp(dst + used, "realm=", 6) == 0)
8152 return hs20_nai_home_realm_list(wpa_s, dst_addr,
8153 dst + used + 6);
8154
8155 len = os_strlen(dst + used);
8156
8157 if (len == 0 && cred && cred->realm)
8158 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
8159
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07008160 if (len & 1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008161 return -1;
8162 len /= 2;
8163 buf = os_malloc(len);
8164 if (buf == NULL)
8165 return -1;
8166 if (hexstr2bin(dst + used, buf, len) < 0) {
8167 os_free(buf);
8168 return -1;
8169 }
8170
8171 ret = hs20_anqp_send_req(wpa_s, dst_addr,
8172 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008173 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008174 os_free(buf);
8175
8176 return ret;
8177}
8178
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008179
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008180static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
8181 int buflen)
8182{
8183 u8 dst_addr[ETH_ALEN];
8184 int used;
8185 char *ctx = NULL, *icon, *poffset, *psize;
8186
8187 used = hwaddr_aton2(cmd, dst_addr);
8188 if (used < 0)
8189 return -1;
8190 cmd += used;
8191
8192 icon = str_token(cmd, " ", &ctx);
8193 poffset = str_token(cmd, " ", &ctx);
8194 psize = str_token(cmd, " ", &ctx);
8195 if (!icon || !poffset || !psize)
8196 return -1;
8197
8198 wpa_s->fetch_osu_icon_in_progress = 0;
8199 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
8200 reply, buflen);
8201}
8202
8203
8204static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
8205{
8206 u8 dst_addr[ETH_ALEN];
8207 int used;
8208 char *icon;
8209
8210 if (!cmd[0])
8211 return hs20_del_icon(wpa_s, NULL, NULL);
8212
8213 used = hwaddr_aton2(cmd, dst_addr);
8214 if (used < 0)
8215 return -1;
8216
8217 while (cmd[used] == ' ')
8218 used++;
8219 icon = cmd[used] ? &cmd[used] : NULL;
8220
8221 return hs20_del_icon(wpa_s, dst_addr, icon);
8222}
8223
8224
8225static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008226{
8227 u8 dst_addr[ETH_ALEN];
8228 int used;
8229 char *icon;
8230
8231 used = hwaddr_aton2(cmd, dst_addr);
8232 if (used < 0)
8233 return -1;
8234
8235 while (cmd[used] == ' ')
8236 used++;
8237 icon = &cmd[used];
8238
8239 wpa_s->fetch_osu_icon_in_progress = 0;
8240 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008241 (u8 *) icon, os_strlen(icon), inmem);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008242}
8243
Dmitry Shmidt04949592012-07-19 12:16:46 -07008244#endif /* CONFIG_HS20 */
8245
8246
Dmitry Shmidt04949592012-07-19 12:16:46 -07008247#ifdef CONFIG_AUTOSCAN
8248
8249static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
8250 char *cmd)
8251{
8252 enum wpa_states state = wpa_s->wpa_state;
8253 char *new_params = NULL;
8254
8255 if (os_strlen(cmd) > 0) {
8256 new_params = os_strdup(cmd);
8257 if (new_params == NULL)
8258 return -1;
8259 }
8260
8261 os_free(wpa_s->conf->autoscan);
8262 wpa_s->conf->autoscan = new_params;
8263
8264 if (wpa_s->conf->autoscan == NULL)
8265 autoscan_deinit(wpa_s);
8266 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
8267 autoscan_init(wpa_s, 1);
8268 else if (state == WPA_SCANNING)
8269 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08008270 else
8271 wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
8272 wpa_supplicant_state_txt(state));
Dmitry Shmidt04949592012-07-19 12:16:46 -07008273
8274 return 0;
8275}
8276
8277#endif /* CONFIG_AUTOSCAN */
8278
8279
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008280#ifdef CONFIG_WNM
8281
8282static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
8283{
8284 int enter;
8285 int intval = 0;
8286 char *pos;
8287 int ret;
8288 struct wpabuf *tfs_req = NULL;
8289
8290 if (os_strncmp(cmd, "enter", 5) == 0)
8291 enter = 1;
8292 else if (os_strncmp(cmd, "exit", 4) == 0)
8293 enter = 0;
8294 else
8295 return -1;
8296
8297 pos = os_strstr(cmd, " interval=");
8298 if (pos)
8299 intval = atoi(pos + 10);
8300
8301 pos = os_strstr(cmd, " tfs_req=");
8302 if (pos) {
8303 char *end;
8304 size_t len;
8305 pos += 9;
8306 end = os_strchr(pos, ' ');
8307 if (end)
8308 len = end - pos;
8309 else
8310 len = os_strlen(pos);
8311 if (len & 1)
8312 return -1;
8313 len /= 2;
8314 tfs_req = wpabuf_alloc(len);
8315 if (tfs_req == NULL)
8316 return -1;
8317 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
8318 wpabuf_free(tfs_req);
8319 return -1;
8320 }
8321 }
8322
8323 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
8324 WNM_SLEEP_MODE_EXIT, intval,
8325 tfs_req);
8326 wpabuf_free(tfs_req);
8327
8328 return ret;
8329}
8330
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008331
8332static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
8333{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008334 int query_reason, list = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008335 char *btm_candidates = NULL;
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008336
8337 query_reason = atoi(cmd);
8338
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008339 cmd = os_strchr(cmd, ' ');
8340 if (cmd) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008341 if (os_strncmp(cmd, " list", 5) == 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008342 list = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008343 else
8344 btm_candidates = cmd;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008345 }
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008346
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008347 wpa_printf(MSG_DEBUG,
8348 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8349 query_reason, list ? " candidate list" : "");
8350
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008351 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8352 btm_candidates,
8353 list);
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008354}
8355
Hai Shalom39ba6fc2019-01-22 12:40:38 -08008356
8357static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8358 char *cmd)
8359{
8360 struct wpabuf *elems;
8361 int ret;
8362
8363 elems = wpabuf_parse_bin(cmd);
8364 if (!elems)
8365 return -1;
8366
8367 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8368 wpabuf_free(elems);
8369 return ret;
8370}
8371
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008372#endif /* CONFIG_WNM */
8373
8374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008375static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8376 size_t buflen)
8377{
8378 struct wpa_signal_info si;
8379 int ret;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008380 char *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008381
8382 ret = wpa_drv_signal_poll(wpa_s, &si);
8383 if (ret)
8384 return -1;
8385
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008386 pos = buf;
8387 end = buf + buflen;
8388
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008389 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008390 "NOISE=%d\nFREQUENCY=%u\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008391 si.data.signal, si.data.current_tx_rate / 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008392 si.current_noise, si.frequency);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008393 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008394 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008395 pos += ret;
8396
8397 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8398 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008399 channel_width_to_string(si.chanwidth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008400 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008401 return -1;
8402 pos += ret;
8403 }
8404
Roshan Pius3a1667e2018-07-03 15:17:14 -07008405 if (si.center_frq1 > 0) {
8406 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8407 si.center_frq1);
8408 if (os_snprintf_error(end - pos, ret))
8409 return -1;
8410 pos += ret;
8411 }
8412
8413 if (si.center_frq2 > 0) {
8414 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8415 si.center_frq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008416 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008417 return -1;
8418 pos += ret;
8419 }
8420
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008421 if (si.data.avg_signal) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008422 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008423 "AVG_RSSI=%d\n", si.data.avg_signal);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008424 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008425 return -1;
8426 pos += ret;
8427 }
8428
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008429 if (si.data.avg_beacon_signal) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07008430 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008431 "AVG_BEACON_RSSI=%d\n",
8432 si.data.avg_beacon_signal);
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07008433 if (os_snprintf_error(end - pos, ret))
8434 return -1;
8435 pos += ret;
8436 }
8437
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008438 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008439}
8440
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008441
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008442static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8443 const char *cmd)
8444{
8445 const char *pos;
8446 int threshold = 0;
8447 int hysteresis = 0;
8448
8449 if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8450 wpa_printf(MSG_DEBUG,
8451 "Reject SIGNAL_MONITOR command - bgscan is active");
8452 return -1;
8453 }
8454 pos = os_strstr(cmd, "THRESHOLD=");
8455 if (pos)
8456 threshold = atoi(pos + 10);
8457 pos = os_strstr(cmd, "HYSTERESIS=");
8458 if (pos)
8459 hysteresis = atoi(pos + 11);
8460 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8461}
8462
8463
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008464#ifdef CONFIG_TESTING_OPTIONS
8465int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8466 enum wpa_driver_if_type if_type,
8467 unsigned int *num,
Sunil8cd6f4d2022-06-28 18:40:46 +00008468 struct weighted_pcl *freq_list)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008469{
8470 char *pos = wpa_s->get_pref_freq_list_override;
8471 char *end;
8472 unsigned int count = 0;
8473
8474 /* Override string format:
8475 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8476
8477 while (pos) {
8478 if (atoi(pos) == (int) if_type)
8479 break;
8480 pos = os_strchr(pos, ' ');
8481 if (pos)
8482 pos++;
8483 }
8484 if (!pos)
8485 return -1;
8486 pos = os_strchr(pos, ':');
8487 if (!pos)
8488 return -1;
8489 pos++;
8490 end = os_strchr(pos, ' ');
8491 while (pos && (!end || pos < end) && count < *num) {
Sunil8cd6f4d2022-06-28 18:40:46 +00008492 freq_list[count].freq = atoi(pos);
8493 freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008494 pos = os_strchr(pos, ',');
8495 if (pos)
8496 pos++;
8497 }
8498
8499 *num = count;
8500 return 0;
8501}
8502#endif /* CONFIG_TESTING_OPTIONS */
8503
8504
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008505static int wpas_ctrl_iface_get_pref_freq_list(
8506 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8507{
Sunil8cd6f4d2022-06-28 18:40:46 +00008508 unsigned int num = 100, i;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008509 int ret;
8510 enum wpa_driver_if_type iface_type;
8511 char *pos, *end;
Sunil8cd6f4d2022-06-28 18:40:46 +00008512 struct weighted_pcl freq_list[100];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008513
8514 pos = buf;
8515 end = buf + buflen;
8516
8517 /* buf: "<interface_type>" */
8518 if (os_strcmp(cmd, "STATION") == 0)
8519 iface_type = WPA_IF_STATION;
8520 else if (os_strcmp(cmd, "AP") == 0)
8521 iface_type = WPA_IF_AP_BSS;
8522 else if (os_strcmp(cmd, "P2P_GO") == 0)
8523 iface_type = WPA_IF_P2P_GO;
8524 else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8525 iface_type = WPA_IF_P2P_CLIENT;
8526 else if (os_strcmp(cmd, "IBSS") == 0)
8527 iface_type = WPA_IF_IBSS;
8528 else if (os_strcmp(cmd, "TDLS") == 0)
8529 iface_type = WPA_IF_TDLS;
8530 else
8531 return -1;
8532
8533 wpa_printf(MSG_DEBUG,
8534 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
Hai Shalom5f92bc92019-04-18 11:54:11 -07008535 iface_type, cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008536
8537 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8538 if (ret)
8539 return -1;
8540
8541 for (i = 0; i < num; i++) {
8542 ret = os_snprintf(pos, end - pos, "%s%u",
Sunil8cd6f4d2022-06-28 18:40:46 +00008543 i > 0 ? "," : "", freq_list[i].freq);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008544 if (os_snprintf_error(end - pos, ret))
8545 return -1;
8546 pos += ret;
8547 }
8548
8549 return pos - buf;
8550}
8551
8552
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008553static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8554 char *buf, size_t buflen)
8555{
8556 int ret, i;
8557 char *pos, *end;
8558
8559 ret = os_snprintf(buf, buflen, "%016llX:\n",
8560 (long long unsigned) wpa_s->drv_flags);
8561 if (os_snprintf_error(buflen, ret))
8562 return -1;
8563
8564 pos = buf + ret;
8565 end = buf + buflen;
8566
8567 for (i = 0; i < 64; i++) {
8568 if (wpa_s->drv_flags & (1LLU << i)) {
8569 ret = os_snprintf(pos, end - pos, "%s\n",
8570 driver_flag_to_string(1LLU << i));
8571 if (os_snprintf_error(end - pos, ret))
8572 return -1;
8573 pos += ret;
8574 }
8575 }
8576
8577 return pos - buf;
8578}
8579
8580
Hai Shalomb755a2a2020-04-23 21:49:02 -07008581static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8582 char *buf, size_t buflen)
8583{
8584 int ret, i;
8585 char *pos, *end;
8586
8587 ret = os_snprintf(buf, buflen, "%016llX:\n",
8588 (long long unsigned) wpa_s->drv_flags2);
8589 if (os_snprintf_error(buflen, ret))
8590 return -1;
8591
8592 pos = buf + ret;
8593 end = buf + buflen;
8594
8595 for (i = 0; i < 64; i++) {
8596 if (wpa_s->drv_flags2 & (1LLU << i)) {
8597 ret = os_snprintf(pos, end - pos, "%s\n",
8598 driver_flag2_to_string(1LLU << i));
8599 if (os_snprintf_error(end - pos, ret))
8600 return -1;
8601 pos += ret;
8602 }
8603 }
8604
8605 return pos - buf;
8606}
8607
8608
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008609static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8610 size_t buflen)
8611{
8612 struct hostap_sta_driver_data sta;
8613 int ret;
8614
8615 ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8616 if (ret)
8617 return -1;
8618
8619 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008620 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008621 if (os_snprintf_error(buflen, ret))
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008622 return -1;
8623 return ret;
8624}
8625
8626
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008627#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008628static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8629 char *buf, size_t buflen)
8630{
8631 int ret;
8632
8633 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008634 if (ret == 0) {
8635 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8636 struct p2p_data *p2p = wpa_s->global->p2p;
8637 if (p2p) {
8638 char country[3];
8639 country[0] = cmd[8];
8640 country[1] = cmd[9];
8641 country[2] = 0x04;
8642 p2p_set_country(p2p, country);
8643 }
8644 }
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008645 ret = os_snprintf(buf, buflen, "%s\n", "OK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008646 if (os_snprintf_error(buflen, ret))
8647 ret = -1;
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008648 }
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008649 return ret;
8650}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008651#endif /* ANDROID */
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008652
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07008653
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008654static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8655 char *buf, size_t buflen)
8656{
8657 int ret;
Hai Shalom60840252021-02-19 19:02:11 -08008658 char *pos, *temp = NULL;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008659 u8 *data = NULL;
8660 unsigned int vendor_id, subcmd;
Hai Shalom60840252021-02-19 19:02:11 -08008661 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008662 struct wpabuf *reply;
8663 size_t data_len = 0;
8664
Hai Shalom60840252021-02-19 19:02:11 -08008665 /**
8666 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8667 * [nested=<0|1>]
8668 */
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008669 vendor_id = strtoul(cmd, &pos, 16);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008670 if (!isblank((unsigned char) *pos))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008671 return -EINVAL;
8672
8673 subcmd = strtoul(pos, &pos, 10);
8674
8675 if (*pos != '\0') {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008676 if (!isblank((unsigned char) *pos++))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008677 return -EINVAL;
Hai Shalom60840252021-02-19 19:02:11 -08008678
8679 temp = os_strchr(pos, ' ');
8680 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008681 }
8682
8683 if (data_len) {
8684 data_len /= 2;
8685 data = os_malloc(data_len);
8686 if (!data)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008687 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008688
8689 if (hexstr2bin(pos, data, data_len)) {
8690 wpa_printf(MSG_DEBUG,
8691 "Vendor command: wrong parameter format");
8692 os_free(data);
8693 return -EINVAL;
8694 }
8695 }
8696
Hai Shalom60840252021-02-19 19:02:11 -08008697 pos = os_strstr(cmd, "nested=");
8698 if (pos)
8699 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8700 NESTED_ATTR_NOT_USED;
8701
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008702 reply = wpabuf_alloc((buflen - 1) / 2);
8703 if (!reply) {
8704 os_free(data);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008705 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008706 }
8707
8708 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
Hai Shalom60840252021-02-19 19:02:11 -08008709 nested_attr_flag, reply);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008710
8711 if (ret == 0)
8712 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8713 wpabuf_len(reply));
8714
8715 wpabuf_free(reply);
8716 os_free(data);
8717
8718 return ret;
8719}
8720
8721
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008722static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8723{
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008724#ifdef CONFIG_P2P
8725 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8726 wpa_s->global->p2p_init_wpa_s : wpa_s;
8727#endif /* CONFIG_P2P */
8728
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008729 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8730
Dmitry Shmidt29333592017-01-09 12:27:11 -08008731 if (wpas_abort_ongoing_scan(wpa_s) == 0)
8732 wpa_s->ignore_post_flush_scan_res = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008733
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008734 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8735 /*
8736 * Avoid possible auto connect re-connection on getting
8737 * disconnected due to state flush.
8738 */
8739 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8740 }
8741
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008742#ifdef CONFIG_P2P
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008743 wpas_p2p_group_remove(p2p_wpa_s, "*");
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008744 wpas_p2p_cancel(p2p_wpa_s);
8745 p2p_ctrl_flush(p2p_wpa_s);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008746 wpas_p2p_service_flush(p2p_wpa_s);
8747 p2p_wpa_s->global->p2p_disabled = 0;
8748 p2p_wpa_s->global->p2p_per_sta_psk = 0;
8749 p2p_wpa_s->conf->num_sec_device_types = 0;
8750 p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8751 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8752 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008753 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08008754 p2p_wpa_s->global->pending_p2ps_group = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008755 p2p_wpa_s->global->pending_p2ps_group_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008756#endif /* CONFIG_P2P */
8757
8758#ifdef CONFIG_WPS_TESTING
8759 wps_version_number = 0x20;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008760 wps_testing_stub_cred = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008761 wps_corrupt_pkhash = 0;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008762 wps_force_auth_types_in_use = 0;
8763 wps_force_encr_types_in_use = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008764#endif /* CONFIG_WPS_TESTING */
8765#ifdef CONFIG_WPS
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008766 wpa_s->wps_fragment_size = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008767 wpas_wps_cancel(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008768 wps_registrar_flush(wpa_s->wps->registrar);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008769#endif /* CONFIG_WPS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07008770 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008771 wpa_s->known_wps_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008772
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008773#ifdef CONFIG_DPP
8774 wpas_dpp_deinit(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07008775 wpa_s->dpp_init_max_tries = 0;
8776 wpa_s->dpp_init_retry_time = 0;
8777 wpa_s->dpp_resp_wait_time = 0;
8778 wpa_s->dpp_resp_max_tries = 0;
8779 wpa_s->dpp_resp_retry_time = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008780#ifdef CONFIG_DPP2
8781 wpas_dpp_chirp_stop(wpa_s);
8782 wpa_s->dpp_pfs_fallback = 0;
8783#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008784#ifdef CONFIG_DPP3
8785 {
8786 int i;
8787
8788 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
8789 struct dpp_pb_info *info;
8790
8791 info = &wpa_s->dpp_pb[i];
8792 info->rx_time.sec = 0;
8793 info->rx_time.usec = 0;
8794 }
8795 }
8796#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008797#ifdef CONFIG_TESTING_OPTIONS
8798 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8799 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8800 dpp_pkex_ephemeral_key_override_len = 0;
8801 dpp_protocol_key_override_len = 0;
8802 dpp_nonce_override_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008803#ifdef CONFIG_DPP3
8804 dpp_version_override = 3;
8805#elif defined(CONFIG_DPP2)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07008806 dpp_version_override = 2;
8807#else /* CONFIG_DPP2 */
8808 dpp_version_override = 1;
8809#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008810#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008811#endif /* CONFIG_DPP */
8812
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008813#ifdef CONFIG_TDLS
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008814#ifdef CONFIG_TDLS_TESTING
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008815 tdls_testing = 0;
8816#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008817 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8818 wpa_tdls_enable(wpa_s->wpa, 1);
8819#endif /* CONFIG_TDLS */
8820
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008821 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8822 wpa_supplicant_stop_countermeasures(wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07008823 wpa_s->last_michael_mic_error.sec = 0;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008824
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008825 wpa_s->no_keep_alive = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008826 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008827 wpa_s->own_reconnect_req = 0;
8828 wpa_s->deny_ptk0_rekey = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008829
8830 os_free(wpa_s->disallow_aps_bssid);
8831 wpa_s->disallow_aps_bssid = NULL;
8832 wpa_s->disallow_aps_bssid_count = 0;
8833 os_free(wpa_s->disallow_aps_ssid);
8834 wpa_s->disallow_aps_ssid = NULL;
8835 wpa_s->disallow_aps_ssid_count = 0;
8836
8837 wpa_s->set_sta_uapsd = 0;
8838 wpa_s->sta_uapsd = 0;
8839
Hai Shalom899fcc72020-10-19 14:38:18 -07008840 wpa_s->consecutive_conn_failures = 0;
8841
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008842 wpa_drv_radio_disable(wpa_s, 0);
Hai Shalom60840252021-02-19 19:02:11 -08008843 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008844 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
8845 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
Dmitry Shmidt344abd32014-01-14 13:17:00 -08008846 wpa_config_flush_blobs(wpa_s->conf);
Dmitry Shmidt18463232014-01-24 12:29:41 -08008847 wpa_s->conf->auto_interworking = 0;
8848 wpa_s->conf->okc = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008849
Hai Shalom60840252021-02-19 19:02:11 -08008850 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008851 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
8852 rsn_preauth_deinit(wpa_s->wpa);
8853
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008854 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
8855 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
8856 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
Hai Shalome21d4e82020-04-29 16:34:06 -07008857 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008858
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08008859 radio_remove_works(wpa_s, NULL, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008860 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008861
8862 wpa_s->next_ssid = NULL;
8863
Sunil Ravi99c035e2024-07-12 01:42:03 +00008864 wnm_btm_reset(wpa_s);
8865
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008866#ifdef CONFIG_INTERWORKING
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008867#ifdef CONFIG_HS20
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008868 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008869 hs20_del_icon(wpa_s, NULL, NULL);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008870#endif /* CONFIG_HS20 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008871#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt818ea482014-03-10 13:15:21 -07008872
8873 wpa_s->ext_mgmt_frame_handling = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008874 wpa_s->ext_eapol_frame_io = 0;
8875#ifdef CONFIG_TESTING_OPTIONS
8876 wpa_s->extra_roc_dur = 0;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008877 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008878 wpa_s->p2p_go_csa_on_inv = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07008879 wpa_s->ignore_auth_resp = 0;
8880 wpa_s->ignore_assoc_disallow = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008881 wpa_s->disable_sa_query = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008882 wpa_s->testing_resend_assoc = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008883 wpa_s->ignore_sae_h2e_only = 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07008884 wpa_s->ft_rsnxe_used = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07008885 wpa_s->reject_btm_req_reason = 0;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008886 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008887 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
8888 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
8889 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
8890 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008891 os_free(wpa_s->get_pref_freq_list_override);
8892 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008893 wpabuf_free(wpa_s->sae_commit_override);
8894 wpa_s->sae_commit_override = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008895 os_free(wpa_s->extra_sae_rejected_groups);
8896 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008897 wpabuf_free(wpa_s->rsne_override_eapol);
8898 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008899 wpabuf_free(wpa_s->rsnxe_override_assoc);
8900 wpa_s->rsnxe_override_assoc = NULL;
8901 wpabuf_free(wpa_s->rsnxe_override_eapol);
8902 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008903 wpas_clear_driver_signal_override(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008904#ifndef CONFIG_NO_ROBUST_AV
Hai Shaloma20dcd72022-02-04 13:43:00 -08008905 wpa_s->disable_scs_support = 0;
8906 wpa_s->disable_mscs_support = 0;
8907 wpa_s->enable_dscp_policy_capa = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008908#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07008909 wpa_s->oci_freq_override_eapol = 0;
8910 wpa_s->oci_freq_override_saquery_req = 0;
8911 wpa_s->oci_freq_override_saquery_resp = 0;
8912 wpa_s->oci_freq_override_eapol_g2 = 0;
8913 wpa_s->oci_freq_override_ft_assoc = 0;
8914 wpa_s->oci_freq_override_fils_assoc = 0;
8915 wpa_s->oci_freq_override_wnm_sleep = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07008916 wpa_s->disable_eapol_g2_tx = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008917 wpa_s->test_assoc_comeback_type = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008918#ifdef CONFIG_DPP
8919 os_free(wpa_s->dpp_config_obj_override);
8920 wpa_s->dpp_config_obj_override = NULL;
8921 os_free(wpa_s->dpp_discovery_override);
8922 wpa_s->dpp_discovery_override = NULL;
8923 os_free(wpa_s->dpp_groups_override);
8924 wpa_s->dpp_groups_override = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00008925 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
8926 wpa_s->dpp_discard_public_action = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008927 dpp_test = DPP_TEST_DISABLED;
8928#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008929#endif /* CONFIG_TESTING_OPTIONS */
8930
8931 wpa_s->disconnected = 0;
8932 os_free(wpa_s->next_scan_freqs);
8933 wpa_s->next_scan_freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07008934 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
8935 wpa_s->next_scan_bssid_wildcard_ssid = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008936 os_free(wpa_s->select_network_scan_freqs);
8937 wpa_s->select_network_scan_freqs = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008938#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07008939 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008940#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008941
8942 wpa_bss_flush(wpa_s);
8943 if (!dl_list_empty(&wpa_s->bss)) {
8944 wpa_printf(MSG_DEBUG,
8945 "BSS table not empty after flush: %u entries, current_bss=%p bssid="
8946 MACSTR " pending_bssid=" MACSTR,
8947 dl_list_len(&wpa_s->bss), wpa_s->current_bss,
8948 MAC2STR(wpa_s->bssid),
8949 MAC2STR(wpa_s->pending_bssid));
8950 }
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07008951
8952 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Dmitry Shmidtb70d0bb2015-11-16 10:43:06 -08008953 wpa_s->wnmsleep_used = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008954
8955#ifdef CONFIG_SME
8956 wpa_s->sme.last_unprot_disconnect.sec = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008957 wpa_s->sme.auth_alg = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008958#endif /* CONFIG_SME */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008959
8960 wpabuf_free(wpa_s->ric_ies);
8961 wpa_s->ric_ies = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08008962
8963 wpa_supplicant_update_channel_list(wpa_s, NULL);
8964
8965 free_bss_tmp_disallowed(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07008966
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008967#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07008968 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008969#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08008970
8971#ifdef CONFIG_PASN
8972 wpas_pasn_auth_stop(wpa_s);
8973#endif /* CONFIG_PASN */
8974
8975 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
8976 wpas_restore_permanent_mac_addr(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07008977
8978 wpa_s->conf->ignore_old_scan_res = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008979
8980#ifdef CONFIG_NAN_USD
8981 wpas_nan_usd_flush(wpa_s);
8982#endif /* CONFIG_NAN_USD */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008983}
8984
8985
8986static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
8987 char *buf, size_t buflen)
8988{
8989 struct wpa_radio_work *work;
8990 char *pos, *end;
8991 struct os_reltime now, diff;
8992
8993 pos = buf;
8994 end = buf + buflen;
8995
8996 os_get_reltime(&now);
8997
8998 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
8999 {
9000 int ret;
9001
9002 os_reltime_sub(&now, &work->time, &diff);
9003 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
9004 work->type, work->wpa_s->ifname, work->freq,
9005 work->started, diff.sec, diff.usec);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009006 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009007 break;
9008 pos += ret;
9009 }
9010
9011 return pos - buf;
9012}
9013
9014
9015static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
9016{
9017 struct wpa_radio_work *work = eloop_ctx;
9018 struct wpa_external_work *ework = work->ctx;
9019
9020 wpa_dbg(work->wpa_s, MSG_DEBUG,
9021 "Timing out external radio work %u (%s)",
9022 ework->id, work->type);
9023 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009024 work->wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009025 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07009026 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009027}
9028
9029
9030static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
9031{
9032 struct wpa_external_work *ework = work->ctx;
9033
9034 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08009035 if (work->started)
9036 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9037 work, NULL);
9038
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009039 /*
9040 * work->type points to a buffer in ework, so need to replace
9041 * that here with a fixed string to avoid use of freed memory
9042 * in debug prints.
9043 */
9044 work->type = "freed-ext-work";
9045 work->ctx = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009046 os_free(ework);
9047 return;
9048 }
9049
9050 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
9051 ework->id, ework->type);
9052 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009053 work->wpa_s->ext_work_in_progress = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009054 if (!ework->timeout)
9055 ework->timeout = 10;
9056 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
9057 work, NULL);
9058}
9059
9060
9061static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
9062 char *buf, size_t buflen)
9063{
9064 struct wpa_external_work *ework;
9065 char *pos, *pos2;
9066 size_t type_len;
9067 int ret;
9068 unsigned int freq = 0;
9069
9070 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
9071
9072 ework = os_zalloc(sizeof(*ework));
9073 if (ework == NULL)
9074 return -1;
9075
9076 pos = os_strchr(cmd, ' ');
9077 if (pos) {
9078 type_len = pos - cmd;
9079 pos++;
9080
9081 pos2 = os_strstr(pos, "freq=");
9082 if (pos2)
9083 freq = atoi(pos2 + 5);
9084
9085 pos2 = os_strstr(pos, "timeout=");
9086 if (pos2)
9087 ework->timeout = atoi(pos2 + 8);
9088 } else {
9089 type_len = os_strlen(cmd);
9090 }
9091 if (4 + type_len >= sizeof(ework->type))
9092 type_len = sizeof(ework->type) - 4 - 1;
9093 os_strlcpy(ework->type, "ext:", sizeof(ework->type));
9094 os_memcpy(ework->type + 4, cmd, type_len);
9095 ework->type[4 + type_len] = '\0';
9096
9097 wpa_s->ext_work_id++;
9098 if (wpa_s->ext_work_id == 0)
9099 wpa_s->ext_work_id++;
9100 ework->id = wpa_s->ext_work_id;
9101
9102 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
9103 ework) < 0) {
9104 os_free(ework);
9105 return -1;
9106 }
9107
9108 ret = os_snprintf(buf, buflen, "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009109 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009110 return -1;
9111 return ret;
9112}
9113
9114
9115static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
9116{
9117 struct wpa_radio_work *work;
9118 unsigned int id = atoi(cmd);
9119
9120 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9121 {
9122 struct wpa_external_work *ework;
9123
9124 if (os_strncmp(work->type, "ext:", 4) != 0)
9125 continue;
9126 ework = work->ctx;
9127 if (id && ework->id != id)
9128 continue;
9129 wpa_dbg(wpa_s, MSG_DEBUG,
9130 "Completed external radio work %u (%s)",
9131 ework->id, ework->type);
9132 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009133 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009134 radio_work_done(work);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07009135 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009136 return 3; /* "OK\n" */
9137 }
9138
9139 return -1;
9140}
9141
9142
9143static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
9144 char *buf, size_t buflen)
9145{
9146 if (os_strcmp(cmd, "show") == 0)
9147 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
9148 if (os_strncmp(cmd, "add ", 4) == 0)
9149 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
9150 if (os_strncmp(cmd, "done ", 5) == 0)
9151 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
9152 return -1;
9153}
9154
9155
9156void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
9157{
9158 struct wpa_radio_work *work, *tmp;
9159
Dmitry Shmidt18463232014-01-24 12:29:41 -08009160 if (!wpa_s || !wpa_s->radio)
9161 return;
9162
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009163 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
9164 struct wpa_radio_work, list) {
9165 struct wpa_external_work *ework;
9166
9167 if (os_strncmp(work->type, "ext:", 4) != 0)
9168 continue;
9169 ework = work->ctx;
9170 wpa_dbg(wpa_s, MSG_DEBUG,
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07009171 "Flushing%s external radio work %u (%s)",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009172 work->started ? " started" : "", ework->id,
9173 ework->type);
9174 if (work->started)
9175 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9176 work, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009177 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07009178 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009179 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07009180}
9181
9182
Dmitry Shmidt051af732013-10-22 13:52:46 -07009183static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
9184{
9185 struct wpa_supplicant *wpa_s = eloop_ctx;
9186 eapol_sm_notify_ctrl_response(wpa_s->eapol);
9187}
9188
9189
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009190static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
9191 unsigned int *scan_id_count, int scan_id[])
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009192{
9193 const char *pos = value;
9194
9195 while (pos) {
9196 if (*pos == ' ' || *pos == '\0')
9197 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009198 if (*scan_id_count == MAX_SCAN_ID)
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009199 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009200 scan_id[(*scan_id_count)++] = atoi(pos);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009201 pos = os_strchr(pos, ',');
9202 if (pos)
9203 pos++;
9204 }
9205
9206 return 0;
9207}
9208
9209
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009210static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9211 char *reply, int reply_size, int *reply_len)
9212{
9213 char *pos;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009214 unsigned int manual_scan_passive = 0;
9215 unsigned int manual_scan_use_id = 0;
9216 unsigned int manual_scan_only_new = 0;
9217 unsigned int scan_only = 0;
9218 unsigned int scan_id_count = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00009219 unsigned int manual_non_coloc_6ghz = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009220 int scan_id[MAX_SCAN_ID];
9221 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
9222 struct wpa_scan_results *scan_res);
9223 int *manual_scan_freqs = NULL;
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009224 struct wpa_ssid_value *ssid = NULL, *ns;
9225 unsigned int ssid_count = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009226
9227 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
9228 *reply_len = -1;
9229 return;
9230 }
9231
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009232 if (radio_work_pending(wpa_s, "scan")) {
9233 wpa_printf(MSG_DEBUG,
9234 "Pending scan scheduled - reject new request");
9235 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9236 return;
9237 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009238
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07009239#ifdef CONFIG_INTERWORKING
9240 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
9241 wpa_printf(MSG_DEBUG,
9242 "Interworking select in progress - reject new scan");
9243 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9244 return;
9245 }
9246#endif /* CONFIG_INTERWORKING */
9247
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009248 if (params) {
9249 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009250 scan_only = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009251
9252 pos = os_strstr(params, "freq=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009253 if (pos) {
9254 manual_scan_freqs = freq_range_to_channel_list(wpa_s,
9255 pos + 5);
9256 if (manual_scan_freqs == NULL) {
9257 *reply_len = -1;
9258 goto done;
9259 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009260 }
9261
9262 pos = os_strstr(params, "passive=");
9263 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009264 manual_scan_passive = !!atoi(pos + 8);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009265
9266 pos = os_strstr(params, "use_id=");
9267 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009268 manual_scan_use_id = atoi(pos + 7);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009269
9270 pos = os_strstr(params, "only_new=1");
9271 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009272 manual_scan_only_new = 1;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009273
9274 pos = os_strstr(params, "scan_id=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009275 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
9276 scan_id) < 0) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009277 *reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009278 goto done;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009279 }
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009280
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009281 pos = os_strstr(params, "bssid=");
9282 if (pos) {
9283 u8 bssid[ETH_ALEN];
9284
9285 pos += 6;
9286 if (hwaddr_aton(pos, bssid)) {
9287 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
9288 *reply_len = -1;
9289 goto done;
9290 }
9291 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07009292
9293 wpa_s->next_scan_bssid_wildcard_ssid =
9294 os_strstr(params, "wildcard_ssid=1") != NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009295 }
9296
Sunil8cd6f4d2022-06-28 18:40:46 +00009297 pos = os_strstr(params, "non_coloc_6ghz=");
9298 if (pos)
9299 manual_non_coloc_6ghz = !!atoi(pos + 15);
9300
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009301 pos = params;
9302 while (pos && *pos != '\0') {
9303 if (os_strncmp(pos, "ssid ", 5) == 0) {
9304 char *end;
9305
9306 pos += 5;
9307 end = pos;
9308 while (*end) {
9309 if (*end == '\0' || *end == ' ')
9310 break;
9311 end++;
9312 }
9313
9314 ns = os_realloc_array(
9315 ssid, ssid_count + 1,
9316 sizeof(struct wpa_ssid_value));
9317 if (ns == NULL) {
9318 *reply_len = -1;
9319 goto done;
9320 }
9321 ssid = ns;
9322
9323 if ((end - pos) & 0x01 ||
9324 end - pos > 2 * SSID_MAX_LEN ||
9325 hexstr2bin(pos, ssid[ssid_count].ssid,
9326 (end - pos) / 2) < 0) {
9327 wpa_printf(MSG_DEBUG,
9328 "Invalid SSID value '%s'",
9329 pos);
9330 *reply_len = -1;
9331 goto done;
9332 }
9333 ssid[ssid_count].ssid_len = (end - pos) / 2;
9334 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
9335 ssid[ssid_count].ssid,
9336 ssid[ssid_count].ssid_len);
9337 ssid_count++;
9338 pos = end;
9339 }
9340
9341 pos = os_strchr(pos, ' ');
9342 if (pos)
9343 pos++;
9344 }
9345 }
9346
9347 wpa_s->num_ssids_from_scan_req = ssid_count;
9348 os_free(wpa_s->ssids_from_scan_req);
9349 if (ssid_count) {
9350 wpa_s->ssids_from_scan_req = ssid;
9351 ssid = NULL;
9352 } else {
9353 wpa_s->ssids_from_scan_req = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009354 }
9355
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009356 if (scan_only)
9357 scan_res_handler = scan_only_handler;
9358 else if (wpa_s->scan_res_handler == scan_only_handler)
9359 scan_res_handler = NULL;
9360 else
9361 scan_res_handler = wpa_s->scan_res_handler;
9362
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009363 if (!wpa_s->sched_scanning && !wpa_s->scanning &&
9364 ((wpa_s->wpa_state <= WPA_SCANNING) ||
9365 (wpa_s->wpa_state == WPA_COMPLETED))) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009366 wpa_s->manual_scan_passive = manual_scan_passive;
9367 wpa_s->manual_scan_use_id = manual_scan_use_id;
9368 wpa_s->manual_scan_only_new = manual_scan_only_new;
9369 wpa_s->scan_id_count = scan_id_count;
Sunil8cd6f4d2022-06-28 18:40:46 +00009370 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009371 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9372 wpa_s->scan_res_handler = scan_res_handler;
9373 os_free(wpa_s->manual_scan_freqs);
9374 wpa_s->manual_scan_freqs = manual_scan_freqs;
9375 manual_scan_freqs = NULL;
9376
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009377 wpa_s->normal_scans = 0;
9378 wpa_s->scan_req = MANUAL_SCAN_REQ;
9379 wpa_s->after_wps = 0;
9380 wpa_s->known_wps_freq = 0;
9381 wpa_supplicant_req_scan(wpa_s, 0, 0);
9382 if (wpa_s->manual_scan_use_id) {
9383 wpa_s->manual_scan_id++;
9384 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9385 wpa_s->manual_scan_id);
9386 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9387 wpa_s->manual_scan_id);
9388 }
9389 } else if (wpa_s->sched_scanning) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009390 wpa_s->manual_scan_passive = manual_scan_passive;
9391 wpa_s->manual_scan_use_id = manual_scan_use_id;
9392 wpa_s->manual_scan_only_new = manual_scan_only_new;
9393 wpa_s->scan_id_count = scan_id_count;
Sunil8cd6f4d2022-06-28 18:40:46 +00009394 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009395 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9396 wpa_s->scan_res_handler = scan_res_handler;
9397 os_free(wpa_s->manual_scan_freqs);
9398 wpa_s->manual_scan_freqs = manual_scan_freqs;
9399 manual_scan_freqs = NULL;
9400
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009401 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9402 wpa_supplicant_cancel_sched_scan(wpa_s);
9403 wpa_s->scan_req = MANUAL_SCAN_REQ;
9404 wpa_supplicant_req_scan(wpa_s, 0, 0);
9405 if (wpa_s->manual_scan_use_id) {
9406 wpa_s->manual_scan_id++;
9407 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9408 wpa_s->manual_scan_id);
9409 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9410 wpa_s->manual_scan_id);
9411 }
9412 } else {
9413 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9414 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9415 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009416
9417done:
9418 os_free(manual_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009419 os_free(ssid);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009420}
9421
9422
Dmitry Shmidt818ea482014-03-10 13:15:21 -07009423#ifdef CONFIG_TESTING_OPTIONS
9424
9425static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9426 unsigned int freq, const u8 *dst,
9427 const u8 *src, const u8 *bssid,
9428 const u8 *data, size_t data_len,
9429 enum offchannel_send_action_result
9430 result)
9431{
9432 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9433 " src=" MACSTR " bssid=" MACSTR " result=%s",
9434 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9435 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9436 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9437 "NO_ACK" : "FAILED"));
9438}
9439
9440
9441static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9442{
9443 char *pos, *param;
9444 size_t len;
9445 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9446 int res, used;
9447 int freq = 0, no_cck = 0, wait_time = 0;
9448
9449 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9450 * <action=Action frame payload> */
9451
9452 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9453
9454 pos = cmd;
9455 used = hwaddr_aton2(pos, da);
9456 if (used < 0)
9457 return -1;
9458 pos += used;
9459 while (*pos == ' ')
9460 pos++;
9461 used = hwaddr_aton2(pos, bssid);
9462 if (used < 0)
9463 return -1;
9464 pos += used;
9465
9466 param = os_strstr(pos, " freq=");
9467 if (param) {
9468 param += 6;
9469 freq = atoi(param);
9470 }
9471
9472 param = os_strstr(pos, " no_cck=");
9473 if (param) {
9474 param += 8;
9475 no_cck = atoi(param);
9476 }
9477
9478 param = os_strstr(pos, " wait_time=");
9479 if (param) {
9480 param += 11;
9481 wait_time = atoi(param);
9482 }
9483
9484 param = os_strstr(pos, " action=");
9485 if (param == NULL)
9486 return -1;
9487 param += 8;
9488
9489 len = os_strlen(param);
9490 if (len & 1)
9491 return -1;
9492 len /= 2;
9493
9494 buf = os_malloc(len);
9495 if (buf == NULL)
9496 return -1;
9497
9498 if (hexstr2bin(param, buf, len) < 0) {
9499 os_free(buf);
9500 return -1;
9501 }
9502
9503 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9504 buf, len, wait_time,
9505 wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9506 os_free(buf);
9507 return res;
9508}
9509
9510
9511static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9512{
9513 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9514 offchannel_send_action_done(wpa_s);
9515}
9516
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009517
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009518static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9519 char *cmd)
9520{
9521 char *pos, *param;
9522 size_t len;
9523 u8 *buf;
9524 int freq = 0, datarate = 0, ssi_signal = 0;
9525 union wpa_event_data event;
9526
9527 if (!wpa_s->ext_mgmt_frame_handling)
9528 return -1;
9529
9530 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9531
9532 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9533
9534 pos = cmd;
9535 param = os_strstr(pos, "freq=");
9536 if (param) {
9537 param += 5;
9538 freq = atoi(param);
9539 }
9540
9541 param = os_strstr(pos, " datarate=");
9542 if (param) {
9543 param += 10;
9544 datarate = atoi(param);
9545 }
9546
9547 param = os_strstr(pos, " ssi_signal=");
9548 if (param) {
9549 param += 12;
9550 ssi_signal = atoi(param);
9551 }
9552
9553 param = os_strstr(pos, " frame=");
9554 if (param == NULL)
9555 return -1;
9556 param += 7;
9557
9558 len = os_strlen(param);
9559 if (len & 1)
9560 return -1;
9561 len /= 2;
9562
9563 buf = os_malloc(len);
9564 if (buf == NULL)
9565 return -1;
9566
9567 if (hexstr2bin(param, buf, len) < 0) {
9568 os_free(buf);
9569 return -1;
9570 }
9571
9572 os_memset(&event, 0, sizeof(event));
9573 event.rx_mgmt.freq = freq;
9574 event.rx_mgmt.frame = buf;
9575 event.rx_mgmt.frame_len = len;
9576 event.rx_mgmt.ssi_signal = ssi_signal;
9577 event.rx_mgmt.datarate = datarate;
9578 wpa_s->ext_mgmt_frame_handling = 0;
9579 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9580 wpa_s->ext_mgmt_frame_handling = 1;
9581
9582 os_free(buf);
9583
9584 return 0;
9585}
9586
9587
Paul Stewart092955c2017-02-06 09:13:09 -08009588static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9589 char *param)
9590{
9591 struct wpa_scan_res *res;
9592 struct os_reltime now;
9593 char *pos, *end;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009594 int ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -08009595
9596 if (!param)
9597 return -1;
9598
9599 if (os_strcmp(param, "START") == 0) {
9600 wpa_bss_update_start(wpa_s);
9601 return 0;
9602 }
9603
9604 if (os_strcmp(param, "END") == 0) {
9605 wpa_bss_update_end(wpa_s, NULL, 1);
9606 return 0;
9607 }
9608
9609 if (os_strncmp(param, "BSS ", 4) != 0)
9610 return -1;
9611 param += 3;
9612
9613 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9614 if (!res)
9615 return -1;
9616
9617 pos = os_strstr(param, " flags=");
9618 if (pos)
9619 res->flags = strtol(pos + 7, NULL, 16);
9620
9621 pos = os_strstr(param, " bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009622 if (pos && hwaddr_aton(pos + 7, res->bssid))
9623 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009624
9625 pos = os_strstr(param, " freq=");
9626 if (pos)
9627 res->freq = atoi(pos + 6);
9628
9629 pos = os_strstr(param, " beacon_int=");
9630 if (pos)
9631 res->beacon_int = atoi(pos + 12);
9632
9633 pos = os_strstr(param, " caps=");
9634 if (pos)
9635 res->caps = strtol(pos + 6, NULL, 16);
9636
9637 pos = os_strstr(param, " qual=");
9638 if (pos)
9639 res->qual = atoi(pos + 6);
9640
9641 pos = os_strstr(param, " noise=");
9642 if (pos)
9643 res->noise = atoi(pos + 7);
9644
9645 pos = os_strstr(param, " level=");
9646 if (pos)
9647 res->level = atoi(pos + 7);
9648
9649 pos = os_strstr(param, " tsf=");
9650 if (pos)
9651 res->tsf = strtoll(pos + 5, NULL, 16);
9652
9653 pos = os_strstr(param, " age=");
9654 if (pos)
9655 res->age = atoi(pos + 5);
9656
9657 pos = os_strstr(param, " est_throughput=");
9658 if (pos)
9659 res->est_throughput = atoi(pos + 16);
9660
9661 pos = os_strstr(param, " snr=");
9662 if (pos)
9663 res->snr = atoi(pos + 5);
9664
9665 pos = os_strstr(param, " parent_tsf=");
9666 if (pos)
9667 res->parent_tsf = strtoll(pos + 7, NULL, 16);
9668
9669 pos = os_strstr(param, " tsf_bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009670 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9671 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009672
9673 pos = os_strstr(param, " ie=");
9674 if (pos) {
9675 pos += 4;
9676 end = os_strchr(pos, ' ');
9677 if (!end)
9678 end = pos + os_strlen(pos);
9679 res->ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009680 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9681 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009682 }
9683
9684 pos = os_strstr(param, " beacon_ie=");
9685 if (pos) {
9686 pos += 11;
9687 end = os_strchr(pos, ' ');
9688 if (!end)
9689 end = pos + os_strlen(pos);
9690 res->beacon_ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009691 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9692 res->beacon_ie_len))
9693 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009694 }
9695
9696 os_get_reltime(&now);
9697 wpa_bss_update_scan_res(wpa_s, res, &now);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009698 ret = 0;
9699fail:
Paul Stewart092955c2017-02-06 09:13:09 -08009700 os_free(res);
9701
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009702 return ret;
Paul Stewart092955c2017-02-06 09:13:09 -08009703}
9704
9705
Hai Shaloma20dcd72022-02-04 13:43:00 -08009706static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9707 char *param)
9708{
9709 union wpa_event_data event;
9710 struct assoc_info *ai;
9711 char *ctx = NULL;
9712 int ret = -1;
9713 struct wpabuf *req_ies = NULL;
9714 struct wpabuf *resp_ies = NULL;
9715 struct wpabuf *resp_frame = NULL;
9716 struct wpabuf *beacon_ies = NULL;
9717 struct wpabuf *key_replay_ctr = NULL;
9718 struct wpabuf *ptk_kck = NULL;
9719 struct wpabuf *ptk_kek = NULL;
9720 struct wpabuf *fils_pmk = NULL;
9721 char *str, *pos;
9722 u8 addr[ETH_ALEN];
9723 u8 fils_pmkid[PMKID_LEN];
9724
9725 os_memset(&event, 0, sizeof(event));
9726 ai = &event.assoc_info;
9727
9728 while ((str = str_token(param, " ", &ctx))) {
9729 pos = os_strchr(str, '=');
9730 if (!pos)
9731 goto fail;
9732 *pos++ = '\0';
9733
9734 if (os_strcmp(str, "reassoc") == 0) {
9735 ai->reassoc = atoi(pos);
9736 } else if (os_strcmp(str, "req_ies") == 0) {
9737 wpabuf_free(req_ies);
9738 req_ies = wpabuf_parse_bin(pos);
9739 if (!req_ies)
9740 goto fail;
9741 ai->req_ies = wpabuf_head(req_ies);
9742 ai->req_ies_len = wpabuf_len(req_ies);
9743 } else if (os_strcmp(str, "resp_ies") == 0) {
9744 wpabuf_free(resp_ies);
9745 resp_ies = wpabuf_parse_bin(pos);
9746 if (!resp_ies)
9747 goto fail;
9748 ai->resp_ies = wpabuf_head(resp_ies);
9749 ai->resp_ies_len = wpabuf_len(resp_ies);
9750 } else if (os_strcmp(str, "resp_frame") == 0) {
9751 wpabuf_free(resp_frame);
9752 resp_frame = wpabuf_parse_bin(pos);
9753 if (!resp_frame)
9754 goto fail;
9755 ai->resp_frame = wpabuf_head(resp_frame);
9756 ai->resp_frame_len = wpabuf_len(resp_frame);
9757 } else if (os_strcmp(str, "beacon_ies") == 0) {
9758 wpabuf_free(beacon_ies);
9759 beacon_ies = wpabuf_parse_bin(pos);
9760 if (!beacon_ies)
9761 goto fail;
9762 ai->beacon_ies = wpabuf_head(beacon_ies);
9763 ai->beacon_ies_len = wpabuf_len(beacon_ies);
9764 } else if (os_strcmp(str, "freq") == 0) {
9765 ai->freq = atoi(pos);
9766 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9767 ai->wmm_params.info_bitmap = atoi(pos);
9768 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9769 ai->wmm_params.uapsd_queues = atoi(pos);
9770 } else if (os_strcmp(str, "addr") == 0) {
9771 if (hwaddr_aton(pos, addr))
9772 goto fail;
9773 ai->addr = addr;
9774 } else if (os_strcmp(str, "authorized") == 0) {
9775 ai->authorized = atoi(pos);
9776 } else if (os_strcmp(str, "key_replay_ctr") == 0) {
9777 wpabuf_free(key_replay_ctr);
9778 key_replay_ctr = wpabuf_parse_bin(pos);
9779 if (!key_replay_ctr)
9780 goto fail;
9781 ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9782 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9783 } else if (os_strcmp(str, "ptk_kck") == 0) {
9784 wpabuf_free(ptk_kck);
9785 ptk_kck = wpabuf_parse_bin(pos);
9786 if (!ptk_kck)
9787 goto fail;
9788 ai->ptk_kck = wpabuf_head(ptk_kck);
9789 ai->ptk_kck_len = wpabuf_len(ptk_kck);
9790 } else if (os_strcmp(str, "ptk_kek") == 0) {
9791 wpabuf_free(ptk_kek);
9792 ptk_kek = wpabuf_parse_bin(pos);
9793 if (!ptk_kek)
9794 goto fail;
9795 ai->ptk_kek = wpabuf_head(ptk_kek);
9796 ai->ptk_kek_len = wpabuf_len(ptk_kek);
9797 } else if (os_strcmp(str, "subnet_status") == 0) {
9798 ai->subnet_status = atoi(pos);
9799 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9800 ai->fils_erp_next_seq_num = atoi(pos);
9801 } else if (os_strcmp(str, "fils_pmk") == 0) {
9802 wpabuf_free(fils_pmk);
9803 fils_pmk = wpabuf_parse_bin(pos);
9804 if (!fils_pmk)
9805 goto fail;
9806 ai->fils_pmk = wpabuf_head(fils_pmk);
9807 ai->fils_pmk_len = wpabuf_len(fils_pmk);
9808 } else if (os_strcmp(str, "fils_pmkid") == 0) {
9809 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9810 goto fail;
9811 ai->fils_pmkid = fils_pmkid;
9812 } else {
9813 goto fail;
9814 }
9815 }
9816
9817 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9818 ret = 0;
9819fail:
9820 wpabuf_free(req_ies);
9821 wpabuf_free(resp_ies);
9822 wpabuf_free(resp_frame);
9823 wpabuf_free(beacon_ies);
9824 wpabuf_free(key_replay_ctr);
9825 wpabuf_free(ptk_kck);
9826 wpabuf_free(ptk_kek);
9827 wpabuf_free(fils_pmk);
9828 return ret;
9829}
9830
9831
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009832static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9833{
9834 char *pos, *param;
9835 union wpa_event_data event;
9836 enum wpa_event_type ev;
9837
9838 /* <event name> [parameters..] */
9839
9840 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
9841
9842 pos = cmd;
9843 param = os_strchr(pos, ' ');
9844 if (param)
9845 *param++ = '\0';
9846
9847 os_memset(&event, 0, sizeof(event));
9848
9849 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
9850 ev = EVENT_INTERFACE_ENABLED;
9851 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
9852 ev = EVENT_INTERFACE_DISABLED;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07009853 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
9854 ev = EVENT_AVOID_FREQUENCIES;
9855 if (param == NULL)
9856 param = "";
9857 if (freq_range_list_parse(&event.freq_range, param) < 0)
9858 return -1;
9859 wpa_supplicant_event(wpa_s, ev, &event);
9860 os_free(event.freq_range.range);
9861 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -08009862 } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
9863 return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
Hai Shaloma20dcd72022-02-04 13:43:00 -08009864 } else if (os_strcmp(cmd, "ASSOC") == 0) {
9865 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009866 } else {
9867 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
9868 cmd);
9869 return -1;
9870 }
9871
9872 wpa_supplicant_event(wpa_s, ev, &event);
9873
9874 return 0;
9875}
9876
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009877
9878static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
9879{
9880 char *pos;
9881 u8 src[ETH_ALEN], *buf;
9882 int used;
9883 size_t len;
9884
9885 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
9886
9887 pos = cmd;
9888 used = hwaddr_aton2(pos, src);
9889 if (used < 0)
9890 return -1;
9891 pos += used;
9892 while (*pos == ' ')
9893 pos++;
9894
9895 len = os_strlen(pos);
9896 if (len & 1)
9897 return -1;
9898 len /= 2;
9899
9900 buf = os_malloc(len);
9901 if (buf == NULL)
9902 return -1;
9903
9904 if (hexstr2bin(pos, buf, len) < 0) {
9905 os_free(buf);
9906 return -1;
9907 }
9908
Sunil8cd6f4d2022-06-28 18:40:46 +00009909 wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009910 os_free(buf);
9911
9912 return 0;
9913}
9914
9915
Hai Shaloma20dcd72022-02-04 13:43:00 -08009916static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
9917{
9918 char *pos;
9919 u8 dst[ETH_ALEN], *buf;
9920 int used, ret;
9921 size_t len;
9922 unsigned int prev;
9923
9924 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
9925
9926 pos = cmd;
9927 used = hwaddr_aton2(pos, dst);
9928 if (used < 0)
9929 return -1;
9930 pos += used;
9931 while (*pos == ' ')
9932 pos++;
9933
9934 len = os_strlen(pos);
9935 if (len & 1)
9936 return -1;
9937 len /= 2;
9938
9939 buf = os_malloc(len);
9940 if (!buf || hexstr2bin(pos, buf, len) < 0) {
9941 os_free(buf);
9942 return -1;
9943 }
9944
9945 prev = wpa_s->ext_eapol_frame_io;
9946 wpa_s->ext_eapol_frame_io = 0;
9947 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
9948 wpa_s->ext_eapol_frame_io = prev;
9949 os_free(buf);
9950
9951 return ret;
9952}
9953
9954
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009955static u16 ipv4_hdr_checksum(const void *buf, size_t len)
9956{
9957 size_t i;
9958 u32 sum = 0;
9959 const u16 *pos = buf;
9960
9961 for (i = 0; i < len / 2; i++)
9962 sum += *pos++;
9963
9964 while (sum >> 16)
9965 sum = (sum & 0xffff) + (sum >> 16);
9966
9967 return sum ^ 0xffff;
9968}
9969
9970
9971#define HWSIM_PACKETLEN 1500
9972#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
9973
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07009974static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
9975 size_t len)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009976{
9977 struct wpa_supplicant *wpa_s = ctx;
9978 const struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -07009979 struct ip ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009980 const u8 *pos;
9981 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -08009982 char extra[30];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009983
Hai Shalom74f70d42019-02-11 14:42:39 -08009984 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
9985 wpa_printf(MSG_DEBUG,
9986 "test data: RX - ignore unexpected length %d",
9987 (int) len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009988 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08009989 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009990
9991 eth = (const struct ether_header *) buf;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009992 os_memcpy(&ip, eth + 1, sizeof(ip));
9993 pos = &buf[sizeof(*eth) + sizeof(ip)];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009994
Hai Shalomfdcde762020-04-02 11:19:20 -07009995 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
Hai Shalom74f70d42019-02-11 14:42:39 -08009996 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07009997 "test data: RX - ignore unexpected IP header");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009998 return;
Hai Shalom39bc25d2019-02-06 16:32:13 -08009999 }
Hai Shalombf6e0ba2019-02-11 12:01:50 -080010000
Hai Shalomfdcde762020-04-02 11:19:20 -070010001 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
Hai Shalom74f70d42019-02-11 14:42:39 -080010002 if (*pos != (u8) i) {
10003 wpa_printf(MSG_DEBUG,
10004 "test data: RX - ignore mismatching payload");
10005 return;
10006 }
10007 pos++;
10008 }
10009 extra[0] = '\0';
Hai Shalomfdcde762020-04-02 11:19:20 -070010010 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
10011 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
Hai Shalom74f70d42019-02-11 14:42:39 -080010012 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
10013 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010014}
10015
10016
10017static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
10018 char *cmd)
10019{
10020 int enabled = atoi(cmd);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080010021 char *pos;
10022 const char *ifname;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010023
10024 if (!enabled) {
10025 if (wpa_s->l2_test) {
10026 l2_packet_deinit(wpa_s->l2_test);
10027 wpa_s->l2_test = NULL;
10028 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
10029 }
10030 return 0;
10031 }
10032
10033 if (wpa_s->l2_test)
10034 return 0;
10035
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080010036 pos = os_strstr(cmd, " ifname=");
10037 if (pos)
10038 ifname = pos + 8;
10039 else
10040 ifname = wpa_s->ifname;
10041
10042 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010043 ETHERTYPE_IP, wpas_data_test_rx,
10044 wpa_s, 1);
10045 if (wpa_s->l2_test == NULL)
10046 return -1;
10047
10048 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
10049
10050 return 0;
10051}
10052
10053
10054static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
10055{
10056 u8 dst[ETH_ALEN], src[ETH_ALEN];
Hai Shalom74f70d42019-02-11 14:42:39 -080010057 char *pos, *pos2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010058 int used;
10059 long int val;
10060 u8 tos;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010061 u8 buf[2 + HWSIM_PACKETLEN];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010062 struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -070010063 struct ip *ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010064 u8 *dpos;
10065 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -080010066 size_t send_len = HWSIM_IP_LEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010067
10068 if (wpa_s->l2_test == NULL)
10069 return -1;
10070
Hai Shalom74f70d42019-02-11 14:42:39 -080010071 /* format: <dst> <src> <tos> [len=<length>] */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010072
10073 pos = cmd;
10074 used = hwaddr_aton2(pos, dst);
10075 if (used < 0)
10076 return -1;
10077 pos += used;
10078 while (*pos == ' ')
10079 pos++;
10080 used = hwaddr_aton2(pos, src);
10081 if (used < 0)
10082 return -1;
10083 pos += used;
10084
Hai Shalom74f70d42019-02-11 14:42:39 -080010085 val = strtol(pos, &pos2, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010086 if (val < 0 || val > 0xff)
10087 return -1;
10088 tos = val;
10089
Hai Shalom74f70d42019-02-11 14:42:39 -080010090 pos = os_strstr(pos2, " len=");
10091 if (pos) {
10092 i = atoi(pos + 5);
10093 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
10094 return -1;
10095 send_len = i;
10096 }
10097
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010098 eth = (struct ether_header *) &buf[2];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010099 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
10100 os_memcpy(eth->ether_shost, src, ETH_ALEN);
10101 eth->ether_type = htons(ETHERTYPE_IP);
Hai Shalomfdcde762020-04-02 11:19:20 -070010102 ip = (struct ip *) (eth + 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010103 os_memset(ip, 0, sizeof(*ip));
Hai Shalomfdcde762020-04-02 11:19:20 -070010104 ip->ip_hl = 5;
10105 ip->ip_v = 4;
10106 ip->ip_ttl = 64;
10107 ip->ip_tos = tos;
10108 ip->ip_len = htons(send_len);
10109 ip->ip_p = 1;
10110 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
10111 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
10112 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010113 dpos = (u8 *) (ip + 1);
Hai Shalom74f70d42019-02-11 14:42:39 -080010114 for (i = 0; i < send_len - sizeof(*ip); i++)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010115 *dpos++ = i;
10116
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010117 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
Hai Shalom74f70d42019-02-11 14:42:39 -080010118 sizeof(struct ether_header) + send_len) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010119 return -1;
10120
10121 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
10122 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
10123
10124 return 0;
10125}
10126
10127
10128static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
10129 char *cmd)
10130{
10131 u8 *buf;
10132 struct ether_header *eth;
10133 struct l2_packet_data *l2 = NULL;
10134 size_t len;
10135 u16 ethertype;
10136 int res = -1;
10137
10138 len = os_strlen(cmd);
10139 if (len & 1 || len < ETH_HLEN * 2)
10140 return -1;
10141 len /= 2;
10142
10143 buf = os_malloc(len);
10144 if (buf == NULL)
10145 return -1;
10146
10147 if (hexstr2bin(cmd, buf, len) < 0)
10148 goto done;
10149
10150 eth = (struct ether_header *) buf;
10151 ethertype = ntohs(eth->ether_type);
10152
10153 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
10154 wpas_data_test_rx, wpa_s, 1);
10155 if (l2 == NULL)
10156 goto done;
10157
10158 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
10159 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
10160done:
10161 if (l2)
10162 l2_packet_deinit(l2);
10163 os_free(buf);
10164
10165 return res < 0 ? -1 : 0;
10166}
10167
Dmitry Shmidtff787d52015-01-12 13:01:47 -080010168
Jouni Malinenc4818362015-10-04 11:45:13 +030010169static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
10170{
10171 struct wpa_supplicant *wpa_s = eloop_ctx;
10172 int i, count = (intptr_t) timeout_ctx;
10173
10174 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
10175 count);
10176 for (i = 0; i < count; i++) {
10177 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
10178 i + 1, count);
10179 }
10180}
10181
10182
10183static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
10184{
10185 int count;
10186
10187 count = atoi(cmd);
10188 if (count <= 0)
10189 return -1;
10190
10191 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
10192 (void *) (intptr_t) count);
10193}
10194
Dmitry Shmidt818ea482014-03-10 13:15:21 -070010195
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010196static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010197{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010198 struct wpabuf *buf;
10199 size_t len;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010200
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010201 len = os_strlen(val);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010202 if (len & 1)
10203 return -1;
10204 len /= 2;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010205
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010206 if (len == 0) {
10207 buf = NULL;
10208 } else {
10209 buf = wpabuf_alloc(len);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010210 if (!buf)
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010211 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010212
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010213 if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010214 wpabuf_free(buf);
10215 return -1;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010216 }
10217 }
10218
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010219 *ret = buf;
10220 return 0;
10221}
10222
10223
10224static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
10225 const char *cmd)
10226{
10227 struct wpabuf *buf;
10228
10229 if (wpas_get_hex_buf(cmd, &buf) < 0)
10230 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010231 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
10232 return 0;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010233}
10234
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010235
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010236static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
10237 const char *cmd)
10238{
10239 struct wpabuf *buf;
10240
10241 if (wpas_get_hex_buf(cmd, &buf) < 0)
10242 return -1;
10243 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
10244 return 0;
10245}
10246
10247
10248static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
10249 const char *cmd)
10250{
10251 struct wpabuf *buf;
10252
10253 if (wpas_get_hex_buf(cmd, &buf) < 0)
10254 return -1;
10255 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
10256 return 0;
10257}
10258
10259
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010260static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
10261{
10262 u8 zero[WPA_TK_MAX_LEN];
10263
10264 if (wpa_s->last_tk_alg == WPA_ALG_NONE)
10265 return -1;
10266
10267 wpa_printf(MSG_INFO, "TESTING: Reset PN");
10268 os_memset(zero, 0, sizeof(zero));
10269
10270 /* First, use a zero key to avoid any possible duplicate key avoidance
10271 * in the driver. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000010272 if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010273 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -070010274 zero, wpa_s->last_tk_len,
10275 KEY_FLAG_PAIRWISE_RX_TX) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010276 return -1;
10277
10278 /* Set the previously configured key to reset its TSC/RSC */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000010279 return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg,
10280 wpa_s->last_tk_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010281 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -070010282 wpa_s->last_tk, wpa_s->last_tk_len,
10283 KEY_FLAG_PAIRWISE_RX_TX);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010284}
10285
10286
10287static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
10288{
10289 const char *pos = cmd;
10290 int error, pairwise;
10291
10292 error = atoi(pos);
10293 pos = os_strchr(pos, ' ');
10294 if (!pos)
10295 return -1;
10296 pairwise = atoi(pos);
10297 wpa_sm_key_request(wpa_s->wpa, error, pairwise);
10298 return 0;
10299}
10300
10301
10302static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
10303{
10304#ifdef CONFIG_SME
10305 struct wpa_driver_associate_params params;
10306 int ret;
10307
10308 os_memset(&params, 0, sizeof(params));
10309 params.bssid = wpa_s->bssid;
10310 params.ssid = wpa_s->sme.ssid;
10311 params.ssid_len = wpa_s->sme.ssid_len;
10312 params.freq.freq = wpa_s->sme.freq;
10313 if (wpa_s->last_assoc_req_wpa_ie) {
10314 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
10315 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
10316 }
10317 params.pairwise_suite = wpa_s->pairwise_cipher;
10318 params.group_suite = wpa_s->group_cipher;
10319 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
10320 params.key_mgmt_suite = wpa_s->key_mgmt;
10321 params.wpa_proto = wpa_s->wpa_proto;
10322 params.mgmt_frame_protection = wpa_s->sme.mfp;
10323 params.rrm_used = wpa_s->rrm.rrm_used;
10324 if (wpa_s->sme.prev_bssid_set)
10325 params.prev_bssid = wpa_s->sme.prev_bssid;
10326 wpa_printf(MSG_INFO, "TESTING: Resend association request");
10327 ret = wpa_drv_associate(wpa_s, &params);
10328 wpa_s->testing_resend_assoc = 1;
10329 return ret;
10330#else /* CONFIG_SME */
10331 return -1;
10332#endif /* CONFIG_SME */
10333}
10334
Hai Shaloma20dcd72022-02-04 13:43:00 -080010335
10336static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
10337 const char *cmd)
10338{
10339 u8 dtok = 1;
10340 int exponent = 10;
10341 int mantissa = 8192;
10342 u8 min_twt = 255;
10343 unsigned long long twt = 0;
10344 bool requestor = true;
10345 int setup_cmd = 0;
10346 bool trigger = true;
10347 bool implicit = true;
10348 bool flow_type = true;
10349 int flow_id = 0;
10350 bool protection = false;
10351 u8 twt_channel = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -070010352 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021,
10353 * Figure 9-687 - Control field format):
10354 * B4 = TWT Information Frame Disabled */
Hai Shaloma20dcd72022-02-04 13:43:00 -080010355 const char *tok_s;
10356
10357 tok_s = os_strstr(cmd, " dialog=");
10358 if (tok_s)
10359 dtok = atoi(tok_s + os_strlen(" dialog="));
10360
10361 tok_s = os_strstr(cmd, " exponent=");
10362 if (tok_s)
10363 exponent = atoi(tok_s + os_strlen(" exponent="));
10364
10365 tok_s = os_strstr(cmd, " mantissa=");
10366 if (tok_s)
10367 mantissa = atoi(tok_s + os_strlen(" mantissa="));
10368
10369 tok_s = os_strstr(cmd, " min_twt=");
10370 if (tok_s)
10371 min_twt = atoi(tok_s + os_strlen(" min_twt="));
10372
10373 tok_s = os_strstr(cmd, " setup_cmd=");
10374 if (tok_s)
10375 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10376
10377 tok_s = os_strstr(cmd, " twt=");
Sunil8cd6f4d2022-06-28 18:40:46 +000010378 if (tok_s &&
10379 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1)
10380 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080010381
10382 tok_s = os_strstr(cmd, " requestor=");
10383 if (tok_s)
10384 requestor = atoi(tok_s + os_strlen(" requestor="));
10385
10386 tok_s = os_strstr(cmd, " trigger=");
10387 if (tok_s)
10388 trigger = atoi(tok_s + os_strlen(" trigger="));
10389
10390 tok_s = os_strstr(cmd, " implicit=");
10391 if (tok_s)
10392 implicit = atoi(tok_s + os_strlen(" implicit="));
10393
10394 tok_s = os_strstr(cmd, " flow_type=");
10395 if (tok_s)
10396 flow_type = atoi(tok_s + os_strlen(" flow_type="));
10397
10398 tok_s = os_strstr(cmd, " flow_id=");
10399 if (tok_s)
10400 flow_id = atoi(tok_s + os_strlen(" flow_id="));
10401
10402 tok_s = os_strstr(cmd, " protection=");
10403 if (tok_s)
10404 protection = atoi(tok_s + os_strlen(" protection="));
10405
10406 tok_s = os_strstr(cmd, " twt_channel=");
10407 if (tok_s)
10408 twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10409
10410 tok_s = os_strstr(cmd, " control=");
10411 if (tok_s)
10412 control = atoi(tok_s + os_strlen(" control="));
10413
10414 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10415 setup_cmd, twt, requestor, trigger, implicit,
10416 flow_type, flow_id, protection, twt_channel,
10417 control);
10418}
10419
10420
10421static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10422 const char *cmd)
10423{
10424 u8 flags = 0x1;
10425 const char *tok_s;
10426
10427 tok_s = os_strstr(cmd, " flags=");
10428 if (tok_s)
10429 flags = atoi(tok_s + os_strlen(" flags="));
10430
10431 return wpas_twt_send_teardown(wpa_s, flags);
10432}
10433
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010434#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010435
10436
10437static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10438{
10439 char *pos = cmd;
10440 int frame;
10441 size_t len;
10442 struct wpabuf *buf;
10443 struct ieee802_11_elems elems;
10444
10445 frame = atoi(pos);
10446 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10447 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010448 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010449
10450 pos = os_strchr(pos, ' ');
10451 if (pos == NULL)
10452 return -1;
10453 pos++;
10454
10455 len = os_strlen(pos);
10456 if (len == 0)
10457 return 0;
10458 if (len & 1)
10459 return -1;
10460 len /= 2;
10461
10462 buf = wpabuf_alloc(len);
10463 if (buf == NULL)
10464 return -1;
10465
10466 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10467 wpabuf_free(buf);
10468 return -1;
10469 }
10470
10471 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10472 ParseFailed) {
10473 wpabuf_free(buf);
10474 return -1;
10475 }
10476
10477 if (wpa_s->vendor_elem[frame] == NULL) {
10478 wpa_s->vendor_elem[frame] = buf;
Hai Shalom60840252021-02-19 19:02:11 -080010479 goto update_ies;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010480 }
10481
10482 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10483 wpabuf_free(buf);
10484 return -1;
10485 }
10486
10487 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10488 wpabuf_free(buf);
Hai Shalom60840252021-02-19 19:02:11 -080010489
10490update_ies:
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010491 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010492
Hai Shalom60840252021-02-19 19:02:11 -080010493 if (frame == VENDOR_ELEM_PROBE_REQ ||
10494 frame == VENDOR_ELEM_PROBE_REQ_P2P)
10495 wpa_supplicant_set_default_scan_ies(wpa_s);
10496
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010497 return 0;
10498}
10499
10500
10501static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10502 char *buf, size_t buflen)
10503{
10504 int frame = atoi(cmd);
10505
10506 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10507 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010508 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010509
10510 if (wpa_s->vendor_elem[frame] == NULL)
10511 return 0;
10512
10513 return wpa_snprintf_hex(buf, buflen,
10514 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10515 wpabuf_len(wpa_s->vendor_elem[frame]));
10516}
10517
10518
10519static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10520{
10521 char *pos = cmd;
10522 int frame;
10523 size_t len;
10524 u8 *buf;
10525 struct ieee802_11_elems elems;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010526 int res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010527
10528 frame = atoi(pos);
10529 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10530 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010531 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010532
10533 pos = os_strchr(pos, ' ');
10534 if (pos == NULL)
10535 return -1;
10536 pos++;
10537
10538 if (*pos == '*') {
10539 wpabuf_free(wpa_s->vendor_elem[frame]);
10540 wpa_s->vendor_elem[frame] = NULL;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010541 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010542 return 0;
10543 }
10544
10545 if (wpa_s->vendor_elem[frame] == NULL)
10546 return -1;
10547
10548 len = os_strlen(pos);
10549 if (len == 0)
10550 return 0;
10551 if (len & 1)
10552 return -1;
10553 len /= 2;
10554
10555 buf = os_malloc(len);
10556 if (buf == NULL)
10557 return -1;
10558
10559 if (hexstr2bin(pos, buf, len) < 0) {
10560 os_free(buf);
10561 return -1;
10562 }
10563
10564 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10565 os_free(buf);
10566 return -1;
10567 }
10568
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010569 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010570 os_free(buf);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010571 return res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010572}
10573
10574
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010575#ifndef CONFIG_NO_RRM
10576
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010577static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10578{
10579 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010580 size_t len;
10581 const u8 *data;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010582
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010583 /*
10584 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10585 * BSSID[6]
10586 * BSSID Information[4]
10587 * Operating Class[1]
10588 * Channel Number[1]
10589 * PHY Type[1]
10590 * Optional Subelements[variable]
10591 */
10592#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10593
10594 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010595 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010596 goto out;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010597 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010598
10599 data = wpabuf_head_u8(neighbor_rep);
10600 len = wpabuf_len(neighbor_rep);
10601
10602 while (len >= 2 + NR_IE_MIN_LEN) {
10603 const u8 *nr;
10604 char lci[256 * 2 + 1];
10605 char civic[256 * 2 + 1];
10606 u8 nr_len = data[1];
10607 const u8 *pos = data, *end;
10608
10609 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
10610 nr_len < NR_IE_MIN_LEN) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010611 wpa_dbg(wpa_s, MSG_DEBUG,
10612 "CTRL: Invalid Neighbor Report element: id=%u len=%u",
10613 data[0], nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010614 goto out;
10615 }
10616
10617 if (2U + nr_len > len) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010618 wpa_dbg(wpa_s, MSG_DEBUG,
10619 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
10620 data[0], len, nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010621 goto out;
10622 }
10623 pos += 2;
10624 end = pos + nr_len;
10625
10626 nr = pos;
10627 pos += NR_IE_MIN_LEN;
10628
10629 lci[0] = '\0';
10630 civic[0] = '\0';
10631 while (end - pos > 2) {
10632 u8 s_id, s_len;
10633
10634 s_id = *pos++;
10635 s_len = *pos++;
10636 if (s_len > end - pos)
10637 goto out;
10638 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
10639 /* Measurement Token[1] */
10640 /* Measurement Report Mode[1] */
10641 /* Measurement Type[1] */
10642 /* Measurement Report[variable] */
10643 switch (pos[2]) {
10644 case MEASURE_TYPE_LCI:
10645 if (lci[0])
10646 break;
10647 wpa_snprintf_hex(lci, sizeof(lci),
10648 pos, s_len);
10649 break;
10650 case MEASURE_TYPE_LOCATION_CIVIC:
10651 if (civic[0])
10652 break;
10653 wpa_snprintf_hex(civic, sizeof(civic),
10654 pos, s_len);
10655 break;
10656 }
10657 }
10658
10659 pos += s_len;
10660 }
10661
10662 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10663 "bssid=" MACSTR
10664 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10665 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10666 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10667 nr[ETH_ALEN + 6],
10668 lci[0] ? " lci=" : "", lci,
10669 civic[0] ? " civic=" : "", civic);
10670
10671 data = end;
10672 len -= 2 + nr_len;
10673 }
10674
10675out:
10676 wpabuf_free(neighbor_rep);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010677}
10678
10679
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010680static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10681 char *cmd)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010682{
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010683 struct wpa_ssid_value ssid, *ssid_p = NULL;
10684 int ret, lci = 0, civic = 0;
10685 char *ssid_s;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010686
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010687 ssid_s = os_strstr(cmd, "ssid=");
10688 if (ssid_s) {
10689 if (ssid_parse(ssid_s + 5, &ssid)) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010690 wpa_msg(wpa_s, MSG_INFO,
10691 "CTRL: Send Neighbor Report: bad SSID");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010692 return -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010693 }
10694
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010695 ssid_p = &ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010696
10697 /*
10698 * Move cmd after the SSID text that may include "lci" or
10699 * "civic".
10700 */
10701 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10702 if (cmd)
10703 cmd++;
10704
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010705 }
10706
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010707 if (cmd && os_strstr(cmd, "lci"))
10708 lci = 1;
10709
10710 if (cmd && os_strstr(cmd, "civic"))
10711 civic = 1;
10712
10713 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010714 wpas_ctrl_neighbor_rep_cb,
10715 wpa_s);
10716
10717 return ret;
10718}
10719
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010720#endif /* CONFIG_NO_RRM */
10721
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010722
10723static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10724{
10725 eapol_sm_erp_flush(wpa_s->eapol);
10726 return 0;
10727}
10728
10729
10730static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10731 char *cmd)
10732{
10733 char *token, *context = NULL;
10734 unsigned int enable = ~0, type = 0;
10735 u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10736 u8 *addr = NULL, *mask = NULL;
10737
10738 while ((token = str_token(cmd, " ", &context))) {
10739 if (os_strcasecmp(token, "scan") == 0) {
10740 type |= MAC_ADDR_RAND_SCAN;
10741 } else if (os_strcasecmp(token, "sched") == 0) {
10742 type |= MAC_ADDR_RAND_SCHED_SCAN;
10743 } else if (os_strcasecmp(token, "pno") == 0) {
10744 type |= MAC_ADDR_RAND_PNO;
10745 } else if (os_strcasecmp(token, "all") == 0) {
10746 type = wpa_s->mac_addr_rand_supported;
10747 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
10748 enable = atoi(token + 7);
10749 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
10750 addr = _addr;
10751 if (hwaddr_aton(token + 5, addr)) {
10752 wpa_printf(MSG_INFO,
10753 "CTRL: Invalid MAC address: %s",
10754 token);
10755 return -1;
10756 }
10757 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
10758 mask = _mask;
10759 if (hwaddr_aton(token + 5, mask)) {
10760 wpa_printf(MSG_INFO,
10761 "CTRL: Invalid MAC address mask: %s",
10762 token);
10763 return -1;
10764 }
10765 } else {
10766 wpa_printf(MSG_INFO,
10767 "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10768 token);
10769 return -1;
10770 }
10771 }
10772
10773 if (!type) {
10774 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10775 return -1;
10776 }
10777
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010778 if (enable > 1) {
10779 wpa_printf(MSG_INFO,
10780 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10781 return -1;
10782 }
10783
Hai Shalom81f62d82019-07-22 12:10:00 -070010784 if (!enable)
10785 return wpas_disable_mac_addr_randomization(wpa_s, type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010786
Hai Shalom81f62d82019-07-22 12:10:00 -070010787 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010788}
10789
10790
Dmitry Shmidte4663042016-04-04 10:07:49 -070010791static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10792 char *buf, size_t buflen)
10793{
10794 size_t reply_len;
10795
10796 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10797#ifdef CONFIG_AP
10798 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10799 buflen - reply_len);
10800#endif /* CONFIG_AP */
10801 return reply_len;
10802}
10803
10804
10805static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10806{
Hai Shalom60840252021-02-19 19:02:11 -080010807 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidte4663042016-04-04 10:07:49 -070010808 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10809#ifdef CONFIG_AP
10810 wpas_ap_pmksa_cache_flush(wpa_s);
10811#endif /* CONFIG_AP */
10812}
10813
10814
Dmitry Shmidt29333592017-01-09 12:27:11 -080010815#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
10816
10817static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
10818 const char *cmd, char *buf, size_t buflen)
10819{
10820 struct rsn_pmksa_cache_entry *entry;
10821 struct wpa_ssid *ssid;
10822 char *pos, *pos2, *end;
10823 int ret;
10824 struct os_reltime now;
10825
10826 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10827 if (!ssid)
10828 return -1;
10829
10830 pos = buf;
10831 end = buf + buflen;
10832
10833 os_get_reltime(&now);
10834
10835 /*
10836 * Entry format:
10837 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10838 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010839 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080010840 */
10841
10842 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
10843 entry = entry->next) {
10844 if (entry->network_ctx != ssid)
10845 continue;
10846
10847 pos2 = pos;
10848 ret = os_snprintf(pos2, end - pos2, MACSTR " ",
10849 MAC2STR(entry->aa));
10850 if (os_snprintf_error(end - pos2, ret))
10851 break;
10852 pos2 += ret;
10853
10854 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
10855 PMKID_LEN);
10856
10857 ret = os_snprintf(pos2, end - pos2, " ");
10858 if (os_snprintf_error(end - pos2, ret))
10859 break;
10860 pos2 += ret;
10861
10862 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
10863 entry->pmk_len);
10864
10865 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
10866 (int) (entry->reauth_time - now.sec),
10867 (int) (entry->expiration - now.sec),
10868 entry->akmp,
10869 entry->opportunistic);
10870 if (os_snprintf_error(end - pos2, ret))
10871 break;
10872 pos2 += ret;
10873
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010874 if (entry->fils_cache_id_set) {
10875 ret = os_snprintf(pos2, end - pos2, " %02x%02x",
10876 entry->fils_cache_id[0],
10877 entry->fils_cache_id[1]);
10878 if (os_snprintf_error(end - pos2, ret))
10879 break;
10880 pos2 += ret;
10881 }
10882
Dmitry Shmidt29333592017-01-09 12:27:11 -080010883 ret = os_snprintf(pos2, end - pos2, "\n");
10884 if (os_snprintf_error(end - pos2, ret))
10885 break;
10886 pos2 += ret;
10887
10888 pos = pos2;
10889 }
10890
10891 return pos - buf;
10892}
10893
10894
10895static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
10896 char *cmd)
10897{
10898 struct rsn_pmksa_cache_entry *entry;
10899 struct wpa_ssid *ssid;
10900 char *pos, *pos2;
10901 int ret = -1;
10902 struct os_reltime now;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010903 int reauth_time = 0, expiration = 0, i;
Dmitry Shmidt29333592017-01-09 12:27:11 -080010904
10905 /*
10906 * Entry format:
10907 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
10908 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010909 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080010910 */
10911
10912 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
10913 if (!ssid)
10914 return -1;
10915
10916 pos = os_strchr(cmd, ' ');
10917 if (!pos)
10918 return -1;
10919 pos++;
10920
10921 entry = os_zalloc(sizeof(*entry));
10922 if (!entry)
10923 return -1;
10924
10925 if (hwaddr_aton(pos, entry->aa))
10926 goto fail;
10927
10928 pos = os_strchr(pos, ' ');
10929 if (!pos)
10930 goto fail;
10931 pos++;
10932
10933 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
10934 goto fail;
10935
10936 pos = os_strchr(pos, ' ');
10937 if (!pos)
10938 goto fail;
10939 pos++;
10940
10941 pos2 = os_strchr(pos, ' ');
10942 if (!pos2)
10943 goto fail;
10944 entry->pmk_len = (pos2 - pos) / 2;
10945 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
10946 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
10947 goto fail;
10948
10949 pos = os_strchr(pos, ' ');
10950 if (!pos)
10951 goto fail;
10952 pos++;
10953
10954 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
10955 &entry->akmp, &entry->opportunistic) != 4)
10956 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -080010957 if (reauth_time > expiration)
10958 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010959 for (i = 0; i < 4; i++) {
10960 pos = os_strchr(pos, ' ');
10961 if (!pos) {
10962 if (i < 3)
10963 goto fail;
10964 break;
10965 }
10966 pos++;
10967 }
10968 if (pos) {
10969 if (hexstr2bin(pos, entry->fils_cache_id,
10970 FILS_CACHE_ID_LEN) < 0)
10971 goto fail;
10972 entry->fils_cache_id_set = 1;
10973 }
Dmitry Shmidt29333592017-01-09 12:27:11 -080010974 os_get_reltime(&now);
10975 entry->expiration = now.sec + expiration;
10976 entry->reauth_time = now.sec + reauth_time;
10977
10978 entry->network_ctx = ssid;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000010979 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt29333592017-01-09 12:27:11 -080010980
Hai Shaloma20dcd72022-02-04 13:43:00 -080010981 entry->external = true;
10982
Dmitry Shmidt29333592017-01-09 12:27:11 -080010983 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
10984 entry = NULL;
10985 ret = 0;
10986fail:
10987 os_free(entry);
10988 return ret;
10989}
10990
Paul Stewart092955c2017-02-06 09:13:09 -080010991
10992#ifdef CONFIG_MESH
10993
10994static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
10995 const char *cmd, char *buf,
10996 size_t buflen)
10997{
10998 u8 spa[ETH_ALEN];
10999
11000 if (!wpa_s->ifmsh)
11001 return -1;
11002
11003 if (os_strcasecmp(cmd, "any") == 0)
11004 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
11005
11006 if (hwaddr_aton(cmd, spa))
11007 return -1;
11008
11009 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
11010}
11011
11012
11013static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
11014 char *cmd)
11015{
11016 /*
Hai Shalom60840252021-02-19 19:02:11 -080011017 * We do not check mesh interface existence because PMKSA should be
Paul Stewart092955c2017-02-06 09:13:09 -080011018 * stored before wpa_s->ifmsh creation to suppress commit message
11019 * creation.
11020 */
11021 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
11022}
11023
11024#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080011025#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
11026
11027
Paul Stewart092955c2017-02-06 09:13:09 -080011028#ifdef CONFIG_FILS
11029static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
11030 const char *cmd)
11031{
11032 struct fils_hlp_req *req;
11033 const char *pos;
11034
11035 /* format: <dst> <packet starting from ethertype> */
11036
11037 req = os_zalloc(sizeof(*req));
11038 if (!req)
11039 return -1;
11040
11041 if (hwaddr_aton(cmd, req->dst))
11042 goto fail;
11043
11044 pos = os_strchr(cmd, ' ');
11045 if (!pos)
11046 goto fail;
11047 pos++;
11048 req->pkt = wpabuf_parse_bin(pos);
11049 if (!req->pkt)
11050 goto fail;
11051
11052 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
11053 return 0;
11054fail:
11055 wpabuf_free(req->pkt);
11056 os_free(req);
11057 return -1;
11058}
11059#endif /* CONFIG_FILS */
11060
11061
Sunil Ravia04bd252022-05-02 22:54:18 -070011062int wpas_ctrl_cmd_debug_level(const char *cmd)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080011063{
11064 if (os_strcmp(cmd, "PING") == 0 ||
11065 os_strncmp(cmd, "BSS ", 4) == 0 ||
11066 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
11067 os_strncmp(cmd, "STATUS", 6) == 0 ||
11068 os_strncmp(cmd, "STA ", 4) == 0 ||
11069 os_strncmp(cmd, "STA-", 4) == 0)
11070 return MSG_EXCESSIVE;
11071 return MSG_DEBUG;
11072}
11073
11074
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011075#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -070011076static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
11077 const char *cmd)
11078{
11079 size_t frame_classifier_len;
11080 const char *pos, *end;
11081 struct robust_av_data *robust_av = &wpa_s->robust_av;
11082 int val;
11083
11084 /*
11085 * format:
11086 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
11087 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
11088 */
11089 os_memset(robust_av, 0, sizeof(struct robust_av_data));
11090 if (os_strncmp(cmd, "add ", 4) == 0) {
11091 robust_av->request_type = SCS_REQ_ADD;
11092 } else if (os_strcmp(cmd, "remove") == 0) {
11093 robust_av->request_type = SCS_REQ_REMOVE;
11094 robust_av->valid_config = false;
11095 return wpas_send_mscs_req(wpa_s);
11096 } else if (os_strncmp(cmd, "change ", 7) == 0) {
11097 robust_av->request_type = SCS_REQ_CHANGE;
11098 } else {
11099 return -1;
11100 }
11101
11102 pos = os_strstr(cmd, "up_bitmap=");
11103 if (!pos)
11104 return -1;
11105
11106 val = hex2byte(pos + 10);
11107 if (val < 0)
11108 return -1;
11109 robust_av->up_bitmap = val;
11110
11111 pos = os_strstr(cmd, "up_limit=");
11112 if (!pos)
11113 return -1;
11114
11115 robust_av->up_limit = atoi(pos + 9);
11116
11117 pos = os_strstr(cmd, "stream_timeout=");
11118 if (!pos)
11119 return -1;
11120
11121 robust_av->stream_timeout = atoi(pos + 15);
11122 if (robust_av->stream_timeout == 0)
11123 return -1;
11124
11125 pos = os_strstr(cmd, "frame_classifier=");
11126 if (!pos)
11127 return -1;
11128
11129 pos += 17;
11130 end = os_strchr(pos, ' ');
11131 if (!end)
11132 end = pos + os_strlen(pos);
11133
11134 frame_classifier_len = (end - pos) / 2;
11135 if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
11136 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
11137 return -1;
11138
11139 robust_av->frame_classifier_len = frame_classifier_len;
11140 robust_av->valid_config = true;
11141
11142 return wpas_send_mscs_req(wpa_s);
11143}
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011144#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -070011145
11146
Hai Shalom60840252021-02-19 19:02:11 -080011147#ifdef CONFIG_PASN
11148static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
11149{
11150 char *token, *context = NULL;
11151 u8 bssid[ETH_ALEN];
11152 int akmp = -1, cipher = -1, got_bssid = 0;
11153 u16 group = 0xFFFF;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011154 u8 *comeback = NULL;
11155 size_t comeback_len = 0;
11156 int id = 0, ret = -1;
Hai Shalom60840252021-02-19 19:02:11 -080011157
11158 /*
11159 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
Hai Shaloma20dcd72022-02-04 13:43:00 -080011160 * [comeback=<hexdump>]
Hai Shalom60840252021-02-19 19:02:11 -080011161 */
11162 while ((token = str_token(cmd, " ", &context))) {
11163 if (os_strncmp(token, "bssid=", 6) == 0) {
11164 if (hwaddr_aton(token + 6, bssid))
Hai Shaloma20dcd72022-02-04 13:43:00 -080011165 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011166 got_bssid = 1;
11167 } else if (os_strcmp(token, "akmp=PASN") == 0) {
11168 akmp = WPA_KEY_MGMT_PASN;
11169#ifdef CONFIG_IEEE80211R
11170 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
11171 akmp = WPA_KEY_MGMT_FT_PSK;
11172 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
11173 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
11174 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
11175 akmp = WPA_KEY_MGMT_FT_IEEE8021X;
11176#endif /* CONFIG_IEEE80211R */
11177#ifdef CONFIG_SAE
11178 } else if (os_strcmp(token, "akmp=SAE") == 0) {
11179 akmp = WPA_KEY_MGMT_SAE;
Sunil Ravi89eba102022-09-13 21:04:37 -070011180 } else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) {
11181 akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
Hai Shalom60840252021-02-19 19:02:11 -080011182#endif /* CONFIG_SAE */
11183#ifdef CONFIG_FILS
11184 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
11185 akmp = WPA_KEY_MGMT_FILS_SHA256;
11186 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
11187 akmp = WPA_KEY_MGMT_FILS_SHA384;
11188#endif /* CONFIG_FILS */
11189 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
11190 cipher = WPA_CIPHER_CCMP_256;
11191 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
11192 cipher = WPA_CIPHER_GCMP_256;
11193 } else if (os_strcmp(token, "cipher=CCMP") == 0) {
11194 cipher = WPA_CIPHER_CCMP;
11195 } else if (os_strcmp(token, "cipher=GCMP") == 0) {
11196 cipher = WPA_CIPHER_GCMP;
11197 } else if (os_strncmp(token, "group=", 6) == 0) {
11198 group = atoi(token + 6);
11199 } else if (os_strncmp(token, "nid=", 4) == 0) {
11200 id = atoi(token + 4);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011201 } else if (os_strncmp(token, "comeback=", 9) == 0) {
11202 comeback_len = os_strlen(token + 9);
11203 if (comeback || !comeback_len || comeback_len % 2)
11204 goto out;
11205
11206 comeback_len /= 2;
11207 comeback = os_malloc(comeback_len);
11208 if (!comeback ||
11209 hexstr2bin(token + 9, comeback, comeback_len))
11210 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011211 } else {
11212 wpa_printf(MSG_DEBUG,
11213 "CTRL: PASN Invalid parameter: '%s'",
11214 token);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011215 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011216 }
11217 }
11218
11219 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
11220 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
Hai Shaloma20dcd72022-02-04 13:43:00 -080011221 goto out;
11222 }
11223
Sunil Ravi89eba102022-09-13 21:04:37 -070011224 ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher,
11225 group, id, comeback, comeback_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011226out:
11227 os_free(comeback);
11228 return ret;
11229}
11230
11231
11232static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
11233 const char *cmd)
11234{
11235 u8 bssid[ETH_ALEN];
11236
11237 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
11238 wpa_printf(MSG_DEBUG,
11239 "CTRL: PASN_DEAUTH without valid BSSID");
Hai Shalom60840252021-02-19 19:02:11 -080011240 return -1;
11241 }
11242
Sunil Ravi89eba102022-09-13 21:04:37 -070011243 return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
Hai Shalom60840252021-02-19 19:02:11 -080011244}
Hai Shaloma20dcd72022-02-04 13:43:00 -080011245
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011246
11247#ifdef CONFIG_TESTING_OPTIONS
11248static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
11249 const char *cmd)
11250{
11251 union wpa_event_data event;
11252 const char *pos = cmd;
11253 u8 addr[ETH_ALEN];
11254
11255 os_memset(&event, 0, sizeof(event));
11256
11257 if (os_strncmp(pos, "auth ", 5) == 0)
11258 event.pasn_auth.action = PASN_ACTION_AUTH;
11259 else if (os_strncmp(pos, "del ", 4) == 0)
11260 event.pasn_auth.action =
11261 PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
11262 else
11263 return -1;
11264
11265 pos = os_strchr(pos, ' ');
11266 if (!pos)
11267 return -1;
11268 pos++;
11269 while (hwaddr_aton(pos, addr) == 0) {
11270 struct pasn_peer *peer;
11271
11272 if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
11273 return -1;
11274 peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
11275 os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
11276 os_memcpy(peer->peer_addr, addr, ETH_ALEN);
11277 event.pasn_auth.num_peers++;
11278
11279 pos = os_strchr(pos, ' ');
11280 if (!pos)
11281 break;
11282 pos++;
11283 }
11284
11285 wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
11286 return 0;
11287}
11288#endif /* CONFIG_TESTING_OPTIONS */
11289
Hai Shalom60840252021-02-19 19:02:11 -080011290#endif /* CONFIG_PASN */
11291
11292
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011293#ifndef CONFIG_NO_ROBUST_AV
11294
Hai Shaloma20dcd72022-02-04 13:43:00 -080011295static int set_type4_frame_classifier(const char *cmd,
11296 struct type4_params *param)
11297{
11298 const char *pos, *end;
11299 u8 classifier_mask = 0;
11300 int ret;
11301 char addr[INET6_ADDRSTRLEN];
11302 size_t alen;
11303
11304 if (os_strstr(cmd, "ip_version=ipv4")) {
11305 param->ip_version = IPV4;
11306 } else if (os_strstr(cmd, "ip_version=ipv6")) {
11307 param->ip_version = IPV6;
11308 } else {
11309 wpa_printf(MSG_ERROR, "IP version missing/invalid");
11310 return -1;
11311 }
11312
11313 classifier_mask |= BIT(0);
11314
11315 pos = os_strstr(cmd, "src_ip=");
11316 if (pos) {
11317 pos += 7;
11318 end = os_strchr(pos, ' ');
11319 if (!end)
11320 end = pos + os_strlen(pos);
11321
11322 alen = end - pos;
11323 if (alen >= INET6_ADDRSTRLEN)
11324 return -1;
11325 os_memcpy(addr, pos, alen);
11326 addr[alen] = '\0';
11327 if (param->ip_version == IPV4)
11328 ret = inet_pton(AF_INET, addr,
11329 &param->ip_params.v4.src_ip);
11330 else
11331 ret = inet_pton(AF_INET6, addr,
11332 &param->ip_params.v6.src_ip);
11333
11334 if (ret != 1) {
11335 wpa_printf(MSG_ERROR,
11336 "Error converting src IP address to binary ret=%d",
11337 ret);
11338 return -1;
11339 }
11340
11341 classifier_mask |= BIT(1);
11342 }
11343
11344 pos = os_strstr(cmd, "dst_ip=");
11345 if (pos) {
11346 pos += 7;
11347 end = os_strchr(pos, ' ');
11348 if (!end)
11349 end = pos + os_strlen(pos);
11350
11351 alen = end - pos;
11352 if (alen >= INET6_ADDRSTRLEN)
11353 return -1;
11354 os_memcpy(addr, pos, alen);
11355 addr[alen] = '\0';
11356 if (param->ip_version == IPV4)
11357 ret = inet_pton(AF_INET, addr,
11358 &param->ip_params.v4.dst_ip);
11359 else
11360 ret = inet_pton(AF_INET6, addr,
11361 &param->ip_params.v6.dst_ip);
11362
11363 if (ret != 1) {
11364 wpa_printf(MSG_ERROR,
11365 "Error converting dst IP address to binary ret=%d",
11366 ret);
11367 return -1;
11368 }
11369
11370 classifier_mask |= BIT(2);
11371 }
11372
11373 pos = os_strstr(cmd, "src_port=");
11374 if (pos && atoi(pos + 9) > 0) {
11375 if (param->ip_version == IPV4)
11376 param->ip_params.v4.src_port = atoi(pos + 9);
11377 else
11378 param->ip_params.v6.src_port = atoi(pos + 9);
11379 classifier_mask |= BIT(3);
11380 }
11381
11382 pos = os_strstr(cmd, "dst_port=");
11383 if (pos && atoi(pos + 9) > 0) {
11384 if (param->ip_version == IPV4)
11385 param->ip_params.v4.dst_port = atoi(pos + 9);
11386 else
11387 param->ip_params.v6.dst_port = atoi(pos + 9);
11388 classifier_mask |= BIT(4);
11389 }
11390
11391 pos = os_strstr(cmd, "dscp=");
11392 if (pos && atoi(pos + 5) > 0) {
11393 if (param->ip_version == IPV4)
11394 param->ip_params.v4.dscp = atoi(pos + 5);
11395 else
11396 param->ip_params.v6.dscp = atoi(pos + 5);
11397 classifier_mask |= BIT(5);
11398 }
11399
11400 if (param->ip_version == IPV4) {
11401 pos = os_strstr(cmd, "protocol=");
11402 if (pos) {
11403 if (os_strstr(pos, "udp")) {
11404 param->ip_params.v4.protocol = 17;
11405 } else if (os_strstr(pos, "tcp")) {
11406 param->ip_params.v4.protocol = 6;
11407 } else if (os_strstr(pos, "esp")) {
11408 param->ip_params.v4.protocol = 50;
11409 } else {
11410 wpa_printf(MSG_ERROR, "Invalid protocol");
11411 return -1;
11412 }
11413 classifier_mask |= BIT(6);
11414 }
11415 } else {
11416 pos = os_strstr(cmd, "next_header=");
11417 if (pos) {
11418 if (os_strstr(pos, "udp")) {
11419 param->ip_params.v6.next_header = 17;
11420 } else if (os_strstr(pos, "tcp")) {
11421 param->ip_params.v6.next_header = 6;
11422 } else if (os_strstr(pos, "esp")) {
11423 param->ip_params.v6.next_header = 50;
11424 } else {
11425 wpa_printf(MSG_ERROR, "Invalid next header");
11426 return -1;
11427 }
11428
11429 classifier_mask |= BIT(6);
11430 }
11431
11432 pos = os_strstr(cmd, "flow_label=");
11433 if (pos) {
11434 pos += 11;
11435 end = os_strchr(pos, ' ');
11436 if (!end)
11437 end = pos + os_strlen(pos);
11438
11439 if (end - pos != 6 ||
11440 hexstr2bin(pos, param->ip_params.v6.flow_label,
11441 3) ||
11442 param->ip_params.v6.flow_label[0] > 0x0F) {
11443 wpa_printf(MSG_ERROR, "Invalid flow label");
11444 return -1;
11445 }
11446
11447 classifier_mask |= BIT(7);
11448 }
11449 }
11450
11451 param->classifier_mask = classifier_mask;
11452 return 0;
11453}
11454
11455
11456static int set_type10_frame_classifier(const char *cmd,
11457 struct type10_params *param)
11458{
11459 const char *pos, *end;
11460 size_t filter_len;
11461
11462 pos = os_strstr(cmd, "prot_instance=");
11463 if (!pos) {
11464 wpa_printf(MSG_ERROR, "Protocol instance missing");
11465 return -1;
11466 }
11467 param->prot_instance = atoi(pos + 14);
11468
11469 pos = os_strstr(cmd, "prot_number=");
11470 if (!pos) {
11471 wpa_printf(MSG_ERROR, "Protocol number missing");
11472 return -1;
11473 }
11474 if (os_strstr(pos, "udp")) {
11475 param->prot_number = 17;
11476 } else if (os_strstr(pos, "tcp")) {
11477 param->prot_number = 6;
11478 } else if (os_strstr(pos, "esp")) {
11479 param->prot_number = 50;
11480 } else {
11481 wpa_printf(MSG_ERROR, "Invalid protocol number");
11482 return -1;
11483 }
11484
11485 pos = os_strstr(cmd, "filter_value=");
11486 if (!pos) {
11487 wpa_printf(MSG_ERROR,
11488 "Classifier parameter filter_value missing");
11489 return -1;
11490 }
11491
11492 pos += 13;
11493 end = os_strchr(pos, ' ');
11494 if (!end)
11495 end = pos + os_strlen(pos);
11496
11497 filter_len = (end - pos) / 2;
11498 param->filter_value = os_malloc(filter_len);
11499 if (!param->filter_value)
11500 return -1;
11501
11502 if (hexstr2bin(pos, param->filter_value, filter_len)) {
11503 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11504 goto free;
11505 }
11506
11507 pos = os_strstr(cmd, "filter_mask=");
11508 if (!pos) {
11509 wpa_printf(MSG_ERROR,
11510 "Classifier parameter filter_mask missing");
11511 goto free;
11512 }
11513
11514 pos += 12;
11515 end = os_strchr(pos, ' ');
11516 if (!end)
11517 end = pos + os_strlen(pos);
11518
11519 if (filter_len != (size_t) (end - pos) / 2) {
11520 wpa_printf(MSG_ERROR,
11521 "Filter mask length mismatch expected=%zu received=%zu",
11522 filter_len, (size_t) (end - pos) / 2);
11523 goto free;
11524 }
11525
11526 param->filter_mask = os_malloc(filter_len);
11527 if (!param->filter_mask)
11528 goto free;
11529
11530 if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11531 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11532 os_free(param->filter_mask);
11533 param->filter_mask = NULL;
11534 goto free;
11535 }
11536
11537 param->filter_len = filter_len;
11538 return 0;
11539free:
11540 os_free(param->filter_value);
11541 param->filter_value = NULL;
11542 return -1;
11543}
11544
11545
11546static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11547{
11548 struct type4_params type4_param = { 0 };
11549
11550 if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11551 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11552 return -1;
11553 }
11554
11555 os_memcpy(&elem->frame_classifier.type4_param,
11556 &type4_param, sizeof(struct type4_params));
11557 return 0;
11558}
11559
11560
11561static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11562{
11563 struct type10_params type10_param = { 0 };
11564
11565 if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11566 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11567 return -1;
11568 }
11569
11570 os_memcpy(&elem->frame_classifier.type10_param,
11571 &type10_param, sizeof(struct type10_params));
11572 return 0;
11573}
11574
11575
11576static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11577 char *cmd)
11578{
11579 char *pos1, *pos;
11580 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11581 struct scs_desc_elem desc_elem = { 0 };
11582 int val;
11583 unsigned int num_scs_desc = 0;
11584
11585 if (wpa_s->ongoing_scs_req) {
11586 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11587 __func__);
11588 return -1;
11589 }
11590
11591 /**
11592 * format:
11593 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11594 * [classifier_type=<4|10>]
11595 * [classifier params based on classifier type]
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011596 * [tclas_processing=<0|1>]
11597 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>]
11598 * [max_si=<decimal number>] [min_data_rate=<decimal number>]
11599 * [delay_bound=<decimal number>] [max_msdu=<decimal number>]
11600 * [service_start_time=<decimal number>]
11601 * [service_start_time_link_id=<decimal number>]
11602 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>]
11603 * [msdu_lifetime=<decimal number>]
11604 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>]
11605 * [scs_id=<decimal number>] ...
Hai Shaloma20dcd72022-02-04 13:43:00 -080011606 */
11607 pos1 = os_strstr(cmd, "scs_id=");
11608 if (!pos1) {
11609 wpa_printf(MSG_ERROR, "SCSID not present");
11610 return -1;
11611 }
11612
11613 free_up_scs_desc(scs_data);
11614
11615 while (pos1) {
11616 struct scs_desc_elem *n1;
11617 struct active_scs_elem *active_scs_desc;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011618 char *next_scs_desc, *pos2;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011619 unsigned int num_tclas_elem = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011620 bool scsid_active = false, tclas_present = false;
11621 struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011622
11623 desc_elem.scs_id = atoi(pos1 + 7);
11624 pos1 += 7;
11625
11626 next_scs_desc = os_strstr(pos1, "scs_id=");
11627 if (next_scs_desc) {
11628 char temp[20];
11629
11630 os_snprintf(temp, sizeof(temp), "scs_id=%d ",
11631 desc_elem.scs_id);
11632 if (os_strstr(next_scs_desc, temp)) {
11633 wpa_printf(MSG_ERROR,
11634 "Multiple SCS descriptors configured with same SCSID(=%d)",
11635 desc_elem.scs_id);
11636 goto free_scs_desc;
11637 }
11638 pos1[next_scs_desc - pos1 - 1] = '\0';
11639 }
11640
11641 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
11642 struct active_scs_elem, list) {
11643 if (desc_elem.scs_id == active_scs_desc->scs_id) {
11644 scsid_active = true;
11645 break;
11646 }
11647 }
11648
11649 if (os_strstr(pos1, "add ")) {
11650 desc_elem.request_type = SCS_REQ_ADD;
11651 if (scsid_active) {
11652 wpa_printf(MSG_ERROR, "SCSID %d already active",
11653 desc_elem.scs_id);
11654 return -1;
11655 }
11656 } else if (os_strstr(pos1, "remove")) {
11657 desc_elem.request_type = SCS_REQ_REMOVE;
11658 if (!scsid_active) {
11659 wpa_printf(MSG_ERROR, "SCSID %d not active",
11660 desc_elem.scs_id);
11661 return -1;
11662 }
11663 goto scs_desc_end;
11664 } else if (os_strstr(pos1, "change ")) {
11665 desc_elem.request_type = SCS_REQ_CHANGE;
11666 if (!scsid_active) {
11667 wpa_printf(MSG_ERROR, "SCSID %d not active",
11668 desc_elem.scs_id);
11669 return -1;
11670 }
11671 } else {
11672 wpa_printf(MSG_ERROR, "SCS Request type invalid");
11673 goto free_scs_desc;
11674 }
11675
11676 pos1 = os_strstr(pos1, "scs_up=");
11677 if (!pos1) {
11678 wpa_printf(MSG_ERROR,
11679 "Intra-Access user priority not present");
11680 goto free_scs_desc;
11681 }
11682
11683 val = atoi(pos1 + 7);
11684 if (val < 0 || val > 7) {
11685 wpa_printf(MSG_ERROR,
11686 "Intra-Access user priority invalid %d",
11687 val);
11688 goto free_scs_desc;
11689 }
11690
11691 desc_elem.intra_access_priority = val;
11692 desc_elem.scs_up_avail = true;
11693
11694 pos = os_strstr(pos1, "classifier_type=");
11695 if (!pos) {
11696 wpa_printf(MSG_ERROR, "classifier type empty");
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011697 goto qos_characteristics;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011698 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011699 tclas_present = true;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011700
11701 while (pos) {
11702 struct tclas_element elem = { 0 }, *n;
11703 char *next_tclas_elem;
11704
11705 val = atoi(pos + 16);
11706 if (val != 4 && val != 10) {
11707 wpa_printf(MSG_ERROR,
11708 "classifier type invalid %d", val);
11709 goto free_scs_desc;
11710 }
11711
11712 elem.classifier_type = val;
11713 pos += 16;
11714
11715 next_tclas_elem = os_strstr(pos, "classifier_type=");
11716 if (next_tclas_elem) {
11717 pos1 = next_tclas_elem;
11718 pos[next_tclas_elem - pos - 1] = '\0';
11719 }
11720
11721 switch (val) {
11722 case 4:
11723 if (scs_parse_type4(&elem, pos) < 0)
11724 goto free_scs_desc;
11725 break;
11726 case 10:
11727 if (scs_parse_type10(&elem, pos) < 0)
11728 goto free_scs_desc;
11729 break;
11730 }
11731
11732 n = os_realloc(desc_elem.tclas_elems,
11733 (num_tclas_elem + 1) * sizeof(elem));
11734 if (!n)
11735 goto free_scs_desc;
11736
11737 desc_elem.tclas_elems = n;
11738 os_memcpy((u8 *) desc_elem.tclas_elems +
11739 num_tclas_elem * sizeof(elem),
11740 &elem, sizeof(elem));
11741 num_tclas_elem++;
11742 desc_elem.num_tclas_elem = num_tclas_elem;
11743 pos = next_tclas_elem;
11744 }
11745
11746 if (desc_elem.num_tclas_elem > 1) {
11747 pos1 = os_strstr(pos1, "tclas_processing=");
11748 if (!pos1) {
11749 wpa_printf(MSG_ERROR, "tclas_processing empty");
11750 goto free_scs_desc;
11751 }
11752
11753 val = atoi(pos1 + 17);
11754 if (val != 0 && val != 1) {
11755 wpa_printf(MSG_ERROR,
11756 "tclas_processing invalid");
11757 goto free_scs_desc;
11758 }
11759
11760 desc_elem.tclas_processing = val;
11761 }
11762
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011763 qos_characteristics:
11764 pos1 = os_strstr(pos1, "qos_characteristics");
11765 if (!pos1 && !tclas_present)
11766 goto free_scs_desc;
11767 if (!pos1)
11768 goto scs_desc_end;
11769
11770 qos_elem->available = true;
11771 if (os_strstr(pos1, "up ")) {
11772 qos_elem->direction = SCS_DIRECTION_UP;
11773 if (tclas_present) {
11774 wpa_printf(MSG_ERROR,
11775 "TCLAS with direction:UP not allowed");
11776 goto free_scs_desc;
11777 }
11778 } else if (os_strstr(pos1, "down ")) {
11779 qos_elem->direction = SCS_DIRECTION_DOWN;
11780 } else if (os_strstr(pos1, "direct ")) {
11781 qos_elem->direction = SCS_DIRECTION_DIRECT;
11782 }
11783
11784 pos1 = os_strstr(pos1, "min_si=");
11785 if (!pos1) {
11786 wpa_printf(MSG_ERROR, "Min SI is required");
11787 goto free_scs_desc;
11788 }
11789 qos_elem->min_si = atoi(pos1 + 7);
11790
11791 pos1 = os_strstr(pos1, "max_si=");
11792 if (!pos1) {
11793 wpa_printf(MSG_ERROR, "Max SI is required");
11794 goto free_scs_desc;
11795 }
11796 qos_elem->max_si = atoi(pos1 + 7);
11797
11798 if (qos_elem->min_si && qos_elem->max_si &&
11799 qos_elem->max_si < qos_elem->min_si) {
11800 wpa_printf(MSG_ERROR, "Invalid Max SI");
11801 goto free_scs_desc;
11802 }
11803
11804 pos1 = os_strstr(pos1, "min_data_rate=");
11805 if (!pos1) {
11806 wpa_printf(MSG_ERROR, "Min data rate is required");
11807 goto free_scs_desc;
11808 }
11809 qos_elem->min_data_rate = atoi(pos1 + 14);
11810
11811 pos1 = os_strstr(pos1, "delay_bound=");
11812 if (!pos1) {
11813 wpa_printf(MSG_ERROR, "Delay Bound is required");
11814 goto free_scs_desc;
11815 }
11816 qos_elem->delay_bound = atoi(pos1 + 12);
11817
11818 if (qos_elem->min_data_rate >= BIT(24) ||
11819 qos_elem->delay_bound >= BIT(24)) {
11820 wpa_printf(MSG_ERROR,
11821 "Invalid min_data_rate or delay_bound");
11822 goto free_scs_desc;
11823 }
11824
11825 pos2 = os_strstr(pos1, "max_msdu=");
11826 if (pos2) {
11827 qos_elem->max_msdu_size = atoi(pos2 + 9);
11828 qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE;
11829 }
11830
11831 pos2 = os_strstr(pos1, "service_start_time=");
11832 if (pos2) {
11833 qos_elem->service_start_time = atoi(pos2 + 19);
11834 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME;
11835 }
11836
11837 pos2 = os_strstr(pos1, "service_start_time_link_id=");
11838 if (pos2) {
11839 qos_elem->service_start_time_link_id = atoi(pos2 + 27);
11840 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
11841 }
11842
11843 pos2 = os_strstr(pos1, "mean_data_rate=");
11844 if (pos2) {
11845 qos_elem->mean_data_rate = atoi(pos2 + 15);
11846 qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE;
11847 }
11848
11849 pos2 = os_strstr(pos1, "burst_size=");
11850 if (pos2) {
11851 qos_elem->burst_size = atoi(pos2 + 11);
11852 qos_elem->mask |=
11853 SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE;
11854 }
11855
11856 pos2 = os_strstr(pos1, "msdu_lifetime=");
11857 if (pos2) {
11858 qos_elem->msdu_lifetime = atoi(pos2 + 14);
11859 qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME;
11860 }
11861
11862 pos2 = os_strstr(pos1, "msdu_delivery_info=");
11863 if (pos2) {
11864 qos_elem->msdu_delivery_info = atoi(pos2 + 19);
11865 qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO;
11866 }
11867
11868 pos2 = os_strstr(pos1, "medium_time=");
11869 if (pos2) {
11870 qos_elem->medium_time = atoi(pos2 + 12);
11871 qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME;
11872 }
11873
Hai Shaloma20dcd72022-02-04 13:43:00 -080011874scs_desc_end:
11875 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
11876 sizeof(struct scs_desc_elem));
11877 if (!n1)
11878 goto free_scs_desc;
11879
11880 scs_data->scs_desc_elems = n1;
11881 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
11882 sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
11883 num_scs_desc++;
11884 scs_data->num_scs_desc = num_scs_desc;
11885 pos1 = next_scs_desc;
11886 os_memset(&desc_elem, 0, sizeof(desc_elem));
11887 }
11888
11889 return wpas_send_scs_req(wpa_s);
11890
11891free_scs_desc:
11892 free_up_tclas_elem(&desc_elem);
11893 free_up_scs_desc(scs_data);
11894 return -1;
11895}
11896
11897
11898static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
11899 const char *cmd)
11900{
11901 char *pos;
11902 struct dscp_policy_status *policy = NULL, *n;
11903 int num_policies = 0, ret = -1;
11904 struct dscp_resp_data resp_data;
11905
11906 /*
11907 * format:
11908 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
11909 */
11910
11911 os_memset(&resp_data, 0, sizeof(resp_data));
11912
11913 resp_data.more = os_strstr(cmd, "more") != NULL;
11914
11915 if (os_strstr(cmd, "reset")) {
11916 resp_data.reset = true;
11917 resp_data.solicited = false;
11918 goto send_resp;
11919 }
11920
11921 resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
11922
11923 pos = os_strstr(cmd, "policy_id=");
11924 while (pos) {
11925 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
11926 if (!n)
11927 goto fail;
11928
11929 policy = n;
11930 pos += 10;
11931 policy[num_policies].id = atoi(pos);
11932 if (policy[num_policies].id == 0) {
11933 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
11934 goto fail;
11935 }
11936
11937 pos = os_strstr(pos, "status=");
11938 if (!pos) {
11939 wpa_printf(MSG_ERROR,
11940 "DSCP: Status is not found for a policy");
11941 goto fail;
11942 }
11943
11944 pos += 7;
11945 policy[num_policies].status = atoi(pos);
11946 num_policies++;
11947
11948 pos = os_strstr(pos, "policy_id");
11949 }
11950
11951 resp_data.policy = policy;
11952 resp_data.num_policies = num_policies;
11953send_resp:
11954 ret = wpas_send_dscp_response(wpa_s, &resp_data);
11955 if (ret)
11956 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
11957fail:
11958 os_free(policy);
11959 return ret;
11960}
11961
11962
11963static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
11964 const char *cmd)
11965{
11966 char *pos;
11967
11968 /*
11969 * format:
11970 * Wildcard DSCP query
11971 * <wildcard>
11972 *
11973 * DSCP query with a domain name attribute:
11974 * [domain_name=<string>]
11975 */
11976
11977 if (os_strstr(cmd, "wildcard")) {
11978 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
11979 return wpas_send_dscp_query(wpa_s, NULL, 0);
11980 }
11981
11982 pos = os_strstr(cmd, "domain_name=");
11983 if (!pos || !os_strlen(pos + 12)) {
11984 wpa_printf(MSG_ERROR, "QM: Domain name not preset");
11985 return -1;
11986 }
11987
11988 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
11989}
11990
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011991#endif /* CONFIG_NO_ROBUST_AV */
11992
Hai Shaloma20dcd72022-02-04 13:43:00 -080011993
Sunil Ravi89eba102022-09-13 21:04:37 -070011994static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
11995 char *buf, size_t buflen)
11996{
11997 int ret, i;
11998 char *pos, *end;
11999 struct wpa_mlo_signal_info mlo_si;
12000
12001 if (!wpa_s->valid_links)
12002 return -1;
12003
12004 ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si);
12005 if (ret)
12006 return -1;
12007
12008 pos = buf;
12009 end = buf + buflen;
12010
Sunil Ravi99c035e2024-07-12 01:42:03 +000012011 for_each_link(mlo_si.valid_links, i) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012012 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012013 "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
Sunil Ravi89eba102022-09-13 21:04:37 -070012014 "NOISE=%d\nFREQUENCY=%u\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012015 i, mlo_si.links[i].data.signal,
12016 mlo_si.links[i].data.current_tx_rate / 1000,
Sunil Ravi89eba102022-09-13 21:04:37 -070012017 mlo_si.links[i].current_noise,
12018 mlo_si.links[i].frequency);
12019 if (os_snprintf_error(end - pos, ret))
12020 return -1;
12021 pos += ret;
12022
12023 if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) {
12024 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
12025 channel_width_to_string(
12026 mlo_si.links[i].chanwidth));
12027 if (os_snprintf_error(end - pos, ret))
12028 return -1;
12029 pos += ret;
12030 }
12031
12032 if (mlo_si.links[i].center_frq1 > 0) {
12033 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
12034 mlo_si.links[i].center_frq1);
12035 if (os_snprintf_error(end - pos, ret))
12036 return -1;
12037 pos += ret;
12038 }
12039
12040 if (mlo_si.links[i].center_frq2 > 0) {
12041 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
12042 mlo_si.links[i].center_frq2);
12043 if (os_snprintf_error(end - pos, ret))
12044 return -1;
12045 pos += ret;
12046 }
12047
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012048 if (mlo_si.links[i].data.avg_signal) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012049 ret = os_snprintf(pos, end - pos,
12050 "AVG_RSSI=%d\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012051 mlo_si.links[i].data.avg_signal);
Sunil Ravi89eba102022-09-13 21:04:37 -070012052 if (os_snprintf_error(end - pos, ret))
12053 return -1;
12054 pos += ret;
12055 }
12056
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012057 if (mlo_si.links[i].data.avg_beacon_signal) {
12058 ret = os_snprintf(
12059 pos, end - pos, "AVG_BEACON_RSSI=%d\n",
12060 mlo_si.links[i].data.avg_beacon_signal);
Sunil Ravi89eba102022-09-13 21:04:37 -070012061 if (os_snprintf_error(end - pos, ret))
12062 return -1;
12063 pos += ret;
12064 }
12065 }
12066
12067 return pos - buf;
12068}
12069
12070
12071static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s,
12072 char *buf, size_t buflen)
12073{
12074 int ret, i;
12075 char *pos, *end;
12076
12077 if (!wpa_s->valid_links)
12078 return -1;
12079
12080 pos = buf;
12081 end = buf + buflen;
12082
Sunil Ravi99c035e2024-07-12 01:42:03 +000012083 for_each_link(wpa_s->valid_links, i) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012084 ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n"
12085 "ap_link_addr=" MACSTR
12086 "\nsta_link_addr=" MACSTR "\n",
12087 i, wpa_s->links[i].freq,
12088 MAC2STR(wpa_s->links[i].bssid),
12089 MAC2STR(wpa_s->links[i].addr));
12090 if (os_snprintf_error(end - pos, ret))
12091 return pos - buf;
12092 pos += ret;
12093 }
12094
12095 return pos - buf;
12096}
12097
12098
Sunil Ravi2a14cf12023-11-21 00:54:38 +000012099#ifdef CONFIG_TESTING_OPTIONS
12100static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd)
12101{
12102 char *token, *context = NULL;
12103 u8 bssid[ETH_ALEN];
12104 int mld_id = -1, link_id = -1;
12105 struct wpa_bss *bss;
12106 int *freqs;
12107
12108 os_memset(bssid, 0, sizeof(bssid));
12109
12110 while ((token = str_token(cmd, " ", &context))) {
12111 if (os_strncmp(token, "bssid=", 6) == 0) {
12112 if (hwaddr_aton(token + 6, bssid))
12113 return -1;
12114 } else if (os_strncmp(token, "mld_id=", 7) == 0) {
12115 mld_id = atoi(token + 7);
12116 } else if (os_strncmp(token, "link_id=", 8) == 0) {
12117 link_id = atoi(token + 8);
12118 }
12119 }
12120
12121 if (mld_id < 0 || is_zero_ether_addr(bssid)) {
12122 wpa_printf(MSG_DEBUG,
12123 "MLD: Failed parsing ML probe request arguments");
12124 return -1;
12125 }
12126
12127 bss = wpa_bss_get_bssid(wpa_s, bssid);
12128 if (!bss) {
12129 wpa_printf(MSG_DEBUG,
12130 "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid));
12131 return -1;
12132 }
12133
12134 if (wpa_s->sched_scanning || wpa_s->scanning ||
12135 (wpa_s->wpa_state > WPA_SCANNING &&
12136 wpa_s->wpa_state != WPA_COMPLETED)) {
12137 wpa_printf(MSG_DEBUG,
12138 "MLO: Ongoing scan: Reject ML probe request");
12139 return -1;
12140 }
12141
12142 freqs = os_malloc(sizeof(int) * 2);
12143 if (!freqs)
12144 return -1;
12145
12146 freqs[0] = bss->freq;
12147 freqs[1] = 0;
12148
12149 wpa_s->manual_scan_passive = 0;
12150 wpa_s->manual_scan_use_id = 0;
12151 wpa_s->manual_scan_only_new = 0;
12152 wpa_s->scan_id_count = 0;
12153 wpa_s->scan_res_handler = scan_only_handler;
12154 os_free(wpa_s->manual_scan_freqs);
12155 wpa_s->manual_scan_freqs = freqs;
12156
12157 os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN);
12158 wpa_s->ml_probe_mld_id = mld_id;
12159 if (link_id >= 0)
12160 wpa_s->ml_probe_links = BIT(link_id);
12161
12162 wpa_s->normal_scans = 0;
12163 wpa_s->scan_req = MANUAL_SCAN_REQ;
12164 wpa_s->after_wps = 0;
12165 wpa_s->known_wps_freq = 0;
12166 wpa_supplicant_req_scan(wpa_s, 0, 0);
12167
12168 return 0;
12169}
12170#endif /* CONFIG_TESTING_OPTIONS */
12171
12172
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012173#ifdef CONFIG_NAN_USD
12174
12175static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
12176 char *buf, size_t buflen)
12177{
12178 char *token, *context = NULL;
12179 int publish_id;
12180 struct nan_publish_params params;
12181 const char *service_name = NULL;
12182 struct wpabuf *ssi = NULL;
12183 int ret = -1;
12184 enum nan_service_protocol_type srv_proto_type = 0;
12185 int *freq_list = NULL;
12186
12187 os_memset(&params, 0, sizeof(params));
12188 /* USD shall use both solicited and unsolicited transmissions */
12189 params.unsolicited = true;
12190 params.solicited = true;
12191 /* USD shall require FSD without GAS */
12192 params.fsd = true;
12193 params.freq = NAN_USD_DEFAULT_FREQ;
12194
12195 while ((token = str_token(cmd, " ", &context))) {
12196 if (os_strncmp(token, "service_name=", 13) == 0) {
12197 service_name = token + 13;
12198 continue;
12199 }
12200
12201 if (os_strncmp(token, "ttl=", 4) == 0) {
12202 params.ttl = atoi(token + 4);
12203 continue;
12204 }
12205
12206 if (os_strncmp(token, "freq=", 5) == 0) {
12207 params.freq = atoi(token + 5);
12208 continue;
12209 }
12210
12211 if (os_strncmp(token, "freq_list=", 10) == 0) {
12212 char *pos = token + 10;
12213
12214 if (os_strcmp(pos, "all") == 0) {
12215 os_free(freq_list);
12216 freq_list = wpas_nan_usd_all_freqs(wpa_s);
12217 params.freq_list = freq_list;
12218 continue;
12219 }
12220
12221 while (pos && pos[0]) {
12222 int_array_add_unique(&freq_list, atoi(pos));
12223 pos = os_strchr(pos, ',');
12224 if (pos)
12225 pos++;
12226 }
12227
12228 params.freq_list = freq_list;
12229 continue;
12230 }
12231
12232 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12233 srv_proto_type = atoi(token + 15);
12234 continue;
12235 }
12236
12237 if (os_strncmp(token, "ssi=", 4) == 0) {
12238 if (ssi)
12239 goto fail;
12240 ssi = wpabuf_parse_bin(token + 4);
12241 if (!ssi)
12242 goto fail;
12243 continue;
12244 }
12245
12246 if (os_strcmp(token, "solicited=0") == 0) {
12247 params.solicited = false;
12248 continue;
12249 }
12250
12251 if (os_strcmp(token, "unsolicited=0") == 0) {
12252 params.unsolicited = false;
12253 continue;
12254 }
12255
12256 if (os_strcmp(token, "fsd=0") == 0) {
12257 params.fsd = false;
12258 continue;
12259 }
12260
12261 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
12262 token);
12263 goto fail;
12264 }
12265
12266 publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
12267 ssi, &params);
12268 if (publish_id > 0)
12269 ret = os_snprintf(buf, buflen, "%d", publish_id);
12270fail:
12271 wpabuf_free(ssi);
12272 os_free(freq_list);
12273 return ret;
12274}
12275
12276
12277static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
12278 char *cmd)
12279{
12280 char *token, *context = NULL;
12281 int publish_id = 0;
12282
12283 while ((token = str_token(cmd, " ", &context))) {
12284 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12285 continue;
12286 wpa_printf(MSG_INFO,
12287 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
12288 token);
12289 return -1;
12290 }
12291
12292 if (publish_id <= 0) {
12293 wpa_printf(MSG_INFO,
12294 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
12295 return -1;
12296 }
12297
12298 wpas_nan_usd_cancel_publish(wpa_s, publish_id);
12299 return 0;
12300}
12301
12302
12303static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
12304 char *cmd)
12305{
12306 char *token, *context = NULL;
12307 int publish_id = 0;
12308 struct wpabuf *ssi = NULL;
12309 int ret = -1;
12310
12311 while ((token = str_token(cmd, " ", &context))) {
12312 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12313 continue;
12314 if (os_strncmp(token, "ssi=", 4) == 0) {
12315 if (ssi)
12316 goto fail;
12317 ssi = wpabuf_parse_bin(token + 4);
12318 if (!ssi)
12319 goto fail;
12320 continue;
12321 }
12322 wpa_printf(MSG_INFO,
12323 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
12324 token);
12325 goto fail;
12326 }
12327
12328 if (publish_id <= 0) {
12329 wpa_printf(MSG_INFO,
12330 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
12331 goto fail;
12332 }
12333
12334 ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
12335fail:
12336 wpabuf_free(ssi);
12337 return ret;
12338}
12339
12340
12341static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
12342 char *buf, size_t buflen)
12343{
12344 char *token, *context = NULL;
12345 int subscribe_id;
12346 struct nan_subscribe_params params;
12347 const char *service_name = NULL;
12348 struct wpabuf *ssi = NULL;
12349 int ret = -1;
12350 enum nan_service_protocol_type srv_proto_type = 0;
12351
12352 os_memset(&params, 0, sizeof(params));
12353 params.freq = NAN_USD_DEFAULT_FREQ;
12354
12355 while ((token = str_token(cmd, " ", &context))) {
12356 if (os_strncmp(token, "service_name=", 13) == 0) {
12357 service_name = token + 13;
12358 continue;
12359 }
12360
12361 if (os_strcmp(token, "active=1") == 0) {
12362 params.active = true;
12363 continue;
12364 }
12365
12366 if (os_strncmp(token, "ttl=", 4) == 0) {
12367 params.ttl = atoi(token + 4);
12368 continue;
12369 }
12370
12371 if (os_strncmp(token, "freq=", 5) == 0) {
12372 params.freq = atoi(token + 5);
12373 continue;
12374 }
12375
12376 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12377 srv_proto_type = atoi(token + 15);
12378 continue;
12379 }
12380
12381 if (os_strncmp(token, "ssi=", 4) == 0) {
12382 if (ssi)
12383 goto fail;
12384 ssi = wpabuf_parse_bin(token + 4);
12385 if (!ssi)
12386 goto fail;
12387 continue;
12388 }
12389
12390 wpa_printf(MSG_INFO,
12391 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
12392 token);
12393 goto fail;
12394 }
12395
12396 subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
12397 srv_proto_type, ssi,
12398 &params);
12399 if (subscribe_id > 0)
12400 ret = os_snprintf(buf, buflen, "%d", subscribe_id);
12401fail:
12402 wpabuf_free(ssi);
12403 return ret;
12404}
12405
12406
12407static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
12408 char *cmd)
12409{
12410 char *token, *context = NULL;
12411 int subscribe_id = 0;
12412
12413 while ((token = str_token(cmd, " ", &context))) {
12414 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
12415 continue;
12416 wpa_printf(MSG_INFO,
12417 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
12418 token);
12419 return -1;
12420 }
12421
12422 if (subscribe_id <= 0) {
12423 wpa_printf(MSG_INFO,
12424 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
12425 return -1;
12426 }
12427
12428 wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
12429 return 0;
12430}
12431
12432
12433static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
12434{
12435 char *token, *context = NULL;
12436 int handle = 0;
12437 int req_instance_id = 0;
12438 struct wpabuf *ssi = NULL;
12439 u8 peer_addr[ETH_ALEN];
12440 int ret = -1;
12441
12442 os_memset(peer_addr, 0, ETH_ALEN);
12443
12444 while ((token = str_token(cmd, " ", &context))) {
12445 if (sscanf(token, "handle=%i", &handle) == 1)
12446 continue;
12447
12448 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
12449 continue;
12450
12451 if (os_strncmp(token, "address=", 8) == 0) {
12452 if (hwaddr_aton(token + 8, peer_addr) < 0)
12453 return -1;
12454 continue;
12455 }
12456
12457 if (os_strncmp(token, "ssi=", 4) == 0) {
12458 if (ssi)
12459 goto fail;
12460 ssi = wpabuf_parse_bin(token + 4);
12461 if (!ssi)
12462 goto fail;
12463 continue;
12464 }
12465
12466 wpa_printf(MSG_INFO,
12467 "CTRL: Invalid NAN_TRANSMIT parameter: %s",
12468 token);
12469 goto fail;
12470 }
12471
12472 if (handle <= 0) {
12473 wpa_printf(MSG_INFO,
12474 "CTRL: Invalid or missing NAN_TRANSMIT handle");
12475 goto fail;
12476 }
12477
12478 if (is_zero_ether_addr(peer_addr)) {
12479 wpa_printf(MSG_INFO,
12480 "CTRL: Invalid or missing NAN_TRANSMIT address");
12481 goto fail;
12482 }
12483
12484 ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
12485 req_instance_id);
12486fail:
12487 wpabuf_free(ssi);
12488 return ret;
12489}
12490
12491#endif /* CONFIG_NAN_USD */
12492
12493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012494char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
12495 char *buf, size_t *resp_len)
12496{
12497 char *reply;
12498 const int reply_size = 4096;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012499 int reply_len;
12500
12501 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012502 os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
12503 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
12504 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012505 if (wpa_debug_show_keys)
12506 wpa_dbg(wpa_s, MSG_DEBUG,
12507 "Control interface command '%s'", buf);
12508 else
12509 wpa_dbg(wpa_s, MSG_DEBUG,
12510 "Control interface command '%s [REMOVED]'",
12511 os_strncmp(buf, WPA_CTRL_RSP,
12512 os_strlen(WPA_CTRL_RSP)) == 0 ?
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012513 WPA_CTRL_RSP :
12514 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
12515 "SET_NETWORK" : "key-add"));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012516 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
Dmitry Shmidt21de2142014-04-08 10:50:52 -070012517 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012518 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
12519 (const u8 *) buf, os_strlen(buf));
12520 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080012521 int level = wpas_ctrl_cmd_debug_level(buf);
Dmitry Shmidtaa532512012-09-24 10:35:31 -070012522 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012523 }
12524
12525 reply = os_malloc(reply_size);
12526 if (reply == NULL) {
12527 *resp_len = 1;
12528 return NULL;
12529 }
12530
12531 os_memcpy(reply, "OK\n", 3);
12532 reply_len = 3;
12533
12534 if (os_strcmp(buf, "PING") == 0) {
12535 os_memcpy(reply, "PONG\n", 5);
12536 reply_len = 5;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070012537 } else if (os_strcmp(buf, "IFNAME") == 0) {
12538 reply_len = os_strlen(wpa_s->ifname);
12539 os_memcpy(reply, wpa_s->ifname, reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012540 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
12541 if (wpa_debug_reopen_file() < 0)
12542 reply_len = -1;
12543 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
12544 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
12545 } else if (os_strcmp(buf, "MIB") == 0) {
12546 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
12547 if (reply_len >= 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012548 reply_len += eapol_sm_get_mib(wpa_s->eapol,
12549 reply + reply_len,
12550 reply_size - reply_len);
Hai Shalom74f70d42019-02-11 14:42:39 -080012551#ifdef CONFIG_MACSEC
12552 reply_len += ieee802_1x_kay_get_mib(
12553 wpa_s->kay, reply + reply_len,
12554 reply_size - reply_len);
12555#endif /* CONFIG_MACSEC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012556 }
12557 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
12558 reply_len = wpa_supplicant_ctrl_iface_status(
12559 wpa_s, buf + 6, reply, reply_size);
12560 } else if (os_strcmp(buf, "PMKSA") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070012561 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070012562 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070012563 wpas_ctrl_iface_pmksa_flush(wpa_s);
Dmitry Shmidt29333592017-01-09 12:27:11 -080012564#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
12565 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
12566 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
12567 reply, reply_size);
12568 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
12569 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
12570 reply_len = -1;
Paul Stewart092955c2017-02-06 09:13:09 -080012571#ifdef CONFIG_MESH
12572 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
12573 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
12574 reply, reply_size);
12575 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12576 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
12577 reply_len = -1;
12578#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080012579#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012580 } else if (os_strncmp(buf, "SET ", 4) == 0) {
12581 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
12582 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080012583 } else if (os_strncmp(buf, "DUMP", 4) == 0) {
12584 reply_len = wpa_config_dump_values(wpa_s->conf,
12585 reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012586 } else if (os_strncmp(buf, "GET ", 4) == 0) {
12587 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
12588 reply, reply_size);
12589 } else if (os_strcmp(buf, "LOGON") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070012590 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012591 } else if (os_strcmp(buf, "LOGOFF") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070012592 eapol_sm_notify_logoff(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012593 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
12594 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12595 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012596 else
12597 wpas_request_connection(wpa_s);
Dmitry Shmidt98660862014-03-11 17:26:21 -070012598 } else if (os_strcmp(buf, "REATTACH") == 0) {
12599 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
12600 !wpa_s->current_ssid)
12601 reply_len = -1;
12602 else {
12603 wpa_s->reattach = 1;
12604 wpas_request_connection(wpa_s);
12605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012606 } else if (os_strcmp(buf, "RECONNECT") == 0) {
12607 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12608 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012609 else if (wpa_s->disconnected)
12610 wpas_request_connection(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012611#ifdef IEEE8021X_EAPOL
12612 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
12613 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
12614 reply_len = -1;
12615#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012616#ifdef CONFIG_IEEE80211R
12617 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
12618 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
12619 reply_len = -1;
12620#endif /* CONFIG_IEEE80211R */
12621#ifdef CONFIG_WPS
12622 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
12623 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
12624 if (res == -2) {
12625 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12626 reply_len = 17;
12627 } else if (res)
12628 reply_len = -1;
12629 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
12630 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
12631 if (res == -2) {
12632 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12633 reply_len = 17;
12634 } else if (res)
12635 reply_len = -1;
12636 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
12637 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
12638 reply,
12639 reply_size);
12640 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
12641 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
12642 wpa_s, buf + 14, reply, reply_size);
12643 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
12644 if (wpas_wps_cancel(wpa_s))
12645 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012646#ifdef CONFIG_WPS_NFC
12647 } else if (os_strcmp(buf, "WPS_NFC") == 0) {
12648 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
12649 reply_len = -1;
12650 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
12651 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
12652 reply_len = -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -080012653 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
12654 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
12655 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070012656 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
12657 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
12658 wpa_s, buf + 14, reply, reply_size);
12659 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
12660 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
12661 buf + 17))
12662 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012663 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
12664 reply_len = wpas_ctrl_nfc_get_handover_req(
12665 wpa_s, buf + 21, reply, reply_size);
12666 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
12667 reply_len = wpas_ctrl_nfc_get_handover_sel(
12668 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidtf8623282013-02-20 14:34:59 -080012669 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
12670 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
12671 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012672#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012673 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
12674 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
12675 reply_len = -1;
12676#ifdef CONFIG_AP
12677 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
12678 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
12679 wpa_s, buf + 11, reply, reply_size);
12680#endif /* CONFIG_AP */
12681#ifdef CONFIG_WPS_ER
12682 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
12683 if (wpas_wps_er_start(wpa_s, NULL))
12684 reply_len = -1;
12685 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
12686 if (wpas_wps_er_start(wpa_s, buf + 13))
12687 reply_len = -1;
12688 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012689 wpas_wps_er_stop(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012690 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
12691 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
12692 reply_len = -1;
12693 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
12694 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
12695 if (ret == -2) {
12696 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12697 reply_len = 17;
12698 } else if (ret == -3) {
12699 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
12700 reply_len = 18;
12701 } else if (ret == -4) {
12702 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
12703 reply_len = 20;
12704 } else if (ret)
12705 reply_len = -1;
12706 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
12707 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
12708 reply_len = -1;
12709 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
12710 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
12711 buf + 18))
12712 reply_len = -1;
12713 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
12714 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
12715 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012716#ifdef CONFIG_WPS_NFC
12717 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
12718 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
12719 wpa_s, buf + 24, reply, reply_size);
12720#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012721#endif /* CONFIG_WPS_ER */
12722#endif /* CONFIG_WPS */
12723#ifdef CONFIG_IBSS_RSN
12724 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
12725 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
12726 reply_len = -1;
12727#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012728#ifdef CONFIG_MESH
12729 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
12730 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12731 wpa_s, buf + 19, reply, reply_size);
12732 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
12733 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12734 wpa_s, "", reply, reply_size);
12735 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
12736 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
12737 reply_len = -1;
12738 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
12739 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
12740 buf + 18))
12741 reply_len = -1;
Dmitry Shmidte4663042016-04-04 10:07:49 -070012742 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
12743 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
12744 reply_len = -1;
12745 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
12746 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
12747 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070012748 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
12749 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
12750 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012751#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012752#ifdef CONFIG_P2P
12753 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012754 if (p2p_ctrl_find(wpa_s, buf + 8))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012755 reply_len = -1;
12756 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
12757 if (p2p_ctrl_find(wpa_s, ""))
12758 reply_len = -1;
12759 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
12760 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012761 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
12762 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
12763 reply_len = -1;
12764 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
12765 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
12766 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012767 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
12768 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
12769 reply_size);
12770 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
12771 if (p2p_ctrl_listen(wpa_s, buf + 11))
12772 reply_len = -1;
12773 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
12774 if (p2p_ctrl_listen(wpa_s, ""))
12775 reply_len = -1;
12776 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
12777 if (wpas_p2p_group_remove(wpa_s, buf + 17))
12778 reply_len = -1;
12779 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -070012780 if (p2p_ctrl_group_add(wpa_s, ""))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012781 reply_len = -1;
12782 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
12783 if (p2p_ctrl_group_add(wpa_s, buf + 14))
12784 reply_len = -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070012785 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
12786 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
12787 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012788 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
12789 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
12790 reply_len = -1;
12791 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
12792 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
12793 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
12794 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
12795 reply_size);
12796 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
12797 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
12798 reply_len = -1;
12799 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
12800 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
12801 reply_len = -1;
12802 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
12803 wpas_p2p_sd_service_update(wpa_s);
12804 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
12805 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
12806 reply_len = -1;
12807 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
12808 wpas_p2p_service_flush(wpa_s);
12809 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
12810 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
12811 reply_len = -1;
12812 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
12813 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
12814 reply_len = -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012815 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
12816 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
12817 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012818 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
12819 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
12820 reply_len = -1;
12821 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
12822 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
12823 reply_len = -1;
12824 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
12825 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
12826 reply_size);
12827 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
12828 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
12829 reply_len = -1;
12830 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
Dmitry Shmidt444d5672013-04-01 13:08:44 -070012831 p2p_ctrl_flush(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012832 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
12833 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
12834 reply_len = -1;
12835 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
12836 if (wpas_p2p_cancel(wpa_s))
12837 reply_len = -1;
12838 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
12839 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
12840 reply_len = -1;
12841 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
12842 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
12843 reply_len = -1;
12844 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
12845 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
12846 reply_len = -1;
12847 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
12848 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
12849 reply_len = -1;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070012850 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
12851 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
12852 reply_len = -1;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070012853 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
12854 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
12855 reply_len = -1;
12856 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
12857 if (wpas_p2p_lo_stop(wpa_s))
12858 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012859#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070012860#ifdef CONFIG_WIFI_DISPLAY
12861 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
12862 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
12863 reply_len = -1;
12864 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
12865 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
12866 reply, reply_size);
12867#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012868#ifdef CONFIG_INTERWORKING
12869 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
12870 if (interworking_fetch_anqp(wpa_s) < 0)
12871 reply_len = -1;
12872 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
12873 interworking_stop_fetch_anqp(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012874 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
12875 if (ctrl_interworking_select(wpa_s, NULL) < 0)
12876 reply_len = -1;
12877 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
12878 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012879 reply_len = -1;
12880 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -080012881 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012882 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080012883 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
12884 int id;
12885
12886 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
12887 if (id < 0)
12888 reply_len = -1;
12889 else {
12890 reply_len = os_snprintf(reply, reply_size, "%d\n", id);
12891 if (os_snprintf_error(reply_size, reply_len))
12892 reply_len = -1;
12893 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012894 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
12895 if (get_anqp(wpa_s, buf + 9) < 0)
12896 reply_len = -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070012897 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
12898 if (gas_request(wpa_s, buf + 12) < 0)
12899 reply_len = -1;
12900 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
12901 reply_len = gas_response_get(wpa_s, buf + 17, reply,
12902 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012903#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -070012904#ifdef CONFIG_HS20
12905 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
12906 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
12907 reply_len = -1;
12908 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
12909 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
12910 reply_len = -1;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080012911 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080012912 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
12913 reply_len = -1;
12914 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
12915 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
12916 reply_len = -1;
12917 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
12918 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
12919 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
12920 if (del_hs20_icon(wpa_s, buf + 14) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080012921 reply_len = -1;
12922 } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070012923 if (hs20_fetch_osu(wpa_s, 0) < 0)
12924 reply_len = -1;
12925 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
12926 if (hs20_fetch_osu(wpa_s, 1) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080012927 reply_len = -1;
12928 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
12929 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -070012930#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012931 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
12932 {
12933 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
12934 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
12935 reply_len = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -070012936 else {
12937 /*
12938 * Notify response from timeout to allow the control
12939 * interface response to be sent first.
12940 */
12941 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
12942 wpa_s, NULL);
12943 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012944 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
12945 if (wpa_supplicant_reload_configuration(wpa_s))
12946 reply_len = -1;
12947 } else if (os_strcmp(buf, "TERMINATE") == 0) {
12948 wpa_supplicant_terminate_proc(wpa_s->global);
12949 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
12950 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
12951 reply_len = -1;
Hai Shalom60840252021-02-19 19:02:11 -080012952 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
12953 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
12954 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidte19501d2011-03-16 14:32:18 -070012955 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -080012956 /* deprecated backwards compatibility alias for BSSID_IGNORE */
12957 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012958 wpa_s, buf + 9, reply, reply_size);
12959 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
12960 reply_len = wpa_supplicant_ctrl_iface_log_level(
12961 wpa_s, buf + 9, reply, reply_size);
Vinit Deshpandeda134e92014-12-02 10:59:29 -080012962 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
12963 reply_len = wpa_supplicant_ctrl_iface_list_networks(
12964 wpa_s, buf + 14, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012965 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
12966 reply_len = wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -080012967 wpa_s, NULL, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012968 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070012969 wpas_request_disconnection(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012970 } else if (os_strcmp(buf, "SCAN") == 0) {
12971 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
12972 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
12973 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012974 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
12975 reply_len = wpa_supplicant_ctrl_iface_scan_results(
12976 wpa_s, reply, reply_size);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080012977 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
12978 if (wpas_abort_ongoing_scan(wpa_s) < 0)
12979 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012980 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
12981 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
12982 reply_len = -1;
12983 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
12984 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
12985 reply_len = -1;
12986 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
12987 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
12988 reply_len = -1;
12989 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
12990 reply_len = wpa_supplicant_ctrl_iface_add_network(
12991 wpa_s, reply, reply_size);
12992 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
12993 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
12994 reply_len = -1;
12995 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
12996 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
12997 reply_len = -1;
12998 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
12999 reply_len = wpa_supplicant_ctrl_iface_get_network(
13000 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidt684785c2014-05-12 13:34:29 -070013001 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013002 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
13003 wpa_s))
Dmitry Shmidt684785c2014-05-12 13:34:29 -070013004 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070013005 } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
13006 reply_len = wpa_supplicant_ctrl_iface_list_creds(
13007 wpa_s, reply, reply_size);
13008 } else if (os_strcmp(buf, "ADD_CRED") == 0) {
13009 reply_len = wpa_supplicant_ctrl_iface_add_cred(
13010 wpa_s, reply, reply_size);
13011 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
13012 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
13013 reply_len = -1;
13014 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
13015 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
13016 reply_len = -1;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -070013017 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
13018 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
13019 reply,
13020 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013021#ifndef CONFIG_NO_CONFIG_WRITE
13022 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
13023 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
13024 reply_len = -1;
13025#endif /* CONFIG_NO_CONFIG_WRITE */
13026 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
13027 reply_len = wpa_supplicant_ctrl_iface_get_capability(
13028 wpa_s, buf + 15, reply, reply_size);
13029 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
13030 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
13031 reply_len = -1;
13032 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
13033 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
13034 reply_len = -1;
13035 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
13036 reply_len = wpa_supplicant_global_iface_list(
13037 wpa_s->global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013038 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013039 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013040 wpa_s->global, buf + 10, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013041 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
13042 reply_len = wpa_supplicant_ctrl_iface_bss(
13043 wpa_s, buf + 4, reply, reply_size);
13044#ifdef CONFIG_AP
13045 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
13046 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13047 } else if (os_strncmp(buf, "STA ", 4) == 0) {
13048 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
13049 reply_size);
13050 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13051 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13052 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070013053 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13054 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13055 reply_len = -1;
13056 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13057 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13058 reply_len = -1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080013059 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13060 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13061 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080013062 } else if (os_strcmp(buf, "STOP_AP") == 0) {
13063 if (wpas_ap_stop_ap(wpa_s))
13064 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013065 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
13066 if (wpas_ap_update_beacon(wpa_s))
13067 reply_len = -1;
Sunil Ravia04bd252022-05-02 22:54:18 -070013068 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
13069 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
13070 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13071 DENY_UNLESS_ACCEPTED,
13072 buf + 19) ||
13073 ap_ctrl_iface_set_acl(wpa_s))
13074 reply_len = -1;
13075 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
13076 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13077 DENY_UNLESS_ACCEPTED,
13078 buf + 19) ||
13079 ap_ctrl_iface_set_acl(wpa_s) ||
13080 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13081 reply_len = -1;
13082 } else if (os_strcmp(buf + 11, "SHOW") == 0) {
13083 reply_len = ap_ctrl_iface_acl_show_mac(
13084 wpa_s, DENY_UNLESS_ACCEPTED,
13085 reply, reply_size);
13086 } else if (os_strcmp(buf + 11, "CLEAR") == 0) {
13087 ap_ctrl_iface_acl_clear_list(wpa_s,
13088 DENY_UNLESS_ACCEPTED);
13089 if (ap_ctrl_iface_set_acl(wpa_s) ||
13090 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13091 reply_len = -1;
13092 } else {
13093 reply_len = -1;
13094 }
13095 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
13096 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
13097 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13098 ACCEPT_UNLESS_DENIED,
13099 buf + 17) ||
13100 ap_ctrl_iface_set_acl(wpa_s) ||
13101 ap_ctrl_iface_disassoc_deny_mac(wpa_s))
13102 reply_len = -1;
13103 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
13104 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13105 ACCEPT_UNLESS_DENIED,
13106 buf + 17) ||
13107 ap_ctrl_iface_set_acl(wpa_s))
13108 reply_len = -1;
13109 } else if (os_strcmp(buf + 9, "SHOW") == 0) {
13110 reply_len = ap_ctrl_iface_acl_show_mac(
13111 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size);
13112 } else if (os_strcmp(buf + 9, "CLEAR") == 0) {
13113 ap_ctrl_iface_acl_clear_list(wpa_s,
13114 ACCEPT_UNLESS_DENIED);
13115 if (ap_ctrl_iface_set_acl(wpa_s))
13116 reply_len = -1;
13117 } else {
13118 reply_len = -1;
13119 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013120#endif /* CONFIG_AP */
13121 } else if (os_strcmp(buf, "SUSPEND") == 0) {
13122 wpas_notify_suspend(wpa_s->global);
13123 } else if (os_strcmp(buf, "RESUME") == 0) {
13124 wpas_notify_resume(wpa_s->global);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070013125#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013126 } else if (os_strcmp(buf, "DROP_SA") == 0) {
13127 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070013128#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013129 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
13130 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
13131 reply_len = -1;
13132 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013133 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013134 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
13135 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
13136 reply_len = -1;
13137 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
13138 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
13139 buf + 17))
13140 reply_len = -1;
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -070013141 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013142 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013143#ifdef CONFIG_TDLS
13144 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
13145 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
13146 reply_len = -1;
13147 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
13148 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
13149 reply_len = -1;
13150 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
13151 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
13152 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013153 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
13154 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
13155 buf + 17))
13156 reply_len = -1;
13157 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
13158 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
13159 buf + 24))
13160 reply_len = -1;
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -070013161 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
13162 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
13163 wpa_s, buf + 17, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013164#endif /* CONFIG_TDLS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013165#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013166 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
13167 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
13168 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
13169 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
13170 reply_len = -1;
13171 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
13172 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
13173 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013174#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013175 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
13176 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
13177 reply_size);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080013178 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
13179 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
13180 reply_len = -1;
Yuhao Zhengfcd6f212012-07-27 10:37:52 -070013181 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
13182 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
13183 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070013184#ifdef CONFIG_AUTOSCAN
13185 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
13186 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
13187 reply_len = -1;
13188#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070013189 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
13190 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
13191 reply_size);
Hai Shalomb755a2a2020-04-23 21:49:02 -070013192 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
13193 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
13194 reply_size);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080013195#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -070013196 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
13197 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
13198 reply_size);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080013199#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080013200 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
13201 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
13202 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013203 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080013204 pmksa_cache_clear_current(wpa_s->wpa);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013205 eapol_sm_request_reauth(wpa_s->eapol);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080013206#ifdef CONFIG_WNM
13207 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
13208 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
13209 reply_len = -1;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080013210 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
13211 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
Dmitry Shmidt44c95782013-05-17 09:51:35 -070013212 reply_len = -1;
Hai Shalom39ba6fc2019-01-22 12:40:38 -080013213 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
13214 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13215 reply_len = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080013216#endif /* CONFIG_WNM */
Sunil Ravia04bd252022-05-02 22:54:18 -070013217#ifdef CONFIG_WNM_AP
13218 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13219 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13220 reply_len = -1;
13221 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
13222 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13))
13223 reply_len = -1;
13224 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13225 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13226 reply_len = -1;
13227#endif /* CONFIG_WNM_AP */
Dmitry Shmidt444d5672013-04-01 13:08:44 -070013228 } else if (os_strcmp(buf, "FLUSH") == 0) {
13229 wpa_supplicant_ctrl_iface_flush(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080013230 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13231 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
13232 reply_size);
Dmitry Shmidt818ea482014-03-10 13:15:21 -070013233#ifdef CONFIG_TESTING_OPTIONS
13234 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
13235 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
13236 reply_len = -1;
13237 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
13238 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013239 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
13240 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
13241 reply_len = -1;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -070013242 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
13243 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
13244 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013245 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
13246 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
13247 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013248 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
13249 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
13250 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013251 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
13252 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
13253 reply_len = -1;
13254 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
13255 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
13256 reply_len = -1;
13257 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
13258 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
13259 reply_len = -1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080013260 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013261 if (testing_set_fail_pattern(true, buf + 16) < 0)
Dmitry Shmidtff787d52015-01-12 13:01:47 -080013262 reply_len = -1;
13263 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013264 reply_len = testing_get_fail_pattern(true, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013265 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013266 if (testing_set_fail_pattern(false, buf + 10) < 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013267 reply_len = -1;
13268 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013269 reply_len = testing_get_fail_pattern(false, reply, reply_size);
Jouni Malinenc4818362015-10-04 11:45:13 +030013270 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
13271 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
13272 reply_len = -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080013273 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
13274 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
13275 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013276 } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
13277 if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
13278 reply_len = -1;
13279 } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
13280 if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
13281 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013282 } else if (os_strcmp(buf, "RESET_PN") == 0) {
13283 if (wpas_ctrl_reset_pn(wpa_s) < 0)
13284 reply_len = -1;
13285 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
13286 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
13287 reply_len = -1;
13288 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
13289 if (wpas_ctrl_resend_assoc(wpa_s) < 0)
13290 reply_len = -1;
Hai Shalom74f70d42019-02-11 14:42:39 -080013291 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
13292 sme_event_unprot_disconnect(
13293 wpa_s, wpa_s->bssid, NULL,
13294 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
Hai Shaloma20dcd72022-02-04 13:43:00 -080013295 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
13296 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
13297 reply_len = -1;
13298 } else if (os_strcmp(buf, "TWT_SETUP") == 0) {
13299 if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
13300 reply_len = -1;
13301 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
13302 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
13303 reply_len = -1;
13304 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
13305 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
13306 reply_len = -1;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000013307 } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
13308 if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
13309 reply_len = -1;
Dmitry Shmidt818ea482014-03-10 13:15:21 -070013310#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070013311 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
13312 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
13313 reply_len = -1;
13314 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
13315 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
13316 reply_size);
13317 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
13318 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
13319 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013320#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013321 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013322 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013323 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013324#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013325 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
13326 wpas_ctrl_iface_erp_flush(wpa_s);
13327 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
13328 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
13329 reply_len = -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013330 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
13331 reply_len = wpas_ctrl_iface_get_pref_freq_list(
13332 wpa_s, buf + 19, reply, reply_size);
Paul Stewart092955c2017-02-06 09:13:09 -080013333#ifdef CONFIG_FILS
13334 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
13335 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
13336 reply_len = -1;
13337 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
13338 wpas_flush_fils_hlp_req(wpa_s);
13339#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013340#ifdef CONFIG_DPP
13341 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
13342 int res;
13343
13344 res = wpas_dpp_qr_code(wpa_s, buf + 12);
13345 if (res < 0) {
13346 reply_len = -1;
13347 } else {
13348 reply_len = os_snprintf(reply, reply_size, "%d", res);
13349 if (os_snprintf_error(reply_size, reply_len))
13350 reply_len = -1;
13351 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080013352 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
13353 int res;
13354
13355 res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
13356 if (res < 0) {
13357 reply_len = -1;
13358 } else {
13359 reply_len = os_snprintf(reply, reply_size, "%d", res);
13360 if (os_snprintf_error(reply_size, reply_len))
13361 reply_len = -1;
13362 }
Hai Shalomfdcde762020-04-02 11:19:20 -070013363 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
13364 int res;
13365
13366 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
13367 if (res < 0) {
13368 reply_len = -1;
13369 } else {
13370 reply_len = os_snprintf(reply, reply_size, "%d", res);
13371 if (os_snprintf_error(reply_size, reply_len))
13372 reply_len = -1;
13373 }
13374 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
13375 int res;
13376
13377 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
13378 if (res < 0) {
13379 reply_len = -1;
13380 } else {
13381 reply_len = os_snprintf(reply, reply_size, "%d", res);
13382 if (os_snprintf_error(reply_size, reply_len))
13383 reply_len = -1;
13384 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013385 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
13386 int res;
13387
Hai Shalom021b0b52019-04-10 11:17:58 -070013388 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013389 if (res < 0) {
13390 reply_len = -1;
13391 } else {
13392 reply_len = os_snprintf(reply, reply_size, "%d", res);
13393 if (os_snprintf_error(reply_size, reply_len))
13394 reply_len = -1;
13395 }
13396 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013397 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013398 reply_len = -1;
13399 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
13400 const char *uri;
13401
Hai Shalom021b0b52019-04-10 11:17:58 -070013402 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013403 if (!uri) {
13404 reply_len = -1;
13405 } else {
13406 reply_len = os_snprintf(reply, reply_size, "%s", uri);
13407 if (os_snprintf_error(reply_size, reply_len))
13408 reply_len = -1;
13409 }
13410 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013411 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
13412 reply, reply_size);
Hai Shalomfdcde762020-04-02 11:19:20 -070013413 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
13414 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
13415 os_strchr(buf + 18, ' ')) < 0)
13416 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013417 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
13418 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
13419 reply_len = -1;
13420 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
13421 if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
13422 reply_len = -1;
13423 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -070013424 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013425 wpas_dpp_listen_stop(wpa_s);
13426 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
13427 int res;
13428
Hai Shalom021b0b52019-04-10 11:17:58 -070013429 res = dpp_configurator_add(wpa_s->dpp, buf + 20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013430 if (res < 0) {
13431 reply_len = -1;
13432 } else {
13433 reply_len = os_snprintf(reply, reply_size, "%d", res);
13434 if (os_snprintf_error(reply_size, reply_len))
13435 reply_len = -1;
13436 }
Sunil Ravia04bd252022-05-02 22:54:18 -070013437 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
13438 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0)
13439 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013440 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013441 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013442 reply_len = -1;
13443 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -080013444 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013445 reply_len = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -070013446 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013447 reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
13448 atoi(buf + 25),
13449 reply, reply_size);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013450 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
13451 int res;
13452
13453 res = wpas_dpp_pkex_add(wpa_s, buf + 12);
13454 if (res < 0) {
13455 reply_len = -1;
13456 } else {
13457 reply_len = os_snprintf(reply, reply_size, "%d", res);
13458 if (os_snprintf_error(reply_size, reply_len))
13459 reply_len = -1;
13460 }
13461 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
13462 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
13463 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013464 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
13465 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
13466 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070013467#ifdef CONFIG_DPP2
13468 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
13469 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
13470 reply_len = -1;
13471 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
13472 if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
13473 reply_len = -1;
13474 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
13475 dpp_controller_stop(wpa_s->dpp);
Hai Shalomfdcde762020-04-02 11:19:20 -070013476 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
13477 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
13478 reply_len = -1;
13479 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
13480 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070013481 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
Hai Shalom899fcc72020-10-19 14:38:18 -070013482 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
13483 reply_len = -1;
13484 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
13485 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -070013486 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070013487#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -070013488#ifdef CONFIG_DPP3
13489 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
13490 if (wpas_dpp_push_button(wpa_s, NULL) < 0)
13491 reply_len = -1;
13492 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
13493 if (wpas_dpp_push_button(wpa_s, buf + 15) < 0)
13494 reply_len = -1;
13495#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013496#endif /* CONFIG_DPP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013497#ifdef CONFIG_NAN_USD
13498 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
13499 reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
13500 reply_size);
13501 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
13502 if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
Hai Shalom899fcc72020-10-19 14:38:18 -070013503 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013504 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
13505 if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
13506 reply_len = -1;
13507 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
13508 reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
13509 reply_size);
13510 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
13511 if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
13512 reply_len = -1;
13513 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
13514 if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
13515 reply_len = -1;
13516#endif /* CONFIG_NAN_USD */
Hai Shalom60840252021-02-19 19:02:11 -080013517#ifdef CONFIG_PASN
13518 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
13519 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
13520 reply_len = -1;
13521 } else if (os_strcmp(buf, "PASN_STOP") == 0) {
13522 wpas_pasn_auth_stop(wpa_s);
13523 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
13524 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
Hai Shaloma20dcd72022-02-04 13:43:00 -080013525 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
13526 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
13527 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013528#ifdef CONFIG_TESTING_OPTIONS
13529 } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
13530 if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
13531 reply_len = -1;
13532#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -080013533#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013534#ifndef CONFIG_NO_ROBUST_AV
13535 } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
13536 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
13537 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013538 } else if (os_strncmp(buf, "SCS ", 4) == 0) {
13539 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
13540 reply_len = -1;
13541 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
13542 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
13543 reply_len = -1;
13544 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
13545 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
13546 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013547#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi89eba102022-09-13 21:04:37 -070013548 } else if (os_strcmp(buf, "MLO_STATUS") == 0) {
13549 reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
13550 reply_size);
13551 } else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) {
13552 reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply,
13553 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013554 } else {
13555 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13556 reply_len = 16;
13557 }
13558
13559 if (reply_len < 0) {
13560 os_memcpy(reply, "FAIL\n", 5);
13561 reply_len = 5;
13562 }
13563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013564 *resp_len = reply_len;
13565 return reply;
13566}
13567
13568
13569static int wpa_supplicant_global_iface_add(struct wpa_global *global,
13570 char *cmd)
13571{
13572 struct wpa_interface iface;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013573 char *pos, *extra;
13574 struct wpa_supplicant *wpa_s;
13575 unsigned int create_iface = 0;
13576 u8 mac_addr[ETH_ALEN];
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013577 enum wpa_driver_if_type type = WPA_IF_STATION;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013578
13579 /*
13580 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013581 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013582 */
13583 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
13584
13585 os_memset(&iface, 0, sizeof(iface));
13586
13587 do {
13588 iface.ifname = pos = cmd;
13589 pos = os_strchr(pos, '\t');
13590 if (pos)
13591 *pos++ = '\0';
13592 if (iface.ifname[0] == '\0')
13593 return -1;
13594 if (pos == NULL)
13595 break;
13596
13597 iface.confname = pos;
13598 pos = os_strchr(pos, '\t');
13599 if (pos)
13600 *pos++ = '\0';
13601 if (iface.confname[0] == '\0')
13602 iface.confname = NULL;
13603 if (pos == NULL)
13604 break;
13605
13606 iface.driver = pos;
13607 pos = os_strchr(pos, '\t');
13608 if (pos)
13609 *pos++ = '\0';
13610 if (iface.driver[0] == '\0')
13611 iface.driver = NULL;
13612 if (pos == NULL)
13613 break;
13614
13615 iface.ctrl_interface = pos;
13616 pos = os_strchr(pos, '\t');
13617 if (pos)
13618 *pos++ = '\0';
13619 if (iface.ctrl_interface[0] == '\0')
13620 iface.ctrl_interface = NULL;
13621 if (pos == NULL)
13622 break;
13623
13624 iface.driver_param = pos;
13625 pos = os_strchr(pos, '\t');
13626 if (pos)
13627 *pos++ = '\0';
13628 if (iface.driver_param[0] == '\0')
13629 iface.driver_param = NULL;
13630 if (pos == NULL)
13631 break;
13632
13633 iface.bridge_ifname = pos;
13634 pos = os_strchr(pos, '\t');
13635 if (pos)
13636 *pos++ = '\0';
13637 if (iface.bridge_ifname[0] == '\0')
13638 iface.bridge_ifname = NULL;
13639 if (pos == NULL)
13640 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013641
13642 extra = pos;
13643 pos = os_strchr(pos, '\t');
13644 if (pos)
13645 *pos++ = '\0';
Dmitry Shmidt83474442015-04-15 13:47:09 -070013646 if (!extra[0])
13647 break;
13648
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013649 if (os_strcmp(extra, "create") == 0) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013650 create_iface = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013651 if (!pos)
13652 break;
13653
13654 if (os_strcmp(pos, "sta") == 0) {
13655 type = WPA_IF_STATION;
13656 } else if (os_strcmp(pos, "ap") == 0) {
13657 type = WPA_IF_AP_BSS;
13658 } else {
13659 wpa_printf(MSG_DEBUG,
13660 "INTERFACE_ADD unsupported interface type: '%s'",
13661 pos);
13662 return -1;
13663 }
13664 } else {
Dmitry Shmidt83474442015-04-15 13:47:09 -070013665 wpa_printf(MSG_DEBUG,
13666 "INTERFACE_ADD unsupported extra parameter: '%s'",
13667 extra);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013668 return -1;
Dmitry Shmidt83474442015-04-15 13:47:09 -070013669 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013670 } while (0);
13671
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013672 if (create_iface) {
13673 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
13674 iface.ifname);
13675 if (!global->ifaces)
13676 return -1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013677 if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013678 NULL, NULL, NULL, mac_addr, NULL) < 0) {
13679 wpa_printf(MSG_ERROR,
13680 "CTRL_IFACE interface creation failed");
13681 return -1;
13682 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013683
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013684 wpa_printf(MSG_DEBUG,
13685 "CTRL_IFACE interface '%s' created with MAC addr: "
13686 MACSTR, iface.ifname, MAC2STR(mac_addr));
13687 }
13688
13689 if (wpa_supplicant_get_iface(global, iface.ifname))
13690 goto fail;
13691
13692 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
13693 if (!wpa_s)
13694 goto fail;
13695 wpa_s->added_vif = create_iface;
13696 return 0;
13697
13698fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013699 if (create_iface) {
13700 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13701 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013702 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013703 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013704 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013705}
13706
13707
13708static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
13709 char *cmd)
13710{
13711 struct wpa_supplicant *wpa_s;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013712 int ret;
13713 unsigned int delete_iface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013714
13715 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
13716
13717 wpa_s = wpa_supplicant_get_iface(global, cmd);
13718 if (wpa_s == NULL)
13719 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013720 delete_iface = wpa_s->added_vif;
13721 ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
13722 if (!ret && delete_iface) {
13723 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
13724 cmd);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013725 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13726 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013727 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
13728 }
13729 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013730}
13731
13732
13733static void wpa_free_iface_info(struct wpa_interface_info *iface)
13734{
13735 struct wpa_interface_info *prev;
13736
13737 while (iface) {
13738 prev = iface;
13739 iface = iface->next;
13740
13741 os_free(prev->ifname);
13742 os_free(prev->desc);
13743 os_free(prev);
13744 }
13745}
13746
13747
13748static int wpa_supplicant_global_iface_list(struct wpa_global *global,
13749 char *buf, int len)
13750{
13751 int i, res;
13752 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
13753 char *pos, *end;
13754
13755 for (i = 0; wpa_drivers[i]; i++) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070013756 const struct wpa_driver_ops *drv = wpa_drivers[i];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013757 if (drv->get_interfaces == NULL)
13758 continue;
13759 tmp = drv->get_interfaces(global->drv_priv[i]);
13760 if (tmp == NULL)
13761 continue;
13762
13763 if (last == NULL)
13764 iface = last = tmp;
13765 else
13766 last->next = tmp;
13767 while (last->next)
13768 last = last->next;
13769 }
13770
13771 pos = buf;
13772 end = buf + len;
13773 for (tmp = iface; tmp; tmp = tmp->next) {
13774 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
13775 tmp->drv_name, tmp->ifname,
13776 tmp->desc ? tmp->desc : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013777 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013778 *pos = '\0';
13779 break;
13780 }
13781 pos += res;
13782 }
13783
13784 wpa_free_iface_info(iface);
13785
13786 return pos - buf;
13787}
13788
13789
13790static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013791 const char *input,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013792 char *buf, int len)
13793{
13794 int res;
13795 char *pos, *end;
13796 struct wpa_supplicant *wpa_s;
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013797 int show_ctrl = 0;
13798
13799 if (input)
13800 show_ctrl = !!os_strstr(input, "ctrl");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013801
13802 wpa_s = global->ifaces;
13803 pos = buf;
13804 end = buf + len;
13805
13806 while (wpa_s) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013807 if (show_ctrl)
13808 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
13809 wpa_s->ifname,
13810 wpa_s->conf->ctrl_interface ?
13811 wpa_s->conf->ctrl_interface : "N/A");
13812 else
13813 res = os_snprintf(pos, end - pos, "%s\n",
13814 wpa_s->ifname);
13815
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013816 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013817 *pos = '\0';
13818 break;
13819 }
13820 pos += res;
13821 wpa_s = wpa_s->next;
13822 }
13823 return pos - buf;
13824}
13825
13826
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013827static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
13828 const char *ifname,
13829 char *cmd, size_t *resp_len)
13830{
13831 struct wpa_supplicant *wpa_s;
13832
13833 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
13834 if (os_strcmp(ifname, wpa_s->ifname) == 0)
13835 break;
13836 }
13837
13838 if (wpa_s == NULL) {
13839 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
13840 if (resp)
13841 *resp_len = os_strlen(resp);
13842 else
13843 *resp_len = 1;
13844 return resp;
13845 }
13846
13847 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
13848}
13849
13850
13851static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
13852 char *buf, size_t *resp_len)
13853{
13854#ifdef CONFIG_P2P
13855 static const char * cmd[] = {
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070013856 "LIST_NETWORKS",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013857 "P2P_FIND",
13858 "P2P_STOP_FIND",
13859 "P2P_LISTEN",
13860 "P2P_GROUP_ADD",
13861 "P2P_GET_PASSPHRASE",
13862 "P2P_SERVICE_UPDATE",
13863 "P2P_SERVICE_FLUSH",
13864 "P2P_FLUSH",
13865 "P2P_CANCEL",
13866 "P2P_PRESENCE_REQ",
13867 "P2P_EXT_LISTEN",
Paul Stewart092955c2017-02-06 09:13:09 -080013868#ifdef CONFIG_AP
13869 "STA-FIRST",
13870#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013871 NULL
13872 };
13873 static const char * prefix[] = {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080013874#ifdef ANDROID
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070013875 "DRIVER ",
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080013876#endif /* ANDROID */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013877 "GET_CAPABILITY ",
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070013878 "GET_NETWORK ",
13879 "REMOVE_NETWORK ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013880 "P2P_FIND ",
13881 "P2P_CONNECT ",
13882 "P2P_LISTEN ",
13883 "P2P_GROUP_REMOVE ",
13884 "P2P_GROUP_ADD ",
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013885 "P2P_GROUP_MEMBER ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013886 "P2P_PROV_DISC ",
13887 "P2P_SERV_DISC_REQ ",
13888 "P2P_SERV_DISC_CANCEL_REQ ",
13889 "P2P_SERV_DISC_RESP ",
13890 "P2P_SERV_DISC_EXTERNAL ",
13891 "P2P_SERVICE_ADD ",
13892 "P2P_SERVICE_DEL ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080013893 "P2P_SERVICE_REP ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013894 "P2P_REJECT ",
13895 "P2P_INVITE ",
13896 "P2P_PEER ",
13897 "P2P_SET ",
13898 "P2P_UNAUTHORIZE ",
13899 "P2P_PRESENCE_REQ ",
13900 "P2P_EXT_LISTEN ",
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070013901 "P2P_REMOVE_CLIENT ",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080013902 "WPS_NFC_TOKEN ",
13903 "WPS_NFC_TAG_READ ",
Dmitry Shmidt413dde72014-04-11 10:23:22 -070013904 "NFC_GET_HANDOVER_SEL ",
13905 "NFC_GET_HANDOVER_REQ ",
13906 "NFC_REPORT_HANDOVER ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080013907 "P2P_ASP_PROVISION ",
13908 "P2P_ASP_PROVISION_RESP ",
Paul Stewart092955c2017-02-06 09:13:09 -080013909#ifdef CONFIG_AP
13910 "STA ",
13911 "STA-NEXT ",
13912#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070013913 NULL
13914 };
13915 int found = 0;
13916 int i;
13917
13918 if (global->p2p_init_wpa_s == NULL)
13919 return NULL;
13920
13921 for (i = 0; !found && cmd[i]; i++) {
13922 if (os_strcmp(buf, cmd[i]) == 0)
13923 found = 1;
13924 }
13925
13926 for (i = 0; !found && prefix[i]; i++) {
13927 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
13928 found = 1;
13929 }
13930
13931 if (found)
13932 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13933 buf, resp_len);
13934#endif /* CONFIG_P2P */
13935 return NULL;
13936}
13937
13938
13939static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
13940 char *buf, size_t *resp_len)
13941{
13942#ifdef CONFIG_WIFI_DISPLAY
13943 if (global->p2p_init_wpa_s == NULL)
13944 return NULL;
13945 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
13946 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
13947 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
13948 buf, resp_len);
13949#endif /* CONFIG_WIFI_DISPLAY */
13950 return NULL;
13951}
13952
13953
13954static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
13955 char *buf, size_t *resp_len)
13956{
13957 char *ret;
13958
13959 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
13960 if (ret)
13961 return ret;
13962
13963 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
13964 if (ret)
13965 return ret;
13966
13967 return NULL;
13968}
13969
13970
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013971static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
13972{
13973 char *value;
13974
13975 value = os_strchr(cmd, ' ');
13976 if (value == NULL)
13977 return -1;
13978 *value++ = '\0';
13979
13980 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
13981
13982#ifdef CONFIG_WIFI_DISPLAY
13983 if (os_strcasecmp(cmd, "wifi_display") == 0) {
13984 wifi_display_enable(global, !!atoi(value));
13985 return 0;
13986 }
13987#endif /* CONFIG_WIFI_DISPLAY */
13988
Dmitry Shmidt61593f02014-04-21 16:27:35 -070013989 /* Restore cmd to its original value to allow redirection */
13990 value[-1] = ' ';
13991
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070013992 return -1;
13993}
13994
13995
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013996static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
13997 char *cmd)
13998{
13999 struct wpa_supplicant *wpa_s[2]; /* src, dst */
14000 char *p;
14001 unsigned int i;
14002
14003 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
14004 * <variable name> */
14005
14006 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
14007 p = os_strchr(cmd, ' ');
14008 if (p == NULL)
14009 return -1;
14010 *p = '\0';
14011
14012 wpa_s[i] = global->ifaces;
14013 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
14014 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
14015 break;
14016 }
14017
14018 if (!wpa_s[i]) {
14019 wpa_printf(MSG_DEBUG,
14020 "CTRL_IFACE: Could not find iface=%s", cmd);
14021 return -1;
14022 }
14023
14024 cmd = p + 1;
14025 }
14026
14027 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
14028}
14029
14030
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014031#ifndef CONFIG_NO_CONFIG_WRITE
14032static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
14033{
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014034 int ret = 0, saved = 0;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014035 struct wpa_supplicant *wpa_s;
14036
14037 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14038 if (!wpa_s->conf->update_config) {
14039 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
14040 continue;
14041 }
14042
14043 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
14044 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
14045 ret = 1;
14046 } else {
14047 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014048 saved++;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014049 }
14050 }
14051
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014052 if (!saved && !ret) {
14053 wpa_dbg(wpa_s, MSG_DEBUG,
14054 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
14055 ret = 1;
14056 }
14057
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014058 return ret;
14059}
14060#endif /* CONFIG_NO_CONFIG_WRITE */
14061
14062
14063static int wpas_global_ctrl_iface_status(struct wpa_global *global,
14064 char *buf, size_t buflen)
14065{
14066 char *pos, *end;
14067 int ret;
14068 struct wpa_supplicant *wpa_s;
14069
14070 pos = buf;
14071 end = buf + buflen;
14072
14073#ifdef CONFIG_P2P
14074 if (global->p2p && !global->p2p_disabled) {
14075 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
14076 "\n"
14077 "p2p_state=%s\n",
14078 MAC2STR(global->p2p_dev_addr),
14079 p2p_get_state_txt(global->p2p));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014080 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014081 return pos - buf;
14082 pos += ret;
14083 } else if (global->p2p) {
14084 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014085 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014086 return pos - buf;
14087 pos += ret;
14088 }
14089#endif /* CONFIG_P2P */
14090
14091#ifdef CONFIG_WIFI_DISPLAY
14092 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
14093 !!global->wifi_display);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014094 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014095 return pos - buf;
14096 pos += ret;
14097#endif /* CONFIG_WIFI_DISPLAY */
14098
14099 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14100 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
14101 "address=" MACSTR "\n",
14102 wpa_s->ifname, MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014103 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014104 return pos - buf;
14105 pos += ret;
14106 }
14107
14108 return pos - buf;
14109}
14110
14111
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014112#ifdef CONFIG_FST
14113
14114static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
14115 char *cmd, char *buf,
14116 size_t reply_size)
14117{
14118 char ifname[IFNAMSIZ + 1];
14119 struct fst_iface_cfg cfg;
14120 struct wpa_supplicant *wpa_s;
14121 struct fst_wpa_obj iface_obj;
14122
14123 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
14124 wpa_s = wpa_supplicant_get_iface(global, ifname);
14125 if (wpa_s) {
14126 if (wpa_s->fst) {
14127 wpa_printf(MSG_INFO, "FST: Already attached");
14128 return -1;
14129 }
14130 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
14131 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
14132 &iface_obj, &cfg);
14133 if (wpa_s->fst)
14134 return os_snprintf(buf, reply_size, "OK\n");
14135 }
14136 }
14137
14138 return -1;
14139}
14140
14141
14142static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
14143 char *cmd, char *buf,
14144 size_t reply_size)
14145{
14146 char ifname[IFNAMSIZ + 1];
14147 struct wpa_supplicant *wpa_s;
14148
14149 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
14150 wpa_s = wpa_supplicant_get_iface(global, ifname);
14151 if (wpa_s) {
14152 if (!fst_iface_detach(ifname)) {
14153 wpa_s->fst = NULL;
14154 return os_snprintf(buf, reply_size, "OK\n");
14155 }
14156 }
14157 }
14158
14159 return -1;
14160}
14161
14162#endif /* CONFIG_FST */
14163
14164
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014165char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
14166 char *buf, size_t *resp_len)
14167{
14168 char *reply;
14169 const int reply_size = 2048;
14170 int reply_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080014171 int level = MSG_DEBUG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014172
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014173 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
14174 char *pos = os_strchr(buf + 7, ' ');
14175 if (pos) {
14176 *pos++ = '\0';
14177 return wpas_global_ctrl_iface_ifname(global,
14178 buf + 7, pos,
14179 resp_len);
14180 }
14181 }
14182
14183 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
14184 if (reply)
14185 return reply;
14186
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080014187 if (os_strcmp(buf, "PING") == 0)
14188 level = MSG_EXCESSIVE;
14189 wpa_hexdump_ascii(level, "RX global ctrl_iface",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014190 (const u8 *) buf, os_strlen(buf));
14191
14192 reply = os_malloc(reply_size);
14193 if (reply == NULL) {
14194 *resp_len = 1;
14195 return NULL;
14196 }
14197
14198 os_memcpy(reply, "OK\n", 3);
14199 reply_len = 3;
14200
14201 if (os_strcmp(buf, "PING") == 0) {
14202 os_memcpy(reply, "PONG\n", 5);
14203 reply_len = 5;
14204 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
14205 if (wpa_supplicant_global_iface_add(global, buf + 14))
14206 reply_len = -1;
14207 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
14208 if (wpa_supplicant_global_iface_remove(global, buf + 17))
14209 reply_len = -1;
14210 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
14211 reply_len = wpa_supplicant_global_iface_list(
14212 global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014213 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014214 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014215 global, buf + 10, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014216#ifdef CONFIG_FST
14217 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
14218 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
14219 reply,
14220 reply_size);
14221 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
14222 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
14223 reply,
14224 reply_size);
14225 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
14226 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
14227#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014228 } else if (os_strcmp(buf, "TERMINATE") == 0) {
14229 wpa_supplicant_terminate_proc(global);
14230 } else if (os_strcmp(buf, "SUSPEND") == 0) {
14231 wpas_notify_suspend(global);
14232 } else if (os_strcmp(buf, "RESUME") == 0) {
14233 wpas_notify_resume(global);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014234 } else if (os_strncmp(buf, "SET ", 4) == 0) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014235 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
14236#ifdef CONFIG_P2P
14237 if (global->p2p_init_wpa_s) {
14238 os_free(reply);
14239 /* Check if P2P redirection would work for this
14240 * command. */
14241 return wpa_supplicant_ctrl_iface_process(
14242 global->p2p_init_wpa_s,
14243 buf, resp_len);
14244 }
14245#endif /* CONFIG_P2P */
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014246 reply_len = -1;
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014247 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014248 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
14249 if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
14250 reply_len = -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014251#ifndef CONFIG_NO_CONFIG_WRITE
14252 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
14253 if (wpas_global_ctrl_iface_save_config(global))
14254 reply_len = -1;
14255#endif /* CONFIG_NO_CONFIG_WRITE */
14256 } else if (os_strcmp(buf, "STATUS") == 0) {
14257 reply_len = wpas_global_ctrl_iface_status(global, reply,
14258 reply_size);
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080014259#ifdef CONFIG_MODULE_TESTS
14260 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080014261 if (wpas_module_tests() < 0)
14262 reply_len = -1;
14263#endif /* CONFIG_MODULE_TESTS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014264 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
14265 if (wpa_debug_reopen_file() < 0)
14266 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014267 } else {
14268 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
14269 reply_len = 16;
14270 }
14271
14272 if (reply_len < 0) {
14273 os_memcpy(reply, "FAIL\n", 5);
14274 reply_len = 5;
14275 }
14276
14277 *resp_len = reply_len;
14278 return reply;
14279}