blob: 43d1a66f892c5b7be66caa2a912d9d22bab76ecf [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 */
Sunil Ravi79e6c4f2025-01-04 00:47:06 +0000884 } else if (os_strcasecmp(cmd, "eapol_2_key_info_set_mask") == 0) {
885 wpa_s->eapol_2_key_info_set_mask = strtoul(value, NULL, 0x10);
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700886#endif /* CONFIG_TESTING_OPTIONS */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700887#ifdef CONFIG_FILS
888 } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
889 wpa_s->disable_fils = !!atoi(value);
890 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
891 wpa_supplicant_set_default_scan_ies(wpa_s);
892#endif /* CONFIG_FILS */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700893#ifndef CONFIG_NO_CONFIG_BLOBS
894 } else if (os_strcmp(cmd, "blob") == 0) {
895 ret = wpas_ctrl_set_blob(wpa_s, value);
896#endif /* CONFIG_NO_CONFIG_BLOBS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800897 } else if (os_strcasecmp(cmd, "setband") == 0) {
Ravi Joshie6ccb162015-07-16 17:45:41 -0700898 ret = wpas_ctrl_set_band(wpa_s, value);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800899#ifdef CONFIG_MBO
900 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
901 ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
Paul Stewart092955c2017-02-06 09:13:09 -0800902 if (ret == 0) {
903 value[-1] = '=';
904 wpa_config_process_global(wpa_s->conf, cmd, -1);
905 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800906 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
Sunil Ravi99c035e2024-07-12 01:42:03 +0000907 int val = atoi(value);
908
909 if (val < MBO_CELL_CAPA_AVAILABLE ||
910 val > MBO_CELL_CAPA_NOT_SUPPORTED)
911 return -1;
912
913 wpas_mbo_update_cell_capa(wpa_s, val);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700914 } else if (os_strcasecmp(cmd, "oce") == 0) {
Sunil Ravi99c035e2024-07-12 01:42:03 +0000915 int val = atoi(value);
916
917 if (val < 0 || val > 3)
918 return -1;
919
920 wpa_s->conf->oce = val;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700921 if (wpa_s->conf->oce) {
922 if ((wpa_s->conf->oce & OCE_STA) &&
923 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
924 wpa_s->enable_oce = OCE_STA;
925
926 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
927 (wpa_s->drv_flags &
928 WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
929 /* TODO: Need to add STA-CFON support */
930 wpa_printf(MSG_ERROR,
931 "OCE STA-CFON feature is not yet supported");
932 return -1;
933 }
934 } else {
935 wpa_s->enable_oce = 0;
936 }
937 wpa_supplicant_set_default_scan_ies(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800938#endif /* CONFIG_MBO */
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700939 } else if (os_strcasecmp(cmd, "lci") == 0) {
940 ret = wpas_ctrl_iface_set_lci(wpa_s, value);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800941 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
942 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800943 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
944 ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
945 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
946 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
947 } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
948 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700949 } else if (os_strcasecmp(cmd, "roaming") == 0) {
950 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800951#ifdef CONFIG_WNM
952 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
953 struct wpabuf *elems;
954
955 elems = wpabuf_parse_bin(value);
956 if (!elems)
957 return -1;
958 wnm_set_coloc_intf_elems(wpa_s, elems);
959#endif /* CONFIG_WNM */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000960#ifndef CONFIG_NO_ROBUST_AV
Hai Shaloma20dcd72022-02-04 13:43:00 -0800961 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
962 wpa_s->enable_dscp_policy_capa = !!atoi(value);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000963#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700964 } else {
965 value[-1] = '=';
966 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
967 if (ret == 0)
968 wpa_supplicant_update_config(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -0700969 else if (ret == 1)
970 ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 }
972
973 return ret;
974}
975
976
977static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
978 char *cmd, char *buf, size_t buflen)
979{
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700980 int res = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981
982 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
983
984 if (os_strcmp(cmd, "version") == 0) {
985 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700986 } else if (os_strcasecmp(cmd, "max_command_len") == 0) {
987 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN);
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700988 } else if (os_strcasecmp(cmd, "country") == 0) {
989 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
990 res = os_snprintf(buf, buflen, "%c%c",
991 wpa_s->conf->country[0],
992 wpa_s->conf->country[1]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700993#ifdef CONFIG_WIFI_DISPLAY
994 } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
Dmitry Shmidted003d22014-02-06 10:09:12 -0800995 int enabled;
996 if (wpa_s->global->p2p == NULL ||
997 wpa_s->global->p2p_disabled)
998 enabled = 0;
999 else
1000 enabled = wpa_s->global->wifi_display;
1001 res = os_snprintf(buf, buflen, "%d", enabled);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001002#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001003#ifdef CONFIG_TESTING_GET_GTK
1004 } else if (os_strcmp(cmd, "gtk") == 0) {
1005 if (wpa_s->last_gtk_len == 0)
1006 return -1;
1007 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
1008 wpa_s->last_gtk_len);
1009 return res;
1010#endif /* CONFIG_TESTING_GET_GTK */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001011 } else if (os_strcmp(cmd, "tls_library") == 0) {
1012 res = tls_get_library_version(buf, buflen);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001013#ifdef CONFIG_TESTING_OPTIONS
1014 } else if (os_strcmp(cmd, "anonce") == 0) {
1015 return wpa_snprintf_hex(buf, buflen,
1016 wpa_sm_get_anonce(wpa_s->wpa),
1017 WPA_NONCE_LEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001018 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) {
1019 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001020#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001021 } else {
1022 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023 }
1024
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001025 if (os_snprintf_error(buflen, res))
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -07001026 return -1;
1027 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001028}
1029
1030
1031#ifdef IEEE8021X_EAPOL
1032static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
1033 char *addr)
1034{
1035 u8 bssid[ETH_ALEN];
1036 struct wpa_ssid *ssid = wpa_s->current_ssid;
1037
1038 if (hwaddr_aton(addr, bssid)) {
1039 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
1040 "'%s'", addr);
1041 return -1;
1042 }
1043
1044 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
1045 rsn_preauth_deinit(wpa_s->wpa);
1046 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
1047 return -1;
1048
1049 return 0;
1050}
1051#endif /* IEEE8021X_EAPOL */
1052
1053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054#ifdef CONFIG_TDLS
1055
1056static int wpa_supplicant_ctrl_iface_tdls_discover(
1057 struct wpa_supplicant *wpa_s, char *addr)
1058{
1059 u8 peer[ETH_ALEN];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001060 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001061
1062 if (hwaddr_aton(addr, peer)) {
1063 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
1064 "address '%s'", addr);
1065 return -1;
1066 }
1067
1068 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
1069 MAC2STR(peer));
1070
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001071 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1072 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
1073 else
1074 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
1075
1076 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001077}
1078
1079
1080static int wpa_supplicant_ctrl_iface_tdls_setup(
1081 struct wpa_supplicant *wpa_s, char *addr)
1082{
1083 u8 peer[ETH_ALEN];
1084 int ret;
1085
1086 if (hwaddr_aton(addr, peer)) {
1087 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
1088 "address '%s'", addr);
1089 return -1;
1090 }
1091
1092 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
1093 MAC2STR(peer));
1094
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001095 if ((wpa_s->conf->tdls_external_control) &&
1096 wpa_tdls_is_external_setup(wpa_s->wpa))
1097 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
1098
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001099 wpa_tdls_remove(wpa_s->wpa, peer);
1100
1101 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1102 ret = wpa_tdls_start(wpa_s->wpa, peer);
1103 else
1104 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 return ret;
1107}
1108
1109
1110static int wpa_supplicant_ctrl_iface_tdls_teardown(
1111 struct wpa_supplicant *wpa_s, char *addr)
1112{
1113 u8 peer[ETH_ALEN];
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001114 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001115
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001116 if (os_strcmp(addr, "*") == 0) {
1117 /* remove everyone */
1118 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
1119 wpa_tdls_teardown_peers(wpa_s->wpa);
1120 return 0;
1121 }
1122
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123 if (hwaddr_aton(addr, peer)) {
1124 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
1125 "address '%s'", addr);
1126 return -1;
1127 }
1128
1129 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
1130 MAC2STR(peer));
1131
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001132 if ((wpa_s->conf->tdls_external_control) &&
1133 wpa_tdls_is_external_setup(wpa_s->wpa))
1134 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1135
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001136 if (wpa_tdls_is_external_setup(wpa_s->wpa))
1137 ret = wpa_tdls_teardown_link(
1138 wpa_s->wpa, peer,
1139 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
1140 else
1141 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
1142
1143 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144}
1145
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001146
1147static int ctrl_iface_get_capability_tdls(
1148 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1149{
1150 int ret;
1151
1152 ret = os_snprintf(buf, buflen, "%s\n",
1153 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
1154 (wpa_s->drv_flags &
1155 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
1156 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001157 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001158 return -1;
1159 return ret;
1160}
1161
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001162
1163static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
1164 struct wpa_supplicant *wpa_s, char *cmd)
1165{
1166 u8 peer[ETH_ALEN];
1167 struct hostapd_freq_params freq_params;
1168 u8 oper_class;
1169 char *pos, *end;
1170
1171 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1172 wpa_printf(MSG_INFO,
1173 "tdls_chanswitch: Only supported with external setup");
1174 return -1;
1175 }
1176
1177 os_memset(&freq_params, 0, sizeof(freq_params));
1178
1179 pos = os_strchr(cmd, ' ');
1180 if (pos == NULL)
1181 return -1;
1182 *pos++ = '\0';
1183
1184 oper_class = strtol(pos, &end, 10);
1185 if (pos == end) {
1186 wpa_printf(MSG_INFO,
1187 "tdls_chanswitch: Invalid op class provided");
1188 return -1;
1189 }
1190
1191 pos = end;
1192 freq_params.freq = atoi(pos);
1193 if (freq_params.freq == 0) {
1194 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
1195 return -1;
1196 }
1197
1198#define SET_FREQ_SETTING(str) \
1199 do { \
1200 const char *pos2 = os_strstr(pos, " " #str "="); \
1201 if (pos2) { \
1202 pos2 += sizeof(" " #str "=") - 1; \
1203 freq_params.str = atoi(pos2); \
1204 } \
1205 } while (0)
1206
1207 SET_FREQ_SETTING(center_freq1);
1208 SET_FREQ_SETTING(center_freq2);
1209 SET_FREQ_SETTING(bandwidth);
1210 SET_FREQ_SETTING(sec_channel_offset);
1211#undef SET_FREQ_SETTING
1212
1213 freq_params.ht_enabled = !!os_strstr(pos, " ht");
1214 freq_params.vht_enabled = !!os_strstr(pos, " vht");
1215
1216 if (hwaddr_aton(cmd, peer)) {
1217 wpa_printf(MSG_DEBUG,
1218 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
1219 cmd);
1220 return -1;
1221 }
1222
1223 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
1224 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
1225 MAC2STR(peer), oper_class, freq_params.freq,
1226 freq_params.center_freq1, freq_params.center_freq2,
1227 freq_params.bandwidth, freq_params.sec_channel_offset,
1228 freq_params.ht_enabled ? " HT" : "",
1229 freq_params.vht_enabled ? " VHT" : "");
1230
1231 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
1232 &freq_params);
1233}
1234
1235
1236static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
1237 struct wpa_supplicant *wpa_s, char *cmd)
1238{
1239 u8 peer[ETH_ALEN];
1240
1241 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
1242 wpa_printf(MSG_INFO,
1243 "tdls_chanswitch: Only supported with external setup");
1244 return -1;
1245 }
1246
1247 if (hwaddr_aton(cmd, peer)) {
1248 wpa_printf(MSG_DEBUG,
1249 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
1250 cmd);
1251 return -1;
1252 }
1253
1254 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
1255 MAC2STR(peer));
1256
1257 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
1258}
1259
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07001260
1261static int wpa_supplicant_ctrl_iface_tdls_link_status(
1262 struct wpa_supplicant *wpa_s, const char *addr,
1263 char *buf, size_t buflen)
1264{
1265 u8 peer[ETH_ALEN];
1266 const char *tdls_status;
1267 int ret;
1268
1269 if (hwaddr_aton(addr, peer)) {
1270 wpa_printf(MSG_DEBUG,
1271 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'",
1272 addr);
1273 return -1;
1274 }
1275 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR,
1276 MAC2STR(peer));
1277
1278 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
1279 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status);
1280 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status);
1281 if (os_snprintf_error(buflen, ret))
1282 return -1;
1283
1284 return ret;
1285}
1286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287#endif /* CONFIG_TDLS */
1288
1289
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001290#ifndef CONFIG_NO_WMM_AC
1291
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001292static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
1293{
1294 char *token, *context = NULL;
1295 struct wmm_ac_ts_setup_params params = {
1296 .tsid = 0xff,
1297 .direction = 0xff,
1298 };
1299
1300 while ((token = str_token(cmd, " ", &context))) {
1301 if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
1302 sscanf(token, "up=%i", &params.user_priority) == 1 ||
1303 sscanf(token, "nominal_msdu_size=%i",
1304 &params.nominal_msdu_size) == 1 ||
1305 sscanf(token, "mean_data_rate=%i",
1306 &params.mean_data_rate) == 1 ||
1307 sscanf(token, "min_phy_rate=%i",
1308 &params.minimum_phy_rate) == 1 ||
1309 sscanf(token, "sba=%i",
1310 &params.surplus_bandwidth_allowance) == 1)
1311 continue;
1312
1313 if (os_strcasecmp(token, "downlink") == 0) {
1314 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
1315 } else if (os_strcasecmp(token, "uplink") == 0) {
1316 params.direction = WMM_TSPEC_DIRECTION_UPLINK;
1317 } else if (os_strcasecmp(token, "bidi") == 0) {
1318 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
1319 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
1320 params.fixed_nominal_msdu = 1;
1321 } else {
1322 wpa_printf(MSG_DEBUG,
1323 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
1324 token);
1325 return -1;
1326 }
1327
1328 }
1329
1330 return wpas_wmm_ac_addts(wpa_s, &params);
1331}
1332
1333
1334static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
1335{
1336 u8 tsid = atoi(cmd);
1337
1338 return wpas_wmm_ac_delts(wpa_s, tsid);
1339}
1340
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001341#endif /* CONFIG_NO_WMM_AC */
1342
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001343
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344#ifdef CONFIG_IEEE80211R
1345static int wpa_supplicant_ctrl_iface_ft_ds(
1346 struct wpa_supplicant *wpa_s, char *addr)
1347{
1348 u8 target_ap[ETH_ALEN];
1349 struct wpa_bss *bss;
1350 const u8 *mdie;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001351 bool force = os_strstr(addr, " force") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001352
1353 if (hwaddr_aton(addr, target_ap)) {
1354 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
1355 "address '%s'", addr);
1356 return -1;
1357 }
1358
1359 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
1360
1361 bss = wpa_bss_get_bssid(wpa_s, target_ap);
1362 if (bss)
1363 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1364 else
1365 mdie = NULL;
1366
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001367 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368}
1369#endif /* CONFIG_IEEE80211R */
1370
1371
1372#ifdef CONFIG_WPS
1373static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
1374 char *cmd)
1375{
1376 u8 bssid[ETH_ALEN], *_bssid = bssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001377#ifdef CONFIG_P2P
1378 u8 p2p_dev_addr[ETH_ALEN];
1379#endif /* CONFIG_P2P */
1380#ifdef CONFIG_AP
1381 u8 *_p2p_dev_addr = NULL;
1382#endif /* CONFIG_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001383 char *pos;
1384 int multi_ap = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001385
Hai Shalom021b0b52019-04-10 11:17:58 -07001386 if (!cmd || os_strcmp(cmd, "any") == 0 ||
1387 os_strncmp(cmd, "any ", 4) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388 _bssid = NULL;
1389#ifdef CONFIG_P2P
1390 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
1391 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
1392 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
1393 "P2P Device Address '%s'",
1394 cmd + 13);
1395 return -1;
1396 }
1397 _p2p_dev_addr = p2p_dev_addr;
1398#endif /* CONFIG_P2P */
Hai Shalom021b0b52019-04-10 11:17:58 -07001399 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
1400 _bssid = NULL;
1401 multi_ap = atoi(cmd + 9);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 } else if (hwaddr_aton(cmd, bssid)) {
1403 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
1404 cmd);
1405 return -1;
1406 }
1407
Hai Shalom021b0b52019-04-10 11:17:58 -07001408 if (cmd) {
1409 pos = os_strstr(cmd, " multi_ap=");
1410 if (pos) {
1411 pos += 10;
1412 multi_ap = atoi(pos);
1413 }
1414 }
1415
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001416#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 if (wpa_s->ap_iface)
1418 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
1419#endif /* CONFIG_AP */
1420
Hai Shalom021b0b52019-04-10 11:17:58 -07001421 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422}
1423
1424
1425static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
1426 char *cmd, char *buf,
1427 size_t buflen)
1428{
1429 u8 bssid[ETH_ALEN], *_bssid = bssid;
1430 char *pin;
1431 int ret;
1432
1433 pin = os_strchr(cmd, ' ');
1434 if (pin)
1435 *pin++ = '\0';
1436
1437 if (os_strcmp(cmd, "any") == 0)
1438 _bssid = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001439 else if (os_strcmp(cmd, "get") == 0) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001440 if (wps_generate_pin((unsigned int *) &ret) < 0)
1441 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001442 goto done;
1443 } else if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001444 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
1445 cmd);
1446 return -1;
1447 }
1448
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001449#ifdef CONFIG_AP
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001450 if (wpa_s->ap_iface) {
1451 int timeout = 0;
1452 char *pos;
1453
1454 if (pin) {
1455 pos = os_strchr(pin, ' ');
1456 if (pos) {
1457 *pos++ = '\0';
1458 timeout = atoi(pos);
1459 }
1460 }
1461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001463 buf, buflen, timeout);
1464 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465#endif /* CONFIG_AP */
1466
1467 if (pin) {
1468 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
1469 DEV_PW_DEFAULT);
1470 if (ret < 0)
1471 return -1;
1472 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001473 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001474 return -1;
1475 return ret;
1476 }
1477
1478 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
1479 if (ret < 0)
1480 return -1;
1481
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001482done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483 /* Return the generated PIN */
1484 ret = os_snprintf(buf, buflen, "%08d", ret);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001485 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486 return -1;
1487 return ret;
1488}
1489
1490
1491static int wpa_supplicant_ctrl_iface_wps_check_pin(
1492 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1493{
1494 char pin[9];
1495 size_t len;
1496 char *pos;
1497 int ret;
1498
1499 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
1500 (u8 *) cmd, os_strlen(cmd));
1501 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
1502 if (*pos < '0' || *pos > '9')
1503 continue;
1504 pin[len++] = *pos;
1505 if (len == 9) {
1506 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
1507 return -1;
1508 }
1509 }
1510 if (len != 4 && len != 8) {
1511 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
1512 return -1;
1513 }
1514 pin[len] = '\0';
1515
1516 if (len == 8) {
1517 unsigned int pin_val;
1518 pin_val = atoi(pin);
1519 if (!wps_pin_valid(pin_val)) {
1520 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
1521 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001522 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001523 return -1;
1524 return ret;
1525 }
1526 }
1527
1528 ret = os_snprintf(buf, buflen, "%s", pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001529 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001530 return -1;
1531
1532 return ret;
1533}
1534
1535
Dmitry Shmidt04949592012-07-19 12:16:46 -07001536#ifdef CONFIG_WPS_NFC
1537
1538static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
1539 char *cmd)
1540{
1541 u8 bssid[ETH_ALEN], *_bssid = bssid;
1542
1543 if (cmd == NULL || cmd[0] == '\0')
1544 _bssid = NULL;
1545 else if (hwaddr_aton(cmd, bssid))
1546 return -1;
1547
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001548 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1549 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001550}
1551
1552
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001553static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1554 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1555{
1556 int ndef;
1557 struct wpabuf *buf;
1558 int res;
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001559 char *pos;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001560
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001561 pos = os_strchr(cmd, ' ');
1562 if (pos)
1563 *pos++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001564 if (os_strcmp(cmd, "WPS") == 0)
1565 ndef = 0;
1566 else if (os_strcmp(cmd, "NDEF") == 0)
1567 ndef = 1;
1568 else
1569 return -1;
1570
Dmitry Shmidt1e78e762013-04-02 11:05:36 -07001571 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001572 if (buf == NULL)
1573 return -1;
1574
1575 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1576 wpabuf_len(buf));
1577 reply[res++] = '\n';
1578 reply[res] = '\0';
1579
1580 wpabuf_free(buf);
1581
1582 return res;
1583}
1584
1585
Dmitry Shmidt04949592012-07-19 12:16:46 -07001586static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1587 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1588{
1589 int ndef;
1590 struct wpabuf *buf;
1591 int res;
1592
1593 if (os_strcmp(cmd, "WPS") == 0)
1594 ndef = 0;
1595 else if (os_strcmp(cmd, "NDEF") == 0)
1596 ndef = 1;
1597 else
1598 return -1;
1599
1600 buf = wpas_wps_nfc_token(wpa_s, ndef);
1601 if (buf == NULL)
1602 return -1;
1603
1604 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1605 wpabuf_len(buf));
1606 reply[res++] = '\n';
1607 reply[res] = '\0';
1608
1609 wpabuf_free(buf);
1610
1611 return res;
1612}
1613
1614
1615static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1616 struct wpa_supplicant *wpa_s, char *pos)
1617{
1618 size_t len;
1619 struct wpabuf *buf;
1620 int ret;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001621 char *freq;
1622 int forced_freq = 0;
1623
1624 freq = strstr(pos, " freq=");
1625 if (freq) {
1626 *freq = '\0';
1627 freq += 6;
1628 forced_freq = atoi(freq);
1629 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001630
1631 len = os_strlen(pos);
1632 if (len & 0x01)
1633 return -1;
1634 len /= 2;
1635
1636 buf = wpabuf_alloc(len);
1637 if (buf == NULL)
1638 return -1;
1639 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1640 wpabuf_free(buf);
1641 return -1;
1642 }
1643
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001644 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001645 wpabuf_free(buf);
1646
1647 return ret;
1648}
1649
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001650
1651static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001652 char *reply, size_t max_len,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001653 int ndef)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001654{
1655 struct wpabuf *buf;
1656 int res;
1657
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001658 buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001659 if (buf == NULL)
1660 return -1;
1661
1662 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1663 wpabuf_len(buf));
1664 reply[res++] = '\n';
1665 reply[res] = '\0';
1666
1667 wpabuf_free(buf);
1668
1669 return res;
1670}
1671
1672
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001673#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001674static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1675 char *reply, size_t max_len,
1676 int ndef)
1677{
1678 struct wpabuf *buf;
1679 int res;
1680
1681 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1682 if (buf == NULL) {
1683 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1684 return -1;
1685 }
1686
1687 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1688 wpabuf_len(buf));
1689 reply[res++] = '\n';
1690 reply[res] = '\0';
1691
1692 wpabuf_free(buf);
1693
1694 return res;
1695}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001696#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001697
1698
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001699static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1700 char *cmd, char *reply,
1701 size_t max_len)
1702{
1703 char *pos;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001704 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001705
1706 pos = os_strchr(cmd, ' ');
1707 if (pos == NULL)
1708 return -1;
1709 *pos++ = '\0';
1710
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001711 if (os_strcmp(cmd, "WPS") == 0)
1712 ndef = 0;
1713 else if (os_strcmp(cmd, "NDEF") == 0)
1714 ndef = 1;
1715 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001716 return -1;
1717
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001718 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001719 if (!ndef)
1720 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001721 return wpas_ctrl_nfc_get_handover_req_wps(
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001722 wpa_s, reply, max_len, ndef);
1723 }
1724
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001725#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001726 if (os_strcmp(pos, "P2P-CR") == 0) {
1727 return wpas_ctrl_nfc_get_handover_req_p2p(
1728 wpa_s, reply, max_len, ndef);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001729 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001730#endif /* CONFIG_P2P */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001731
1732 return -1;
1733}
1734
1735
1736static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001737 char *reply, size_t max_len,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001738 int ndef, int cr, char *uuid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001739{
1740 struct wpabuf *buf;
1741 int res;
1742
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001743 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001744 if (buf == NULL)
1745 return -1;
1746
1747 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1748 wpabuf_len(buf));
1749 reply[res++] = '\n';
1750 reply[res] = '\0';
1751
1752 wpabuf_free(buf);
1753
1754 return res;
1755}
1756
1757
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001758#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001759static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1760 char *reply, size_t max_len,
1761 int ndef, int tag)
1762{
1763 struct wpabuf *buf;
1764 int res;
1765
1766 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1767 if (buf == NULL)
1768 return -1;
1769
1770 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1771 wpabuf_len(buf));
1772 reply[res++] = '\n';
1773 reply[res] = '\0';
1774
1775 wpabuf_free(buf);
1776
1777 return res;
1778}
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001779#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001780
1781
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001782static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1783 char *cmd, char *reply,
1784 size_t max_len)
1785{
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001786 char *pos, *pos2;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001787 int ndef;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001788
1789 pos = os_strchr(cmd, ' ');
1790 if (pos == NULL)
1791 return -1;
1792 *pos++ = '\0';
1793
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001794 if (os_strcmp(cmd, "WPS") == 0)
1795 ndef = 0;
1796 else if (os_strcmp(cmd, "NDEF") == 0)
1797 ndef = 1;
1798 else
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001799 return -1;
1800
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001801 pos2 = os_strchr(pos, ' ');
1802 if (pos2)
1803 *pos2++ = '\0';
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001804 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001805 if (!ndef)
1806 return -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001807 return wpas_ctrl_nfc_get_handover_sel_wps(
1808 wpa_s, reply, max_len, ndef,
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001809 os_strcmp(pos, "WPS-CR") == 0, pos2);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001810 }
1811
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001812#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001813 if (os_strcmp(pos, "P2P-CR") == 0) {
1814 return wpas_ctrl_nfc_get_handover_sel_p2p(
1815 wpa_s, reply, max_len, ndef, 0);
1816 }
1817
1818 if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1819 return wpas_ctrl_nfc_get_handover_sel_p2p(
1820 wpa_s, reply, max_len, ndef, 1);
1821 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001822#endif /* CONFIG_P2P */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001823
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001824 return -1;
1825}
1826
1827
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001828static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1829 char *cmd)
1830{
1831 size_t len;
1832 struct wpabuf *req, *sel;
1833 int ret;
1834 char *pos, *role, *type, *pos2;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001835#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001836 char *freq;
1837 int forced_freq = 0;
1838
1839 freq = strstr(cmd, " freq=");
1840 if (freq) {
1841 *freq = '\0';
1842 freq += 6;
1843 forced_freq = atoi(freq);
1844 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001845#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001846
1847 role = cmd;
1848 pos = os_strchr(role, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001849 if (pos == NULL) {
1850 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001851 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001852 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001853 *pos++ = '\0';
1854
1855 type = pos;
1856 pos = os_strchr(type, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001857 if (pos == NULL) {
1858 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001859 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001860 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001861 *pos++ = '\0';
1862
1863 pos2 = os_strchr(pos, ' ');
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001864 if (pos2 == NULL) {
1865 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001866 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001867 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001868 *pos2++ = '\0';
1869
1870 len = os_strlen(pos);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001871 if (len & 0x01) {
1872 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001873 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001874 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001875 len /= 2;
1876
1877 req = wpabuf_alloc(len);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001878 if (req == NULL) {
1879 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001880 return -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001881 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001882 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001883 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001884 wpabuf_free(req);
1885 return -1;
1886 }
1887
1888 len = os_strlen(pos2);
1889 if (len & 0x01) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001890 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001891 wpabuf_free(req);
1892 return -1;
1893 }
1894 len /= 2;
1895
1896 sel = wpabuf_alloc(len);
1897 if (sel == NULL) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001898 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001899 wpabuf_free(req);
1900 return -1;
1901 }
1902 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001903 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001904 wpabuf_free(req);
1905 wpabuf_free(sel);
1906 return -1;
1907 }
1908
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001909 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1910 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1911
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001912 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1913 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001914#ifdef CONFIG_AP
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001915 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1916 {
1917 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1918 if (ret < 0)
1919 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001920#endif /* CONFIG_AP */
1921#ifdef CONFIG_P2P
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001922 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1923 {
1924 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1925 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1926 {
1927 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1928 forced_freq);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001929#endif /* CONFIG_P2P */
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001930 } else {
1931 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1932 "reported: role=%s type=%s", role, type);
1933 ret = -1;
1934 }
1935 wpabuf_free(req);
1936 wpabuf_free(sel);
1937
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001938 if (ret)
1939 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1940
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001941 return ret;
1942}
1943
Dmitry Shmidt04949592012-07-19 12:16:46 -07001944#endif /* CONFIG_WPS_NFC */
1945
1946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1948 char *cmd)
1949{
1950 u8 bssid[ETH_ALEN];
1951 char *pin;
1952 char *new_ssid;
1953 char *new_auth;
1954 char *new_encr;
1955 char *new_key;
1956 struct wps_new_ap_settings ap;
1957
1958 pin = os_strchr(cmd, ' ');
1959 if (pin == NULL)
1960 return -1;
1961 *pin++ = '\0';
1962
1963 if (hwaddr_aton(cmd, bssid)) {
1964 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1965 cmd);
1966 return -1;
1967 }
1968
1969 new_ssid = os_strchr(pin, ' ');
1970 if (new_ssid == NULL)
1971 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1972 *new_ssid++ = '\0';
1973
1974 new_auth = os_strchr(new_ssid, ' ');
1975 if (new_auth == NULL)
1976 return -1;
1977 *new_auth++ = '\0';
1978
1979 new_encr = os_strchr(new_auth, ' ');
1980 if (new_encr == NULL)
1981 return -1;
1982 *new_encr++ = '\0';
1983
1984 new_key = os_strchr(new_encr, ' ');
1985 if (new_key == NULL)
1986 return -1;
1987 *new_key++ = '\0';
1988
1989 os_memset(&ap, 0, sizeof(ap));
1990 ap.ssid_hex = new_ssid;
1991 ap.auth = new_auth;
1992 ap.encr = new_encr;
1993 ap.key_hex = new_key;
1994 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1995}
1996
1997
1998#ifdef CONFIG_AP
1999static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
2000 char *cmd, char *buf,
2001 size_t buflen)
2002{
2003 int timeout = 300;
2004 char *pos;
2005 const char *pin_txt;
2006
2007 if (!wpa_s->ap_iface)
2008 return -1;
2009
2010 pos = os_strchr(cmd, ' ');
2011 if (pos)
2012 *pos++ = '\0';
2013
2014 if (os_strcmp(cmd, "disable") == 0) {
2015 wpas_wps_ap_pin_disable(wpa_s);
2016 return os_snprintf(buf, buflen, "OK\n");
2017 }
2018
2019 if (os_strcmp(cmd, "random") == 0) {
2020 if (pos)
2021 timeout = atoi(pos);
2022 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
2023 if (pin_txt == NULL)
2024 return -1;
2025 return os_snprintf(buf, buflen, "%s", pin_txt);
2026 }
2027
2028 if (os_strcmp(cmd, "get") == 0) {
2029 pin_txt = wpas_wps_ap_pin_get(wpa_s);
2030 if (pin_txt == NULL)
2031 return -1;
2032 return os_snprintf(buf, buflen, "%s", pin_txt);
2033 }
2034
2035 if (os_strcmp(cmd, "set") == 0) {
2036 char *pin;
2037 if (pos == NULL)
2038 return -1;
2039 pin = pos;
2040 pos = os_strchr(pos, ' ');
2041 if (pos) {
2042 *pos++ = '\0';
2043 timeout = atoi(pos);
2044 }
2045 if (os_strlen(pin) > buflen)
2046 return -1;
2047 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
2048 return -1;
2049 return os_snprintf(buf, buflen, "%s", pin);
2050 }
2051
2052 return -1;
2053}
2054#endif /* CONFIG_AP */
2055
2056
2057#ifdef CONFIG_WPS_ER
2058static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
2059 char *cmd)
2060{
2061 char *uuid = cmd, *pin, *pos;
2062 u8 addr_buf[ETH_ALEN], *addr = NULL;
2063 pin = os_strchr(uuid, ' ');
2064 if (pin == NULL)
2065 return -1;
2066 *pin++ = '\0';
2067 pos = os_strchr(pin, ' ');
2068 if (pos) {
2069 *pos++ = '\0';
2070 if (hwaddr_aton(pos, addr_buf) == 0)
2071 addr = addr_buf;
2072 }
2073 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
2074}
2075
2076
2077static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
2078 char *cmd)
2079{
2080 char *uuid = cmd, *pin;
2081 pin = os_strchr(uuid, ' ');
2082 if (pin == NULL)
2083 return -1;
2084 *pin++ = '\0';
2085 return wpas_wps_er_learn(wpa_s, uuid, pin);
2086}
2087
2088
2089static int wpa_supplicant_ctrl_iface_wps_er_set_config(
2090 struct wpa_supplicant *wpa_s, char *cmd)
2091{
2092 char *uuid = cmd, *id;
2093 id = os_strchr(uuid, ' ');
2094 if (id == NULL)
2095 return -1;
2096 *id++ = '\0';
2097 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
2098}
2099
2100
2101static int wpa_supplicant_ctrl_iface_wps_er_config(
2102 struct wpa_supplicant *wpa_s, char *cmd)
2103{
2104 char *pin;
2105 char *new_ssid;
2106 char *new_auth;
2107 char *new_encr;
2108 char *new_key;
2109 struct wps_new_ap_settings ap;
2110
2111 pin = os_strchr(cmd, ' ');
2112 if (pin == NULL)
2113 return -1;
2114 *pin++ = '\0';
2115
2116 new_ssid = os_strchr(pin, ' ');
2117 if (new_ssid == NULL)
2118 return -1;
2119 *new_ssid++ = '\0';
2120
2121 new_auth = os_strchr(new_ssid, ' ');
2122 if (new_auth == NULL)
2123 return -1;
2124 *new_auth++ = '\0';
2125
2126 new_encr = os_strchr(new_auth, ' ');
2127 if (new_encr == NULL)
2128 return -1;
2129 *new_encr++ = '\0';
2130
2131 new_key = os_strchr(new_encr, ' ');
2132 if (new_key == NULL)
2133 return -1;
2134 *new_key++ = '\0';
2135
2136 os_memset(&ap, 0, sizeof(ap));
2137 ap.ssid_hex = new_ssid;
2138 ap.auth = new_auth;
2139 ap.encr = new_encr;
2140 ap.key_hex = new_key;
2141 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
2142}
Dmitry Shmidt04949592012-07-19 12:16:46 -07002143
2144
2145#ifdef CONFIG_WPS_NFC
2146static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
2147 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2148{
2149 int ndef;
2150 struct wpabuf *buf;
2151 int res;
2152 char *uuid;
2153
2154 uuid = os_strchr(cmd, ' ');
2155 if (uuid == NULL)
2156 return -1;
2157 *uuid++ = '\0';
2158
2159 if (os_strcmp(cmd, "WPS") == 0)
2160 ndef = 0;
2161 else if (os_strcmp(cmd, "NDEF") == 0)
2162 ndef = 1;
2163 else
2164 return -1;
2165
2166 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
2167 if (buf == NULL)
2168 return -1;
2169
2170 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
2171 wpabuf_len(buf));
2172 reply[res++] = '\n';
2173 reply[res] = '\0';
2174
2175 wpabuf_free(buf);
2176
2177 return res;
2178}
2179#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180#endif /* CONFIG_WPS_ER */
2181
2182#endif /* CONFIG_WPS */
2183
2184
2185#ifdef CONFIG_IBSS_RSN
2186static int wpa_supplicant_ctrl_iface_ibss_rsn(
2187 struct wpa_supplicant *wpa_s, char *addr)
2188{
2189 u8 peer[ETH_ALEN];
2190
2191 if (hwaddr_aton(addr, peer)) {
2192 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
2193 "address '%s'", addr);
2194 return -1;
2195 }
2196
2197 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
2198 MAC2STR(peer));
2199
2200 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
2201}
2202#endif /* CONFIG_IBSS_RSN */
2203
2204
2205static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
2206 char *rsp)
2207{
2208#ifdef IEEE8021X_EAPOL
2209 char *pos, *id_pos;
2210 int id;
2211 struct wpa_ssid *ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212
2213 pos = os_strchr(rsp, '-');
2214 if (pos == NULL)
2215 return -1;
2216 *pos++ = '\0';
2217 id_pos = pos;
2218 pos = os_strchr(pos, ':');
2219 if (pos == NULL)
2220 return -1;
2221 *pos++ = '\0';
2222 id = atoi(id_pos);
2223 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
2224 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2225 (u8 *) pos, os_strlen(pos));
2226
2227 ssid = wpa_config_get_network(wpa_s->conf, id);
2228 if (ssid == NULL) {
2229 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2230 "to update", id);
2231 return -1;
2232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002233
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002234 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
2235 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236#else /* IEEE8021X_EAPOL */
2237 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
2238 return -1;
2239#endif /* IEEE8021X_EAPOL */
2240}
2241
2242
2243static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
2244 const char *params,
2245 char *buf, size_t buflen)
2246{
2247 char *pos, *end, tmp[30];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002248 int res, verbose, wps, ret;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002249#ifdef CONFIG_HS20
2250 const u8 *hs20;
2251#endif /* CONFIG_HS20 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002252 const u8 *sess_id;
2253 size_t sess_id_len;
Dmitry Shmidt44da0252011-08-23 12:30:30 -07002254
Dmitry Shmidt56052862013-10-04 10:23:25 -07002255 if (os_strcmp(params, "-DRIVER") == 0)
2256 return wpa_drv_status(wpa_s, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 verbose = os_strcmp(params, "-VERBOSE") == 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002258 wps = os_strcmp(params, "-WPS") == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 pos = buf;
2260 end = buf + buflen;
2261 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
2262 struct wpa_ssid *ssid = wpa_s->current_ssid;
2263 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2264 MAC2STR(wpa_s->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002265 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002266 return pos - buf;
2267 pos += ret;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002268 ret = os_snprintf(pos, end - pos, "freq=%u\n",
2269 wpa_s->assoc_freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002270 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002271 return pos - buf;
2272 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002273 if (ssid) {
2274 u8 *_ssid = ssid->ssid;
2275 size_t ssid_len = ssid->ssid_len;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002276 u8 ssid_buf[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277 if (ssid_len == 0) {
2278 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
2279 if (_res < 0)
2280 ssid_len = 0;
2281 else
2282 ssid_len = _res;
2283 _ssid = ssid_buf;
2284 }
2285 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
2286 wpa_ssid_txt(_ssid, ssid_len),
2287 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002288 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002289 return pos - buf;
2290 pos += ret;
2291
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002292 if (wps && ssid->passphrase &&
2293 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
2294 (ssid->mode == WPAS_MODE_AP ||
2295 ssid->mode == WPAS_MODE_P2P_GO)) {
2296 ret = os_snprintf(pos, end - pos,
2297 "passphrase=%s\n",
2298 ssid->passphrase);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002299 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002300 return pos - buf;
2301 pos += ret;
2302 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303 if (ssid->id_str) {
2304 ret = os_snprintf(pos, end - pos,
2305 "id_str=%s\n",
2306 ssid->id_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002307 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002308 return pos - buf;
2309 pos += ret;
2310 }
2311
2312 switch (ssid->mode) {
2313 case WPAS_MODE_INFRA:
2314 ret = os_snprintf(pos, end - pos,
2315 "mode=station\n");
2316 break;
2317 case WPAS_MODE_IBSS:
2318 ret = os_snprintf(pos, end - pos,
2319 "mode=IBSS\n");
2320 break;
2321 case WPAS_MODE_AP:
2322 ret = os_snprintf(pos, end - pos,
2323 "mode=AP\n");
2324 break;
2325 case WPAS_MODE_P2P_GO:
2326 ret = os_snprintf(pos, end - pos,
2327 "mode=P2P GO\n");
2328 break;
2329 case WPAS_MODE_P2P_GROUP_FORMATION:
2330 ret = os_snprintf(pos, end - pos,
2331 "mode=P2P GO - group "
2332 "formation\n");
2333 break;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002334 case WPAS_MODE_MESH:
2335 ret = os_snprintf(pos, end - pos,
2336 "mode=mesh\n");
2337 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338 default:
2339 ret = 0;
2340 break;
2341 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002342 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002343 return pos - buf;
2344 pos += ret;
2345 }
2346
Hai Shalom021b0b52019-04-10 11:17:58 -07002347 if (wpa_s->connection_set &&
2348 (wpa_s->connection_ht || wpa_s->connection_vht ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002349 wpa_s->connection_he || wpa_s->connection_eht)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002350 ret = os_snprintf(pos, end - pos,
2351 "wifi_generation=%u\n",
Sunil Ravia04bd252022-05-02 22:54:18 -07002352 wpa_s->connection_eht ? 7 :
2353 (wpa_s->connection_he ? 6 :
2354 (wpa_s->connection_vht ? 5 : 4)));
Hai Shalom021b0b52019-04-10 11:17:58 -07002355 if (os_snprintf_error(end - pos, ret))
2356 return pos - buf;
2357 pos += ret;
2358 }
2359
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002360#ifdef CONFIG_AP
2361 if (wpa_s->ap_iface) {
2362 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
2363 end - pos,
2364 verbose);
2365 } else
2366#endif /* CONFIG_AP */
2367 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
2368 }
Paul Stewart092955c2017-02-06 09:13:09 -08002369#ifdef CONFIG_SME
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002370#ifdef CONFIG_SAE
2371 if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002372#ifdef CONFIG_AP
2373 !wpa_s->ap_iface &&
2374#endif /* CONFIG_AP */
2375 wpa_s->sme.sae.state == SAE_ACCEPTED) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002376 ret = os_snprintf(pos, end - pos, "sae_group=%d\n"
2377 "sae_h2e=%d\n"
2378 "sae_pk=%d\n",
2379 wpa_s->sme.sae.group,
2380 wpa_s->sme.sae.h2e,
2381 wpa_s->sme.sae.pk);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002382 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002383 return pos - buf;
2384 pos += ret;
2385 }
2386#endif /* CONFIG_SAE */
Paul Stewart092955c2017-02-06 09:13:09 -08002387#endif /* CONFIG_SME */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
2389 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002390 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 return pos - buf;
2392 pos += ret;
2393
2394 if (wpa_s->l2 &&
2395 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
2396 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002397 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398 return pos - buf;
2399 pos += ret;
2400 }
2401
2402#ifdef CONFIG_P2P
2403 if (wpa_s->global->p2p) {
2404 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
2405 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002406 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 return pos - buf;
2408 pos += ret;
2409 }
2410#endif /* CONFIG_P2P */
2411
2412 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
2413 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002414 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 return pos - buf;
2416 pos += ret;
2417
Sunil Ravi89eba102022-09-13 21:04:37 -07002418 if (wpa_s->valid_links) {
2419 ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n",
2420 MAC2STR(wpa_s->ap_mld_addr));
2421 if (os_snprintf_error(end - pos, ret))
2422 return pos - buf;
2423 pos += ret;
2424 }
2425
Dmitry Shmidt04949592012-07-19 12:16:46 -07002426#ifdef CONFIG_HS20
2427 if (wpa_s->current_bss &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002428 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
2429 HS20_IE_VENDOR_TYPE)) &&
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002430 wpa_s->wpa_proto == WPA_PROTO_RSN &&
2431 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002432 int release = 1;
2433 if (hs20[1] >= 5) {
2434 u8 rel_num = (hs20[6] & 0xf0) >> 4;
2435 release = rel_num + 1;
2436 }
2437 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002438 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07002439 return pos - buf;
2440 pos += ret;
2441 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002442
2443 if (wpa_s->current_ssid) {
2444 struct wpa_cred *cred;
2445 char *type;
2446
2447 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002448 size_t i;
2449
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002450 if (wpa_s->current_ssid->parent_cred != cred)
2451 continue;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002452
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002453 if (cred->provisioning_sp) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002454 ret = os_snprintf(pos, end - pos,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002455 "provisioning_sp=%s\n",
2456 cred->provisioning_sp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002457 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt051af732013-10-22 13:52:46 -07002458 return pos - buf;
2459 pos += ret;
2460 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002461
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002462 if (!cred->domain)
2463 goto no_domain;
2464
2465 i = 0;
2466 if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
2467 struct wpabuf *names =
2468 wpa_s->current_bss->anqp->domain_name;
2469 for (i = 0; names && i < cred->num_domain; i++)
2470 {
2471 if (domain_name_list_contains(
2472 names, cred->domain[i], 1))
2473 break;
2474 }
2475 if (i == cred->num_domain)
2476 i = 0; /* show first entry by default */
2477 }
2478 ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
2479 cred->domain[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002480 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002481 return pos - buf;
2482 pos += ret;
2483
2484 no_domain:
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002485 if (wpa_s->current_bss == NULL ||
2486 wpa_s->current_bss->anqp == NULL)
2487 res = -1;
2488 else
2489 res = interworking_home_sp_cred(
2490 wpa_s, cred,
2491 wpa_s->current_bss->anqp->domain_name);
2492 if (res > 0)
2493 type = "home";
2494 else if (res == 0)
2495 type = "roaming";
2496 else
2497 type = "unknown";
2498
2499 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002500 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002501 return pos - buf;
2502 pos += ret;
2503
2504 break;
2505 }
2506 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002507#endif /* CONFIG_HS20 */
2508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2510 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2511 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
2512 verbose);
2513 if (res >= 0)
2514 pos += res;
2515 }
2516
Dmitry Shmidt29333592017-01-09 12:27:11 -08002517#ifdef CONFIG_MACSEC
2518 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
2519 if (res > 0)
2520 pos += res;
2521#endif /* CONFIG_MACSEC */
2522
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002523 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
2524 if (sess_id) {
2525 char *start = pos;
2526
2527 ret = os_snprintf(pos, end - pos, "eap_session_id=");
2528 if (os_snprintf_error(end - pos, ret))
2529 return start - buf;
2530 pos += ret;
2531 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
2532 if (ret <= 0)
2533 return start - buf;
2534 pos += ret;
2535 ret = os_snprintf(pos, end - pos, "\n");
2536 if (os_snprintf_error(end - pos, ret))
2537 return start - buf;
2538 pos += ret;
2539 }
2540
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
2542 if (res >= 0)
2543 pos += res;
2544
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002545#ifdef CONFIG_WPS
2546 {
2547 char uuid_str[100];
2548 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
2549 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002550 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002551 return pos - buf;
2552 pos += ret;
2553 }
2554#endif /* CONFIG_WPS */
2555
Roshan Pius3a1667e2018-07-03 15:17:14 -07002556 if (wpa_s->ieee80211ac) {
2557 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
2558 if (os_snprintf_error(end - pos, ret))
2559 return pos - buf;
2560 pos += ret;
2561 }
2562
Sunil Ravi7f769292024-07-23 22:21:32 +00002563#ifdef CONFIG_SME
2564 if (wpa_s->sme.bss_max_idle_period) {
2565 ret = os_snprintf(pos, end - pos, "bss_max_idle_period=%d\n",
2566 wpa_s->sme.bss_max_idle_period);
2567 if (os_snprintf_error(end - pos, ret))
2568 return pos - buf;
2569 pos += ret;
2570 }
2571#endif /* CONFIG_SME */
2572
2573 if (wpa_s->ssid_verified) {
2574 ret = os_snprintf(pos, end - pos, "ssid_verified=1\n");
2575 if (os_snprintf_error(end - pos, ret))
2576 return pos - buf;
2577 pos += ret;
2578 }
2579
2580 if (wpa_s->bigtk_set) {
2581 ret = os_snprintf(pos, end - pos, "bigtk_set=1\n");
2582 if (os_snprintf_error(end - pos, ret))
2583 return pos - buf;
2584 pos += ret;
2585 }
2586
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002587#ifdef ANDROID
vandwalleffc70182014-09-11 11:40:14 -07002588 /*
2589 * Allow using the STATUS command with default behavior, say for debug,
2590 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
2591 * events with STATUS-NO_EVENTS.
2592 */
2593 if (os_strcmp(params, "-NO_EVENTS")) {
2594 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
2595 "id=%d state=%d BSSID=" MACSTR " SSID=%s",
2596 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
2597 wpa_s->wpa_state,
2598 MAC2STR(wpa_s->bssid),
2599 wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
2600 wpa_ssid_txt(wpa_s->current_ssid->ssid,
2601 wpa_s->current_ssid->ssid_len) : "");
2602 if (wpa_s->wpa_state == WPA_COMPLETED) {
2603 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi89eba102022-09-13 21:04:37 -07002604 char mld_addr[50];
2605
2606 mld_addr[0] = '\0';
2607 if (wpa_s->valid_links)
2608 os_snprintf(mld_addr, sizeof(mld_addr),
2609 " ap_mld_addr=" MACSTR,
2610 MAC2STR(wpa_s->ap_mld_addr));
2611
vandwalleffc70182014-09-11 11:40:14 -07002612 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
2613 "- connection to " MACSTR
Sunil Ravi89eba102022-09-13 21:04:37 -07002614 " completed %s [id=%d id_str=%s]%s",
vandwalleffc70182014-09-11 11:40:14 -07002615 MAC2STR(wpa_s->bssid), "(auth)",
2616 ssid ? ssid->id : -1,
Sunil Ravi89eba102022-09-13 21:04:37 -07002617 ssid && ssid->id_str ? ssid->id_str : "",
2618 mld_addr);
vandwalleffc70182014-09-11 11:40:14 -07002619 }
Irfan Sheriffbf5edf42012-01-11 16:54:57 -08002620 }
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -08002621#endif /* ANDROID */
2622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 return pos - buf;
2624}
2625
2626
2627static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2628 char *cmd)
2629{
2630 char *pos;
2631 int id;
2632 struct wpa_ssid *ssid;
2633 u8 bssid[ETH_ALEN];
2634
2635 /* cmd: "<network id> <BSSID>" */
2636 pos = os_strchr(cmd, ' ');
2637 if (pos == NULL)
2638 return -1;
2639 *pos++ = '\0';
2640 id = atoi(cmd);
2641 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2642 if (hwaddr_aton(pos, bssid)) {
2643 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2644 return -1;
2645 }
2646
2647 ssid = wpa_config_get_network(wpa_s->conf, id);
2648 if (ssid == NULL) {
2649 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2650 "to update", id);
2651 return -1;
2652 }
2653
2654 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2655 ssid->bssid_set = !is_zero_ether_addr(bssid);
2656
2657 return 0;
2658}
2659
2660
Hai Shalom60840252021-02-19 19:02:11 -08002661static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
2662 char *cmd, char *buf,
2663 size_t buflen)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002664{
2665 u8 bssid[ETH_ALEN];
Hai Shalom60840252021-02-19 19:02:11 -08002666 struct wpa_bssid_ignore *e;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002667 char *pos, *end;
2668 int ret;
2669
Hai Shalom60840252021-02-19 19:02:11 -08002670 /* cmd: "BSSID_IGNORE [<BSSID>]" */
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002671 if (*cmd == '\0') {
2672 pos = buf;
2673 end = buf + buflen;
Hai Shalom60840252021-02-19 19:02:11 -08002674 e = wpa_s->bssid_ignore;
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002675 while (e) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002676 ret = os_snprintf(pos, end - pos, MACSTR "\n",
2677 MAC2STR(e->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002678 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002679 return pos - buf;
2680 pos += ret;
2681 e = e->next;
2682 }
2683 return pos - buf;
2684 }
2685
2686 cmd++;
2687 if (os_strncmp(cmd, "clear", 5) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -08002688 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002689 os_memcpy(buf, "OK\n", 3);
2690 return 3;
2691 }
2692
Hai Shalom60840252021-02-19 19:02:11 -08002693 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002694 if (hwaddr_aton(cmd, bssid)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002695 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002696 return -1;
2697 }
2698
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002699 /*
2700 * Add the BSSID twice, so its count will be 2, causing it to be
2701 * skipped when processing scan results.
2702 */
Hai Shalom60840252021-02-19 19:02:11 -08002703 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002704 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002705 return -1;
Hai Shalom60840252021-02-19 19:02:11 -08002706 ret = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002707 if (ret < 0)
Dmitry Shmidte19501d2011-03-16 14:32:18 -07002708 return -1;
2709 os_memcpy(buf, "OK\n", 3);
2710 return 3;
2711}
2712
2713
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002714static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2715 char *cmd, char *buf,
2716 size_t buflen)
2717{
2718 char *pos, *end, *stamp;
2719 int ret;
2720
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002721 /* cmd: "LOG_LEVEL [<level>]" */
2722 if (*cmd == '\0') {
2723 pos = buf;
2724 end = buf + buflen;
2725 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2726 "Timestamp: %d\n",
2727 debug_level_str(wpa_debug_level),
2728 wpa_debug_timestamp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002729 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002730 ret = 0;
2731
2732 return ret;
2733 }
2734
2735 while (*cmd == ' ')
2736 cmd++;
2737
2738 stamp = os_strchr(cmd, ' ');
2739 if (stamp) {
2740 *stamp++ = '\0';
2741 while (*stamp == ' ') {
2742 stamp++;
2743 }
2744 }
2745
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002746 if (os_strlen(cmd)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002747 int level = str_to_debug_level(cmd);
2748 if (level < 0)
2749 return -1;
2750 wpa_debug_level = level;
2751 }
2752
2753 if (stamp && os_strlen(stamp))
2754 wpa_debug_timestamp = atoi(stamp);
2755
2756 os_memcpy(buf, "OK\n", 3);
2757 return 3;
2758}
2759
2760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761static int wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002762 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763{
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002764 char *pos, *end, *prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 struct wpa_ssid *ssid;
2766 int ret;
2767
2768 pos = buf;
2769 end = buf + buflen;
2770 ret = os_snprintf(pos, end - pos,
2771 "network id / ssid / bssid / flags\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002772 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773 return pos - buf;
2774 pos += ret;
2775
2776 ssid = wpa_s->conf->ssid;
Vinit Deshpandeda134e92014-12-02 10:59:29 -08002777
2778 /* skip over ssids until we find next one */
2779 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2780 int last_id = atoi(cmd + 8);
2781 if (last_id != -1) {
2782 while (ssid != NULL && ssid->id <= last_id) {
2783 ssid = ssid->next;
2784 }
2785 }
2786 }
2787
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002788 while (ssid) {
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002789 prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002790 ret = os_snprintf(pos, end - pos, "%d\t%s",
2791 ssid->id,
2792 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002793 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002794 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 pos += ret;
2796 if (ssid->bssid_set) {
2797 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2798 MAC2STR(ssid->bssid));
2799 } else {
2800 ret = os_snprintf(pos, end - pos, "\tany");
2801 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002802 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002803 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804 pos += ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 ssid == wpa_s->current_ssid ?
2807 "[CURRENT]" : "",
2808 ssid->disabled ? "[DISABLED]" : "",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 ssid->disabled_until.sec ?
2810 "[TEMP-DISABLED]" : "",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2812 "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002813 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002814 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002815 pos += ret;
2816 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002817 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt9e37fc22014-12-03 11:48:46 -08002818 return prev - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002819 pos += ret;
2820
2821 ssid = ssid->next;
2822 }
2823
2824 return pos - buf;
2825}
2826
2827
2828static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2829{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002830 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831 ret = os_snprintf(pos, end - pos, "-");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002832 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002833 return pos;
2834 pos += ret;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002835 ret = wpa_write_ciphers(pos, end, cipher, "+");
2836 if (ret < 0)
2837 return pos;
2838 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839 return pos;
2840}
2841
2842
2843static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2844 const u8 *ie, size_t ie_len)
2845{
2846 struct wpa_ie_data data;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002847 char *start;
2848 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849
2850 ret = os_snprintf(pos, end - pos, "[%s-", proto);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002851 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002852 return pos;
2853 pos += ret;
2854
2855 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2856 ret = os_snprintf(pos, end - pos, "?]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002857 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002858 return pos;
2859 pos += ret;
2860 return pos;
2861 }
2862
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002863 start = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002865 ret = os_snprintf(pos, end - pos, "%sEAP",
2866 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002867 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868 return pos;
2869 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870 }
2871 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002872 ret = os_snprintf(pos, end - pos, "%sPSK",
2873 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002874 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002875 return pos;
2876 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 }
2878 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002879 ret = os_snprintf(pos, end - pos, "%sNone",
2880 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002881 if (os_snprintf_error(end - pos, ret))
2882 return pos;
2883 pos += ret;
2884 }
2885 if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2886 ret = os_snprintf(pos, end - pos, "%sSAE",
2887 pos == start ? "" : "+");
2888 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889 return pos;
2890 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002891 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002892 if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
2893 ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY",
2894 pos == start ? "" : "+");
2895 if (os_snprintf_error(end - pos, ret))
2896 return pos;
2897 pos += ret;
2898 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002899#ifdef CONFIG_IEEE80211R
2900 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2901 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002902 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002903 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 return pos;
2905 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906 }
2907 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2908 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002909 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002910 if (os_snprintf_error(end - pos, ret))
2911 return pos;
2912 pos += ret;
2913 }
2914 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2915 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2916 pos == start ? "" : "+");
2917 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002918 return pos;
2919 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002921 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
2922 ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY",
2923 pos == start ? "" : "+");
2924 if (os_snprintf_error(end - pos, ret))
2925 return pos;
2926 pos += ret;
2927 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002929 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2930 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002931 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002932 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002933 return pos;
2934 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002935 }
2936 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2937 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002938 pos == start ? "" : "+");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002939 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 return pos;
2941 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002944#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002945 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2946 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2947 pos == start ? "" : "+");
2948 if (os_snprintf_error(end - pos, ret))
2949 return pos;
2950 pos += ret;
2951 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002952#endif /* CONFIG_SUITEB */
2953
2954#ifdef CONFIG_SUITEB192
2955 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2956 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2957 pos == start ? "" : "+");
2958 if (os_snprintf_error(end - pos, ret))
2959 return pos;
2960 pos += ret;
2961 }
2962#endif /* CONFIG_SUITEB192 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002963
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002964#ifdef CONFIG_FILS
2965 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
2966 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
2967 pos == start ? "" : "+");
2968 if (os_snprintf_error(end - pos, ret))
2969 return pos;
2970 pos += ret;
2971 }
2972 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
2973 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
2974 pos == start ? "" : "+");
2975 if (os_snprintf_error(end - pos, ret))
2976 return pos;
2977 pos += ret;
2978 }
2979#ifdef CONFIG_IEEE80211R
2980 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
2981 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
2982 pos == start ? "" : "+");
2983 if (os_snprintf_error(end - pos, ret))
2984 return pos;
2985 pos += ret;
2986 }
2987 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
2988 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
2989 pos == start ? "" : "+");
2990 if (os_snprintf_error(end - pos, ret))
2991 return pos;
2992 pos += ret;
2993 }
2994#endif /* CONFIG_IEEE80211R */
2995#endif /* CONFIG_FILS */
2996
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002997#ifdef CONFIG_OWE
2998 if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
2999 ret = os_snprintf(pos, end - pos, "%sOWE",
3000 pos == start ? "" : "+");
3001 if (os_snprintf_error(end - pos, ret))
3002 return pos;
3003 pos += ret;
3004 }
3005#endif /* CONFIG_OWE */
3006
3007#ifdef CONFIG_DPP
3008 if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
3009 ret = os_snprintf(pos, end - pos, "%sDPP",
3010 pos == start ? "" : "+");
3011 if (os_snprintf_error(end - pos, ret))
3012 return pos;
3013 pos += ret;
3014 }
3015#endif /* CONFIG_DPP */
3016
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003017 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
3018 ret = os_snprintf(pos, end - pos, "%sOSEN",
3019 pos == start ? "" : "+");
3020 if (os_snprintf_error(end - pos, ret))
3021 return pos;
3022 pos += ret;
3023 }
3024
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003025#ifdef CONFIG_SHA384
3026 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
3027 ret = os_snprintf(pos, end - pos, "%sEAP-SHA384",
3028 pos == start ? "" : "+");
3029 if (os_snprintf_error(end - pos, ret))
3030 return pos;
3031 pos += ret;
3032 }
3033#endif /* CONFIG_SHA384 */
3034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003035 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
3036
3037 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
3038 ret = os_snprintf(pos, end - pos, "-preauth");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003039 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003040 return pos;
3041 pos += ret;
3042 }
3043
3044 ret = os_snprintf(pos, end - pos, "]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003045 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046 return pos;
3047 pos += ret;
3048
3049 return pos;
3050}
3051
3052
3053#ifdef CONFIG_WPS
3054static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
3055 char *pos, char *end,
3056 struct wpabuf *wps_ie)
3057{
3058 int ret;
3059 const char *txt;
3060
3061 if (wps_ie == NULL)
3062 return pos;
3063 if (wps_is_selected_pbc_registrar(wps_ie))
3064 txt = "[WPS-PBC]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
3066 txt = "[WPS-AUTH]";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 else if (wps_is_selected_pin_registrar(wps_ie))
3068 txt = "[WPS-PIN]";
3069 else
3070 txt = "[WPS]";
3071
3072 ret = os_snprintf(pos, end - pos, "%s", txt);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003073 if (!os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074 pos += ret;
3075 wpabuf_free(wps_ie);
3076 return pos;
3077}
3078#endif /* CONFIG_WPS */
3079
3080
3081static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
3082 char *pos, char *end,
3083 const struct wpa_bss *bss)
3084{
3085#ifdef CONFIG_WPS
3086 struct wpabuf *wps_ie;
3087 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
3088 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
3089#else /* CONFIG_WPS */
3090 return pos;
3091#endif /* CONFIG_WPS */
3092}
3093
3094
3095/* Format one result on one text line into a buffer. */
3096static int wpa_supplicant_ctrl_iface_scan_result(
3097 struct wpa_supplicant *wpa_s,
3098 const struct wpa_bss *bss, char *buf, size_t buflen)
3099{
3100 char *pos, *end;
3101 int ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003102 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003104 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003105 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt96571392013-10-14 12:54:46 -07003106 if (!p2p)
3107 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
3109 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
3110 0)
3111 return 0; /* Do not show P2P listen discovery results here */
3112
3113 pos = buf;
3114 end = buf + buflen;
3115
3116 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
3117 MAC2STR(bss->bssid), bss->freq, bss->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003118 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 return -1;
3120 pos += ret;
3121 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3122 if (ie)
3123 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
Sunil Ravi7f769292024-07-23 22:21:32 +00003124 ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003125 if (ie2) {
3126 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
3127 ie2, 2 + ie2[1]);
3128 }
Sunil Ravi7f769292024-07-23 22:21:32 +00003129 rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003130 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
3131 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
3132 if (os_snprintf_error(end - pos, ret))
3133 return -1;
3134 pos += ret;
3135 }
3136 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
3137 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
3138 if (os_snprintf_error(end - pos, ret))
3139 return -1;
3140 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07003141 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003142 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
3143 if (osen_ie)
3144 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
3145 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003146 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3147 if (owe) {
3148 ret = os_snprintf(pos, end - pos,
3149 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
3150 if (os_snprintf_error(end - pos, ret))
3151 return -1;
3152 pos += ret;
3153 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003154 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003155 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003156 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003157 if (os_snprintf_error(end - pos, ret))
3158 return -1;
3159 pos += ret;
3160 }
3161 if (mesh) {
3162 ret = os_snprintf(pos, end - pos, "[MESH]");
3163 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003164 return -1;
3165 pos += ret;
3166 }
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003167 if (bss_is_dmg(bss)) {
3168 const char *s;
Hai Shalomc3565922019-10-28 11:58:20 -07003169
Hai Shalom60840252021-02-19 19:02:11 -08003170 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) {
Hai Shalomc3565922019-10-28 11:58:20 -07003171 ret = os_snprintf(pos, end - pos, "[EDMG]");
3172 if (os_snprintf_error(end - pos, ret))
3173 return -1;
3174 pos += ret;
3175 }
3176
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003177 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003178 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003179 return -1;
3180 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003181 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
3182 case IEEE80211_CAP_DMG_IBSS:
3183 s = "[IBSS]";
3184 break;
3185 case IEEE80211_CAP_DMG_AP:
3186 s = "[ESS]";
3187 break;
3188 case IEEE80211_CAP_DMG_PBSS:
3189 s = "[PBSS]";
3190 break;
3191 default:
3192 s = "";
3193 break;
3194 }
3195 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003196 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 return -1;
3198 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003199 } else {
3200 if (bss->caps & IEEE80211_CAP_IBSS) {
3201 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003202 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003203 return -1;
3204 pos += ret;
3205 }
3206 if (bss->caps & IEEE80211_CAP_ESS) {
3207 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003208 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003209 return -1;
3210 pos += ret;
3211 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003212 }
3213 if (p2p) {
3214 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003215 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 return -1;
3217 pos += ret;
3218 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003219#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003220 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003221 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003222 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003223 return -1;
3224 pos += ret;
3225 }
3226#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003227#ifdef CONFIG_FILS
3228 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
3229 ret = os_snprintf(pos, end - pos, "[FILS]");
3230 if (os_snprintf_error(end - pos, ret))
3231 return -1;
3232 pos += ret;
3233 }
3234#endif /* CONFIG_FILS */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003235#ifdef CONFIG_FST
3236 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
3237 ret = os_snprintf(pos, end - pos, "[FST]");
3238 if (os_snprintf_error(end - pos, ret))
3239 return -1;
3240 pos += ret;
3241 }
3242#endif /* CONFIG_FST */
Hai Shalom74f70d42019-02-11 14:42:39 -08003243 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
3244 ret = os_snprintf(pos, end - pos, "[UTF-8]");
3245 if (os_snprintf_error(end - pos, ret))
3246 return -1;
3247 pos += ret;
3248 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003249
3250 ret = os_snprintf(pos, end - pos, "\t%s",
3251 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003252 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003253 return -1;
3254 pos += ret;
3255
3256 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003257 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 return -1;
3259 pos += ret;
3260
3261 return pos - buf;
3262}
3263
3264
3265static int wpa_supplicant_ctrl_iface_scan_results(
3266 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3267{
3268 char *pos, *end;
3269 struct wpa_bss *bss;
3270 int ret;
3271
3272 pos = buf;
3273 end = buf + buflen;
3274 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
3275 "flags / ssid\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003276 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003277 return pos - buf;
3278 pos += ret;
3279
3280 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3281 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
3282 end - pos);
3283 if (ret < 0 || ret >= end - pos)
3284 return pos - buf;
3285 pos += ret;
3286 }
3287
3288 return pos - buf;
3289}
3290
3291
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003292#ifdef CONFIG_MESH
3293
3294static int wpa_supplicant_ctrl_iface_mesh_interface_add(
3295 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
3296{
3297 char *pos, ifname[IFNAMSIZ + 1];
3298
3299 ifname[0] = '\0';
3300
3301 pos = os_strstr(cmd, "ifname=");
3302 if (pos) {
3303 pos += 7;
3304 os_strlcpy(ifname, pos, sizeof(ifname));
3305 }
3306
3307 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
3308 return -1;
3309
3310 os_strlcpy(reply, ifname, max_len);
3311 return os_strlen(ifname);
3312}
3313
3314
3315static int wpa_supplicant_ctrl_iface_mesh_group_add(
3316 struct wpa_supplicant *wpa_s, char *cmd)
3317{
3318 int id;
3319 struct wpa_ssid *ssid;
3320
3321 id = atoi(cmd);
3322 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
3323
3324 ssid = wpa_config_get_network(wpa_s->conf, id);
3325 if (ssid == NULL) {
3326 wpa_printf(MSG_DEBUG,
3327 "CTRL_IFACE: Could not find network id=%d", id);
3328 return -1;
3329 }
3330 if (ssid->mode != WPAS_MODE_MESH) {
3331 wpa_printf(MSG_DEBUG,
3332 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
3333 return -1;
3334 }
3335 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
Sunil Ravi89eba102022-09-13 21:04:37 -07003336 ssid->key_mgmt != WPA_KEY_MGMT_SAE &&
3337 ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003338 wpa_printf(MSG_ERROR,
3339 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
3340 return -1;
3341 }
3342
3343 /*
3344 * TODO: If necessary write our own group_add function,
3345 * for now we can reuse select_network
3346 */
3347 wpa_supplicant_select_network(wpa_s, ssid);
3348
3349 return 0;
3350}
3351
3352
3353static int wpa_supplicant_ctrl_iface_mesh_group_remove(
3354 struct wpa_supplicant *wpa_s, char *cmd)
3355{
3356 struct wpa_supplicant *orig;
3357 struct wpa_global *global;
3358 int found = 0;
3359
3360 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
3361
3362 global = wpa_s->global;
3363 orig = wpa_s;
3364
3365 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3366 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
3367 found = 1;
3368 break;
3369 }
3370 }
3371 if (!found) {
3372 wpa_printf(MSG_ERROR,
3373 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
3374 cmd);
3375 return -1;
3376 }
3377 if (wpa_s->mesh_if_created && wpa_s == orig) {
3378 wpa_printf(MSG_ERROR,
3379 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
3380 return -1;
3381 }
3382
3383 wpa_s->reassociate = 0;
3384 wpa_s->disconnected = 1;
3385 wpa_supplicant_cancel_sched_scan(wpa_s);
3386 wpa_supplicant_cancel_scan(wpa_s);
3387
3388 /*
3389 * TODO: If necessary write our own group_remove function,
3390 * for now we can reuse deauthenticate
3391 */
3392 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3393
3394 if (wpa_s->mesh_if_created)
3395 wpa_supplicant_remove_iface(global, wpa_s, 0);
3396
3397 return 0;
3398}
3399
Dmitry Shmidte4663042016-04-04 10:07:49 -07003400
3401static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
3402 struct wpa_supplicant *wpa_s, char *cmd)
3403{
3404 u8 addr[ETH_ALEN];
3405
3406 if (hwaddr_aton(cmd, addr) < 0)
3407 return -1;
3408
3409 return wpas_mesh_peer_remove(wpa_s, addr);
3410}
3411
3412
3413static int wpa_supplicant_ctrl_iface_mesh_peer_add(
3414 struct wpa_supplicant *wpa_s, char *cmd)
3415{
3416 u8 addr[ETH_ALEN];
3417 int duration;
3418 char *pos;
3419
3420 pos = os_strstr(cmd, " duration=");
3421 if (pos) {
3422 *pos = '\0';
3423 duration = atoi(pos + 10);
3424 } else {
3425 duration = -1;
3426 }
3427
3428 if (hwaddr_aton(cmd, addr))
3429 return -1;
3430
3431 return wpas_mesh_peer_add(wpa_s, addr, duration);
3432}
3433
Hai Shalom81f62d82019-07-22 12:10:00 -07003434
3435static int wpa_supplicant_ctrl_iface_mesh_link_probe(
3436 struct wpa_supplicant *wpa_s, char *cmd)
3437{
3438 struct ether_header *eth;
3439 u8 addr[ETH_ALEN];
3440 u8 *buf;
3441 char *pos;
3442 size_t payload_len = 0, len;
3443 int ret = -1;
3444
3445 if (hwaddr_aton(cmd, addr))
3446 return -1;
3447
3448 pos = os_strstr(cmd, " payload=");
3449 if (pos) {
3450 pos = pos + 9;
3451 payload_len = os_strlen(pos);
3452 if (payload_len & 1)
3453 return -1;
3454
3455 payload_len /= 2;
3456 }
3457
3458 len = ETH_HLEN + payload_len;
3459 buf = os_malloc(len);
3460 if (!buf)
3461 return -1;
3462
3463 eth = (struct ether_header *) buf;
3464 os_memcpy(eth->ether_dhost, addr, ETH_ALEN);
3465 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN);
3466 eth->ether_type = htons(ETH_P_802_3);
3467
3468 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0)
3469 goto fail;
3470
3471 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len);
3472fail:
3473 os_free(buf);
3474 return -ret;
3475}
3476
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003477#endif /* CONFIG_MESH */
3478
3479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480static int wpa_supplicant_ctrl_iface_select_network(
3481 struct wpa_supplicant *wpa_s, char *cmd)
3482{
3483 int id;
3484 struct wpa_ssid *ssid;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003485 char *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003486
3487 /* cmd: "<network id>" or "any" */
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003488 if (os_strncmp(cmd, "any", 3) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
3490 ssid = NULL;
3491 } else {
3492 id = atoi(cmd);
3493 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
3494
3495 ssid = wpa_config_get_network(wpa_s->conf, id);
3496 if (ssid == NULL) {
3497 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3498 "network id=%d", id);
3499 return -1;
3500 }
3501 if (ssid->disabled == 2) {
3502 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3503 "SELECT_NETWORK with persistent P2P group");
3504 return -1;
3505 }
3506 }
3507
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003508 pos = os_strstr(cmd, " freq=");
3509 if (pos) {
3510 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
3511 if (freqs) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003512 os_free(wpa_s->select_network_scan_freqs);
3513 wpa_s->select_network_scan_freqs = freqs;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003514 }
3515 }
3516
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003517 wpa_s->scan_min_time.sec = 0;
3518 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003519 wpa_supplicant_select_network(wpa_s, ssid);
3520
3521 return 0;
3522}
3523
3524
3525static int wpa_supplicant_ctrl_iface_enable_network(
3526 struct wpa_supplicant *wpa_s, char *cmd)
3527{
3528 int id;
3529 struct wpa_ssid *ssid;
3530
3531 /* cmd: "<network id>" or "all" */
3532 if (os_strcmp(cmd, "all") == 0) {
3533 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
3534 ssid = NULL;
3535 } else {
3536 id = atoi(cmd);
3537 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
3538
3539 ssid = wpa_config_get_network(wpa_s->conf, id);
3540 if (ssid == NULL) {
3541 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3542 "network id=%d", id);
3543 return -1;
3544 }
3545 if (ssid->disabled == 2) {
3546 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3547 "ENABLE_NETWORK with persistent P2P group");
3548 return -1;
3549 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003550
3551 if (os_strstr(cmd, " no-connect")) {
3552 ssid->disabled = 0;
3553 return 0;
3554 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003555 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003556 wpa_s->scan_min_time.sec = 0;
3557 wpa_s->scan_min_time.usec = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003558 wpa_supplicant_enable_network(wpa_s, ssid);
3559
3560 return 0;
3561}
3562
3563
3564static int wpa_supplicant_ctrl_iface_disable_network(
3565 struct wpa_supplicant *wpa_s, char *cmd)
3566{
3567 int id;
3568 struct wpa_ssid *ssid;
3569
3570 /* cmd: "<network id>" or "all" */
3571 if (os_strcmp(cmd, "all") == 0) {
3572 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
3573 ssid = NULL;
3574 } else {
3575 id = atoi(cmd);
3576 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
3577
3578 ssid = wpa_config_get_network(wpa_s->conf, id);
3579 if (ssid == NULL) {
3580 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3581 "network id=%d", id);
3582 return -1;
3583 }
3584 if (ssid->disabled == 2) {
3585 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
3586 "DISABLE_NETWORK with persistent P2P "
3587 "group");
3588 return -1;
3589 }
3590 }
3591 wpa_supplicant_disable_network(wpa_s, ssid);
3592
3593 return 0;
3594}
3595
3596
3597static int wpa_supplicant_ctrl_iface_add_network(
3598 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
3599{
3600 struct wpa_ssid *ssid;
3601 int ret;
3602
3603 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
3604
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003605 ssid = wpa_supplicant_add_network(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003606 if (ssid == NULL)
3607 return -1;
3608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003609 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003610 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 return -1;
3612 return ret;
3613}
3614
3615
3616static int wpa_supplicant_ctrl_iface_remove_network(
3617 struct wpa_supplicant *wpa_s, char *cmd)
3618{
3619 int id;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003620 int result;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003621
3622 /* cmd: "<network id>" or "all" */
3623 if (os_strcmp(cmd, "all") == 0) {
3624 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
Hai Shalom899fcc72020-10-19 14:38:18 -07003625 return wpa_supplicant_remove_all_networks(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003626 }
3627
3628 id = atoi(cmd);
3629 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
3630
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003631 result = wpa_supplicant_remove_network(wpa_s, id);
3632 if (result == -1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3634 "id=%d", id);
3635 return -1;
3636 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003637 if (result == -2) {
Deepthi Gowria831d782012-09-03 11:55:38 +03003638 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
3639 "network id=%d", id);
3640 return -1;
3641 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642 return 0;
3643}
3644
3645
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003646static int wpa_supplicant_ctrl_iface_update_network(
3647 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3648 char *name, char *value)
3649{
Dmitry Shmidte4663042016-04-04 10:07:49 -07003650 int ret;
3651
3652 ret = wpa_config_set(ssid, name, value, 0);
3653 if (ret < 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003654 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
3655 "variable '%s'", name);
3656 return -1;
3657 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07003658 if (ret == 1)
3659 return 0; /* No change to the previously configured value */
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003660
Hai Shalom899fcc72020-10-19 14:38:18 -07003661#ifdef CONFIG_BGSCAN
3662 if (os_strcmp(name, "bgscan") == 0) {
3663 /*
3664 * Reset the bgscan parameters for the current network and
3665 * return. There's no need to flush caches for bgscan parameter
3666 * changes.
3667 */
3668 if (wpa_s->current_ssid == ssid &&
3669 wpa_s->wpa_state == WPA_COMPLETED)
3670 wpa_supplicant_reset_bgscan(wpa_s);
3671 return 0;
3672 }
3673#endif /* CONFIG_BGSCAN */
3674
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003675 if (os_strcmp(name, "bssid") != 0 &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003676 os_strncmp(name, "bssid_", 6) != 0 &&
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003677 os_strcmp(name, "scan_freq") != 0 &&
Dmitry Shmidte4663042016-04-04 10:07:49 -07003678 os_strcmp(name, "priority") != 0) {
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003679 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3680
Dmitry Shmidte4663042016-04-04 10:07:49 -07003681 if (wpa_s->current_ssid == ssid ||
3682 wpa_s->current_ssid == NULL) {
3683 /*
3684 * Invalidate the EAP session cache if anything in the
3685 * current or previously used configuration changes.
3686 */
3687 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3688 }
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003689 }
3690
3691 if ((os_strcmp(name, "psk") == 0 &&
3692 value[0] == '"' && ssid->ssid_len) ||
3693 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
3694 wpa_config_update_psk(ssid);
3695 else if (os_strcmp(name, "priority") == 0)
3696 wpa_config_update_prio_list(wpa_s->conf);
3697
3698 return 0;
3699}
3700
3701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702static int wpa_supplicant_ctrl_iface_set_network(
3703 struct wpa_supplicant *wpa_s, char *cmd)
3704{
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003705 int id, ret, prev_bssid_set, prev_disabled;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 struct wpa_ssid *ssid;
3707 char *name, *value;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003708 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003709
3710 /* cmd: "<network id> <variable name> <value>" */
3711 name = os_strchr(cmd, ' ');
3712 if (name == NULL)
3713 return -1;
3714 *name++ = '\0';
3715
3716 value = os_strchr(name, ' ');
3717 if (value == NULL)
3718 return -1;
3719 *value++ = '\0';
3720
3721 id = atoi(cmd);
3722 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
3723 id, name);
3724 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3725 (u8 *) value, os_strlen(value));
3726
3727 ssid = wpa_config_get_network(wpa_s->conf, id);
3728 if (ssid == NULL) {
3729 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3730 "id=%d", id);
3731 return -1;
3732 }
3733
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003734 prev_bssid_set = ssid->bssid_set;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003735 prev_disabled = ssid->disabled;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003736 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
3737 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
3738 value);
3739 if (ret == 0 &&
3740 (ssid->bssid_set != prev_bssid_set ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003741 !ether_addr_equal(ssid->bssid, prev_bssid)))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003742 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003743
3744 if (prev_disabled != ssid->disabled &&
3745 (prev_disabled == 2 || ssid->disabled == 2))
3746 wpas_notify_network_type_changed(wpa_s, ssid);
3747
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003748 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749}
3750
3751
3752static int wpa_supplicant_ctrl_iface_get_network(
3753 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3754{
3755 int id;
3756 size_t res;
3757 struct wpa_ssid *ssid;
3758 char *name, *value;
3759
3760 /* cmd: "<network id> <variable name>" */
3761 name = os_strchr(cmd, ' ');
3762 if (name == NULL || buflen == 0)
3763 return -1;
3764 *name++ = '\0';
3765
3766 id = atoi(cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003767 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 id, name);
3769
3770 ssid = wpa_config_get_network(wpa_s->conf, id);
3771 if (ssid == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003772 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003773 "id=%d", id);
3774 return -1;
3775 }
3776
3777 value = wpa_config_get_no_key(ssid, name);
3778 if (value == NULL) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003779 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003780 "variable '%s'", name);
3781 return -1;
3782 }
3783
3784 res = os_strlcpy(buf, value, buflen);
3785 if (res >= buflen) {
3786 os_free(value);
3787 return -1;
3788 }
3789
3790 os_free(value);
3791
3792 return res;
3793}
3794
3795
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003796static int wpa_supplicant_ctrl_iface_dup_network(
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003797 struct wpa_supplicant *wpa_s, char *cmd,
3798 struct wpa_supplicant *dst_wpa_s)
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003799{
3800 struct wpa_ssid *ssid_s, *ssid_d;
3801 char *name, *id, *value;
3802 int id_s, id_d, ret;
3803
3804 /* cmd: "<src network id> <dst network id> <variable name>" */
3805 id = os_strchr(cmd, ' ');
3806 if (id == NULL)
3807 return -1;
3808 *id++ = '\0';
3809
3810 name = os_strchr(id, ' ');
3811 if (name == NULL)
3812 return -1;
3813 *name++ = '\0';
3814
3815 id_s = atoi(cmd);
3816 id_d = atoi(id);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003817
3818 wpa_printf(MSG_DEBUG,
3819 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'",
3820 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003821
3822 ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3823 if (ssid_s == NULL) {
3824 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3825 "network id=%d", id_s);
3826 return -1;
3827 }
3828
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003829 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003830 if (ssid_d == NULL) {
3831 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003832 "network id=%d", id_d);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003833 return -1;
3834 }
3835
3836 value = wpa_config_get(ssid_s, name);
3837 if (value == NULL) {
3838 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3839 "variable '%s'", name);
3840 return -1;
3841 }
3842
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003843 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name,
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003844 value);
3845
3846 os_free(value);
3847
3848 return ret;
3849}
3850
3851
Dmitry Shmidt04949592012-07-19 12:16:46 -07003852static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3853 char *buf, size_t buflen)
3854{
3855 char *pos, *end;
3856 struct wpa_cred *cred;
3857 int ret;
3858
3859 pos = buf;
3860 end = buf + buflen;
3861 ret = os_snprintf(pos, end - pos,
3862 "cred id / realm / username / domain / imsi\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003863 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003864 return pos - buf;
3865 pos += ret;
3866
3867 cred = wpa_s->conf->cred;
3868 while (cred) {
3869 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3870 cred->id, cred->realm ? cred->realm : "",
3871 cred->username ? cred->username : "",
Dmitry Shmidt051af732013-10-22 13:52:46 -07003872 cred->domain ? cred->domain[0] : "",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003873 cred->imsi ? cred->imsi : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003874 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003875 return pos - buf;
3876 pos += ret;
3877
3878 cred = cred->next;
3879 }
3880
3881 return pos - buf;
3882}
3883
3884
3885static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3886 char *buf, size_t buflen)
3887{
3888 struct wpa_cred *cred;
3889 int ret;
3890
3891 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3892
3893 cred = wpa_config_add_cred(wpa_s->conf);
3894 if (cred == NULL)
3895 return -1;
3896
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003897 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3898
Dmitry Shmidt04949592012-07-19 12:16:46 -07003899 ret = os_snprintf(buf, buflen, "%d\n", cred->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003900 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003901 return -1;
3902 return ret;
3903}
3904
3905
3906static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3907 char *cmd)
3908{
3909 int id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003910 struct wpa_cred *cred, *prev;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003911
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003912 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3913 * "provisioning_sp=<FQDN> */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003914 if (os_strcmp(cmd, "all") == 0) {
3915 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003916 return wpas_remove_all_creds(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003917 }
3918
3919 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3920 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3921 cmd + 8);
3922 cred = wpa_s->conf->cred;
3923 while (cred) {
3924 prev = cred;
3925 cred = cred->next;
Dmitry Shmidt051af732013-10-22 13:52:46 -07003926 if (prev->domain) {
3927 size_t i;
3928 for (i = 0; i < prev->num_domain; i++) {
3929 if (os_strcmp(prev->domain[i], cmd + 8)
3930 != 0)
3931 continue;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003932 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidt051af732013-10-22 13:52:46 -07003933 break;
3934 }
3935 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003936 }
3937 return 0;
3938 }
3939
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003940 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3941 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3942 cmd + 16);
3943 cred = wpa_s->conf->cred;
3944 while (cred) {
3945 prev = cred;
3946 cred = cred->next;
3947 if (prev->provisioning_sp &&
3948 os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
Hai Shaloma20dcd72022-02-04 13:43:00 -08003949 wpas_remove_cred(wpa_s, prev);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003950 }
3951 return 0;
3952 }
3953
Dmitry Shmidt04949592012-07-19 12:16:46 -07003954 id = atoi(cmd);
3955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3956
3957 cred = wpa_config_get_cred(wpa_s->conf, id);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003958 return wpas_remove_cred(wpa_s, cred);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003959}
3960
3961
3962static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3963 char *cmd)
3964{
3965 int id;
3966 struct wpa_cred *cred;
3967 char *name, *value;
3968
3969 /* cmd: "<cred id> <variable name> <value>" */
3970 name = os_strchr(cmd, ' ');
3971 if (name == NULL)
3972 return -1;
3973 *name++ = '\0';
3974
3975 value = os_strchr(name, ' ');
3976 if (value == NULL)
3977 return -1;
3978 *value++ = '\0';
3979
3980 id = atoi(cmd);
3981 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3982 id, name);
3983 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3984 (u8 *) value, os_strlen(value));
3985
3986 cred = wpa_config_get_cred(wpa_s->conf, id);
3987 if (cred == NULL) {
3988 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3989 id);
3990 return -1;
3991 }
3992
3993 if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3994 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3995 "variable '%s'", name);
3996 return -1;
3997 }
3998
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003999 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
4000
Dmitry Shmidt04949592012-07-19 12:16:46 -07004001 return 0;
4002}
4003
4004
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07004005static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
4006 char *cmd, char *buf,
4007 size_t buflen)
4008{
4009 int id;
4010 size_t res;
4011 struct wpa_cred *cred;
4012 char *name, *value;
4013
4014 /* cmd: "<cred id> <variable name>" */
4015 name = os_strchr(cmd, ' ');
4016 if (name == NULL)
4017 return -1;
4018 *name++ = '\0';
4019
4020 id = atoi(cmd);
4021 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
4022 id, name);
4023
4024 cred = wpa_config_get_cred(wpa_s->conf, id);
4025 if (cred == NULL) {
4026 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
4027 id);
4028 return -1;
4029 }
4030
4031 value = wpa_config_get_cred_no_key(cred, name);
4032 if (value == NULL) {
4033 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
4034 name);
4035 return -1;
4036 }
4037
4038 res = os_strlcpy(buf, value, buflen);
4039 if (res >= buflen) {
4040 os_free(value);
4041 return -1;
4042 }
4043
4044 os_free(value);
4045
4046 return res;
4047}
4048
4049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050#ifndef CONFIG_NO_CONFIG_WRITE
4051static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
4052{
4053 int ret;
4054
4055 if (!wpa_s->conf->update_config) {
4056 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
4057 "to update configuration (update_config=0)");
4058 return -1;
4059 }
4060
4061 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
4062 if (ret) {
4063 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
4064 "update configuration");
4065 } else {
4066 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
4067 " updated");
4068 }
4069
4070 return ret;
4071}
4072#endif /* CONFIG_NO_CONFIG_WRITE */
4073
4074
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004075struct cipher_info {
4076 unsigned int capa;
4077 const char *name;
4078 int group_only;
4079};
4080
4081static const struct cipher_info ciphers[] = {
4082 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
4083 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
4084 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
4085 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07004086#ifndef CONFIG_NO_TKIP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004087 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
Hai Shalomb755a2a2020-04-23 21:49:02 -07004088#endif /* CONFIG_NO_TKIP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004089 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
Hai Shalomfdcde762020-04-02 11:19:20 -07004090#ifdef CONFIG_WEP
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004091 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
4092 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004093#endif /* CONFIG_WEP */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004094};
4095
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004096static const struct cipher_info ciphers_group_mgmt[] = {
4097 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
4098 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
4099 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
4100 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
4101};
4102
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004103
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004104static int ctrl_iface_get_capability_pairwise(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004105 struct wpa_driver_capa *capa,
4106 char *buf, size_t buflen)
4107{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004108 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109 char *pos, *end;
4110 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004111 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112
4113 pos = buf;
4114 end = pos + buflen;
4115
4116 if (res < 0) {
4117 if (strict)
4118 return 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07004119#ifdef CONFIG_NO_TKIP
4120 len = os_strlcpy(buf, "CCMP NONE", buflen);
4121#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004123#endif /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 if (len >= buflen)
4125 return -1;
4126 return len;
4127 }
4128
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004129 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4130 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
4131 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004132 pos == buf ? "" : " ",
4133 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004134 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004135 return pos - buf;
4136 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004137 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 }
4139
4140 return pos - buf;
4141}
4142
4143
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004144static int ctrl_iface_get_capability_group(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004145 struct wpa_driver_capa *capa,
4146 char *buf, size_t buflen)
4147{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004148 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 char *pos, *end;
4150 size_t len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004151 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152
4153 pos = buf;
4154 end = pos + buflen;
4155
4156 if (res < 0) {
4157 if (strict)
4158 return 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004159#ifdef CONFIG_WEP
Hai Shalomb755a2a2020-04-23 21:49:02 -07004160#ifdef CONFIG_NO_TKIP
4161 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen);
4162#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004164#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004165#else /* CONFIG_WEP */
Hai Shalomb755a2a2020-04-23 21:49:02 -07004166#ifdef CONFIG_NO_TKIP
4167 len = os_strlcpy(buf, "CCMP", buflen);
4168#else /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004169 len = os_strlcpy(buf, "CCMP TKIP", buflen);
Hai Shalomb755a2a2020-04-23 21:49:02 -07004170#endif /* CONFIG_NO_TKIP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004171#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004172 if (len >= buflen)
4173 return -1;
4174 return len;
4175 }
4176
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004177 for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
4178 if (capa->enc & ciphers[i].capa) {
4179 ret = os_snprintf(pos, end - pos, "%s%s",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004180 pos == buf ? "" : " ",
4181 ciphers[i].name);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004182 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004183 return pos - buf;
4184 pos += ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004186 }
4187
4188 return pos - buf;
4189}
4190
4191
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004192static int ctrl_iface_get_capability_group_mgmt(int res, bool strict,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004193 struct wpa_driver_capa *capa,
4194 char *buf, size_t buflen)
4195{
4196 int ret;
4197 char *pos, *end;
4198 unsigned int i;
4199
4200 pos = buf;
4201 end = pos + buflen;
4202
4203 if (res < 0)
4204 return 0;
4205
4206 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
4207 if (capa->enc & ciphers_group_mgmt[i].capa) {
4208 ret = os_snprintf(pos, end - pos, "%s%s",
4209 pos == buf ? "" : " ",
4210 ciphers_group_mgmt[i].name);
4211 if (os_snprintf_error(end - pos, ret))
4212 return pos - buf;
4213 pos += ret;
4214 }
4215 }
4216
4217 return pos - buf;
4218}
4219
4220
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004221static int iftype_str_to_index(const char *iftype_str)
4222{
4223 if (!iftype_str)
4224 return WPA_IF_MAX;
4225
4226 if (os_strcmp(iftype_str, "STATION") == 0)
4227 return WPA_IF_STATION;
4228
4229 if (os_strcmp(iftype_str, "AP_VLAN") == 0)
4230 return WPA_IF_AP_VLAN;
4231
4232 if (os_strcmp(iftype_str, "AP") == 0)
4233 return WPA_IF_AP_BSS;
4234
4235 if (os_strcmp(iftype_str, "P2P_GO") == 0)
4236 return WPA_IF_P2P_GO;
4237
4238 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0)
4239 return WPA_IF_P2P_CLIENT;
4240
4241 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0)
4242 return WPA_IF_P2P_DEVICE;
4243
4244 if (os_strcmp(iftype_str, "MESH") == 0)
4245 return WPA_IF_MESH;
4246
4247 if (os_strcmp(iftype_str, "IBSS") == 0)
4248 return WPA_IF_IBSS;
4249
4250 if (os_strcmp(iftype_str, "NAN") == 0)
4251 return WPA_IF_NAN;
4252
4253 return WPA_IF_MAX;
4254}
4255
4256
4257static int ctrl_iface_get_capability_key_mgmt(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004258 struct wpa_driver_capa *capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004259 const char *iftype_str,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004260 char *buf, size_t buflen)
4261{
4262 int ret;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004263 unsigned int key_mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004264 char *pos, *end;
4265 size_t len;
4266
4267 pos = buf;
4268 end = pos + buflen;
4269
4270 if (res < 0) {
4271 if (strict)
4272 return 0;
4273 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
4274 "NONE", buflen);
4275 if (len >= buflen)
4276 return -1;
4277 return len;
4278 }
4279
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004280 if (iftype_str) {
4281 enum wpa_driver_if_type iftype;
4282
4283 iftype = iftype_str_to_index(iftype_str);
4284 if (iftype == WPA_IF_MAX)
4285 return -1;
4286 key_mgmt = capa->key_mgmt_iftype[iftype];
4287 } else {
4288 key_mgmt = capa->key_mgmt;
4289 }
4290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004292 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004293 return pos - buf;
4294 pos += ret;
4295
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004296 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4297 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004298 ret = os_snprintf(pos, end - pos, " WPA-EAP");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004299 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300 return pos - buf;
4301 pos += ret;
4302 }
4303
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004304 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
4305 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004306 ret = os_snprintf(pos, end - pos, " WPA-PSK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004307 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004308 return pos - buf;
4309 pos += ret;
4310 }
4311
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004312 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313 ret = os_snprintf(pos, end - pos, " WPA-NONE");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004314 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004315 return pos - buf;
4316 pos += ret;
4317 }
4318
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304319 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) {
4320 ret = os_snprintf(pos, end - pos, " WAPI-PSK");
4321 if (os_snprintf_error(end - pos, ret))
4322 return pos - buf;
4323 pos += ret;
4324 }
4325
4326 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) {
4327 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE");
4328 if (os_snprintf_error(end - pos, ret))
4329 return pos - buf;
4330 pos += ret;
4331 }
4332
4333 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) {
4334 ret = os_snprintf(pos, end - pos, " CCKM");
4335 if (os_snprintf_error(end - pos, ret))
4336 return pos - buf;
4337 pos += ret;
4338 }
4339
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004340#ifdef CONFIG_SUITEB
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004341 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004342 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
4343 if (os_snprintf_error(end - pos, ret))
4344 return pos - buf;
4345 pos += ret;
4346 }
4347#endif /* CONFIG_SUITEB */
4348#ifdef CONFIG_SUITEB192
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004349 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004350 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
4351 if (os_snprintf_error(end - pos, ret))
4352 return pos - buf;
4353 pos += ret;
4354 }
4355#endif /* CONFIG_SUITEB192 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004356#ifdef CONFIG_OWE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004357 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004358 ret = os_snprintf(pos, end - pos, " OWE");
4359 if (os_snprintf_error(end - pos, ret))
4360 return pos - buf;
4361 pos += ret;
4362 }
4363#endif /* CONFIG_OWE */
4364#ifdef CONFIG_DPP
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004365 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004366 ret = os_snprintf(pos, end - pos, " DPP");
4367 if (os_snprintf_error(end - pos, ret))
4368 return pos - buf;
4369 pos += ret;
4370 }
4371#endif /* CONFIG_DPP */
4372#ifdef CONFIG_FILS
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004373 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004374 ret = os_snprintf(pos, end - pos, " FILS-SHA256");
4375 if (os_snprintf_error(end - pos, ret))
4376 return pos - buf;
4377 pos += ret;
4378 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004379 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004380 ret = os_snprintf(pos, end - pos, " FILS-SHA384");
4381 if (os_snprintf_error(end - pos, ret))
4382 return pos - buf;
4383 pos += ret;
4384 }
4385#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004386 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004387 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
4388 if (os_snprintf_error(end - pos, ret))
4389 return pos - buf;
4390 pos += ret;
4391 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004392 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004393 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
4394 if (os_snprintf_error(end - pos, ret))
4395 return pos - buf;
4396 pos += ret;
4397 }
4398#endif /* CONFIG_IEEE80211R */
4399#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08004400#ifdef CONFIG_IEEE80211R
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004401 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004402 ret = os_snprintf(pos, end - pos, " FT-PSK");
4403 if (os_snprintf_error(end - pos, ret))
4404 return pos - buf;
4405 pos += ret;
4406 }
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304407 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) {
4408 ret = os_snprintf(pos, end - pos, " FT-EAP");
4409 if (os_snprintf_error(end - pos, ret))
4410 return pos - buf;
4411 pos += ret;
4412 }
4413#ifdef CONFIG_SAE
4414 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) {
4415 ret = os_snprintf(pos, end - pos, " FT-SAE");
4416 if (os_snprintf_error(end - pos, ret))
4417 return pos - buf;
4418 pos += ret;
4419 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004420 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) {
4421 ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY");
4422 if (os_snprintf_error(end - pos, ret))
4423 return pos - buf;
4424 pos += ret;
4425 }
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304426#endif /* CONFIG_SAE */
4427#ifdef CONFIG_SHA384
4428 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) {
4429 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384");
4430 if (os_snprintf_error(end - pos, ret))
4431 return pos - buf;
4432 pos += ret;
4433 }
4434#endif /* CONFIG_SHA384 */
Hai Shalom74f70d42019-02-11 14:42:39 -08004435#endif /* CONFIG_IEEE80211R */
4436#ifdef CONFIG_SAE
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004437 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004438 ret = os_snprintf(pos, end - pos, " SAE");
4439 if (os_snprintf_error(end - pos, ret))
4440 return pos - buf;
4441 pos += ret;
4442 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004443 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) {
4444 ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY");
4445 if (os_snprintf_error(end - pos, ret))
4446 return pos - buf;
4447 pos += ret;
4448 }
Hai Shalom74f70d42019-02-11 14:42:39 -08004449#endif /* CONFIG_SAE */
Tanmay Garga7fd80d2020-05-18 15:52:44 +05304450#ifdef CONFIG_SHA256
4451 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) {
4452 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256");
4453 if (os_snprintf_error(end - pos, ret))
4454 return pos - buf;
4455 pos += ret;
4456 }
4457
4458 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) {
4459 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256");
4460 if (os_snprintf_error(end - pos, ret))
4461 return pos - buf;
4462 pos += ret;
4463 }
4464#endif /* CONFIG_SHA256 */
4465#ifdef CONFIG_HS20
4466 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) {
4467 ret = os_snprintf(pos, end - pos, " OSEN");
4468 if (os_snprintf_error(end - pos, ret))
4469 return pos - buf;
4470 pos += ret;
4471 }
4472#endif /* CONFIG_HS20 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004474 return pos - buf;
4475}
4476
4477
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004478static int ctrl_iface_get_capability_proto(int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 struct wpa_driver_capa *capa,
4480 char *buf, size_t buflen)
4481{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004482 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483 char *pos, *end;
4484 size_t len;
4485
4486 pos = buf;
4487 end = pos + buflen;
4488
4489 if (res < 0) {
4490 if (strict)
4491 return 0;
4492 len = os_strlcpy(buf, "RSN WPA", buflen);
4493 if (len >= buflen)
4494 return -1;
4495 return len;
4496 }
4497
4498 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
4499 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004500 ret = os_snprintf(pos, end - pos, "%sRSN",
4501 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004502 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503 return pos - buf;
4504 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004505 }
4506
4507 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
4508 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004509 ret = os_snprintf(pos, end - pos, "%sWPA",
4510 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004511 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004512 return pos - buf;
4513 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004514 }
4515
4516 return pos - buf;
4517}
4518
4519
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004520static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004521 int res, bool strict,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 struct wpa_driver_capa *capa,
4523 char *buf, size_t buflen)
4524{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004525 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004526 char *pos, *end;
4527 size_t len;
4528
4529 pos = buf;
4530 end = pos + buflen;
4531
4532 if (res < 0) {
4533 if (strict)
4534 return 0;
4535 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
4536 if (len >= buflen)
4537 return -1;
4538 return len;
4539 }
4540
4541 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004542 ret = os_snprintf(pos, end - pos, "%sOPEN",
4543 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004544 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004545 return pos - buf;
4546 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547 }
4548
4549 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
4550 ret = os_snprintf(pos, end - pos, "%sSHARED",
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004551 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004552 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004553 return pos - buf;
4554 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004555 }
4556
4557 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004558 ret = os_snprintf(pos, end - pos, "%sLEAP",
4559 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004560 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004561 return pos - buf;
4562 pos += ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004563 }
4564
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004565#ifdef CONFIG_SAE
4566 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
4567 ret = os_snprintf(pos, end - pos, "%sSAE",
4568 pos == buf ? "" : " ");
4569 if (os_snprintf_error(end - pos, ret))
4570 return pos - buf;
4571 pos += ret;
4572 }
4573#endif /* CONFIG_SAE */
4574
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004575#ifdef CONFIG_FILS
4576 if (wpa_is_fils_supported(wpa_s)) {
4577 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
4578 pos == buf ? "" : " ");
4579 if (os_snprintf_error(end - pos, ret))
4580 return pos - buf;
4581 pos += ret;
4582 }
4583
4584#ifdef CONFIG_FILS_SK_PFS
4585 if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
4586 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
4587 pos == buf ? "" : " ");
4588 if (os_snprintf_error(end - pos, ret))
4589 return pos - buf;
4590 pos += ret;
4591 }
4592#endif /* CONFIG_FILS_SK_PFS */
4593#endif /* CONFIG_FILS */
4594
Hai Shalom60840252021-02-19 19:02:11 -08004595#ifdef CONFIG_PASN
4596 ret = os_snprintf(pos, end - pos, "%sPASN",
4597 pos == buf ? "" : " ");
4598 if (os_snprintf_error(end - pos, ret))
4599 return pos - buf;
4600 pos += ret;
4601
4602#endif /* CONFIG_PASN */
4603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004604 return pos - buf;
4605}
4606
4607
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004608static int ctrl_iface_get_capability_modes(int res, bool strict,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004609 struct wpa_driver_capa *capa,
4610 char *buf, size_t buflen)
4611{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004612 int ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004613 char *pos, *end;
4614 size_t len;
4615
4616 pos = buf;
4617 end = pos + buflen;
4618
4619 if (res < 0) {
4620 if (strict)
4621 return 0;
4622 len = os_strlcpy(buf, "IBSS AP", buflen);
4623 if (len >= buflen)
4624 return -1;
4625 return len;
4626 }
4627
4628 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004629 ret = os_snprintf(pos, end - pos, "%sIBSS",
4630 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004631 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004632 return pos - buf;
4633 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004634 }
4635
4636 if (capa->flags & WPA_DRIVER_FLAGS_AP) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08004637 ret = os_snprintf(pos, end - pos, "%sAP",
4638 pos == buf ? "" : " ");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004639 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004640 return pos - buf;
4641 pos += ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004642 }
4643
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004644#ifdef CONFIG_MESH
4645 if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
4646 ret = os_snprintf(pos, end - pos, "%sMESH",
4647 pos == buf ? "" : " ");
4648 if (os_snprintf_error(end - pos, ret))
4649 return pos - buf;
4650 pos += ret;
4651 }
4652#endif /* CONFIG_MESH */
4653
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004654 return pos - buf;
4655}
4656
4657
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004658static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
4659 char *buf, size_t buflen)
4660{
4661 struct hostapd_channel_data *chnl;
4662 int ret, i, j;
4663 char *pos, *end, *hmode;
4664
4665 pos = buf;
4666 end = pos + buflen;
4667
4668 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4669 switch (wpa_s->hw.modes[j].mode) {
4670 case HOSTAPD_MODE_IEEE80211B:
4671 hmode = "B";
4672 break;
4673 case HOSTAPD_MODE_IEEE80211G:
4674 hmode = "G";
4675 break;
4676 case HOSTAPD_MODE_IEEE80211A:
4677 hmode = "A";
4678 break;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004679 case HOSTAPD_MODE_IEEE80211AD:
4680 hmode = "AD";
4681 break;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004682 default:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004683 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004684 }
4685 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004686 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004687 return pos - buf;
4688 pos += ret;
4689 chnl = wpa_s->hw.modes[j].channels;
4690 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004691 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4692 continue;
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004693 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004694 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004695 return pos - buf;
4696 pos += ret;
4697 }
4698 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004699 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004700 return pos - buf;
4701 pos += ret;
4702 }
4703
4704 return pos - buf;
4705}
4706
4707
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004708static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
4709 char *buf, size_t buflen)
4710{
4711 struct hostapd_channel_data *chnl;
4712 int ret, i, j;
4713 char *pos, *end, *hmode;
4714
4715 pos = buf;
4716 end = pos + buflen;
4717
4718 for (j = 0; j < wpa_s->hw.num_modes; j++) {
4719 switch (wpa_s->hw.modes[j].mode) {
4720 case HOSTAPD_MODE_IEEE80211B:
4721 hmode = "B";
4722 break;
4723 case HOSTAPD_MODE_IEEE80211G:
4724 hmode = "G";
4725 break;
4726 case HOSTAPD_MODE_IEEE80211A:
4727 hmode = "A";
4728 break;
4729 case HOSTAPD_MODE_IEEE80211AD:
4730 hmode = "AD";
4731 break;
4732 default:
4733 continue;
4734 }
4735 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
4736 hmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004737 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004738 return pos - buf;
4739 pos += ret;
4740 chnl = wpa_s->hw.modes[j].channels;
4741 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
4742 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
4743 continue;
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004744 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004745 chnl[i].chan, chnl[i].freq,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004746 chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
4747 " (NO_IR)" : "",
Dmitry Shmidt5da5e352014-02-03 13:30:46 -08004748 chnl[i].flag & HOSTAPD_CHAN_RADAR ?
4749 " (DFS)" : "");
4750
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004751 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004752 return pos - buf;
4753 pos += ret;
4754 }
4755 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004756 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004757 return pos - buf;
4758 pos += ret;
4759 }
4760
4761 return pos - buf;
4762}
4763
4764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004765static int wpa_supplicant_ctrl_iface_get_capability(
4766 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
4767 size_t buflen)
4768{
4769 struct wpa_driver_capa capa;
4770 int res;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004771 char *next_param, *curr_param, *iftype = NULL;
4772 bool strict = false;
4773 char field[50];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004774 size_t len;
4775
4776 /* Determine whether or not strict checking was requested */
4777 len = os_strlcpy(field, _field, sizeof(field));
4778 if (len >= sizeof(field))
4779 return -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004780
4781 next_param = os_strchr(field, ' ');
4782 while (next_param) {
4783 *next_param++ = '\0';
4784 curr_param = next_param;
4785 next_param = os_strchr(next_param, ' ');
4786
4787 if (next_param)
4788 *next_param = '\0';
4789
4790 if (os_strcmp(curr_param, "strict") == 0)
4791 strict = true;
4792 else if (os_strncmp(curr_param, "iftype=", 7) == 0)
4793 iftype = curr_param + 7;
4794 else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 return -1;
4796 }
4797
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004798 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s",
4799 field, iftype ? " iftype=" : "", iftype ? iftype : "",
4800 strict ? " strict" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801
4802 if (os_strcmp(field, "eap") == 0) {
4803 return eap_get_names(buf, buflen);
4804 }
4805
4806 res = wpa_drv_get_capa(wpa_s, &capa);
4807
4808 if (os_strcmp(field, "pairwise") == 0)
4809 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
4810 buf, buflen);
4811
4812 if (os_strcmp(field, "group") == 0)
4813 return ctrl_iface_get_capability_group(res, strict, &capa,
4814 buf, buflen);
4815
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004816 if (os_strcmp(field, "group_mgmt") == 0)
4817 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
4818 buf, buflen);
4819
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004820 if (os_strcmp(field, "key_mgmt") == 0)
4821 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004822 iftype, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004823
4824 if (os_strcmp(field, "proto") == 0)
4825 return ctrl_iface_get_capability_proto(res, strict, &capa,
4826 buf, buflen);
4827
4828 if (os_strcmp(field, "auth_alg") == 0)
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004829 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
4830 &capa, buf, buflen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004831
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004832 if (os_strcmp(field, "modes") == 0)
4833 return ctrl_iface_get_capability_modes(res, strict, &capa,
4834 buf, buflen);
4835
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07004836 if (os_strcmp(field, "channels") == 0)
4837 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
4838
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004839 if (os_strcmp(field, "freq") == 0)
4840 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
4841
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004842#ifdef CONFIG_TDLS
4843 if (os_strcmp(field, "tdls") == 0)
4844 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
4845#endif /* CONFIG_TDLS */
4846
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004847#ifdef CONFIG_ERP
4848 if (os_strcmp(field, "erp") == 0) {
4849 res = os_snprintf(buf, buflen, "ERP");
4850 if (os_snprintf_error(buflen, res))
4851 return -1;
4852 return res;
4853 }
4854#endif /* CONFIG_EPR */
4855
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004856#ifdef CONFIG_FIPS
4857 if (os_strcmp(field, "fips") == 0) {
4858 res = os_snprintf(buf, buflen, "FIPS");
4859 if (os_snprintf_error(buflen, res))
4860 return -1;
4861 return res;
4862 }
4863#endif /* CONFIG_FIPS */
4864
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08004865#ifdef CONFIG_ACS
4866 if (os_strcmp(field, "acs") == 0) {
4867 res = os_snprintf(buf, buflen, "ACS");
4868 if (os_snprintf_error(buflen, res))
4869 return -1;
4870 return res;
4871 }
4872#endif /* CONFIG_ACS */
4873
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004874#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004875 if (os_strcmp(field, "fils") == 0) {
4876#ifdef CONFIG_FILS_SK_PFS
4877 if (wpa_is_fils_supported(wpa_s) &&
4878 wpa_is_fils_sk_pfs_supported(wpa_s)) {
4879 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
4880 if (os_snprintf_error(buflen, res))
4881 return -1;
4882 return res;
4883 }
4884#endif /* CONFIG_FILS_SK_PFS */
4885
4886 if (wpa_is_fils_supported(wpa_s)) {
4887 res = os_snprintf(buf, buflen, "FILS");
4888 if (os_snprintf_error(buflen, res))
4889 return -1;
4890 return res;
4891 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004892 }
4893#endif /* CONFIG_FILS */
4894
Hai Shalom74f70d42019-02-11 14:42:39 -08004895 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
4896 res = os_snprintf(buf, buflen, "MULTIBSS-STA");
4897 if (os_snprintf_error(buflen, res))
4898 return -1;
4899 return res;
4900 }
4901
Hai Shalom021b0b52019-04-10 11:17:58 -07004902#ifdef CONFIG_DPP
4903 if (os_strcmp(field, "dpp") == 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004904#ifdef CONFIG_DPP3
4905 res = os_snprintf(buf, buflen, "DPP=3");
4906#elif defined(CONFIG_DPP2)
Hai Shalom021b0b52019-04-10 11:17:58 -07004907 res = os_snprintf(buf, buflen, "DPP=2");
4908#else /* CONFIG_DPP2 */
4909 res = os_snprintf(buf, buflen, "DPP=1");
4910#endif /* CONFIG_DPP2 */
4911 if (os_snprintf_error(buflen, res))
4912 return -1;
4913 return res;
4914 }
4915#endif /* CONFIG_DPP */
4916
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004917#ifdef CONFIG_NAN_USD
4918 if (os_strcmp(field, "nan") == 0) {
4919 res = os_snprintf(buf, buflen, "USD");
4920 if (os_snprintf_error(buflen, res))
4921 return -1;
4922 return res;
4923 }
4924#endif /* CONFIG_NAN_USD */
4925
Hai Shalom899fcc72020-10-19 14:38:18 -07004926#ifdef CONFIG_SAE
4927 if (os_strcmp(field, "sae") == 0 &&
4928 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
4929#ifdef CONFIG_SAE_PK
4930 res = os_snprintf(buf, buflen, "H2E PK");
4931#else /* CONFIG_SAE_PK */
4932 res = os_snprintf(buf, buflen, "H2E");
4933#endif /* CONFIG_SAE_PK */
4934 if (os_snprintf_error(buflen, res))
4935 return -1;
4936 return res;
4937 }
4938#endif /* CONFIG_SAE */
4939
Hai Shalom60840252021-02-19 19:02:11 -08004940#ifdef CONFIG_OCV
4941 if (os_strcmp(field, "ocv") == 0) {
4942 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
4943 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
4944 res = os_snprintf(buf, buflen, "supported");
4945 else
4946 res = os_snprintf(buf, buflen, "not supported");
4947 if (os_snprintf_error(buflen, res))
4948 return -1;
4949 return res;
4950 }
4951#endif /* CONFIG_OCV */
4952
4953 if (os_strcmp(field, "beacon_prot") == 0) {
4954 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
4955 (wpa_s->drv_flags2 &
4956 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
4957 res = os_snprintf(buf, buflen, "supported");
4958 else
4959 res = os_snprintf(buf, buflen, "not supported");
4960 if (os_snprintf_error(buflen, res))
4961 return -1;
4962 return res;
4963 }
4964
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004965 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
4966 field);
4967
4968 return -1;
4969}
4970
4971
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004972#ifdef CONFIG_INTERWORKING
4973static char * anqp_add_hex(char *pos, char *end, const char *title,
4974 struct wpabuf *data)
4975{
4976 char *start = pos;
4977 size_t i;
4978 int ret;
4979 const u8 *d;
4980
4981 if (data == NULL)
4982 return start;
4983
4984 ret = os_snprintf(pos, end - pos, "%s=", title);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004985 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004986 return start;
4987 pos += ret;
4988
4989 d = wpabuf_head_u8(data);
4990 for (i = 0; i < wpabuf_len(data); i++) {
4991 ret = os_snprintf(pos, end - pos, "%02x", *d++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004992 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004993 return start;
4994 pos += ret;
4995 }
4996
4997 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004998 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004999 return start;
5000 pos += ret;
5001
5002 return pos;
5003}
5004#endif /* CONFIG_INTERWORKING */
5005
5006
Dmitry Shmidt29333592017-01-09 12:27:11 -08005007#ifdef CONFIG_FILS
5008static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
5009{
5010 char *start = pos;
5011 const u8 *ie, *ie_end;
5012 u16 info, realms;
5013 int ret;
5014
5015 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
5016 if (!ie)
5017 return 0;
5018 ie_end = ie + 2 + ie[1];
5019 ie += 2;
5020 if (ie_end - ie < 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005021 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005022
5023 info = WPA_GET_LE16(ie);
5024 ie += 2;
5025 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
5026 if (os_snprintf_error(end - pos, ret))
5027 return 0;
5028 pos += ret;
5029
5030 if (info & BIT(7)) {
5031 /* Cache Identifier Included */
5032 if (ie_end - ie < 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005033 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005034 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
5035 ie[0], ie[1]);
5036 if (os_snprintf_error(end - pos, ret))
5037 return 0;
5038 pos += ret;
5039 ie += 2;
5040 }
5041
5042 if (info & BIT(8)) {
5043 /* HESSID Included */
5044 if (ie_end - ie < ETH_ALEN)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005045 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005046 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
5047 MAC2STR(ie));
5048 if (os_snprintf_error(end - pos, ret))
5049 return 0;
5050 pos += ret;
5051 ie += ETH_ALEN;
5052 }
5053
5054 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
5055 if (realms) {
5056 if (ie_end - ie < realms * 2)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005057 return 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005058 ret = os_snprintf(pos, end - pos, "fils_realms=");
5059 if (os_snprintf_error(end - pos, ret))
5060 return 0;
5061 pos += ret;
5062
5063 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
5064 if (ret <= 0)
5065 return 0;
5066 pos += ret;
5067 ie += realms * 2;
5068 ret = os_snprintf(pos, end - pos, "\n");
5069 if (os_snprintf_error(end - pos, ret))
5070 return 0;
5071 pos += ret;
5072 }
5073
5074 return pos - start;
5075}
5076#endif /* CONFIG_FILS */
5077
5078
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005079static int print_rnr(struct wpa_bss *bss, char *pos, char *end)
5080{
5081 char *start = pos;
5082 const u8 *ie, *ie_end;
5083 unsigned int n = 0;
5084 int ret;
5085
5086 ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
5087 if (!ie)
5088 return 0;
5089
5090 ie_end = ie + 2 + ie[1];
5091 ie += 2;
5092
5093 while (ie < ie_end) {
5094 const struct ieee80211_neighbor_ap_info *info =
5095 (const struct ieee80211_neighbor_ap_info *) ie;
5096 const u8 *tbtt_start;
5097 size_t left = ie_end - ie;
5098
5099 if (left < sizeof(struct ieee80211_neighbor_ap_info))
5100 return 0;
5101
5102 left -= sizeof(struct ieee80211_neighbor_ap_info);
5103 if (left < info->tbtt_info_len)
5104 return 0;
5105
5106 ret = os_snprintf(pos, end - pos,
5107 "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ",
5108 n, *ie, info->tbtt_info_len,
5109 info->op_class, info->channel);
5110 if (os_snprintf_error(end - pos, ret))
5111 return 0;
5112 pos += ret;
5113
5114 ie += sizeof(struct ieee80211_neighbor_ap_info);
5115 tbtt_start = ie;
5116 if (info->tbtt_info_len >= 1) {
5117 ret = os_snprintf(pos, end - pos,
5118 "tbtt_offset=%u, ", *ie);
5119 if (os_snprintf_error(end - pos, ret))
5120 return 0;
5121
5122 ie++;
5123 pos += ret;
5124 }
5125
5126 if (info->tbtt_info_len >= 7) {
5127 ret = os_snprintf(pos, end - pos,
5128 "bssid=" MACSTR ", ",
5129 MAC2STR(ie));
5130 if (os_snprintf_error(end - pos, ret))
5131 return 0;
5132
5133 ie += ETH_ALEN;
5134 pos += ret;
5135 }
5136
5137 if (info->tbtt_info_len >= 11) {
5138 ret = os_snprintf(pos, end - pos,
5139 "short SSID=0x%x, ",
5140 WPA_GET_LE32(ie));
5141 if (os_snprintf_error(end - pos, ret))
5142 return 0;
5143
5144 ie += 4;
5145 pos += ret;
5146 }
5147
5148 if (info->tbtt_info_len >= 12) {
5149 ret = os_snprintf(pos, end - pos,
5150 "bss_params=0x%x, ", *ie);
5151 if (os_snprintf_error(end - pos, ret))
5152 return 0;
5153
5154 ie++;
5155 pos += ret;
5156 }
5157
5158 if (info->tbtt_info_len >= 13) {
5159 ret = os_snprintf(pos, end - pos,
5160 "PSD=0x%x, ", *ie);
5161 if (os_snprintf_error(end - pos, ret))
5162 return 0;
5163
5164 ie++;
5165 pos += ret;
5166 }
5167
5168 if (info->tbtt_info_len >= 16) {
5169 ret = os_snprintf(pos, end - pos,
5170 "mld ID=%u, link ID=%u",
5171 *ie, *(ie + 1) & 0xF);
5172 if (os_snprintf_error(end - pos, ret))
5173 return 0;
5174
5175 ie += 3;
5176 pos += ret;
5177 }
5178
5179 ie = tbtt_start + info->tbtt_info_len;
5180
5181 ret = os_snprintf(pos, end - pos, "\n");
5182 if (os_snprintf_error(end - pos, ret))
5183 return 0;
5184 pos += ret;
5185
5186 n++;
5187 }
5188
5189 return pos - start;
5190}
5191
5192
5193static int print_ml(struct wpa_bss *bss, char *pos, char *end)
5194{
5195 const struct ieee80211_eht_ml *ml;
5196 char *start = pos;
5197 const u8 *ie, *ie_end;
5198 u16 ml_control;
5199 u8 common_info_length;
5200 int ret;
5201
5202 ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len,
5203 MULTI_LINK_CONTROL_TYPE_BASIC);
5204 if (!ie)
5205 return 0;
5206
5207 ie_end = ie + 2 + ie[1];
5208 ie += 3;
5209 ml = (const struct ieee80211_eht_ml *) ie;
5210
5211 /* control + common info length + MLD MAC Address */
5212 if (ie_end - ie < 2 + 1 + ETH_ALEN)
5213 return 0;
5214
5215 ml_control = le_to_host16(ml->ml_control);
5216
5217 common_info_length = *(ie + 2);
5218 ret = os_snprintf(pos, end - pos,
5219 "multi-link: control=0x%x, common info len=%u",
5220 ml_control, common_info_length);
5221 if (os_snprintf_error(end - pos, ret))
5222 return 0;
5223 pos += ret;
5224
5225 ie += 2;
5226 if (ie_end - ie < common_info_length)
5227 return 0;
5228
5229 ie++;
5230 common_info_length--;
5231
5232 if (common_info_length < ETH_ALEN)
5233 return 0;
5234
5235 ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie));
5236 if (os_snprintf_error(end - pos, ret))
5237 return 0;
5238 pos += ret;
5239
5240 ie += ETH_ALEN;
5241 common_info_length -= ETH_ALEN;
5242
5243 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
5244 if (common_info_length < 1)
5245 return 0;
5246
5247 ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f);
5248 if (os_snprintf_error(end - pos, ret))
5249 return 0;
5250 pos += ret;
5251 ie++;
5252 common_info_length--;
5253 }
5254
5255 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
5256 if (common_info_length < 1)
5257 return 0;
5258
5259 ret = os_snprintf(pos, end - pos,
5260 ", BSS change parameters=0x%x", *ie);
5261 if (os_snprintf_error(end - pos, ret))
5262 return 0;
5263 pos += ret;
5264 ie++;
5265 common_info_length--;
5266 }
5267
5268 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
5269 if (common_info_length < 2)
5270 return 0;
5271
5272 ret = os_snprintf(pos, end - pos, ", MSD Info=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_EML_CAPA) {
5282 if (common_info_length < 2)
5283 return 0;
5284
5285 ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x",
5286 WPA_GET_LE16(ie));
5287 if (os_snprintf_error(end - pos, ret))
5288 return 0;
5289 pos += ret;
5290 ie += 2;
5291 common_info_length -= 2;
5292 }
5293
5294 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
5295 if (common_info_length < 2)
5296 return 0;
5297
5298 ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x",
5299 WPA_GET_LE16(ie));
5300 if (os_snprintf_error(end - pos, ret))
5301 return 0;
5302 pos += ret;
5303 ie += 2;
5304 common_info_length -= 2;
5305 }
5306
5307 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
5308 if (common_info_length < 1)
5309 return 0;
5310
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005311 ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005312 if (os_snprintf_error(end - pos, ret))
5313 return 0;
5314 pos += ret;
5315 ie += 1;
5316 common_info_length--;
5317 }
5318
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005319 ret = os_snprintf(pos, end - pos, "\n");
5320 if (os_snprintf_error(end - pos, ret))
5321 return 0;
5322 pos += ret;
5323
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005324 return pos - start;
5325}
5326
5327
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005328static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5329 unsigned long mask, char *buf, size_t buflen)
5330{
5331 size_t i;
5332 int ret;
5333 char *pos, *end;
Hai Shalom899fcc72020-10-19 14:38:18 -07005334 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005335
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005336 pos = buf;
5337 end = buf + buflen;
5338
5339 if (mask & WPA_BSS_MASK_ID) {
5340 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005341 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005342 return 0;
5343 pos += ret;
5344 }
5345
5346 if (mask & WPA_BSS_MASK_BSSID) {
5347 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
5348 MAC2STR(bss->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005349 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005350 return 0;
5351 pos += ret;
5352 }
5353
5354 if (mask & WPA_BSS_MASK_FREQ) {
5355 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005356 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005357 return 0;
5358 pos += ret;
5359 }
5360
5361 if (mask & WPA_BSS_MASK_BEACON_INT) {
5362 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
5363 bss->beacon_int);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005364 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005365 return 0;
5366 pos += ret;
5367 }
5368
5369 if (mask & WPA_BSS_MASK_CAPABILITIES) {
5370 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
5371 bss->caps);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005372 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005373 return 0;
5374 pos += ret;
5375 }
5376
5377 if (mask & WPA_BSS_MASK_QUAL) {
5378 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005379 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005380 return 0;
5381 pos += ret;
5382 }
5383
5384 if (mask & WPA_BSS_MASK_NOISE) {
5385 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
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_LEVEL) {
5392 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
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 }
5397
5398 if (mask & WPA_BSS_MASK_TSF) {
5399 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
5400 (unsigned long long) bss->tsf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005401 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005402 return 0;
5403 pos += ret;
5404 }
5405
5406 if (mask & WPA_BSS_MASK_AGE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005407 struct os_reltime now;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005408
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005409 os_get_reltime(&now);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005410 ret = os_snprintf(pos, end - pos, "age=%d\n",
5411 (int) (now.sec - bss->last_update.sec));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005412 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005413 return 0;
5414 pos += ret;
5415 }
5416
5417 if (mask & WPA_BSS_MASK_IE) {
5418 ret = os_snprintf(pos, end - pos, "ie=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005419 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005420 return 0;
5421 pos += ret;
5422
Hai Shalom60840252021-02-19 19:02:11 -08005423 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005424 for (i = 0; i < bss->ie_len; i++) {
5425 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005426 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005427 return 0;
5428 pos += ret;
5429 }
5430
5431 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005432 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005433 return 0;
5434 pos += ret;
5435 }
5436
5437 if (mask & WPA_BSS_MASK_FLAGS) {
5438 ret = os_snprintf(pos, end - pos, "flags=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005439 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005440 return 0;
5441 pos += ret;
5442
Dmitry Shmidt29333592017-01-09 12:27:11 -08005443 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
5444
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005445 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
5446 if (ie)
5447 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
5448 2 + ie[1]);
Sunil Ravi7f769292024-07-23 22:21:32 +00005449 ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005450 if (ie2)
Dmitry Shmidt29333592017-01-09 12:27:11 -08005451 pos = wpa_supplicant_ie_txt(pos, end,
5452 mesh ? "RSN" : "WPA2", ie2,
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005453 2 + ie2[1]);
Sunil Ravi7f769292024-07-23 22:21:32 +00005454 rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
Hai Shaloma20dcd72022-02-04 13:43:00 -08005455 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
5456 ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
5457 if (os_snprintf_error(end - pos, ret))
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005458 return 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005459 pos += ret;
5460 }
5461 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
5462 ret = os_snprintf(pos, end - pos, "[SAE-PK]");
5463 if (os_snprintf_error(end - pos, ret))
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005464 return 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005465 pos += ret;
Hai Shalom899fcc72020-10-19 14:38:18 -07005466 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005467 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
5468 if (osen_ie)
5469 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
5470 osen_ie, 2 + osen_ie[1]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005471 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5472 if (owe) {
5473 ret = os_snprintf(
5474 pos, end - pos,
5475 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
5476 if (os_snprintf_error(end - pos, ret))
5477 return 0;
5478 pos += ret;
5479 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005480 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005481 if (!ie && !ie2 && !osen_ie &&
5482 (bss->caps & IEEE80211_CAP_PRIVACY)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005483 ret = os_snprintf(pos, end - pos, "[WEP]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005484 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005485 return 0;
5486 pos += ret;
5487 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005488
5489 if (mesh) {
5490 ret = os_snprintf(pos, end - pos, "[MESH]");
5491 if (os_snprintf_error(end - pos, ret))
5492 return 0;
5493 pos += ret;
5494 }
5495
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005496 if (bss_is_dmg(bss)) {
5497 const char *s;
5498 ret = os_snprintf(pos, end - pos, "[DMG]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005499 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005500 return 0;
5501 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005502 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
5503 case IEEE80211_CAP_DMG_IBSS:
5504 s = "[IBSS]";
5505 break;
5506 case IEEE80211_CAP_DMG_AP:
5507 s = "[ESS]";
5508 break;
5509 case IEEE80211_CAP_DMG_PBSS:
5510 s = "[PBSS]";
5511 break;
5512 default:
5513 s = "";
5514 break;
5515 }
5516 ret = os_snprintf(pos, end - pos, "%s", s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005517 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005518 return 0;
5519 pos += ret;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005520 } else {
5521 if (bss->caps & IEEE80211_CAP_IBSS) {
5522 ret = os_snprintf(pos, end - pos, "[IBSS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005523 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005524 return 0;
5525 pos += ret;
5526 }
5527 if (bss->caps & IEEE80211_CAP_ESS) {
5528 ret = os_snprintf(pos, end - pos, "[ESS]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005529 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005530 return 0;
5531 pos += ret;
5532 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005533 }
Dmitry Shmidt96571392013-10-14 12:54:46 -07005534 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
5535 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005536 ret = os_snprintf(pos, end - pos, "[P2P]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005537 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005538 return 0;
5539 pos += ret;
5540 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005541#ifdef CONFIG_HS20
5542 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
5543 ret = os_snprintf(pos, end - pos, "[HS20]");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005544 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005545 return 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005546 pos += ret;
5547 }
5548#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005549#ifdef CONFIG_FILS
5550 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
5551 ret = os_snprintf(pos, end - pos, "[FILS]");
5552 if (os_snprintf_error(end - pos, ret))
5553 return 0;
5554 pos += ret;
5555 }
5556#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08005557#ifdef CONFIG_FST
5558 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
5559 ret = os_snprintf(pos, end - pos, "[FST]");
5560 if (os_snprintf_error(end - pos, ret))
5561 return 0;
5562 pos += ret;
5563 }
5564#endif /* CONFIG_FST */
5565 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
5566 ret = os_snprintf(pos, end - pos, "[UTF-8]");
5567 if (os_snprintf_error(end - pos, ret))
5568 return 0;
5569 pos += ret;
5570 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005571
5572 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005573 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005574 return 0;
5575 pos += ret;
5576 }
5577
5578 if (mask & WPA_BSS_MASK_SSID) {
5579 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
5580 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005581 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005582 return 0;
5583 pos += ret;
5584 }
5585
5586#ifdef CONFIG_WPS
5587 if (mask & WPA_BSS_MASK_WPS_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005588 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005589 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005590 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005591 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005592 if (ret > 0)
5593 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005594 }
5595#endif /* CONFIG_WPS */
5596
5597#ifdef CONFIG_P2P
5598 if (mask & WPA_BSS_MASK_P2P_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005599 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005600 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005601 if (ret >= end - pos)
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005602 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005603 if (ret > 0)
5604 pos += ret;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005605 }
5606#endif /* CONFIG_P2P */
5607
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005608#ifdef CONFIG_WIFI_DISPLAY
5609 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
5610 struct wpabuf *wfd;
Hai Shalom60840252021-02-19 19:02:11 -08005611
5612 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005613 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
5614 WFD_IE_VENDOR_TYPE);
5615 if (wfd) {
5616 ret = os_snprintf(pos, end - pos, "wfd_subelems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005617 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005618 wpabuf_free(wfd);
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005619 return 0;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005620 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005621 pos += ret;
5622
5623 pos += wpa_snprintf_hex(pos, end - pos,
5624 wpabuf_head(wfd),
5625 wpabuf_len(wfd));
5626 wpabuf_free(wfd);
5627
5628 ret = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005629 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005630 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005631 pos += ret;
5632 }
5633 }
5634#endif /* CONFIG_WIFI_DISPLAY */
5635
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005636#ifdef CONFIG_INTERWORKING
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005637 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
5638 struct wpa_bss_anqp *anqp = bss->anqp;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005639 struct wpa_bss_anqp_elem *elem;
5640
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005641 pos = anqp_add_hex(pos, end, "anqp_capability_list",
5642 anqp->capability_list);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005643 pos = anqp_add_hex(pos, end, "anqp_venue_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005644 anqp->venue_name);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005645 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005646 anqp->network_auth_type);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005647 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005648 anqp->roaming_consortium);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005649 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005650 anqp->ip_addr_type_availability);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005651 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005652 anqp->nai_realm);
5653 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005654 pos = anqp_add_hex(pos, end, "anqp_domain_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005655 anqp->domain_name);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005656 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
5657 anqp->fils_realm_info);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005658#ifdef CONFIG_HS20
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005659 pos = anqp_add_hex(pos, end, "hs20_capability_list",
5660 anqp->hs20_capability_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005661 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005662 anqp->hs20_operator_friendly_name);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005663 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005664 anqp->hs20_wan_metrics);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005665 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005666 anqp->hs20_connection_capability);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005667 pos = anqp_add_hex(pos, end, "hs20_operating_class",
5668 anqp->hs20_operating_class);
5669 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
5670 anqp->hs20_osu_providers_list);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005671 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
5672 anqp->hs20_operator_icon_metadata);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08005673 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
5674 anqp->hs20_osu_providers_nai_list);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005675#endif /* CONFIG_HS20 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005676
5677 dl_list_for_each(elem, &anqp->anqp_elems,
5678 struct wpa_bss_anqp_elem, list) {
5679 char title[20];
5680
5681 os_snprintf(title, sizeof(title), "anqp[%u]",
5682 elem->infoid);
5683 pos = anqp_add_hex(pos, end, title, elem->payload);
Hai Shalom60840252021-02-19 19:02:11 -08005684 if (elem->protected_response) {
5685 ret = os_snprintf(pos, end - pos,
5686 "protected-anqp-info[%u]=1\n",
5687 elem->infoid);
5688 if (os_snprintf_error(end - pos, ret))
5689 return 0;
5690 pos += ret;
5691 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005692 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005693 }
5694#endif /* CONFIG_INTERWORKING */
5695
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005696#ifdef CONFIG_MESH
5697 if (mask & WPA_BSS_MASK_MESH_SCAN) {
Hai Shalom60840252021-02-19 19:02:11 -08005698 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005699 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005700 if (ret >= end - pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005701 return 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005702 if (ret > 0)
5703 pos += ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005704 }
5705#endif /* CONFIG_MESH */
5706
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005707 if (mask & WPA_BSS_MASK_SNR) {
5708 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
5709 if (os_snprintf_error(end - pos, ret))
5710 return 0;
5711 pos += ret;
5712 }
5713
5714 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
5715 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
5716 bss->est_throughput);
5717 if (os_snprintf_error(end - pos, ret))
5718 return 0;
5719 pos += ret;
5720 }
5721
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005722#ifdef CONFIG_FST
5723 if (mask & WPA_BSS_MASK_FST) {
5724 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos);
5725 if (ret < 0 || ret >= end - pos)
5726 return 0;
5727 pos += ret;
5728 }
5729#endif /* CONFIG_FST */
5730
Dmitry Shmidt29333592017-01-09 12:27:11 -08005731 if (mask & WPA_BSS_MASK_UPDATE_IDX) {
5732 ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
5733 bss->last_update_idx);
5734 if (os_snprintf_error(end - pos, ret))
5735 return 0;
5736 pos += ret;
5737 }
5738
5739 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
5740 ret = os_snprintf(pos, end - pos, "beacon_ie=");
5741 if (os_snprintf_error(end - pos, ret))
5742 return 0;
5743 pos += ret;
5744
Hai Shalom60840252021-02-19 19:02:11 -08005745 ie = wpa_bss_ie_ptr(bss);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005746 ie += bss->ie_len;
5747 for (i = 0; i < bss->beacon_ie_len; i++) {
5748 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
5749 if (os_snprintf_error(end - pos, ret))
5750 return 0;
5751 pos += ret;
5752 }
5753
5754 ret = os_snprintf(pos, end - pos, "\n");
5755 if (os_snprintf_error(end - pos, ret))
5756 return 0;
5757 pos += ret;
5758 }
5759
5760#ifdef CONFIG_FILS
5761 if (mask & WPA_BSS_MASK_FILS_INDICATION) {
5762 ret = print_fils_indication(bss, pos, end);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005763 pos += ret;
5764 }
5765#endif /* CONFIG_FILS */
5766
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005767 if (!is_zero_ether_addr(bss->mld_addr) &&
5768 (mask & WPA_BSS_MASK_AP_MLD_ADDR)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07005769 ret = os_snprintf(pos, end - pos,
5770 "ap_mld_addr=" MACSTR "\n",
5771 MAC2STR(bss->mld_addr));
5772 if (os_snprintf_error(end - pos, ret))
5773 return 0;
5774 pos += ret;
5775 }
5776
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005777 if (mask & WPA_BSS_MASK_RNR)
5778 pos += print_rnr(bss, pos, end);
5779
5780 if (mask & WPA_BSS_MASK_ML)
5781 pos += print_ml(bss, pos, end);
5782
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005783 if (mask & WPA_BSS_MASK_DELIM) {
5784 ret = os_snprintf(pos, end - pos, "====\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005785 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005786 return 0;
5787 pos += ret;
5788 }
Irfan Sheriffe2ea0082012-08-13 10:56:16 -07005789
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005790 return pos - buf;
5791}
5792
Dmitry Shmidt04949592012-07-19 12:16:46 -07005793
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005794static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
5795 const char *cmd, char *buf,
5796 size_t buflen)
5797{
5798 u8 bssid[ETH_ALEN];
5799 size_t i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005800 struct wpa_bss *bss;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005801 struct wpa_bss *bsslast = NULL;
5802 struct dl_list *next;
5803 int ret = 0;
5804 int len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005805 char *ctmp, *end = buf + buflen;
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005806 unsigned long mask = WPA_BSS_MASK_ALL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005807
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005808 if (os_strncmp(cmd, "RANGE=", 6) == 0) {
5809 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
5810 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005811 list_id);
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005812 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
5813 list_id);
5814 } else { /* N1-N2 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005815 unsigned int id1, id2;
5816
5817 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
5818 wpa_printf(MSG_INFO, "Wrong BSS range "
5819 "format");
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005820 return 0;
5821 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005822
Dmitry Shmidtf8623282013-02-20 14:34:59 -08005823 if (*(cmd + 6) == '-')
5824 id1 = 0;
5825 else
5826 id1 = atoi(cmd + 6);
5827 ctmp++;
5828 if (*ctmp >= '0' && *ctmp <= '9')
5829 id2 = atoi(ctmp);
5830 else
5831 id2 = (unsigned int) -1;
5832 bss = wpa_bss_get_id_range(wpa_s, id1, id2);
5833 if (id2 == (unsigned int) -1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005834 bsslast = dl_list_last(&wpa_s->bss_id,
5835 struct wpa_bss,
5836 list_id);
5837 else {
5838 bsslast = wpa_bss_get_id(wpa_s, id2);
5839 if (bsslast == NULL && bss && id2 > id1) {
5840 struct wpa_bss *tmp = bss;
5841 for (;;) {
5842 next = tmp->list_id.next;
5843 if (next == &wpa_s->bss_id)
5844 break;
5845 tmp = dl_list_entry(
5846 next, struct wpa_bss,
5847 list_id);
5848 if (tmp->id > id2)
5849 break;
5850 bsslast = tmp;
5851 }
5852 }
5853 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005854 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005855 } else if (os_strncmp(cmd, "FIRST", 5) == 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005856 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005857 else if (os_strncmp(cmd, "LAST", 4) == 0)
5858 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859 else if (os_strncmp(cmd, "ID-", 3) == 0) {
5860 i = atoi(cmd + 3);
5861 bss = wpa_bss_get_id(wpa_s, i);
5862 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5863 i = atoi(cmd + 5);
5864 bss = wpa_bss_get_id(wpa_s, i);
5865 if (bss) {
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005866 next = bss->list_id.next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867 if (next == &wpa_s->bss_id)
5868 bss = NULL;
5869 else
5870 bss = dl_list_entry(next, struct wpa_bss,
5871 list_id);
5872 }
Dmitry Shmidt29333592017-01-09 12:27:11 -08005873 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
5874 bss = wpa_s->current_bss;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005875#ifdef CONFIG_P2P
5876 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
5877 if (hwaddr_aton(cmd + 13, bssid) == 0)
5878 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
5879 else
5880 bss = NULL;
5881#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005882 } else if (hwaddr_aton(cmd, bssid) == 0)
5883 bss = wpa_bss_get_bssid(wpa_s, bssid);
5884 else {
5885 struct wpa_bss *tmp;
5886 i = atoi(cmd);
5887 bss = NULL;
5888 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
5889 {
Hai Shalom021b0b52019-04-10 11:17:58 -07005890 if (i == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005891 bss = tmp;
5892 break;
5893 }
Hai Shalom021b0b52019-04-10 11:17:58 -07005894 i--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005895 }
5896 }
5897
Dmitry Shmidt04949592012-07-19 12:16:46 -07005898 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
5899 mask = strtoul(ctmp + 5, NULL, 0x10);
5900 if (mask == 0)
5901 mask = WPA_BSS_MASK_ALL;
5902 }
5903
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005904 if (bss == NULL)
5905 return 0;
5906
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005907 if (bsslast == NULL)
5908 bsslast = bss;
5909 do {
5910 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
5911 ret += len;
5912 buf += len;
5913 buflen -= len;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005914 if (bss == bsslast) {
5915 if ((mask & WPA_BSS_MASK_DELIM) && len &&
5916 (bss == dl_list_last(&wpa_s->bss_id,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005917 struct wpa_bss, list_id))) {
5918 int res;
5919
5920 res = os_snprintf(buf - 5, end - buf + 5,
5921 "####\n");
5922 if (os_snprintf_error(end - buf + 5, res)) {
5923 wpa_printf(MSG_DEBUG,
5924 "Could not add end delim");
5925 }
5926 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005927 break;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005928 }
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005929 next = bss->list_id.next;
5930 if (next == &wpa_s->bss_id)
5931 break;
5932 bss = dl_list_entry(next, struct wpa_bss, list_id);
5933 } while (bss && len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005934
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07005935 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005936}
5937
5938
5939static int wpa_supplicant_ctrl_iface_ap_scan(
5940 struct wpa_supplicant *wpa_s, char *cmd)
5941{
5942 int ap_scan = atoi(cmd);
5943 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
5944}
5945
5946
5947static int wpa_supplicant_ctrl_iface_scan_interval(
5948 struct wpa_supplicant *wpa_s, char *cmd)
5949{
5950 int scan_int = atoi(cmd);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005951 return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005952}
5953
5954
5955static int wpa_supplicant_ctrl_iface_bss_expire_age(
5956 struct wpa_supplicant *wpa_s, char *cmd)
5957{
5958 int expire_age = atoi(cmd);
5959 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
5960}
5961
5962
5963static int wpa_supplicant_ctrl_iface_bss_expire_count(
5964 struct wpa_supplicant *wpa_s, char *cmd)
5965{
5966 int expire_count = atoi(cmd);
5967 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
5968}
5969
5970
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005971static void wpa_supplicant_ctrl_iface_bss_flush(
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005972 struct wpa_supplicant *wpa_s, char *cmd)
5973{
5974 int flush_age = atoi(cmd);
5975
5976 if (flush_age == 0)
5977 wpa_bss_flush(wpa_s);
5978 else
5979 wpa_bss_flush_by_age(wpa_s, flush_age);
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07005980}
5981
5982
Dmitry Shmidt21de2142014-04-08 10:50:52 -07005983#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005984static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
5985{
5986 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
5987 /* MLME-DELETEKEYS.request */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005988 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005989 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005990 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005991 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005992 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005993 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005994 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005995 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005996 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005997 0, KEY_FLAG_GROUP);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005998 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07005999 0, KEY_FLAG_GROUP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006000
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006001 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0,
6002 NULL, 0, KEY_FLAG_PAIRWISE);
Hai Shalomfdcde762020-04-02 11:19:20 -07006003 if (wpa_sm_ext_key_id(wpa_s->wpa))
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006004 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07006005 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006006 /* MLME-SETPROTECTION.request(None) */
6007 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
6008 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
6009 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
6010 wpa_sm_drop_sa(wpa_s->wpa);
6011}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07006012#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006013
6014
6015static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
6016 char *addr)
6017{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006018#ifdef CONFIG_NO_SCAN_PROCESSING
6019 return -1;
6020#else /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006021 u8 bssid[ETH_ALEN];
6022 struct wpa_bss *bss;
6023 struct wpa_ssid *ssid = wpa_s->current_ssid;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006024 struct wpa_radio_work *already_connecting;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006025
6026 if (hwaddr_aton(addr, bssid)) {
6027 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
6028 "address '%s'", addr);
6029 return -1;
6030 }
6031
6032 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
6033
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006034 if (!ssid) {
6035 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
6036 "configuration known for the target AP");
6037 return -1;
6038 }
6039
Sunil Ravic0f5d412024-09-11 22:12:49 +00006040 bss = wpa_bss_get_connection(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006041 if (!bss) {
6042 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
6043 "from BSS table");
6044 return -1;
6045 }
6046
6047 /*
6048 * TODO: Find best network configuration block from configuration to
6049 * allow roaming to other networks
6050 */
6051
Hai Shaloma20dcd72022-02-04 13:43:00 -08006052 already_connecting = radio_work_pending(wpa_s, "sme-connect");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006053 wpa_s->reassociate = 1;
6054 wpa_supplicant_connect(wpa_s, bss, ssid);
6055
Hai Shaloma20dcd72022-02-04 13:43:00 -08006056 /*
6057 * Indicate that an explicitly requested roam is in progress so scan
6058 * results that come in before the 'sme-connect' radio work gets
6059 * executed do not override the original connection attempt.
6060 */
6061 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
6062 wpa_s->roam_in_progress = true;
6063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006064 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006065#endif /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006066}
6067
6068
6069#ifdef CONFIG_P2P
6070static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
6071{
6072 unsigned int timeout = atoi(cmd);
6073 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006074 u8 dev_id[ETH_ALEN], *_dev_id = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006075 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006076 char *pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006077 unsigned int search_delay;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006078 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006079 u8 seek_count = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006080 int freq = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006081 bool include_6ghz = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006082
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006083 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6084 wpa_dbg(wpa_s, MSG_INFO,
6085 "Reject P2P_FIND since interface is disabled");
6086 return -1;
6087 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08006088
6089 if (os_strstr(cmd, " include_6ghz"))
6090 include_6ghz = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006091 if (os_strstr(cmd, "type=social"))
6092 type = P2P_FIND_ONLY_SOCIAL;
6093 else if (os_strstr(cmd, "type=progressive"))
6094 type = P2P_FIND_PROGRESSIVE;
6095
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006096 pos = os_strstr(cmd, "dev_id=");
6097 if (pos) {
6098 pos += 7;
6099 if (hwaddr_aton(pos, dev_id))
6100 return -1;
6101 _dev_id = dev_id;
6102 }
6103
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006104 pos = os_strstr(cmd, "dev_type=");
6105 if (pos) {
6106 pos += 9;
6107 if (wps_dev_type_str2bin(pos, dev_type) < 0)
6108 return -1;
6109 _dev_type = dev_type;
6110 }
6111
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006112 pos = os_strstr(cmd, "delay=");
6113 if (pos) {
6114 pos += 6;
6115 search_delay = atoi(pos);
6116 } else
6117 search_delay = wpas_p2p_search_delay(wpa_s);
6118
Dmitry Shmidt41712582015-06-29 11:02:15 -07006119 pos = os_strstr(cmd, "freq=");
6120 if (pos) {
6121 pos += 5;
6122 freq = atoi(pos);
6123 if (freq <= 0)
6124 return -1;
6125 }
6126
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006127 /* Must be searched for last, because it adds nul termination */
6128 pos = os_strstr(cmd, " seek=");
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006129 if (pos)
6130 pos += 6;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006131 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
6132 char *term;
6133
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006134 _seek[seek_count++] = pos;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006135 seek = _seek;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006136 term = os_strchr(pos, ' ');
6137 if (!term)
6138 break;
6139 *term = '\0';
6140 pos = os_strstr(term + 1, "seek=");
6141 if (pos)
6142 pos += 5;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006143 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006144 if (seek_count > P2P_MAX_QUERY_HASH) {
6145 seek[0] = NULL;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006146 seek_count = 1;
6147 }
6148
Dmitry Shmidt344abd32014-01-14 13:17:00 -08006149 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
Hai Shaloma20dcd72022-02-04 13:43:00 -08006150 _dev_id, search_delay, seek_count, seek, freq,
6151 include_6ghz);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006152}
6153
6154
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006155static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
6156{
6157 const char *last = NULL;
6158 const char *token;
6159 long int token_len;
6160 unsigned int i;
6161
6162 /* Expected predefined CPT names delimited by ':' */
6163 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
6164 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
6165 wpa_printf(MSG_ERROR,
6166 "P2PS: CPT name list is too long, expected up to %d names",
6167 P2PS_FEATURE_CAPAB_CPT_MAX);
6168 cpt[0] = 0;
6169 return -1;
6170 }
6171
6172 token_len = last - token;
6173
6174 if (token_len == 3 &&
6175 os_memcmp(token, "UDP", token_len) == 0) {
6176 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6177 } else if (token_len == 3 &&
6178 os_memcmp(token, "MAC", token_len) == 0) {
6179 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
6180 } else {
6181 wpa_printf(MSG_ERROR,
6182 "P2PS: Unsupported CPT name '%s'", token);
6183 cpt[0] = 0;
6184 return -1;
6185 }
6186
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006187 if (isblank((unsigned char) *last)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006188 i++;
6189 break;
6190 }
6191 }
6192 cpt[i] = 0;
6193 return 0;
6194}
6195
6196
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006197static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
6198{
6199 struct p2ps_provision *p2ps_prov;
6200 char *pos;
6201 size_t info_len = 0;
6202 char *info = NULL;
6203 u8 role = P2PS_SETUP_NONE;
6204 long long unsigned val;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006205 int i;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006206
6207 pos = os_strstr(cmd, "info=");
6208 if (pos) {
6209 pos += 5;
6210 info_len = os_strlen(pos);
6211
6212 if (info_len) {
6213 info = os_malloc(info_len + 1);
6214 if (info) {
6215 info_len = utf8_unescape(pos, info_len,
6216 info, info_len + 1);
6217 } else
6218 info_len = 0;
6219 }
6220 }
6221
6222 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
6223 if (p2ps_prov == NULL) {
6224 os_free(info);
6225 return NULL;
6226 }
6227
6228 if (info) {
6229 os_memcpy(p2ps_prov->info, info, info_len);
6230 p2ps_prov->info[info_len] = '\0';
6231 os_free(info);
6232 }
6233
6234 pos = os_strstr(cmd, "status=");
6235 if (pos)
6236 p2ps_prov->status = atoi(pos + 7);
6237 else
6238 p2ps_prov->status = -1;
6239
6240 pos = os_strstr(cmd, "adv_id=");
6241 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
6242 goto invalid_args;
6243 p2ps_prov->adv_id = val;
6244
6245 pos = os_strstr(cmd, "method=");
6246 if (pos)
6247 p2ps_prov->method = strtol(pos + 7, NULL, 16);
6248 else
6249 p2ps_prov->method = 0;
6250
6251 pos = os_strstr(cmd, "session=");
6252 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
6253 goto invalid_args;
6254 p2ps_prov->session_id = val;
6255
6256 pos = os_strstr(cmd, "adv_mac=");
6257 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
6258 goto invalid_args;
6259
6260 pos = os_strstr(cmd, "session_mac=");
6261 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
6262 goto invalid_args;
6263
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006264 pos = os_strstr(cmd, "cpt=");
6265 if (pos) {
6266 if (p2ps_ctrl_parse_cpt_priority(pos + 4,
6267 p2ps_prov->cpt_priority))
6268 goto invalid_args;
6269 } else {
6270 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6271 }
6272
6273 for (i = 0; p2ps_prov->cpt_priority[i]; i++)
6274 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
6275
Hai Shaloma20dcd72022-02-04 13:43:00 -08006276 /* force conncap with tstCap (no validity checks) */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006277 pos = os_strstr(cmd, "tstCap=");
6278 if (pos) {
6279 role = strtol(pos + 7, NULL, 16);
6280 } else {
6281 pos = os_strstr(cmd, "role=");
6282 if (pos) {
6283 role = strtol(pos + 5, NULL, 16);
6284 if (role != P2PS_SETUP_CLIENT &&
6285 role != P2PS_SETUP_GROUP_OWNER)
6286 role = P2PS_SETUP_NONE;
6287 }
6288 }
6289 p2ps_prov->role = role;
6290
6291 return p2ps_prov;
6292
6293invalid_args:
6294 os_free(p2ps_prov);
6295 return NULL;
6296}
6297
6298
6299static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
6300{
6301 u8 addr[ETH_ALEN];
6302 struct p2ps_provision *p2ps_prov;
6303 char *pos;
6304
6305 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
6306
6307 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6308
6309 if (hwaddr_aton(cmd, addr))
6310 return -1;
6311
6312 pos = cmd + 17;
6313 if (*pos != ' ')
6314 return -1;
6315
6316 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6317 if (!p2ps_prov)
6318 return -1;
6319
6320 if (p2ps_prov->status < 0) {
6321 os_free(p2ps_prov);
6322 return -1;
6323 }
6324
6325 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6326 p2ps_prov);
6327}
6328
6329
6330static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
6331{
6332 u8 addr[ETH_ALEN];
6333 struct p2ps_provision *p2ps_prov;
6334 char *pos;
6335
6336 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
6337 * session=<ses_id> mac=<ses_mac> [info=<infodata>]
6338 */
6339
6340 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
6341 if (hwaddr_aton(cmd, addr))
6342 return -1;
6343
6344 pos = cmd + 17;
6345 if (*pos != ' ')
6346 return -1;
6347
6348 p2ps_prov = p2p_parse_asp_provision_cmd(pos);
6349 if (!p2ps_prov)
6350 return -1;
6351
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006352 p2ps_prov->pd_seeker = 1;
6353
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006354 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
6355 p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006356}
6357
6358
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006359static bool bootstrap_pwd_required(u16 bootstrap)
6360{
6361 switch (bootstrap) {
6362 case P2P_PBMA_OPPORTUNISTIC:
6363 return false;
6364 case P2P_PBMA_PIN_CODE_DISPLAY:
6365 case P2P_PBMA_PASSPHRASE_DISPLAY:
6366 case P2P_PBMA_QR_DISPLAY:
6367 case P2P_PBMA_NFC_TAG:
6368 case P2P_PBMA_PIN_CODE_KEYPAD:
6369 case P2P_PBMA_PASSPHRASE_KEYPAD:
6370 case P2P_PBMA_QR_SCAN:
6371 case P2P_PBMA_NFC_READER:
6372 return true;
6373 case P2P_PBMA_SERVICE_MANAGED:
6374 case P2P_PBMA_HANDSHAKE_SKIP:
6375 return false;
6376 }
6377
6378 return false;
6379}
6380
6381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006382static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
6383 char *buf, size_t buflen)
6384{
6385 u8 addr[ETH_ALEN];
6386 char *pos, *pos2;
6387 char *pin = NULL;
6388 enum p2p_wps_method wps_method;
6389 int new_pin;
6390 int ret;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006391 int persistent_group, persistent_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006392 int join;
6393 int auth;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006394 int automatic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006395 int go_intent = -1;
6396 int freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006397 int pd;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006398 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006399 int edmg;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006400 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
6401 size_t group_ssid_len = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08006402 int he;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006403 bool allow_6ghz;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006404 bool p2p2, skip_prov;
Sunil Ravic0f5d412024-09-11 22:12:49 +00006405 u16 bootstrap = 0;
6406 const char *password = NULL;
6407 char *token, *context = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006408
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006409 if (!wpa_s->global->p2p_init_wpa_s)
6410 return -1;
6411 if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
6412 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
6413 wpa_s->global->p2p_init_wpa_s->ifname);
6414 wpa_s = wpa_s->global->p2p_init_wpa_s;
6415 }
6416
Sunil Ravic0f5d412024-09-11 22:12:49 +00006417 /* <addr> <"pbc" | "pin" | "pair" | PIN> [label|display|keypad|p2ps]
Dmitry Shmidt04949592012-07-19 12:16:46 -07006418 * [persistent|persistent=<network id>]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006419 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
Sunil Ravic0f5d412024-09-11 22:12:49 +00006420 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>]
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006421 * [p2p2] [skip_prov] [bstrapmethod=<value>] [password=<string>]
Sunil Ravic0f5d412024-09-11 22:12:49 +00006422 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006423
6424 if (hwaddr_aton(cmd, addr))
6425 return -1;
6426
6427 pos = cmd + 17;
6428 if (*pos != ' ')
6429 return -1;
6430 pos++;
6431
6432 persistent_group = os_strstr(pos, " persistent") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006433 pos2 = os_strstr(pos, " persistent=");
6434 if (pos2) {
6435 struct wpa_ssid *ssid;
6436 persistent_id = atoi(pos2 + 12);
6437 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6438 if (ssid == NULL || ssid->disabled != 2 ||
6439 ssid->mode != WPAS_MODE_P2P_GO) {
6440 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
6441 "SSID id=%d for persistent P2P group (GO)",
6442 persistent_id);
6443 return -1;
6444 }
6445 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006446 join = os_strstr(pos, " join") != NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006447 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006448 auth = os_strstr(pos, " auth") != NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006449 automatic = os_strstr(pos, " auto") != NULL;
6450 pd = os_strstr(pos, " provdisc") != NULL;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006451 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
6452 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
6453 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006454 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006455 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Sunil Ravic0f5d412024-09-11 22:12:49 +00006456 p2p2 = os_strstr(pos, " p2p2") != NULL;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006457 skip_prov = os_strstr(pos, " skip_prov") != NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006458
6459 pos2 = os_strstr(pos, " go_intent=");
6460 if (pos2) {
6461 pos2 += 11;
6462 go_intent = atoi(pos2);
6463 if (go_intent < 0 || go_intent > 15)
6464 return -1;
6465 }
6466
6467 pos2 = os_strstr(pos, " freq=");
6468 if (pos2) {
6469 pos2 += 6;
6470 freq = atoi(pos2);
6471 if (freq <= 0)
6472 return -1;
6473 }
6474
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006475 pos2 = os_strstr(pos, " freq2=");
6476 if (pos2)
6477 freq2 = atoi(pos2 + 7);
6478
6479 pos2 = os_strstr(pos, " max_oper_chwidth=");
6480 if (pos2)
6481 chwidth = atoi(pos2 + 18);
6482
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006483 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006484 if (max_oper_chwidth < 0)
6485 return -1;
6486
Hai Shaloma20dcd72022-02-04 13:43:00 -08006487 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00006488 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08006489
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006490 pos2 = os_strstr(pos, " ssid=");
6491 if (pos2) {
6492 char *end;
6493
6494 pos2 += 6;
6495 end = os_strchr(pos2, ' ');
6496 if (!end)
6497 group_ssid_len = os_strlen(pos2) / 2;
6498 else
6499 group_ssid_len = (end - pos2) / 2;
6500 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
6501 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
6502 return -1;
6503 group_ssid = _group_ssid;
6504 }
6505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006506 if (os_strncmp(pos, "pin", 3) == 0) {
6507 /* Request random PIN (to be displayed) and enable the PIN */
6508 wps_method = WPS_PIN_DISPLAY;
6509 } else if (os_strncmp(pos, "pbc", 3) == 0) {
6510 wps_method = WPS_PBC;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006511 } else if (os_strstr(pos, "p2ps") != NULL) {
6512 wps_method = WPS_P2PS;
Sunil Ravic0f5d412024-09-11 22:12:49 +00006513 } else if (os_strncmp(pos, "pair", 4) == 0 && p2p2) {
6514 wps_method = WPS_NOT_READY;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006515 } else {
6516 pin = pos;
6517 pos = os_strchr(pin, ' ');
6518 wps_method = WPS_PIN_KEYPAD;
6519 if (pos) {
6520 *pos++ = '\0';
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006521 if (os_strncmp(pos, "display", 7) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006522 wps_method = WPS_PIN_DISPLAY;
6523 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006524 if (!wps_pin_str_valid(pin)) {
6525 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
6526 return 17;
6527 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006528 }
6529
Sunil Ravic0f5d412024-09-11 22:12:49 +00006530 pos2 = os_strstr(pos, "bstrapmethod=");
6531 if (pos2) {
6532 pos2 += 13;
6533 bootstrap = atoi(pos2);
6534 pd = true;
6535 }
6536
6537 while ((token = str_token(pos, " ", &context))) {
6538 if (os_strncmp(token, "password=", 9) == 0) {
6539 password = token + 9;
6540 continue;
6541 }
6542 }
6543
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006544 if (bootstrap_pwd_required(bootstrap) && !password) {
6545 wpa_printf(MSG_DEBUG,
6546 "CTRL_IFACE: This P2P2 bootstrap method requires password");
6547 return -1;
6548 }
6549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006550 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
Dmitry Shmidt04949592012-07-19 12:16:46 -07006551 persistent_group, automatic, join,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006552 auth, go_intent, freq, freq2, persistent_id,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006553 pd, ht40, vht, max_oper_chwidth, he, edmg,
Sunil Ravic0f5d412024-09-11 22:12:49 +00006554 group_ssid, group_ssid_len, allow_6ghz, p2p2,
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006555 bootstrap, password, skip_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006556 if (new_pin == -2) {
6557 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
6558 return 25;
6559 }
6560 if (new_pin == -3) {
6561 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
6562 return 25;
6563 }
6564 if (new_pin < 0)
6565 return -1;
6566 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
6567 ret = os_snprintf(buf, buflen, "%08d", new_pin);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006568 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006569 return -1;
6570 return ret;
6571 }
6572
6573 os_memcpy(buf, "OK\n", 3);
6574 return 3;
6575}
6576
6577
6578static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
6579{
6580 unsigned int timeout = atoi(cmd);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006581 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6582 wpa_dbg(wpa_s, MSG_INFO,
6583 "Reject P2P_LISTEN since interface is disabled");
6584 return -1;
6585 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006586 return wpas_p2p_listen(wpa_s, timeout);
6587}
6588
6589
6590static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
6591{
6592 u8 addr[ETH_ALEN];
6593 char *pos;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006594 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006595
Dmitry Shmidt04949592012-07-19 12:16:46 -07006596 /* <addr> <config method> [join|auto] */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006597
6598 if (hwaddr_aton(cmd, addr))
6599 return -1;
6600
6601 pos = cmd + 17;
6602 if (*pos != ' ')
6603 return -1;
6604 pos++;
6605
Dmitry Shmidt04949592012-07-19 12:16:46 -07006606 if (os_strstr(pos, " join") != NULL)
6607 use = WPAS_P2P_PD_FOR_JOIN;
6608 else if (os_strstr(pos, " auto") != NULL)
6609 use = WPAS_P2P_PD_AUTO;
6610
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006611 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006612}
6613
6614
6615static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
6616 size_t buflen)
6617{
6618 struct wpa_ssid *ssid = wpa_s->current_ssid;
6619
6620 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6621 ssid->passphrase == NULL)
6622 return -1;
6623
6624 os_strlcpy(buf, ssid->passphrase, buflen);
6625 return os_strlen(buf);
6626}
6627
6628
6629static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
6630 char *buf, size_t buflen)
6631{
6632 u64 ref;
6633 int res;
6634 u8 dst_buf[ETH_ALEN], *dst;
6635 struct wpabuf *tlvs;
6636 char *pos;
6637 size_t len;
6638
6639 if (hwaddr_aton(cmd, dst_buf))
6640 return -1;
6641 dst = dst_buf;
6642 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
6643 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
6644 dst = NULL;
6645 pos = cmd + 17;
6646 if (*pos != ' ')
6647 return -1;
6648 pos++;
6649
6650 if (os_strncmp(pos, "upnp ", 5) == 0) {
6651 u8 version;
6652 pos += 5;
6653 if (hexstr2bin(pos, &version, 1) < 0)
6654 return -1;
6655 pos += 2;
6656 if (*pos != ' ')
6657 return -1;
6658 pos++;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006659 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006660#ifdef CONFIG_WIFI_DISPLAY
6661 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
6662 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
6663#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006664 } else if (os_strncmp(pos, "asp ", 4) == 0) {
6665 char *svc_str;
6666 char *svc_info = NULL;
6667 u32 id;
6668
6669 pos += 4;
6670 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
6671 return -1;
6672
6673 pos = os_strchr(pos, ' ');
6674 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
6675 return -1;
6676
6677 svc_str = pos + 1;
6678
6679 pos = os_strchr(svc_str, ' ');
6680
6681 if (pos)
6682 *pos++ = '\0';
6683
6684 /* All remaining data is the svc_info string */
6685 if (pos && pos[0] && pos[0] != ' ') {
6686 len = os_strlen(pos);
6687
6688 /* Unescape in place */
6689 len = utf8_unescape(pos, len, pos, len);
6690 if (len > 0xff)
6691 return -1;
6692
6693 svc_info = pos;
6694 }
6695
6696 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
6697 svc_str, svc_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006698 } else {
6699 len = os_strlen(pos);
6700 if (len & 1)
6701 return -1;
6702 len /= 2;
6703 tlvs = wpabuf_alloc(len);
6704 if (tlvs == NULL)
6705 return -1;
6706 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
6707 wpabuf_free(tlvs);
6708 return -1;
6709 }
6710
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006711 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006712 wpabuf_free(tlvs);
6713 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006714 if (ref == 0)
6715 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006716 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006717 if (os_snprintf_error(buflen, res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006718 return -1;
6719 return res;
6720}
6721
6722
6723static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
6724 char *cmd)
6725{
6726 long long unsigned val;
6727 u64 req;
6728 if (sscanf(cmd, "%llx", &val) != 1)
6729 return -1;
6730 req = val;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006731 return wpas_p2p_sd_cancel_request(wpa_s, req);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006732}
6733
6734
6735static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
6736{
6737 int freq;
6738 u8 dst[ETH_ALEN];
6739 u8 dialog_token;
6740 struct wpabuf *resp_tlvs;
6741 char *pos, *pos2;
6742 size_t len;
6743
6744 pos = os_strchr(cmd, ' ');
6745 if (pos == NULL)
6746 return -1;
6747 *pos++ = '\0';
6748 freq = atoi(cmd);
6749 if (freq == 0)
6750 return -1;
6751
6752 if (hwaddr_aton(pos, dst))
6753 return -1;
6754 pos += 17;
6755 if (*pos != ' ')
6756 return -1;
6757 pos++;
6758
6759 pos2 = os_strchr(pos, ' ');
6760 if (pos2 == NULL)
6761 return -1;
6762 *pos2++ = '\0';
6763 dialog_token = atoi(pos);
6764
6765 len = os_strlen(pos2);
6766 if (len & 1)
6767 return -1;
6768 len /= 2;
6769 resp_tlvs = wpabuf_alloc(len);
6770 if (resp_tlvs == NULL)
6771 return -1;
6772 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
6773 wpabuf_free(resp_tlvs);
6774 return -1;
6775 }
6776
6777 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
6778 wpabuf_free(resp_tlvs);
6779 return 0;
6780}
6781
6782
6783static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
6784 char *cmd)
6785{
Dmitry Shmidt04949592012-07-19 12:16:46 -07006786 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
6787 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006788 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
6789 return 0;
6790}
6791
6792
6793static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
6794 char *cmd)
6795{
6796 char *pos;
6797 size_t len;
6798 struct wpabuf *query, *resp;
Sunil Ravi7f769292024-07-23 22:21:32 +00006799 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006800
6801 pos = os_strchr(cmd, ' ');
6802 if (pos == NULL)
6803 return -1;
6804 *pos++ = '\0';
6805
6806 len = os_strlen(cmd);
6807 if (len & 1)
6808 return -1;
6809 len /= 2;
6810 query = wpabuf_alloc(len);
6811 if (query == NULL)
6812 return -1;
Sunil Ravi7f769292024-07-23 22:21:32 +00006813 ret = hexstr2bin(cmd, wpabuf_put(query, len), len);
6814 if (ret < 0)
6815 goto err_query;
6816 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006817 len = os_strlen(pos);
Sunil Ravi7f769292024-07-23 22:21:32 +00006818 if (len & 1)
6819 goto err_query;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006820 len /= 2;
6821 resp = wpabuf_alloc(len);
Sunil Ravi7f769292024-07-23 22:21:32 +00006822 if (!resp)
6823 goto err_query;
6824 ret = hexstr2bin(pos, wpabuf_put(resp, len), len);
6825 if (ret < 0)
6826 goto err_resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006827
Sunil Ravi7f769292024-07-23 22:21:32 +00006828 ret = wpas_p2p_service_add_bonjour(wpa_s, query, resp);
6829
6830err_resp:
6831 wpabuf_free(resp);
6832err_query:
6833 wpabuf_free(query);
6834 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006835}
6836
6837
6838static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
6839{
6840 char *pos;
6841 u8 version;
6842
6843 pos = os_strchr(cmd, ' ');
6844 if (pos == NULL)
6845 return -1;
6846 *pos++ = '\0';
6847
6848 if (hexstr2bin(cmd, &version, 1) < 0)
6849 return -1;
6850
6851 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
6852}
6853
6854
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006855static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
6856 u8 replace, char *cmd)
6857{
6858 char *pos;
6859 char *adv_str;
6860 u32 auto_accept, adv_id, svc_state, config_methods;
6861 char *svc_info = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006862 char *cpt_prio_str;
6863 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006864
6865 pos = os_strchr(cmd, ' ');
6866 if (pos == NULL)
6867 return -1;
6868 *pos++ = '\0';
6869
6870 /* Auto-Accept value is mandatory, and must be one of the
6871 * single values (0, 1, 2, 4) */
6872 auto_accept = atoi(cmd);
6873 switch (auto_accept) {
6874 case P2PS_SETUP_NONE: /* No auto-accept */
6875 case P2PS_SETUP_NEW:
6876 case P2PS_SETUP_CLIENT:
6877 case P2PS_SETUP_GROUP_OWNER:
6878 break;
6879 default:
6880 return -1;
6881 }
6882
6883 /* Advertisement ID is mandatory */
6884 cmd = pos;
6885 pos = os_strchr(cmd, ' ');
6886 if (pos == NULL)
6887 return -1;
6888 *pos++ = '\0';
6889
6890 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
6891 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
6892 return -1;
6893
6894 /* Only allow replacements if exist, and adds if not */
6895 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
6896 if (!replace)
6897 return -1;
6898 } else {
6899 if (replace)
6900 return -1;
6901 }
6902
6903 /* svc_state between 0 - 0xff is mandatory */
6904 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
6905 return -1;
6906
6907 pos = os_strchr(pos, ' ');
6908 if (pos == NULL)
6909 return -1;
6910
6911 /* config_methods is mandatory */
6912 pos++;
6913 if (sscanf(pos, "%x", &config_methods) != 1)
6914 return -1;
6915
6916 if (!(config_methods &
6917 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
6918 return -1;
6919
6920 pos = os_strchr(pos, ' ');
6921 if (pos == NULL)
6922 return -1;
6923
6924 pos++;
6925 adv_str = pos;
6926
6927 /* Advertisement string is mandatory */
6928 if (!pos[0] || pos[0] == ' ')
6929 return -1;
6930
6931 /* Terminate svc string */
6932 pos = os_strchr(pos, ' ');
6933 if (pos != NULL)
6934 *pos++ = '\0';
6935
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006936 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
6937 if (cpt_prio_str) {
6938 pos = os_strchr(pos, ' ');
6939 if (pos != NULL)
6940 *pos++ = '\0';
6941
6942 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
6943 return -1;
6944 } else {
6945 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
6946 cpt_prio[1] = 0;
6947 }
6948
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006949 /* Service and Response Information are optional */
6950 if (pos && pos[0]) {
6951 size_t len;
6952
6953 /* Note the bare ' included, which cannot exist legally
6954 * in unescaped string. */
6955 svc_info = os_strstr(pos, "svc_info='");
6956
6957 if (svc_info) {
6958 svc_info += 9;
6959 len = os_strlen(svc_info);
6960 utf8_unescape(svc_info, len, svc_info, len);
6961 }
6962 }
6963
6964 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
6965 (u8) svc_state, (u16) config_methods,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006966 svc_info, cpt_prio);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006967}
6968
6969
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006970static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
6971{
6972 char *pos;
6973
6974 pos = os_strchr(cmd, ' ');
6975 if (pos == NULL)
6976 return -1;
6977 *pos++ = '\0';
6978
6979 if (os_strcmp(cmd, "bonjour") == 0)
6980 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
6981 if (os_strcmp(cmd, "upnp") == 0)
6982 return p2p_ctrl_service_add_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006983 if (os_strcmp(cmd, "asp") == 0)
6984 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006985 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
6986 return -1;
6987}
6988
6989
6990static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
6991 char *cmd)
6992{
6993 size_t len;
6994 struct wpabuf *query;
6995 int ret;
6996
6997 len = os_strlen(cmd);
6998 if (len & 1)
6999 return -1;
7000 len /= 2;
7001 query = wpabuf_alloc(len);
7002 if (query == NULL)
7003 return -1;
7004 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
7005 wpabuf_free(query);
7006 return -1;
7007 }
7008
7009 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
7010 wpabuf_free(query);
7011 return ret;
7012}
7013
7014
7015static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
7016{
7017 char *pos;
7018 u8 version;
7019
7020 pos = os_strchr(cmd, ' ');
7021 if (pos == NULL)
7022 return -1;
7023 *pos++ = '\0';
7024
7025 if (hexstr2bin(cmd, &version, 1) < 0)
7026 return -1;
7027
7028 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
7029}
7030
7031
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007032static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
7033{
7034 u32 adv_id;
7035
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07007036 if (os_strcmp(cmd, "all") == 0) {
7037 wpas_p2p_service_flush_asp(wpa_s);
7038 return 0;
7039 }
7040
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007041 if (sscanf(cmd, "%x", &adv_id) != 1)
7042 return -1;
7043
7044 return wpas_p2p_service_del_asp(wpa_s, adv_id);
7045}
7046
7047
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007048static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
7049{
7050 char *pos;
7051
7052 pos = os_strchr(cmd, ' ');
7053 if (pos == NULL)
7054 return -1;
7055 *pos++ = '\0';
7056
7057 if (os_strcmp(cmd, "bonjour") == 0)
7058 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
7059 if (os_strcmp(cmd, "upnp") == 0)
7060 return p2p_ctrl_service_del_upnp(wpa_s, pos);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007061 if (os_strcmp(cmd, "asp") == 0)
7062 return p2p_ctrl_service_del_asp(wpa_s, pos);
7063 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7064 return -1;
7065}
7066
7067
7068static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
7069{
7070 char *pos;
7071
7072 pos = os_strchr(cmd, ' ');
7073 if (pos == NULL)
7074 return -1;
7075 *pos++ = '\0';
7076
7077 if (os_strcmp(cmd, "asp") == 0)
7078 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
7079
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007080 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
7081 return -1;
7082}
7083
7084
7085static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
7086{
7087 u8 addr[ETH_ALEN];
7088
7089 /* <addr> */
7090
7091 if (hwaddr_aton(cmd, addr))
7092 return -1;
7093
7094 return wpas_p2p_reject(wpa_s, addr);
7095}
7096
7097
7098static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
7099{
7100 char *pos;
7101 int id;
7102 struct wpa_ssid *ssid;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07007103 u8 *_peer = NULL, peer[ETH_ALEN];
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007104 int freq = 0, pref_freq = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08007105 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007106 int edmg;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007107 bool allow_6ghz;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007108 bool p2p2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007109
7110 id = atoi(cmd);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07007111 pos = os_strstr(cmd, " peer=");
7112 if (pos) {
7113 pos += 6;
7114 if (hwaddr_aton(pos, peer))
7115 return -1;
7116 _peer = peer;
7117 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007118 ssid = wpa_config_get_network(wpa_s->conf, id);
7119 if (ssid == NULL || ssid->disabled != 2) {
7120 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7121 "for persistent P2P group",
7122 id);
7123 return -1;
7124 }
7125
Jouni Malinen31be0a42012-08-31 21:20:51 +03007126 pos = os_strstr(cmd, " freq=");
7127 if (pos) {
7128 pos += 6;
7129 freq = atoi(pos);
7130 if (freq <= 0)
7131 return -1;
7132 }
7133
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007134 pos = os_strstr(cmd, " pref=");
7135 if (pos) {
7136 pos += 6;
7137 pref_freq = atoi(pos);
7138 if (pref_freq <= 0)
7139 return -1;
7140 }
7141
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007142 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
7143 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
7144 vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08007145 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007146 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
Jouni Malinen31be0a42012-08-31 21:20:51 +03007147
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007148 pos = os_strstr(cmd, "freq2=");
7149 if (pos)
7150 freq2 = atoi(pos + 6);
7151
7152 pos = os_strstr(cmd, " max_oper_chwidth=");
7153 if (pos)
7154 chwidth = atoi(pos + 18);
7155
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007156 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007157 if (max_oper_chwidth < 0)
7158 return -1;
7159
Hai Shaloma20dcd72022-02-04 13:43:00 -08007160 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
7161
7162 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00007163 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007164
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007165 p2p2 = os_strstr(cmd, " p2p2") != NULL;
7166
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007167 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
Hai Shaloma20dcd72022-02-04 13:43:00 -08007168 max_oper_chwidth, pref_freq, he, edmg,
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007169 allow_6ghz, p2p2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007170}
7171
7172
7173static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
7174{
7175 char *pos;
7176 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007177 bool allow_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007178
7179 pos = os_strstr(cmd, " peer=");
7180 if (!pos)
7181 return -1;
7182
7183 *pos = '\0';
7184 pos += 6;
7185 if (hwaddr_aton(pos, peer)) {
7186 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
7187 return -1;
7188 }
7189
Hai Shaloma20dcd72022-02-04 13:43:00 -08007190 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
7191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007192 pos = os_strstr(pos, " go_dev_addr=");
7193 if (pos) {
7194 pos += 13;
7195 if (hwaddr_aton(pos, go_dev_addr)) {
7196 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
7197 pos);
7198 return -1;
7199 }
7200 go_dev = go_dev_addr;
7201 }
7202
Hai Shaloma20dcd72022-02-04 13:43:00 -08007203 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007204}
7205
7206
7207static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
7208{
7209 if (os_strncmp(cmd, "persistent=", 11) == 0)
7210 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
7211 if (os_strncmp(cmd, "group=", 6) == 0)
7212 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
7213
7214 return -1;
7215}
7216
7217
7218static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007219 int id, int freq, int vht_center_freq2,
Hai Shalom74f70d42019-02-11 14:42:39 -08007220 int ht40, int vht, int vht_chwidth,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007221 int he, int edmg, bool allow_6ghz,
7222 const u8 *go_bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007223{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007224 struct wpa_ssid *ssid;
7225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007226 ssid = wpa_config_get_network(wpa_s->conf, id);
7227 if (ssid == NULL || ssid->disabled != 2) {
7228 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
7229 "for persistent P2P group",
7230 id);
7231 return -1;
7232 }
7233
Sunil Ravic0f5d412024-09-11 22:12:49 +00007234 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, freq,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007235 vht_center_freq2, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007236 vht_chwidth, he, edmg,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007237 NULL, 0, 0, allow_6ghz, 0,
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007238 go_bssid, NULL, NULL, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007239}
7240
7241
7242static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
7243{
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007244 int freq = 0, persistent = 0, group_id = -1;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007245 bool p2p2 = false;
7246 int p2pmode = WPA_P2P_MODE_WFD_R1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007247 bool allow_6ghz = false;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007248 int vht = wpa_s->conf->p2p_go_vht;
7249 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08007250 int he = wpa_s->conf->p2p_go_he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007251 int edmg = wpa_s->conf->p2p_go_edmg;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007252 int max_oper_chwidth, chwidth = 0, freq2 = 0;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007253 char *token, *context = NULL;
Sunil Raviaf8751c2023-03-29 11:35:17 -07007254 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007255#ifdef CONFIG_ACS
7256 int acs = 0;
7257#endif /* CONFIG_ACS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007258
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007259 while ((token = str_token(cmd, " ", &context))) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07007260 if (sscanf(token, "freq2=%d", &freq2) == 1 ||
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007261 sscanf(token, "persistent=%d", &group_id) == 1 ||
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007262 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1 ||
7263 sscanf(token, "p2pmode=%d", &p2pmode) == 1) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007264 continue;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007265#ifdef CONFIG_ACS
7266 } else if (os_strcmp(token, "freq=acs") == 0) {
7267 acs = 1;
7268#endif /* CONFIG_ACS */
7269 } else if (sscanf(token, "freq=%d", &freq) == 1) {
7270 continue;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007271 } else if (os_strcmp(token, "ht40") == 0) {
7272 ht40 = 1;
7273 } else if (os_strcmp(token, "vht") == 0) {
7274 vht = 1;
7275 ht40 = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08007276 } else if (os_strcmp(token, "he") == 0) {
7277 he = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007278 } else if (os_strcmp(token, "edmg") == 0) {
7279 edmg = 1;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007280 } else if (os_strcmp(token, "persistent") == 0) {
7281 persistent = 1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007282 } else if (os_strcmp(token, "allow_6ghz") == 0) {
7283 allow_6ghz = true;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007284 } else if (os_strcmp(token, "p2p2") == 0) {
7285 p2p2 = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07007286 } else if (os_strncmp(token, "go_bssid=", 9) == 0) {
7287 if (hwaddr_aton(token + 9, go_bssid_buf))
7288 return -1;
7289 go_bssid = go_bssid_buf;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007290 } else {
7291 wpa_printf(MSG_DEBUG,
7292 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
7293 token);
7294 return -1;
7295 }
7296 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007297
Roshan Pius3a1667e2018-07-03 15:17:14 -07007298#ifdef CONFIG_ACS
7299 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
7300 (acs || freq == 2 || freq == 5)) {
7301 if (freq == 2 && wpa_s->best_24_freq <= 0) {
7302 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
7303 wpa_s->p2p_go_do_acs = 1;
7304 freq = 0;
7305 } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
7306 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
7307 wpa_s->p2p_go_do_acs = 1;
7308 freq = 0;
7309 } else {
7310 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
7311 wpa_s->p2p_go_do_acs = 1;
7312 }
Hai Shalom021b0b52019-04-10 11:17:58 -07007313 } else {
7314 wpa_s->p2p_go_do_acs = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007315 }
7316#endif /* CONFIG_ACS */
7317
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007318 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007319 if (max_oper_chwidth < 0)
7320 return -1;
7321
Hai Shaloma20dcd72022-02-04 13:43:00 -08007322 if (allow_6ghz && chwidth == 40)
Sunil8cd6f4d2022-06-28 18:40:46 +00007323 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
Hai Shaloma20dcd72022-02-04 13:43:00 -08007324
7325 /* Allow DFS to be used for Autonomous GO */
7326 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
7327 WPA_DRIVER_FLAGS_DFS_OFFLOAD);
7328
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007329 if (group_id >= 0)
7330 return p2p_ctrl_group_add_persistent(wpa_s, group_id,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007331 freq, freq2, ht40, vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007332 max_oper_chwidth, he,
Sunil Raviaf8751c2023-03-29 11:35:17 -07007333 edmg, allow_6ghz,
7334 go_bssid);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007335
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007336 if (p2pmode < WPA_P2P_MODE_WFD_R1 || p2pmode > WPA_P2P_MODE_WFD_PCC)
7337 return -1;
7338
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007339 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007340 max_oper_chwidth, he, edmg, allow_6ghz, p2p2,
7341 (enum wpa_p2p_mode) p2pmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007342}
7343
7344
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007345static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
7346 char *buf, size_t buflen)
7347{
7348 u8 dev_addr[ETH_ALEN];
7349 struct wpa_ssid *ssid;
7350 int res;
7351 const u8 *iaddr;
7352
7353 ssid = wpa_s->current_ssid;
7354 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
7355 hwaddr_aton(cmd, dev_addr))
7356 return -1;
7357
7358 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
7359 if (!iaddr)
7360 return -1;
7361 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
7362 if (os_snprintf_error(buflen, res))
7363 return -1;
7364 return res;
7365}
7366
7367
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007368static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
7369 const u8 *p2p_dev_addr)
7370{
7371 struct wpa_supplicant *wpa_s;
7372
7373 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7374 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
7375 return 1;
7376 }
7377
7378 return 0;
7379}
7380
7381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007382static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
7383 char *buf, size_t buflen)
7384{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007385 u8 addr[ETH_ALEN], *addr_ptr, group_capab;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007386 int next, res;
7387 const struct p2p_peer_info *info;
7388 char *pos, *end;
7389 char devtype[WPS_DEV_TYPE_BUFSIZE];
7390 struct wpa_ssid *ssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007391 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007392
7393 if (!wpa_s->global->p2p)
7394 return -1;
7395
7396 if (os_strcmp(cmd, "FIRST") == 0) {
7397 addr_ptr = NULL;
7398 next = 0;
7399 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
7400 if (hwaddr_aton(cmd + 5, addr) < 0)
7401 return -1;
7402 addr_ptr = addr;
7403 next = 1;
7404 } else {
7405 if (hwaddr_aton(cmd, addr) < 0)
7406 return -1;
7407 addr_ptr = addr;
7408 next = 0;
7409 }
7410
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007411 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
7412 if (info == NULL)
7413 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007414 group_capab = info->group_capab;
7415
7416 if (group_capab &&
7417 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
7418 wpa_printf(MSG_DEBUG,
7419 "P2P: Could not find any BSS with p2p_dev_addr "
7420 MACSTR ", hence override group_capab from 0x%x to 0",
7421 MAC2STR(info->p2p_device_addr), group_capab);
7422 group_capab = 0;
7423 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007424
7425 pos = buf;
7426 end = buf + buflen;
7427
7428 res = os_snprintf(pos, end - pos, MACSTR "\n"
7429 "pri_dev_type=%s\n"
7430 "device_name=%s\n"
7431 "manufacturer=%s\n"
7432 "model_name=%s\n"
7433 "model_number=%s\n"
7434 "serial_number=%s\n"
7435 "config_methods=0x%x\n"
7436 "dev_capab=0x%x\n"
7437 "group_capab=0x%x\n"
7438 "level=%d\n",
7439 MAC2STR(info->p2p_device_addr),
7440 wps_dev_type_bin2str(info->pri_dev_type,
7441 devtype, sizeof(devtype)),
7442 info->device_name,
7443 info->manufacturer,
7444 info->model_name,
7445 info->model_number,
7446 info->serial_number,
7447 info->config_methods,
7448 info->dev_capab,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007449 group_capab,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007450 info->level);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007451 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007452 return pos - buf;
7453 pos += res;
7454
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007455 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
7456 {
7457 const u8 *t;
7458 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
7459 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
7460 wps_dev_type_bin2str(t, devtype,
7461 sizeof(devtype)));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007462 if (os_snprintf_error(end - pos, res))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007463 return pos - buf;
7464 pos += res;
7465 }
7466
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007467 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007468 if (ssid) {
7469 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007470 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007471 return pos - buf;
7472 pos += res;
7473 }
7474
7475 res = p2p_get_peer_info_txt(info, pos, end - pos);
7476 if (res < 0)
7477 return pos - buf;
7478 pos += res;
7479
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007480 if (info->vendor_elems) {
7481 res = os_snprintf(pos, end - pos, "vendor_elems=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007482 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007483 return pos - buf;
7484 pos += res;
7485
7486 pos += wpa_snprintf_hex(pos, end - pos,
7487 wpabuf_head(info->vendor_elems),
7488 wpabuf_len(info->vendor_elems));
7489
7490 res = os_snprintf(pos, end - pos, "\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007491 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07007492 return pos - buf;
7493 pos += res;
7494 }
7495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007496 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007497}
7498
7499
Dmitry Shmidt04949592012-07-19 12:16:46 -07007500static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
7501 const char *param)
7502{
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007503 unsigned int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007504
7505 if (wpa_s->global->p2p == NULL)
7506 return -1;
7507
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007508 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
7509 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007510
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007511 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
7512 struct wpa_freq_range *freq;
7513 freq = &wpa_s->global->p2p_disallow_freq.range[i];
Dmitry Shmidt04949592012-07-19 12:16:46 -07007514 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007515 freq->min, freq->max);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007516 }
7517
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007518 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007519 return 0;
7520}
7521
7522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007523static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
7524{
7525 char *param;
7526
7527 if (wpa_s->global->p2p == NULL)
7528 return -1;
7529
7530 param = os_strchr(cmd, ' ');
7531 if (param == NULL)
7532 return -1;
7533 *param++ = '\0';
7534
7535 if (os_strcmp(cmd, "discoverability") == 0) {
7536 p2p_set_client_discoverability(wpa_s->global->p2p,
7537 atoi(param));
7538 return 0;
7539 }
7540
7541 if (os_strcmp(cmd, "managed") == 0) {
7542 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
7543 return 0;
7544 }
7545
7546 if (os_strcmp(cmd, "listen_channel") == 0) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08007547 char *pos;
7548 u8 channel, op_class;
7549
7550 channel = atoi(param);
7551 pos = os_strchr(param, ' ');
7552 op_class = pos ? atoi(pos) : 81;
7553
7554 return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
7555 channel, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007556 }
7557
7558 if (os_strcmp(cmd, "ssid_postfix") == 0) {
7559 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
7560 os_strlen(param));
7561 }
7562
7563 if (os_strcmp(cmd, "noa") == 0) {
7564 char *pos;
7565 int count, start, duration;
7566 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
7567 count = atoi(param);
7568 pos = os_strchr(param, ',');
7569 if (pos == NULL)
7570 return -1;
7571 pos++;
7572 start = atoi(pos);
7573 pos = os_strchr(pos, ',');
7574 if (pos == NULL)
7575 return -1;
7576 pos++;
7577 duration = atoi(pos);
7578 if (count < 0 || count > 255 || start < 0 || duration < 0)
7579 return -1;
7580 if (count == 0 && duration > 0)
7581 return -1;
7582 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
7583 "start=%d duration=%d", count, start, duration);
7584 return wpas_p2p_set_noa(wpa_s, count, start, duration);
7585 }
7586
7587 if (os_strcmp(cmd, "ps") == 0)
7588 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
7589
7590 if (os_strcmp(cmd, "oppps") == 0)
7591 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
7592
7593 if (os_strcmp(cmd, "ctwindow") == 0)
7594 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
7595
7596 if (os_strcmp(cmd, "disabled") == 0) {
7597 wpa_s->global->p2p_disabled = atoi(param);
7598 wpa_printf(MSG_DEBUG, "P2P functionality %s",
7599 wpa_s->global->p2p_disabled ?
7600 "disabled" : "enabled");
7601 if (wpa_s->global->p2p_disabled) {
7602 wpas_p2p_stop_find(wpa_s);
7603 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7604 p2p_flush(wpa_s->global->p2p);
7605 }
7606 return 0;
7607 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007608
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007609 if (os_strcmp(cmd, "conc_pref") == 0) {
7610 if (os_strcmp(param, "sta") == 0)
7611 wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
7612 else if (os_strcmp(param, "p2p") == 0)
7613 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007614 else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007615 wpa_printf(MSG_INFO, "Invalid conc_pref value");
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007616 return -1;
7617 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007618 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
Dmitry Shmidt04949592012-07-19 12:16:46 -07007619 "%s", param);
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007620 return 0;
7621 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007623 if (os_strcmp(cmd, "force_long_sd") == 0) {
7624 wpa_s->force_long_sd = atoi(param);
7625 return 0;
7626 }
7627
7628 if (os_strcmp(cmd, "peer_filter") == 0) {
7629 u8 addr[ETH_ALEN];
7630 if (hwaddr_aton(param, addr))
7631 return -1;
7632 p2p_set_peer_filter(wpa_s->global->p2p, addr);
7633 return 0;
7634 }
7635
7636 if (os_strcmp(cmd, "cross_connect") == 0)
7637 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
7638
7639 if (os_strcmp(cmd, "go_apsd") == 0) {
7640 if (os_strcmp(param, "disable") == 0)
7641 wpa_s->set_ap_uapsd = 0;
7642 else {
7643 wpa_s->set_ap_uapsd = 1;
7644 wpa_s->ap_uapsd = atoi(param);
7645 }
7646 return 0;
7647 }
7648
7649 if (os_strcmp(cmd, "client_apsd") == 0) {
7650 if (os_strcmp(param, "disable") == 0)
7651 wpa_s->set_sta_uapsd = 0;
7652 else {
7653 int be, bk, vi, vo;
7654 char *pos;
7655 /* format: BE,BK,VI,VO;max SP Length */
7656 be = atoi(param);
7657 pos = os_strchr(param, ',');
7658 if (pos == NULL)
7659 return -1;
7660 pos++;
7661 bk = atoi(pos);
7662 pos = os_strchr(pos, ',');
7663 if (pos == NULL)
7664 return -1;
7665 pos++;
7666 vi = atoi(pos);
7667 pos = os_strchr(pos, ',');
7668 if (pos == NULL)
7669 return -1;
7670 pos++;
7671 vo = atoi(pos);
7672 /* ignore max SP Length for now */
7673
7674 wpa_s->set_sta_uapsd = 1;
7675 wpa_s->sta_uapsd = 0;
7676 if (be)
7677 wpa_s->sta_uapsd |= BIT(0);
7678 if (bk)
7679 wpa_s->sta_uapsd |= BIT(1);
7680 if (vi)
7681 wpa_s->sta_uapsd |= BIT(2);
7682 if (vo)
7683 wpa_s->sta_uapsd |= BIT(3);
7684 }
7685 return 0;
7686 }
7687
Dmitry Shmidt04949592012-07-19 12:16:46 -07007688 if (os_strcmp(cmd, "disallow_freq") == 0)
7689 return p2p_ctrl_disallow_freq(wpa_s, param);
7690
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007691 if (os_strcmp(cmd, "disc_int") == 0) {
7692 int min_disc_int, max_disc_int, max_disc_tu;
7693 char *pos;
7694
7695 pos = param;
7696
7697 min_disc_int = atoi(pos);
7698 pos = os_strchr(pos, ' ');
7699 if (pos == NULL)
7700 return -1;
7701 *pos++ = '\0';
7702
7703 max_disc_int = atoi(pos);
7704 pos = os_strchr(pos, ' ');
7705 if (pos == NULL)
7706 return -1;
7707 *pos++ = '\0';
7708
7709 max_disc_tu = atoi(pos);
7710
7711 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
7712 max_disc_int, max_disc_tu);
7713 }
7714
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007715 if (os_strcmp(cmd, "per_sta_psk") == 0) {
7716 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
7717 return 0;
7718 }
7719
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007720#ifdef CONFIG_WPS_NFC
7721 if (os_strcmp(cmd, "nfc_tag") == 0)
7722 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
7723#endif /* CONFIG_WPS_NFC */
7724
7725 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
7726 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
7727 return 0;
7728 }
7729
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007730 if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
7731 int op_class, chan;
7732
7733 op_class = atoi(param);
7734 param = os_strchr(param, ':');
7735 if (!param)
7736 return -1;
7737 param++;
7738 chan = atoi(param);
7739 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
7740 chan);
7741 return 0;
7742 }
7743
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007744#ifdef CONFIG_TESTING_OPTIONS
7745 if (os_strcmp(cmd, "pairing_setup") == 0) {
7746 p2p_set_pairing_setup(wpa_s->global->p2p, atoi(param));
7747 return 0;
7748 }
7749
7750 if (os_strcmp(cmd, "pairing_cache") == 0) {
7751 p2p_set_pairing_cache(wpa_s->global->p2p, atoi(param));
7752 return 0;
7753 }
7754
7755 if (os_strcmp(cmd, "supported_bootstrapmethods") == 0) {
7756 p2p_set_bootstrapmethods(wpa_s->global->p2p, atoi(param));
7757 return 0;
7758 }
7759
7760 if (os_strcmp(cmd, "pasn_type") == 0) {
7761 p2p_set_pasn_type(wpa_s->global->p2p, atoi(param));
7762 return 0;
7763 }
7764
7765 if (os_strcmp(cmd, "comeback_after") == 0) {
7766 p2p_set_comeback_after(wpa_s->global->p2p, atoi(param));
7767 return 0;
7768 }
7769
7770 if (os_strcmp(cmd, "reginfo") == 0) {
7771 p2p_set_reg_info(wpa_s->global->p2p, atoi(param));
7772 return 0;
7773 }
7774
7775 if (os_strcmp(cmd, "twt_power_mgmt") == 0) {
7776 p2p_set_twt_power_mgmt(wpa_s->global->p2p, atoi(param));
7777 return 0;
7778 }
7779
7780 if (os_strcmp(cmd, "chan_switch_req_enable") == 0) {
7781 p2p_set_chan_switch_req_enable(wpa_s->global->p2p, atoi(param));
7782 return 0;
7783 }
7784
7785 if (os_strcmp(cmd, "inv_oper_freq") == 0) {
7786 p2p_set_invitation_op_freq(wpa_s->global->p2p, atoi(param));
7787 return 0;
7788 }
7789#endif /* CONFIG_TESTING_OPTIONS */
7790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007791 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
7792 cmd);
7793
7794 return -1;
7795}
7796
7797
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007798static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
7799{
7800 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
7801 wpa_s->force_long_sd = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007802
7803#ifdef CONFIG_TESTING_OPTIONS
7804 os_free(wpa_s->get_pref_freq_list_override);
7805 wpa_s->get_pref_freq_list_override = NULL;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007806 p2p_set_invitation_op_freq(wpa_s->global->p2p, -1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007807#endif /* CONFIG_TESTING_OPTIONS */
7808
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007809 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007810 wpa_s->parent->p2ps_method_config_any = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007811 if (wpa_s->global->p2p)
7812 p2p_flush(wpa_s->global->p2p);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007813
7814 wpa_s->p2p2 = false;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07007815}
7816
7817
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
7819{
7820 char *pos, *pos2;
7821 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
7822
7823 if (cmd[0]) {
7824 pos = os_strchr(cmd, ' ');
7825 if (pos == NULL)
7826 return -1;
7827 *pos++ = '\0';
7828 dur1 = atoi(cmd);
7829
7830 pos2 = os_strchr(pos, ' ');
7831 if (pos2)
7832 *pos2++ = '\0';
7833 int1 = atoi(pos);
7834 } else
7835 pos2 = NULL;
7836
7837 if (pos2) {
7838 pos = os_strchr(pos2, ' ');
7839 if (pos == NULL)
7840 return -1;
7841 *pos++ = '\0';
7842 dur2 = atoi(pos2);
7843 int2 = atoi(pos);
7844 }
7845
7846 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
7847}
7848
7849
7850static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
7851{
7852 char *pos;
7853 unsigned int period = 0, interval = 0;
7854
7855 if (cmd[0]) {
7856 pos = os_strchr(cmd, ' ');
7857 if (pos == NULL)
7858 return -1;
7859 *pos++ = '\0';
7860 period = atoi(cmd);
7861 interval = atoi(pos);
7862 }
7863
7864 return wpas_p2p_ext_listen(wpa_s, period, interval);
7865}
7866
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007867
7868static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
7869{
7870 const char *pos;
7871 u8 peer[ETH_ALEN];
7872 int iface_addr = 0;
7873
7874 pos = cmd;
7875 if (os_strncmp(pos, "iface=", 6) == 0) {
7876 iface_addr = 1;
7877 pos += 6;
7878 }
7879 if (hwaddr_aton(pos, peer))
7880 return -1;
7881
7882 wpas_p2p_remove_client(wpa_s, peer, iface_addr);
7883 return 0;
7884}
7885
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07007886
7887static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
7888{
7889 int freq = 0, period = 0, interval = 0, count = 0;
7890
7891 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
7892 {
7893 wpa_printf(MSG_DEBUG,
7894 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
7895 return -1;
7896 }
7897
7898 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
7899}
7900
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007901
7902#ifdef CONFIG_TESTING_OPTIONS
7903static int p2p_ctrl_pmk_get(struct wpa_supplicant *wpa_s, char *buf,
7904 size_t buflen)
7905{
7906 const u8 *pmk;
7907 size_t pmk_len;
7908
7909 /* Return the PMK from the first identity entry. This assumes test
7910 * cases to remove all indentities at the beginning so that only one
7911 * entry is available. */
7912 if (!wpa_s->conf->identity || !wpa_s->conf->identity->pmk)
7913 return -1;
7914
7915 pmk_len = wpabuf_len(wpa_s->conf->identity->pmk);
7916 pmk = wpabuf_head(wpa_s->conf->identity->pmk);
7917
7918 return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
7919}
7920#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007921#endif /* CONFIG_P2P */
7922
7923
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007924static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
7925{
7926 struct wpa_freq_range_list ranges;
7927 int *freqs = NULL;
7928 struct hostapd_hw_modes *mode;
7929 u16 i;
7930
7931 if (wpa_s->hw.modes == NULL)
7932 return NULL;
7933
7934 os_memset(&ranges, 0, sizeof(ranges));
7935 if (freq_range_list_parse(&ranges, val) < 0)
7936 return NULL;
7937
7938 for (i = 0; i < wpa_s->hw.num_modes; i++) {
7939 int j;
7940
7941 mode = &wpa_s->hw.modes[i];
7942 for (j = 0; j < mode->num_channels; j++) {
7943 unsigned int freq;
7944
7945 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
7946 continue;
7947
7948 freq = mode->channels[j].freq;
7949 if (!freq_range_list_includes(&ranges, freq))
7950 continue;
7951
7952 int_array_add_unique(&freqs, freq);
7953 }
7954 }
7955
7956 os_free(ranges.range);
7957 return freqs;
7958}
7959
7960
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007961#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007962
7963static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
7964{
7965 int auto_sel = 0;
7966 int *freqs = NULL;
7967
7968 if (param) {
7969 char *pos;
7970
7971 auto_sel = os_strstr(param, "auto") != NULL;
7972
7973 pos = os_strstr(param, "freq=");
7974 if (pos) {
7975 freqs = freq_range_to_channel_list(wpa_s, pos + 5);
7976 if (freqs == NULL)
7977 return -1;
7978 }
7979
7980 }
7981
7982 return interworking_select(wpa_s, auto_sel, freqs);
7983}
7984
7985
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007986static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
7987 int only_add)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007988{
7989 u8 bssid[ETH_ALEN];
7990 struct wpa_bss *bss;
7991
7992 if (hwaddr_aton(dst, bssid)) {
7993 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
7994 return -1;
7995 }
7996
Hai Shalomfdcde762020-04-02 11:19:20 -07007997 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007998 if (bss == NULL) {
7999 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
8000 MAC2STR(bssid));
8001 return -1;
8002 }
8003
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008004 if (bss->ssid_len == 0) {
8005 int found = 0;
8006
8007 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
8008 " does not have SSID information", MAC2STR(bssid));
8009
8010 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
8011 list) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008012 if (ether_addr_equal(bss->bssid, bssid) &&
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008013 bss->ssid_len > 0) {
8014 found = 1;
8015 break;
8016 }
8017 }
8018
8019 if (!found)
8020 return -1;
8021 wpa_printf(MSG_DEBUG,
8022 "Found another matching BSS entry with SSID");
8023 }
8024
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008025 return interworking_connect(wpa_s, bss, only_add);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008026}
8027
8028
8029static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
8030{
8031 u8 dst_addr[ETH_ALEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07008032 int used, freq = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008033 char *pos;
8034#define MAX_ANQP_INFO_ID 100
8035 u16 id[MAX_ANQP_INFO_ID];
8036 size_t num_id = 0;
Dmitry Shmidt15907092014-03-25 10:42:57 -07008037 u32 subtypes = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008038 u32 mbo_subtypes = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008039
8040 used = hwaddr_aton2(dst, dst_addr);
8041 if (used < 0)
8042 return -1;
8043 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008044 if (*pos == ' ')
8045 pos++;
Hai Shalom899fcc72020-10-19 14:38:18 -07008046
8047 if (os_strncmp(pos, "freq=", 5) == 0) {
8048 freq = atoi(pos + 5);
8049 pos = os_strchr(pos, ' ');
8050 if (!pos)
8051 return -1;
8052 pos++;
8053 }
8054
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008055 while (num_id < MAX_ANQP_INFO_ID) {
Dmitry Shmidt15907092014-03-25 10:42:57 -07008056 if (os_strncmp(pos, "hs20:", 5) == 0) {
8057#ifdef CONFIG_HS20
8058 int num = atoi(pos + 5);
8059 if (num <= 0 || num > 31)
8060 return -1;
8061 subtypes |= BIT(num);
8062#else /* CONFIG_HS20 */
8063 return -1;
8064#endif /* CONFIG_HS20 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08008065 } else if (os_strncmp(pos, "mbo:", 4) == 0) {
8066#ifdef CONFIG_MBO
8067 int num = atoi(pos + 4);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008068
8069 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08008070 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008071 mbo_subtypes |= BIT(num);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08008072#else /* CONFIG_MBO */
8073 return -1;
8074#endif /* CONFIG_MBO */
Dmitry Shmidt15907092014-03-25 10:42:57 -07008075 } else {
8076 id[num_id] = atoi(pos);
8077 if (id[num_id])
8078 num_id++;
8079 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008080 pos = os_strchr(pos + 1, ',');
8081 if (pos == NULL)
8082 break;
8083 pos++;
8084 }
8085
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008086 if (num_id == 0 && !subtypes && !mbo_subtypes)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008087 return -1;
8088
Hai Shalom899fcc72020-10-19 14:38:18 -07008089 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008090 mbo_subtypes);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008091}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008092
8093
8094static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
8095{
8096 u8 dst_addr[ETH_ALEN];
8097 struct wpabuf *advproto, *query = NULL;
8098 int used, ret = -1;
8099 char *pos, *end;
8100 size_t len;
8101
8102 used = hwaddr_aton2(cmd, dst_addr);
8103 if (used < 0)
8104 return -1;
8105
8106 pos = cmd + used;
8107 while (*pos == ' ')
8108 pos++;
8109
8110 /* Advertisement Protocol ID */
8111 end = os_strchr(pos, ' ');
8112 if (end)
8113 len = end - pos;
8114 else
8115 len = os_strlen(pos);
8116 if (len & 0x01)
8117 return -1;
8118 len /= 2;
8119 if (len == 0)
8120 return -1;
8121 advproto = wpabuf_alloc(len);
8122 if (advproto == NULL)
8123 return -1;
8124 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
8125 goto fail;
8126
8127 if (end) {
8128 /* Optional Query Request */
8129 pos = end + 1;
8130 while (*pos == ' ')
8131 pos++;
8132
8133 len = os_strlen(pos);
8134 if (len) {
8135 if (len & 0x01)
8136 goto fail;
8137 len /= 2;
8138 if (len == 0)
8139 goto fail;
8140 query = wpabuf_alloc(len);
8141 if (query == NULL)
8142 goto fail;
8143 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
8144 goto fail;
8145 }
8146 }
8147
8148 ret = gas_send_request(wpa_s, dst_addr, advproto, query);
8149
8150fail:
8151 wpabuf_free(advproto);
8152 wpabuf_free(query);
8153
8154 return ret;
8155}
8156
8157
8158static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
8159 size_t buflen)
8160{
8161 u8 addr[ETH_ALEN];
8162 int dialog_token;
8163 int used;
8164 char *pos;
8165 size_t resp_len, start, requested_len;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008166 struct wpabuf *resp;
8167 int ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008168
8169 used = hwaddr_aton2(cmd, addr);
8170 if (used < 0)
8171 return -1;
8172
8173 pos = cmd + used;
8174 while (*pos == ' ')
8175 pos++;
8176 dialog_token = atoi(pos);
8177
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008178 if (wpa_s->last_gas_resp &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008179 ether_addr_equal(addr, wpa_s->last_gas_addr) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008180 dialog_token == wpa_s->last_gas_dialog_token)
8181 resp = wpa_s->last_gas_resp;
8182 else if (wpa_s->prev_gas_resp &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00008183 ether_addr_equal(addr, wpa_s->prev_gas_addr) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008184 dialog_token == wpa_s->prev_gas_dialog_token)
8185 resp = wpa_s->prev_gas_resp;
8186 else
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008187 return -1;
8188
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008189 resp_len = wpabuf_len(resp);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008190 start = 0;
8191 requested_len = resp_len;
8192
8193 pos = os_strchr(pos, ' ');
8194 if (pos) {
8195 start = atoi(pos);
8196 if (start > resp_len)
8197 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8198 pos = os_strchr(pos, ',');
8199 if (pos == NULL)
8200 return -1;
8201 pos++;
8202 requested_len = atoi(pos);
8203 if (start + requested_len > resp_len)
8204 return os_snprintf(buf, buflen, "FAIL-Invalid range");
8205 }
8206
8207 if (requested_len * 2 + 1 > buflen)
8208 return os_snprintf(buf, buflen, "FAIL-Too long response");
8209
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008210 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
8211 requested_len);
8212
8213 if (start + requested_len == resp_len) {
8214 /*
8215 * Free memory by dropping the response after it has been
8216 * fetched.
8217 */
8218 if (resp == wpa_s->prev_gas_resp) {
8219 wpabuf_free(wpa_s->prev_gas_resp);
8220 wpa_s->prev_gas_resp = NULL;
8221 } else {
8222 wpabuf_free(wpa_s->last_gas_resp);
8223 wpa_s->last_gas_resp = NULL;
8224 }
8225 }
8226
8227 return ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008228}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008229#endif /* CONFIG_INTERWORKING */
8230
8231
Dmitry Shmidt04949592012-07-19 12:16:46 -07008232#ifdef CONFIG_HS20
8233
8234static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
8235{
8236 u8 dst_addr[ETH_ALEN];
8237 int used;
8238 char *pos;
8239 u32 subtypes = 0;
8240
8241 used = hwaddr_aton2(dst, dst_addr);
8242 if (used < 0)
8243 return -1;
8244 pos = dst + used;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008245 if (*pos == ' ')
8246 pos++;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008247 for (;;) {
8248 int num = atoi(pos);
8249 if (num <= 0 || num > 31)
8250 return -1;
8251 subtypes |= BIT(num);
8252 pos = os_strchr(pos + 1, ',');
8253 if (pos == NULL)
8254 break;
8255 pos++;
8256 }
8257
8258 if (subtypes == 0)
8259 return -1;
8260
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008261 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008262}
8263
8264
8265static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8266 const u8 *addr, const char *realm)
8267{
8268 u8 *buf;
8269 size_t rlen, len;
8270 int ret;
8271
8272 rlen = os_strlen(realm);
8273 len = 3 + rlen;
8274 buf = os_malloc(len);
8275 if (buf == NULL)
8276 return -1;
8277 buf[0] = 1; /* NAI Home Realm Count */
8278 buf[1] = 0; /* Formatted in accordance with RFC 4282 */
8279 buf[2] = rlen;
8280 os_memcpy(buf + 3, realm, rlen);
8281
8282 ret = hs20_anqp_send_req(wpa_s, addr,
8283 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008284 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008285
8286 os_free(buf);
8287
8288 return ret;
8289}
8290
8291
8292static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
8293 char *dst)
8294{
8295 struct wpa_cred *cred = wpa_s->conf->cred;
8296 u8 dst_addr[ETH_ALEN];
8297 int used;
8298 u8 *buf;
8299 size_t len;
8300 int ret;
8301
8302 used = hwaddr_aton2(dst, dst_addr);
8303 if (used < 0)
8304 return -1;
8305
8306 while (dst[used] == ' ')
8307 used++;
8308 if (os_strncmp(dst + used, "realm=", 6) == 0)
8309 return hs20_nai_home_realm_list(wpa_s, dst_addr,
8310 dst + used + 6);
8311
8312 len = os_strlen(dst + used);
8313
8314 if (len == 0 && cred && cred->realm)
8315 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
8316
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07008317 if (len & 1)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008318 return -1;
8319 len /= 2;
8320 buf = os_malloc(len);
8321 if (buf == NULL)
8322 return -1;
8323 if (hexstr2bin(dst + used, buf, len) < 0) {
8324 os_free(buf);
8325 return -1;
8326 }
8327
8328 ret = hs20_anqp_send_req(wpa_s, dst_addr,
8329 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008330 buf, len, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008331 os_free(buf);
8332
8333 return ret;
8334}
8335
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008336
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008337static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
8338 int buflen)
8339{
8340 u8 dst_addr[ETH_ALEN];
8341 int used;
8342 char *ctx = NULL, *icon, *poffset, *psize;
8343
8344 used = hwaddr_aton2(cmd, dst_addr);
8345 if (used < 0)
8346 return -1;
8347 cmd += used;
8348
8349 icon = str_token(cmd, " ", &ctx);
8350 poffset = str_token(cmd, " ", &ctx);
8351 psize = str_token(cmd, " ", &ctx);
8352 if (!icon || !poffset || !psize)
8353 return -1;
8354
8355 wpa_s->fetch_osu_icon_in_progress = 0;
8356 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
8357 reply, buflen);
8358}
8359
8360
8361static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
8362{
8363 u8 dst_addr[ETH_ALEN];
8364 int used;
8365 char *icon;
8366
8367 if (!cmd[0])
8368 return hs20_del_icon(wpa_s, NULL, NULL);
8369
8370 used = hwaddr_aton2(cmd, dst_addr);
8371 if (used < 0)
8372 return -1;
8373
8374 while (cmd[used] == ' ')
8375 used++;
8376 icon = cmd[used] ? &cmd[used] : NULL;
8377
8378 return hs20_del_icon(wpa_s, dst_addr, icon);
8379}
8380
8381
8382static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008383{
8384 u8 dst_addr[ETH_ALEN];
8385 int used;
8386 char *icon;
8387
8388 used = hwaddr_aton2(cmd, dst_addr);
8389 if (used < 0)
8390 return -1;
8391
8392 while (cmd[used] == ' ')
8393 used++;
8394 icon = &cmd[used];
8395
8396 wpa_s->fetch_osu_icon_in_progress = 0;
8397 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008398 (u8 *) icon, os_strlen(icon), inmem);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008399}
8400
Dmitry Shmidt04949592012-07-19 12:16:46 -07008401#endif /* CONFIG_HS20 */
8402
8403
Dmitry Shmidt04949592012-07-19 12:16:46 -07008404#ifdef CONFIG_AUTOSCAN
8405
8406static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
8407 char *cmd)
8408{
8409 enum wpa_states state = wpa_s->wpa_state;
8410 char *new_params = NULL;
8411
8412 if (os_strlen(cmd) > 0) {
8413 new_params = os_strdup(cmd);
8414 if (new_params == NULL)
8415 return -1;
8416 }
8417
8418 os_free(wpa_s->conf->autoscan);
8419 wpa_s->conf->autoscan = new_params;
8420
8421 if (wpa_s->conf->autoscan == NULL)
8422 autoscan_deinit(wpa_s);
8423 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
8424 autoscan_init(wpa_s, 1);
8425 else if (state == WPA_SCANNING)
8426 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08008427 else
8428 wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
8429 wpa_supplicant_state_txt(state));
Dmitry Shmidt04949592012-07-19 12:16:46 -07008430
8431 return 0;
8432}
8433
8434#endif /* CONFIG_AUTOSCAN */
8435
8436
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008437#ifdef CONFIG_WNM
8438
8439static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
8440{
8441 int enter;
8442 int intval = 0;
8443 char *pos;
8444 int ret;
8445 struct wpabuf *tfs_req = NULL;
8446
8447 if (os_strncmp(cmd, "enter", 5) == 0)
8448 enter = 1;
8449 else if (os_strncmp(cmd, "exit", 4) == 0)
8450 enter = 0;
8451 else
8452 return -1;
8453
8454 pos = os_strstr(cmd, " interval=");
8455 if (pos)
8456 intval = atoi(pos + 10);
8457
8458 pos = os_strstr(cmd, " tfs_req=");
8459 if (pos) {
8460 char *end;
8461 size_t len;
8462 pos += 9;
8463 end = os_strchr(pos, ' ');
8464 if (end)
8465 len = end - pos;
8466 else
8467 len = os_strlen(pos);
8468 if (len & 1)
8469 return -1;
8470 len /= 2;
8471 tfs_req = wpabuf_alloc(len);
8472 if (tfs_req == NULL)
8473 return -1;
8474 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
8475 wpabuf_free(tfs_req);
8476 return -1;
8477 }
8478 }
8479
8480 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
8481 WNM_SLEEP_MODE_EXIT, intval,
8482 tfs_req);
8483 wpabuf_free(tfs_req);
8484
8485 return ret;
8486}
8487
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008488
8489static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
8490{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008491 int query_reason, list = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008492 char *btm_candidates = NULL;
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008493
8494 query_reason = atoi(cmd);
8495
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008496 cmd = os_strchr(cmd, ' ');
8497 if (cmd) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008498 if (os_strncmp(cmd, " list", 5) == 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008499 list = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008500 else
8501 btm_candidates = cmd;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008502 }
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008503
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008504 wpa_printf(MSG_DEBUG,
8505 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
8506 query_reason, list ? " candidate list" : "");
8507
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008508 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
8509 btm_candidates,
8510 list);
Dmitry Shmidt44c95782013-05-17 09:51:35 -07008511}
8512
Hai Shalom39ba6fc2019-01-22 12:40:38 -08008513
8514static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
8515 char *cmd)
8516{
8517 struct wpabuf *elems;
8518 int ret;
8519
8520 elems = wpabuf_parse_bin(cmd);
8521 if (!elems)
8522 return -1;
8523
8524 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
8525 wpabuf_free(elems);
8526 return ret;
8527}
8528
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008529#endif /* CONFIG_WNM */
8530
8531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008532static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
8533 size_t buflen)
8534{
8535 struct wpa_signal_info si;
8536 int ret;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008537 char *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008538
8539 ret = wpa_drv_signal_poll(wpa_s, &si);
8540 if (ret)
8541 return -1;
8542
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008543 pos = buf;
8544 end = buf + buflen;
8545
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008546 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008547 "NOISE=%d\nFREQUENCY=%u\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008548 si.data.signal, si.data.current_tx_rate / 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008549 si.current_noise, si.frequency);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008550 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008551 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008552 pos += ret;
8553
8554 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
8555 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008556 channel_width_to_string(si.chanwidth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008557 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008558 return -1;
8559 pos += ret;
8560 }
8561
Roshan Pius3a1667e2018-07-03 15:17:14 -07008562 if (si.center_frq1 > 0) {
8563 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
8564 si.center_frq1);
8565 if (os_snprintf_error(end - pos, ret))
8566 return -1;
8567 pos += ret;
8568 }
8569
8570 if (si.center_frq2 > 0) {
8571 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
8572 si.center_frq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008573 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008574 return -1;
8575 pos += ret;
8576 }
8577
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008578 if (si.data.avg_signal) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008579 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008580 "AVG_RSSI=%d\n", si.data.avg_signal);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008581 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008582 return -1;
8583 pos += ret;
8584 }
8585
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008586 if (si.data.avg_beacon_signal) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07008587 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00008588 "AVG_BEACON_RSSI=%d\n",
8589 si.data.avg_beacon_signal);
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07008590 if (os_snprintf_error(end - pos, ret))
8591 return -1;
8592 pos += ret;
8593 }
8594
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008595 return pos - buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008596}
8597
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008598
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08008599static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
8600 const char *cmd)
8601{
8602 const char *pos;
8603 int threshold = 0;
8604 int hysteresis = 0;
8605
8606 if (wpa_s->bgscan && wpa_s->bgscan_priv) {
8607 wpa_printf(MSG_DEBUG,
8608 "Reject SIGNAL_MONITOR command - bgscan is active");
8609 return -1;
8610 }
8611 pos = os_strstr(cmd, "THRESHOLD=");
8612 if (pos)
8613 threshold = atoi(pos + 10);
8614 pos = os_strstr(cmd, "HYSTERESIS=");
8615 if (pos)
8616 hysteresis = atoi(pos + 11);
8617 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
8618}
8619
8620
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008621#ifdef CONFIG_TESTING_OPTIONS
8622int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
8623 enum wpa_driver_if_type if_type,
8624 unsigned int *num,
Sunil8cd6f4d2022-06-28 18:40:46 +00008625 struct weighted_pcl *freq_list)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008626{
8627 char *pos = wpa_s->get_pref_freq_list_override;
8628 char *end;
8629 unsigned int count = 0;
8630
8631 /* Override string format:
8632 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
8633
8634 while (pos) {
8635 if (atoi(pos) == (int) if_type)
8636 break;
8637 pos = os_strchr(pos, ' ');
8638 if (pos)
8639 pos++;
8640 }
8641 if (!pos)
8642 return -1;
8643 pos = os_strchr(pos, ':');
8644 if (!pos)
8645 return -1;
8646 pos++;
8647 end = os_strchr(pos, ' ');
8648 while (pos && (!end || pos < end) && count < *num) {
Sunil8cd6f4d2022-06-28 18:40:46 +00008649 freq_list[count].freq = atoi(pos);
8650 freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008651 pos = os_strchr(pos, ',');
8652 if (pos)
8653 pos++;
8654 }
8655
8656 *num = count;
8657 return 0;
8658}
8659#endif /* CONFIG_TESTING_OPTIONS */
8660
8661
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008662static int wpas_ctrl_iface_get_pref_freq_list(
8663 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
8664{
Sunil8cd6f4d2022-06-28 18:40:46 +00008665 unsigned int num = 100, i;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008666 int ret;
8667 enum wpa_driver_if_type iface_type;
8668 char *pos, *end;
Sunil8cd6f4d2022-06-28 18:40:46 +00008669 struct weighted_pcl freq_list[100];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008670
8671 pos = buf;
8672 end = buf + buflen;
8673
8674 /* buf: "<interface_type>" */
8675 if (os_strcmp(cmd, "STATION") == 0)
8676 iface_type = WPA_IF_STATION;
8677 else if (os_strcmp(cmd, "AP") == 0)
8678 iface_type = WPA_IF_AP_BSS;
8679 else if (os_strcmp(cmd, "P2P_GO") == 0)
8680 iface_type = WPA_IF_P2P_GO;
8681 else if (os_strcmp(cmd, "P2P_CLIENT") == 0)
8682 iface_type = WPA_IF_P2P_CLIENT;
8683 else if (os_strcmp(cmd, "IBSS") == 0)
8684 iface_type = WPA_IF_IBSS;
8685 else if (os_strcmp(cmd, "TDLS") == 0)
8686 iface_type = WPA_IF_TDLS;
8687 else
8688 return -1;
8689
8690 wpa_printf(MSG_DEBUG,
8691 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
Hai Shalom5f92bc92019-04-18 11:54:11 -07008692 iface_type, cmd);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008693
8694 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
8695 if (ret)
8696 return -1;
8697
8698 for (i = 0; i < num; i++) {
8699 ret = os_snprintf(pos, end - pos, "%s%u",
Sunil8cd6f4d2022-06-28 18:40:46 +00008700 i > 0 ? "," : "", freq_list[i].freq);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008701 if (os_snprintf_error(end - pos, ret))
8702 return -1;
8703 pos += ret;
8704 }
8705
8706 return pos - buf;
8707}
8708
8709
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07008710static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
8711 char *buf, size_t buflen)
8712{
8713 int ret, i;
8714 char *pos, *end;
8715
8716 ret = os_snprintf(buf, buflen, "%016llX:\n",
8717 (long long unsigned) wpa_s->drv_flags);
8718 if (os_snprintf_error(buflen, ret))
8719 return -1;
8720
8721 pos = buf + ret;
8722 end = buf + buflen;
8723
8724 for (i = 0; i < 64; i++) {
8725 if (wpa_s->drv_flags & (1LLU << i)) {
8726 ret = os_snprintf(pos, end - pos, "%s\n",
8727 driver_flag_to_string(1LLU << i));
8728 if (os_snprintf_error(end - pos, ret))
8729 return -1;
8730 pos += ret;
8731 }
8732 }
8733
8734 return pos - buf;
8735}
8736
8737
Hai Shalomb755a2a2020-04-23 21:49:02 -07008738static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s,
8739 char *buf, size_t buflen)
8740{
8741 int ret, i;
8742 char *pos, *end;
8743
8744 ret = os_snprintf(buf, buflen, "%016llX:\n",
8745 (long long unsigned) wpa_s->drv_flags2);
8746 if (os_snprintf_error(buflen, ret))
8747 return -1;
8748
8749 pos = buf + ret;
8750 end = buf + buflen;
8751
8752 for (i = 0; i < 64; i++) {
8753 if (wpa_s->drv_flags2 & (1LLU << i)) {
8754 ret = os_snprintf(pos, end - pos, "%s\n",
8755 driver_flag2_to_string(1LLU << i));
8756 if (os_snprintf_error(end - pos, ret))
8757 return -1;
8758 pos += ret;
8759 }
8760 }
8761
8762 return pos - buf;
8763}
8764
8765
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008766static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
8767 size_t buflen)
8768{
8769 struct hostap_sta_driver_data sta;
8770 int ret;
8771
8772 ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
8773 if (ret)
8774 return -1;
8775
8776 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008777 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008778 if (os_snprintf_error(buflen, ret))
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07008779 return -1;
8780 return ret;
8781}
8782
8783
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008784#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008785static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8786 char *buf, size_t buflen)
8787{
8788 int ret;
8789
8790 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
Matthew Wang64297252024-12-02 14:03:31 +00008791#ifdef CONFIG_P2P
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008792 if (ret == 0) {
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00008793#ifdef CONFIG_P2P
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008794 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
8795 struct p2p_data *p2p = wpa_s->global->p2p;
8796 if (p2p) {
8797 char country[3];
8798 country[0] = cmd[8];
8799 country[1] = cmd[9];
8800 country[2] = 0x04;
8801 p2p_set_country(p2p, country);
8802 }
8803 }
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00008804#endif /* CONFIG_P2P */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008805 ret = os_snprintf(buf, buflen, "%s\n", "OK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008806 if (os_snprintf_error(buflen, ret))
8807 ret = -1;
Dmitry Shmidt9432e122013-09-12 12:39:30 -07008808 }
Matthew Wang64297252024-12-02 14:03:31 +00008809#endif /* CONFIG_P2P */
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008810 return ret;
8811}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008812#endif /* ANDROID */
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07008813
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07008814
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008815static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
8816 char *buf, size_t buflen)
8817{
8818 int ret;
Hai Shalom60840252021-02-19 19:02:11 -08008819 char *pos, *temp = NULL;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008820 u8 *data = NULL;
8821 unsigned int vendor_id, subcmd;
Hai Shalom60840252021-02-19 19:02:11 -08008822 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008823 struct wpabuf *reply;
8824 size_t data_len = 0;
8825
Hai Shalom60840252021-02-19 19:02:11 -08008826 /**
8827 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
8828 * [nested=<0|1>]
8829 */
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008830 vendor_id = strtoul(cmd, &pos, 16);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008831 if (!isblank((unsigned char) *pos))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008832 return -EINVAL;
8833
8834 subcmd = strtoul(pos, &pos, 10);
8835
8836 if (*pos != '\0') {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008837 if (!isblank((unsigned char) *pos++))
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008838 return -EINVAL;
Hai Shalom60840252021-02-19 19:02:11 -08008839
8840 temp = os_strchr(pos, ' ');
8841 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008842 }
8843
8844 if (data_len) {
8845 data_len /= 2;
8846 data = os_malloc(data_len);
8847 if (!data)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008848 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008849
8850 if (hexstr2bin(pos, data, data_len)) {
8851 wpa_printf(MSG_DEBUG,
8852 "Vendor command: wrong parameter format");
8853 os_free(data);
8854 return -EINVAL;
8855 }
8856 }
8857
Hai Shalom60840252021-02-19 19:02:11 -08008858 pos = os_strstr(cmd, "nested=");
8859 if (pos)
8860 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
8861 NESTED_ATTR_NOT_USED;
8862
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008863 reply = wpabuf_alloc((buflen - 1) / 2);
8864 if (!reply) {
8865 os_free(data);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008866 return -1;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008867 }
8868
8869 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
Hai Shalom60840252021-02-19 19:02:11 -08008870 nested_attr_flag, reply);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008871
8872 if (ret == 0)
8873 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
8874 wpabuf_len(reply));
8875
8876 wpabuf_free(reply);
8877 os_free(data);
8878
8879 return ret;
8880}
8881
8882
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008883static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
8884{
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008885#ifdef CONFIG_P2P
8886 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
8887 wpa_s->global->p2p_init_wpa_s : wpa_s;
8888#endif /* CONFIG_P2P */
8889
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008890 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
8891
Dmitry Shmidt29333592017-01-09 12:27:11 -08008892 if (wpas_abort_ongoing_scan(wpa_s) == 0)
8893 wpa_s->ignore_post_flush_scan_res = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008894
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008895 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
8896 /*
8897 * Avoid possible auto connect re-connection on getting
8898 * disconnected due to state flush.
8899 */
8900 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
8901 }
8902
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008903#ifdef CONFIG_P2P
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008904 wpas_p2p_group_remove(p2p_wpa_s, "*");
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008905 wpas_p2p_cancel(p2p_wpa_s);
8906 p2p_ctrl_flush(p2p_wpa_s);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008907 wpas_p2p_service_flush(p2p_wpa_s);
8908 p2p_wpa_s->global->p2p_disabled = 0;
8909 p2p_wpa_s->global->p2p_per_sta_psk = 0;
8910 p2p_wpa_s->conf->num_sec_device_types = 0;
8911 p2p_wpa_s->p2p_disable_ip_addr_req = 0;
8912 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
8913 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008914 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08008915 p2p_wpa_s->global->pending_p2ps_group = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008916 p2p_wpa_s->global->pending_p2ps_group_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008917#endif /* CONFIG_P2P */
8918
8919#ifdef CONFIG_WPS_TESTING
8920 wps_version_number = 0x20;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008921 wps_testing_stub_cred = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08008922 wps_corrupt_pkhash = 0;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08008923 wps_force_auth_types_in_use = 0;
8924 wps_force_encr_types_in_use = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008925#endif /* CONFIG_WPS_TESTING */
8926#ifdef CONFIG_WPS
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008927 wpa_s->wps_fragment_size = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008928 wpas_wps_cancel(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008929 wps_registrar_flush(wpa_s->wps->registrar);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008930#endif /* CONFIG_WPS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07008931 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008932 wpa_s->known_wps_freq = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008933
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008934#ifdef CONFIG_DPP
8935 wpas_dpp_deinit(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07008936 wpa_s->dpp_init_max_tries = 0;
8937 wpa_s->dpp_init_retry_time = 0;
8938 wpa_s->dpp_resp_wait_time = 0;
8939 wpa_s->dpp_resp_max_tries = 0;
8940 wpa_s->dpp_resp_retry_time = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008941#ifdef CONFIG_DPP2
8942 wpas_dpp_chirp_stop(wpa_s);
8943 wpa_s->dpp_pfs_fallback = 0;
8944#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008945#ifdef CONFIG_DPP3
8946 {
8947 int i;
8948
8949 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
8950 struct dpp_pb_info *info;
8951
8952 info = &wpa_s->dpp_pb[i];
8953 info->rx_time.sec = 0;
8954 info->rx_time.usec = 0;
8955 }
8956 }
8957#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008958#ifdef CONFIG_TESTING_OPTIONS
8959 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
8960 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
8961 dpp_pkex_ephemeral_key_override_len = 0;
8962 dpp_protocol_key_override_len = 0;
8963 dpp_nonce_override_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08008964#ifdef CONFIG_DPP3
8965 dpp_version_override = 3;
8966#elif defined(CONFIG_DPP2)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07008967 dpp_version_override = 2;
8968#else /* CONFIG_DPP2 */
8969 dpp_version_override = 1;
8970#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07008971#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008972#endif /* CONFIG_DPP */
8973
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008974#ifdef CONFIG_TDLS
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008975#ifdef CONFIG_TDLS_TESTING
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008976 tdls_testing = 0;
8977#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008978 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
8979 wpa_tdls_enable(wpa_s->wpa, 1);
8980#endif /* CONFIG_TDLS */
8981
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008982 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
8983 wpa_supplicant_stop_countermeasures(wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07008984 wpa_s->last_michael_mic_error.sec = 0;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008985
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008986 wpa_s->no_keep_alive = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008987 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07008988 wpa_s->own_reconnect_req = 0;
8989 wpa_s->deny_ptk0_rekey = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008990
8991 os_free(wpa_s->disallow_aps_bssid);
8992 wpa_s->disallow_aps_bssid = NULL;
8993 wpa_s->disallow_aps_bssid_count = 0;
8994 os_free(wpa_s->disallow_aps_ssid);
8995 wpa_s->disallow_aps_ssid = NULL;
8996 wpa_s->disallow_aps_ssid_count = 0;
8997
8998 wpa_s->set_sta_uapsd = 0;
8999 wpa_s->sta_uapsd = 0;
9000
Hai Shalom899fcc72020-10-19 14:38:18 -07009001 wpa_s->consecutive_conn_failures = 0;
9002
Dmitry Shmidt444d5672013-04-01 13:08:44 -07009003 wpa_drv_radio_disable(wpa_s, 0);
Hai Shalom60840252021-02-19 19:02:11 -08009004 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07009005 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
9006 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
Dmitry Shmidt344abd32014-01-14 13:17:00 -08009007 wpa_config_flush_blobs(wpa_s->conf);
Dmitry Shmidt18463232014-01-24 12:29:41 -08009008 wpa_s->conf->auto_interworking = 0;
9009 wpa_s->conf->okc = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009010
Hai Shalom60840252021-02-19 19:02:11 -08009011 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009012 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
9013 rsn_preauth_deinit(wpa_s->wpa);
9014
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009015 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
9016 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
9017 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
Hai Shalome21d4e82020-04-29 16:34:06 -07009018 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009019
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08009020 radio_remove_works(wpa_s, NULL, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009021 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009022
9023 wpa_s->next_ssid = NULL;
9024
Sunil Ravi99c035e2024-07-12 01:42:03 +00009025 wnm_btm_reset(wpa_s);
9026
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009027#ifdef CONFIG_INTERWORKING
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009028#ifdef CONFIG_HS20
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009029 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08009030 hs20_del_icon(wpa_s, NULL, NULL);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009031#endif /* CONFIG_HS20 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08009032#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt818ea482014-03-10 13:15:21 -07009033
9034 wpa_s->ext_mgmt_frame_handling = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009035 wpa_s->ext_eapol_frame_io = 0;
9036#ifdef CONFIG_TESTING_OPTIONS
9037 wpa_s->extra_roc_dur = 0;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009038 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08009039 wpa_s->p2p_go_csa_on_inv = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07009040 wpa_s->ignore_auth_resp = 0;
9041 wpa_s->ignore_assoc_disallow = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07009042 wpa_s->disable_sa_query = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009043 wpa_s->testing_resend_assoc = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009044 wpa_s->ignore_sae_h2e_only = 0;
Hai Shalomb755a2a2020-04-23 21:49:02 -07009045 wpa_s->ft_rsnxe_used = 0;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07009046 wpa_s->reject_btm_req_reason = 0;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08009047 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009048 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
9049 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00009050 wpa_sm_set_test_rsnxe_data(wpa_s->wpa, NULL, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009051 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
9052 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009053 os_free(wpa_s->get_pref_freq_list_override);
9054 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009055 wpabuf_free(wpa_s->sae_commit_override);
9056 wpa_s->sae_commit_override = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009057 os_free(wpa_s->extra_sae_rejected_groups);
9058 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07009059 wpabuf_free(wpa_s->rsne_override_eapol);
9060 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009061 wpabuf_free(wpa_s->rsnxe_override_assoc);
9062 wpa_s->rsnxe_override_assoc = NULL;
9063 wpabuf_free(wpa_s->rsnxe_override_eapol);
9064 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07009065 wpas_clear_driver_signal_override(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009066#ifndef CONFIG_NO_ROBUST_AV
Hai Shaloma20dcd72022-02-04 13:43:00 -08009067 wpa_s->disable_scs_support = 0;
9068 wpa_s->disable_mscs_support = 0;
9069 wpa_s->enable_dscp_policy_capa = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009070#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07009071 wpa_s->oci_freq_override_eapol = 0;
9072 wpa_s->oci_freq_override_saquery_req = 0;
9073 wpa_s->oci_freq_override_saquery_resp = 0;
9074 wpa_s->oci_freq_override_eapol_g2 = 0;
9075 wpa_s->oci_freq_override_ft_assoc = 0;
9076 wpa_s->oci_freq_override_fils_assoc = 0;
9077 wpa_s->oci_freq_override_wnm_sleep = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07009078 wpa_s->disable_eapol_g2_tx = 0;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00009079 wpa_s->eapol_2_key_info_set_mask = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009080 wpa_s->test_assoc_comeback_type = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07009081#ifdef CONFIG_DPP
9082 os_free(wpa_s->dpp_config_obj_override);
9083 wpa_s->dpp_config_obj_override = NULL;
9084 os_free(wpa_s->dpp_discovery_override);
9085 wpa_s->dpp_discovery_override = NULL;
9086 os_free(wpa_s->dpp_groups_override);
9087 wpa_s->dpp_groups_override = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00009088 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
9089 wpa_s->dpp_discard_public_action = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07009090 dpp_test = DPP_TEST_DISABLED;
9091#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009092#endif /* CONFIG_TESTING_OPTIONS */
9093
9094 wpa_s->disconnected = 0;
9095 os_free(wpa_s->next_scan_freqs);
9096 wpa_s->next_scan_freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07009097 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
9098 wpa_s->next_scan_bssid_wildcard_ssid = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009099 os_free(wpa_s->select_network_scan_freqs);
9100 wpa_s->select_network_scan_freqs = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009101#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07009102 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009103#endif /* CONFIG_NO_ROBUST_AV */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009104
9105 wpa_bss_flush(wpa_s);
9106 if (!dl_list_empty(&wpa_s->bss)) {
9107 wpa_printf(MSG_DEBUG,
9108 "BSS table not empty after flush: %u entries, current_bss=%p bssid="
9109 MACSTR " pending_bssid=" MACSTR,
9110 dl_list_len(&wpa_s->bss), wpa_s->current_bss,
9111 MAC2STR(wpa_s->bssid),
9112 MAC2STR(wpa_s->pending_bssid));
9113 }
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07009114
9115 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Dmitry Shmidtb70d0bb2015-11-16 10:43:06 -08009116 wpa_s->wnmsleep_used = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07009117
9118#ifdef CONFIG_SME
9119 wpa_s->sme.last_unprot_disconnect.sec = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07009120 wpa_s->sme.auth_alg = 0;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07009121#endif /* CONFIG_SME */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009122
9123 wpabuf_free(wpa_s->ric_ies);
9124 wpa_s->ric_ies = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08009125
9126 wpa_supplicant_update_channel_list(wpa_s, NULL);
9127
9128 free_bss_tmp_disallowed(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07009129
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009130#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07009131 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009132#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom60840252021-02-19 19:02:11 -08009133
9134#ifdef CONFIG_PASN
9135 wpas_pasn_auth_stop(wpa_s);
9136#endif /* CONFIG_PASN */
9137
9138 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
9139 wpas_restore_permanent_mac_addr(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07009140
9141 wpa_s->conf->ignore_old_scan_res = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00009142
9143#ifdef CONFIG_NAN_USD
9144 wpas_nan_usd_flush(wpa_s);
9145#endif /* CONFIG_NAN_USD */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009146}
9147
9148
9149static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
9150 char *buf, size_t buflen)
9151{
9152 struct wpa_radio_work *work;
9153 char *pos, *end;
9154 struct os_reltime now, diff;
9155
9156 pos = buf;
9157 end = buf + buflen;
9158
9159 os_get_reltime(&now);
9160
9161 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9162 {
9163 int ret;
9164
9165 os_reltime_sub(&now, &work->time, &diff);
9166 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
9167 work->type, work->wpa_s->ifname, work->freq,
9168 work->started, diff.sec, diff.usec);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009169 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009170 break;
9171 pos += ret;
9172 }
9173
9174 return pos - buf;
9175}
9176
9177
9178static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
9179{
9180 struct wpa_radio_work *work = eloop_ctx;
9181 struct wpa_external_work *ework = work->ctx;
9182
9183 wpa_dbg(work->wpa_s, MSG_DEBUG,
9184 "Timing out external radio work %u (%s)",
9185 ework->id, work->type);
9186 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009187 work->wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009188 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07009189 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009190}
9191
9192
9193static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
9194{
9195 struct wpa_external_work *ework = work->ctx;
9196
9197 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08009198 if (work->started)
9199 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9200 work, NULL);
9201
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009202 /*
9203 * work->type points to a buffer in ework, so need to replace
9204 * that here with a fixed string to avoid use of freed memory
9205 * in debug prints.
9206 */
9207 work->type = "freed-ext-work";
9208 work->ctx = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009209 os_free(ework);
9210 return;
9211 }
9212
9213 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
9214 ework->id, ework->type);
9215 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009216 work->wpa_s->ext_work_in_progress = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009217 if (!ework->timeout)
9218 ework->timeout = 10;
9219 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
9220 work, NULL);
9221}
9222
9223
9224static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
9225 char *buf, size_t buflen)
9226{
9227 struct wpa_external_work *ework;
9228 char *pos, *pos2;
9229 size_t type_len;
9230 int ret;
9231 unsigned int freq = 0;
9232
9233 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
9234
9235 ework = os_zalloc(sizeof(*ework));
9236 if (ework == NULL)
9237 return -1;
9238
9239 pos = os_strchr(cmd, ' ');
9240 if (pos) {
9241 type_len = pos - cmd;
9242 pos++;
9243
9244 pos2 = os_strstr(pos, "freq=");
9245 if (pos2)
9246 freq = atoi(pos2 + 5);
9247
9248 pos2 = os_strstr(pos, "timeout=");
9249 if (pos2)
9250 ework->timeout = atoi(pos2 + 8);
9251 } else {
9252 type_len = os_strlen(cmd);
9253 }
9254 if (4 + type_len >= sizeof(ework->type))
9255 type_len = sizeof(ework->type) - 4 - 1;
9256 os_strlcpy(ework->type, "ext:", sizeof(ework->type));
9257 os_memcpy(ework->type + 4, cmd, type_len);
9258 ework->type[4 + type_len] = '\0';
9259
9260 wpa_s->ext_work_id++;
9261 if (wpa_s->ext_work_id == 0)
9262 wpa_s->ext_work_id++;
9263 ework->id = wpa_s->ext_work_id;
9264
9265 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
9266 ework) < 0) {
9267 os_free(ework);
9268 return -1;
9269 }
9270
9271 ret = os_snprintf(buf, buflen, "%u", ework->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009272 if (os_snprintf_error(buflen, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009273 return -1;
9274 return ret;
9275}
9276
9277
9278static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
9279{
9280 struct wpa_radio_work *work;
9281 unsigned int id = atoi(cmd);
9282
9283 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
9284 {
9285 struct wpa_external_work *ework;
9286
9287 if (os_strncmp(work->type, "ext:", 4) != 0)
9288 continue;
9289 ework = work->ctx;
9290 if (id && ework->id != id)
9291 continue;
9292 wpa_dbg(wpa_s, MSG_DEBUG,
9293 "Completed external radio work %u (%s)",
9294 ework->id, ework->type);
9295 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009296 wpa_s->ext_work_in_progress = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009297 radio_work_done(work);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07009298 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009299 return 3; /* "OK\n" */
9300 }
9301
9302 return -1;
9303}
9304
9305
9306static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
9307 char *buf, size_t buflen)
9308{
9309 if (os_strcmp(cmd, "show") == 0)
9310 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
9311 if (os_strncmp(cmd, "add ", 4) == 0)
9312 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
9313 if (os_strncmp(cmd, "done ", 5) == 0)
9314 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
9315 return -1;
9316}
9317
9318
9319void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
9320{
9321 struct wpa_radio_work *work, *tmp;
9322
Dmitry Shmidt18463232014-01-24 12:29:41 -08009323 if (!wpa_s || !wpa_s->radio)
9324 return;
9325
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009326 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
9327 struct wpa_radio_work, list) {
9328 struct wpa_external_work *ework;
9329
9330 if (os_strncmp(work->type, "ext:", 4) != 0)
9331 continue;
9332 ework = work->ctx;
9333 wpa_dbg(wpa_s, MSG_DEBUG,
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07009334 "Flushing%s external radio work %u (%s)",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009335 work->started ? " started" : "", ework->id,
9336 ework->type);
9337 if (work->started)
9338 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
9339 work, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009340 radio_work_done(work);
Dmitry Shmidt71757432014-06-02 13:50:35 -07009341 os_free(ework);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009342 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07009343}
9344
9345
Dmitry Shmidt051af732013-10-22 13:52:46 -07009346static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
9347{
9348 struct wpa_supplicant *wpa_s = eloop_ctx;
9349 eapol_sm_notify_ctrl_response(wpa_s->eapol);
9350}
9351
9352
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009353static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
9354 unsigned int *scan_id_count, int scan_id[])
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009355{
9356 const char *pos = value;
9357
9358 while (pos) {
9359 if (*pos == ' ' || *pos == '\0')
9360 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009361 if (*scan_id_count == MAX_SCAN_ID)
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009362 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009363 scan_id[(*scan_id_count)++] = atoi(pos);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009364 pos = os_strchr(pos, ',');
9365 if (pos)
9366 pos++;
9367 }
9368
9369 return 0;
9370}
9371
9372
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009373static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
9374 char *reply, int reply_size, int *reply_len)
9375{
9376 char *pos;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009377 unsigned int manual_scan_passive = 0;
9378 unsigned int manual_scan_use_id = 0;
9379 unsigned int manual_scan_only_new = 0;
9380 unsigned int scan_only = 0;
9381 unsigned int scan_id_count = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00009382 unsigned int manual_non_coloc_6ghz = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009383 int scan_id[MAX_SCAN_ID];
9384 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
9385 struct wpa_scan_results *scan_res);
9386 int *manual_scan_freqs = NULL;
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009387 struct wpa_ssid_value *ssid = NULL, *ns;
9388 unsigned int ssid_count = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009389
9390 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
9391 *reply_len = -1;
9392 return;
9393 }
9394
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009395 if (radio_work_pending(wpa_s, "scan")) {
9396 wpa_printf(MSG_DEBUG,
9397 "Pending scan scheduled - reject new request");
9398 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9399 return;
9400 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009401
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07009402#ifdef CONFIG_INTERWORKING
9403 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
9404 wpa_printf(MSG_DEBUG,
9405 "Interworking select in progress - reject new scan");
9406 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9407 return;
9408 }
9409#endif /* CONFIG_INTERWORKING */
9410
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009411 if (params) {
9412 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009413 scan_only = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009414
9415 pos = os_strstr(params, "freq=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009416 if (pos) {
9417 manual_scan_freqs = freq_range_to_channel_list(wpa_s,
9418 pos + 5);
9419 if (manual_scan_freqs == NULL) {
9420 *reply_len = -1;
9421 goto done;
9422 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009423 }
9424
9425 pos = os_strstr(params, "passive=");
9426 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009427 manual_scan_passive = !!atoi(pos + 8);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009428
9429 pos = os_strstr(params, "use_id=");
9430 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009431 manual_scan_use_id = atoi(pos + 7);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009432
9433 pos = os_strstr(params, "only_new=1");
9434 if (pos)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009435 manual_scan_only_new = 1;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009436
9437 pos = os_strstr(params, "scan_id=");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009438 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
9439 scan_id) < 0) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009440 *reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009441 goto done;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07009442 }
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009443
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009444 pos = os_strstr(params, "bssid=");
9445 if (pos) {
9446 u8 bssid[ETH_ALEN];
9447
9448 pos += 6;
9449 if (hwaddr_aton(pos, bssid)) {
9450 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
9451 *reply_len = -1;
9452 goto done;
9453 }
9454 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07009455
9456 wpa_s->next_scan_bssid_wildcard_ssid =
9457 os_strstr(params, "wildcard_ssid=1") != NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009458 }
9459
Sunil8cd6f4d2022-06-28 18:40:46 +00009460 pos = os_strstr(params, "non_coloc_6ghz=");
9461 if (pos)
9462 manual_non_coloc_6ghz = !!atoi(pos + 15);
9463
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009464 pos = params;
9465 while (pos && *pos != '\0') {
9466 if (os_strncmp(pos, "ssid ", 5) == 0) {
9467 char *end;
9468
9469 pos += 5;
9470 end = pos;
9471 while (*end) {
9472 if (*end == '\0' || *end == ' ')
9473 break;
9474 end++;
9475 }
9476
9477 ns = os_realloc_array(
9478 ssid, ssid_count + 1,
9479 sizeof(struct wpa_ssid_value));
9480 if (ns == NULL) {
9481 *reply_len = -1;
9482 goto done;
9483 }
9484 ssid = ns;
9485
9486 if ((end - pos) & 0x01 ||
9487 end - pos > 2 * SSID_MAX_LEN ||
9488 hexstr2bin(pos, ssid[ssid_count].ssid,
9489 (end - pos) / 2) < 0) {
9490 wpa_printf(MSG_DEBUG,
9491 "Invalid SSID value '%s'",
9492 pos);
9493 *reply_len = -1;
9494 goto done;
9495 }
9496 ssid[ssid_count].ssid_len = (end - pos) / 2;
9497 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID",
9498 ssid[ssid_count].ssid,
9499 ssid[ssid_count].ssid_len);
9500 ssid_count++;
9501 pos = end;
9502 }
9503
9504 pos = os_strchr(pos, ' ');
9505 if (pos)
9506 pos++;
9507 }
9508 }
9509
9510 wpa_s->num_ssids_from_scan_req = ssid_count;
9511 os_free(wpa_s->ssids_from_scan_req);
9512 if (ssid_count) {
9513 wpa_s->ssids_from_scan_req = ssid;
9514 ssid = NULL;
9515 } else {
9516 wpa_s->ssids_from_scan_req = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009517 }
9518
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009519 if (scan_only)
9520 scan_res_handler = scan_only_handler;
9521 else if (wpa_s->scan_res_handler == scan_only_handler)
9522 scan_res_handler = NULL;
9523 else
9524 scan_res_handler = wpa_s->scan_res_handler;
9525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009526 if (!wpa_s->sched_scanning && !wpa_s->scanning &&
9527 ((wpa_s->wpa_state <= WPA_SCANNING) ||
9528 (wpa_s->wpa_state == WPA_COMPLETED))) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009529 wpa_s->manual_scan_passive = manual_scan_passive;
9530 wpa_s->manual_scan_use_id = manual_scan_use_id;
9531 wpa_s->manual_scan_only_new = manual_scan_only_new;
9532 wpa_s->scan_id_count = scan_id_count;
Sunil8cd6f4d2022-06-28 18:40:46 +00009533 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009534 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9535 wpa_s->scan_res_handler = scan_res_handler;
9536 os_free(wpa_s->manual_scan_freqs);
9537 wpa_s->manual_scan_freqs = manual_scan_freqs;
9538 manual_scan_freqs = NULL;
9539
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009540 wpa_s->normal_scans = 0;
9541 wpa_s->scan_req = MANUAL_SCAN_REQ;
9542 wpa_s->after_wps = 0;
9543 wpa_s->known_wps_freq = 0;
9544 wpa_supplicant_req_scan(wpa_s, 0, 0);
9545 if (wpa_s->manual_scan_use_id) {
9546 wpa_s->manual_scan_id++;
9547 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9548 wpa_s->manual_scan_id);
9549 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9550 wpa_s->manual_scan_id);
9551 }
9552 } else if (wpa_s->sched_scanning) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009553 wpa_s->manual_scan_passive = manual_scan_passive;
9554 wpa_s->manual_scan_use_id = manual_scan_use_id;
9555 wpa_s->manual_scan_only_new = manual_scan_only_new;
9556 wpa_s->scan_id_count = scan_id_count;
Sunil8cd6f4d2022-06-28 18:40:46 +00009557 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009558 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
9559 wpa_s->scan_res_handler = scan_res_handler;
9560 os_free(wpa_s->manual_scan_freqs);
9561 wpa_s->manual_scan_freqs = manual_scan_freqs;
9562 manual_scan_freqs = NULL;
9563
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009564 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
9565 wpa_supplicant_cancel_sched_scan(wpa_s);
9566 wpa_s->scan_req = MANUAL_SCAN_REQ;
9567 wpa_supplicant_req_scan(wpa_s, 0, 0);
9568 if (wpa_s->manual_scan_use_id) {
9569 wpa_s->manual_scan_id++;
9570 *reply_len = os_snprintf(reply, reply_size, "%u\n",
9571 wpa_s->manual_scan_id);
9572 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
9573 wpa_s->manual_scan_id);
9574 }
9575 } else {
9576 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
9577 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
9578 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009579
9580done:
9581 os_free(manual_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07009582 os_free(ssid);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009583}
9584
9585
Dmitry Shmidt818ea482014-03-10 13:15:21 -07009586#ifdef CONFIG_TESTING_OPTIONS
9587
9588static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
9589 unsigned int freq, const u8 *dst,
9590 const u8 *src, const u8 *bssid,
9591 const u8 *data, size_t data_len,
9592 enum offchannel_send_action_result
9593 result)
9594{
9595 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
9596 " src=" MACSTR " bssid=" MACSTR " result=%s",
9597 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
9598 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
9599 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
9600 "NO_ACK" : "FAILED"));
9601}
9602
9603
9604static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
9605{
9606 char *pos, *param;
9607 size_t len;
9608 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
9609 int res, used;
9610 int freq = 0, no_cck = 0, wait_time = 0;
9611
9612 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
9613 * <action=Action frame payload> */
9614
9615 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
9616
9617 pos = cmd;
9618 used = hwaddr_aton2(pos, da);
9619 if (used < 0)
9620 return -1;
9621 pos += used;
9622 while (*pos == ' ')
9623 pos++;
9624 used = hwaddr_aton2(pos, bssid);
9625 if (used < 0)
9626 return -1;
9627 pos += used;
9628
9629 param = os_strstr(pos, " freq=");
9630 if (param) {
9631 param += 6;
9632 freq = atoi(param);
9633 }
9634
9635 param = os_strstr(pos, " no_cck=");
9636 if (param) {
9637 param += 8;
9638 no_cck = atoi(param);
9639 }
9640
9641 param = os_strstr(pos, " wait_time=");
9642 if (param) {
9643 param += 11;
9644 wait_time = atoi(param);
9645 }
9646
9647 param = os_strstr(pos, " action=");
9648 if (param == NULL)
9649 return -1;
9650 param += 8;
9651
9652 len = os_strlen(param);
9653 if (len & 1)
9654 return -1;
9655 len /= 2;
9656
9657 buf = os_malloc(len);
9658 if (buf == NULL)
9659 return -1;
9660
9661 if (hexstr2bin(param, buf, len) < 0) {
9662 os_free(buf);
9663 return -1;
9664 }
9665
9666 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
9667 buf, len, wait_time,
9668 wpas_ctrl_iface_mgmt_tx_cb, no_cck);
9669 os_free(buf);
9670 return res;
9671}
9672
9673
9674static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
9675{
9676 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
9677 offchannel_send_action_done(wpa_s);
9678}
9679
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009680
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009681static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
9682 char *cmd)
9683{
9684 char *pos, *param;
9685 size_t len;
9686 u8 *buf;
9687 int freq = 0, datarate = 0, ssi_signal = 0;
9688 union wpa_event_data event;
9689
9690 if (!wpa_s->ext_mgmt_frame_handling)
9691 return -1;
9692
9693 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
9694
9695 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
9696
9697 pos = cmd;
9698 param = os_strstr(pos, "freq=");
9699 if (param) {
9700 param += 5;
9701 freq = atoi(param);
9702 }
9703
9704 param = os_strstr(pos, " datarate=");
9705 if (param) {
9706 param += 10;
9707 datarate = atoi(param);
9708 }
9709
9710 param = os_strstr(pos, " ssi_signal=");
9711 if (param) {
9712 param += 12;
9713 ssi_signal = atoi(param);
9714 }
9715
9716 param = os_strstr(pos, " frame=");
9717 if (param == NULL)
9718 return -1;
9719 param += 7;
9720
9721 len = os_strlen(param);
9722 if (len & 1)
9723 return -1;
9724 len /= 2;
9725
9726 buf = os_malloc(len);
9727 if (buf == NULL)
9728 return -1;
9729
9730 if (hexstr2bin(param, buf, len) < 0) {
9731 os_free(buf);
9732 return -1;
9733 }
9734
9735 os_memset(&event, 0, sizeof(event));
9736 event.rx_mgmt.freq = freq;
9737 event.rx_mgmt.frame = buf;
9738 event.rx_mgmt.frame_len = len;
9739 event.rx_mgmt.ssi_signal = ssi_signal;
9740 event.rx_mgmt.datarate = datarate;
9741 wpa_s->ext_mgmt_frame_handling = 0;
9742 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
9743 wpa_s->ext_mgmt_frame_handling = 1;
9744
9745 os_free(buf);
9746
9747 return 0;
9748}
9749
9750
Paul Stewart092955c2017-02-06 09:13:09 -08009751static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
9752 char *param)
9753{
9754 struct wpa_scan_res *res;
9755 struct os_reltime now;
9756 char *pos, *end;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009757 int ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -08009758
9759 if (!param)
9760 return -1;
9761
9762 if (os_strcmp(param, "START") == 0) {
9763 wpa_bss_update_start(wpa_s);
9764 return 0;
9765 }
9766
9767 if (os_strcmp(param, "END") == 0) {
9768 wpa_bss_update_end(wpa_s, NULL, 1);
9769 return 0;
9770 }
9771
9772 if (os_strncmp(param, "BSS ", 4) != 0)
9773 return -1;
9774 param += 3;
9775
9776 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
9777 if (!res)
9778 return -1;
9779
9780 pos = os_strstr(param, " flags=");
9781 if (pos)
9782 res->flags = strtol(pos + 7, NULL, 16);
9783
9784 pos = os_strstr(param, " bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009785 if (pos && hwaddr_aton(pos + 7, res->bssid))
9786 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009787
9788 pos = os_strstr(param, " freq=");
9789 if (pos)
9790 res->freq = atoi(pos + 6);
9791
9792 pos = os_strstr(param, " beacon_int=");
9793 if (pos)
9794 res->beacon_int = atoi(pos + 12);
9795
9796 pos = os_strstr(param, " caps=");
9797 if (pos)
9798 res->caps = strtol(pos + 6, NULL, 16);
9799
9800 pos = os_strstr(param, " qual=");
9801 if (pos)
9802 res->qual = atoi(pos + 6);
9803
9804 pos = os_strstr(param, " noise=");
9805 if (pos)
9806 res->noise = atoi(pos + 7);
9807
9808 pos = os_strstr(param, " level=");
9809 if (pos)
9810 res->level = atoi(pos + 7);
9811
9812 pos = os_strstr(param, " tsf=");
9813 if (pos)
9814 res->tsf = strtoll(pos + 5, NULL, 16);
9815
9816 pos = os_strstr(param, " age=");
9817 if (pos)
9818 res->age = atoi(pos + 5);
9819
9820 pos = os_strstr(param, " est_throughput=");
9821 if (pos)
9822 res->est_throughput = atoi(pos + 16);
9823
9824 pos = os_strstr(param, " snr=");
9825 if (pos)
9826 res->snr = atoi(pos + 5);
9827
9828 pos = os_strstr(param, " parent_tsf=");
9829 if (pos)
9830 res->parent_tsf = strtoll(pos + 7, NULL, 16);
9831
9832 pos = os_strstr(param, " tsf_bssid=");
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009833 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
9834 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009835
9836 pos = os_strstr(param, " ie=");
9837 if (pos) {
9838 pos += 4;
9839 end = os_strchr(pos, ' ');
9840 if (!end)
9841 end = pos + os_strlen(pos);
9842 res->ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009843 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
9844 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009845 }
9846
9847 pos = os_strstr(param, " beacon_ie=");
9848 if (pos) {
9849 pos += 11;
9850 end = os_strchr(pos, ' ');
9851 if (!end)
9852 end = pos + os_strlen(pos);
9853 res->beacon_ie_len = (end - pos) / 2;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009854 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
9855 res->beacon_ie_len))
9856 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08009857 }
9858
9859 os_get_reltime(&now);
9860 wpa_bss_update_scan_res(wpa_s, res, &now);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009861 ret = 0;
9862fail:
Paul Stewart092955c2017-02-06 09:13:09 -08009863 os_free(res);
9864
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08009865 return ret;
Paul Stewart092955c2017-02-06 09:13:09 -08009866}
9867
9868
Hai Shaloma20dcd72022-02-04 13:43:00 -08009869static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
9870 char *param)
9871{
9872 union wpa_event_data event;
9873 struct assoc_info *ai;
9874 char *ctx = NULL;
9875 int ret = -1;
9876 struct wpabuf *req_ies = NULL;
9877 struct wpabuf *resp_ies = NULL;
9878 struct wpabuf *resp_frame = NULL;
9879 struct wpabuf *beacon_ies = NULL;
9880 struct wpabuf *key_replay_ctr = NULL;
9881 struct wpabuf *ptk_kck = NULL;
9882 struct wpabuf *ptk_kek = NULL;
9883 struct wpabuf *fils_pmk = NULL;
9884 char *str, *pos;
9885 u8 addr[ETH_ALEN];
9886 u8 fils_pmkid[PMKID_LEN];
9887
9888 os_memset(&event, 0, sizeof(event));
9889 ai = &event.assoc_info;
9890
9891 while ((str = str_token(param, " ", &ctx))) {
9892 pos = os_strchr(str, '=');
9893 if (!pos)
9894 goto fail;
9895 *pos++ = '\0';
9896
9897 if (os_strcmp(str, "reassoc") == 0) {
9898 ai->reassoc = atoi(pos);
9899 } else if (os_strcmp(str, "req_ies") == 0) {
9900 wpabuf_free(req_ies);
9901 req_ies = wpabuf_parse_bin(pos);
9902 if (!req_ies)
9903 goto fail;
9904 ai->req_ies = wpabuf_head(req_ies);
9905 ai->req_ies_len = wpabuf_len(req_ies);
9906 } else if (os_strcmp(str, "resp_ies") == 0) {
9907 wpabuf_free(resp_ies);
9908 resp_ies = wpabuf_parse_bin(pos);
9909 if (!resp_ies)
9910 goto fail;
9911 ai->resp_ies = wpabuf_head(resp_ies);
9912 ai->resp_ies_len = wpabuf_len(resp_ies);
9913 } else if (os_strcmp(str, "resp_frame") == 0) {
9914 wpabuf_free(resp_frame);
9915 resp_frame = wpabuf_parse_bin(pos);
9916 if (!resp_frame)
9917 goto fail;
9918 ai->resp_frame = wpabuf_head(resp_frame);
9919 ai->resp_frame_len = wpabuf_len(resp_frame);
9920 } else if (os_strcmp(str, "beacon_ies") == 0) {
9921 wpabuf_free(beacon_ies);
9922 beacon_ies = wpabuf_parse_bin(pos);
9923 if (!beacon_ies)
9924 goto fail;
9925 ai->beacon_ies = wpabuf_head(beacon_ies);
9926 ai->beacon_ies_len = wpabuf_len(beacon_ies);
9927 } else if (os_strcmp(str, "freq") == 0) {
9928 ai->freq = atoi(pos);
9929 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
9930 ai->wmm_params.info_bitmap = atoi(pos);
9931 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
9932 ai->wmm_params.uapsd_queues = atoi(pos);
9933 } else if (os_strcmp(str, "addr") == 0) {
9934 if (hwaddr_aton(pos, addr))
9935 goto fail;
9936 ai->addr = addr;
9937 } else if (os_strcmp(str, "authorized") == 0) {
9938 ai->authorized = atoi(pos);
9939 } else if (os_strcmp(str, "key_replay_ctr") == 0) {
9940 wpabuf_free(key_replay_ctr);
9941 key_replay_ctr = wpabuf_parse_bin(pos);
9942 if (!key_replay_ctr)
9943 goto fail;
9944 ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
9945 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
9946 } else if (os_strcmp(str, "ptk_kck") == 0) {
9947 wpabuf_free(ptk_kck);
9948 ptk_kck = wpabuf_parse_bin(pos);
9949 if (!ptk_kck)
9950 goto fail;
9951 ai->ptk_kck = wpabuf_head(ptk_kck);
9952 ai->ptk_kck_len = wpabuf_len(ptk_kck);
9953 } else if (os_strcmp(str, "ptk_kek") == 0) {
9954 wpabuf_free(ptk_kek);
9955 ptk_kek = wpabuf_parse_bin(pos);
9956 if (!ptk_kek)
9957 goto fail;
9958 ai->ptk_kek = wpabuf_head(ptk_kek);
9959 ai->ptk_kek_len = wpabuf_len(ptk_kek);
9960 } else if (os_strcmp(str, "subnet_status") == 0) {
9961 ai->subnet_status = atoi(pos);
9962 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
9963 ai->fils_erp_next_seq_num = atoi(pos);
9964 } else if (os_strcmp(str, "fils_pmk") == 0) {
9965 wpabuf_free(fils_pmk);
9966 fils_pmk = wpabuf_parse_bin(pos);
9967 if (!fils_pmk)
9968 goto fail;
9969 ai->fils_pmk = wpabuf_head(fils_pmk);
9970 ai->fils_pmk_len = wpabuf_len(fils_pmk);
9971 } else if (os_strcmp(str, "fils_pmkid") == 0) {
9972 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
9973 goto fail;
9974 ai->fils_pmkid = fils_pmkid;
9975 } else {
9976 goto fail;
9977 }
9978 }
9979
9980 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
9981 ret = 0;
9982fail:
9983 wpabuf_free(req_ies);
9984 wpabuf_free(resp_ies);
9985 wpabuf_free(resp_frame);
9986 wpabuf_free(beacon_ies);
9987 wpabuf_free(key_replay_ctr);
9988 wpabuf_free(ptk_kck);
9989 wpabuf_free(ptk_kek);
9990 wpabuf_free(fils_pmk);
9991 return ret;
9992}
9993
9994
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07009995static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
9996{
9997 char *pos, *param;
9998 union wpa_event_data event;
9999 enum wpa_event_type ev;
10000
10001 /* <event name> [parameters..] */
10002
10003 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
10004
10005 pos = cmd;
10006 param = os_strchr(pos, ' ');
10007 if (param)
10008 *param++ = '\0';
10009
10010 os_memset(&event, 0, sizeof(event));
10011
10012 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
10013 ev = EVENT_INTERFACE_ENABLED;
10014 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
10015 ev = EVENT_INTERFACE_DISABLED;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -070010016 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
10017 ev = EVENT_AVOID_FREQUENCIES;
10018 if (param == NULL)
10019 param = "";
10020 if (freq_range_list_parse(&event.freq_range, param) < 0)
10021 return -1;
10022 wpa_supplicant_event(wpa_s, ev, &event);
10023 os_free(event.freq_range.range);
10024 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -080010025 } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
10026 return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
Hai Shaloma20dcd72022-02-04 13:43:00 -080010027 } else if (os_strcmp(cmd, "ASSOC") == 0) {
10028 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -070010029 } else {
10030 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
10031 cmd);
10032 return -1;
10033 }
10034
10035 wpa_supplicant_event(wpa_s, ev, &event);
10036
10037 return 0;
10038}
10039
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010040
10041static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
10042{
10043 char *pos;
10044 u8 src[ETH_ALEN], *buf;
10045 int used;
10046 size_t len;
10047
10048 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
10049
10050 pos = cmd;
10051 used = hwaddr_aton2(pos, src);
10052 if (used < 0)
10053 return -1;
10054 pos += used;
10055 while (*pos == ' ')
10056 pos++;
10057
10058 len = os_strlen(pos);
10059 if (len & 1)
10060 return -1;
10061 len /= 2;
10062
10063 buf = os_malloc(len);
10064 if (buf == NULL)
10065 return -1;
10066
10067 if (hexstr2bin(pos, buf, len) < 0) {
10068 os_free(buf);
10069 return -1;
10070 }
10071
Sunil8cd6f4d2022-06-28 18:40:46 +000010072 wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010073 os_free(buf);
10074
10075 return 0;
10076}
10077
10078
Hai Shaloma20dcd72022-02-04 13:43:00 -080010079static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
10080{
10081 char *pos;
10082 u8 dst[ETH_ALEN], *buf;
10083 int used, ret;
10084 size_t len;
10085 unsigned int prev;
10086
10087 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
10088
10089 pos = cmd;
10090 used = hwaddr_aton2(pos, dst);
10091 if (used < 0)
10092 return -1;
10093 pos += used;
10094 while (*pos == ' ')
10095 pos++;
10096
10097 len = os_strlen(pos);
10098 if (len & 1)
10099 return -1;
10100 len /= 2;
10101
10102 buf = os_malloc(len);
10103 if (!buf || hexstr2bin(pos, buf, len) < 0) {
10104 os_free(buf);
10105 return -1;
10106 }
10107
10108 prev = wpa_s->ext_eapol_frame_io;
10109 wpa_s->ext_eapol_frame_io = 0;
10110 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
10111 wpa_s->ext_eapol_frame_io = prev;
10112 os_free(buf);
10113
10114 return ret;
10115}
10116
10117
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010118static u16 ipv4_hdr_checksum(const void *buf, size_t len)
10119{
10120 size_t i;
10121 u32 sum = 0;
10122 const u16 *pos = buf;
10123
10124 for (i = 0; i < len / 2; i++)
10125 sum += *pos++;
10126
10127 while (sum >> 16)
10128 sum = (sum & 0xffff) + (sum >> 16);
10129
10130 return sum ^ 0xffff;
10131}
10132
10133
10134#define HWSIM_PACKETLEN 1500
10135#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
10136
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -070010137static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
10138 size_t len)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010139{
10140 struct wpa_supplicant *wpa_s = ctx;
10141 const struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -070010142 struct ip ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010143 const u8 *pos;
10144 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -080010145 char extra[30];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010146
Hai Shalom74f70d42019-02-11 14:42:39 -080010147 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
10148 wpa_printf(MSG_DEBUG,
10149 "test data: RX - ignore unexpected length %d",
10150 (int) len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010151 return;
Hai Shalom74f70d42019-02-11 14:42:39 -080010152 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010153
10154 eth = (const struct ether_header *) buf;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010155 os_memcpy(&ip, eth + 1, sizeof(ip));
10156 pos = &buf[sizeof(*eth) + sizeof(ip)];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010157
Hai Shalomfdcde762020-04-02 11:19:20 -070010158 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) {
Hai Shalom74f70d42019-02-11 14:42:39 -080010159 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -070010160 "test data: RX - ignore unexpected IP header");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010161 return;
Hai Shalom39bc25d2019-02-06 16:32:13 -080010162 }
Hai Shalombf6e0ba2019-02-11 12:01:50 -080010163
Hai Shalomfdcde762020-04-02 11:19:20 -070010164 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
Hai Shalom74f70d42019-02-11 14:42:39 -080010165 if (*pos != (u8) i) {
10166 wpa_printf(MSG_DEBUG,
10167 "test data: RX - ignore mismatching payload");
10168 return;
10169 }
10170 pos++;
10171 }
10172 extra[0] = '\0';
Hai Shalomfdcde762020-04-02 11:19:20 -070010173 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
10174 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
Hai Shalom74f70d42019-02-11 14:42:39 -080010175 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
10176 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010177}
10178
10179
10180static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
10181 char *cmd)
10182{
10183 int enabled = atoi(cmd);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080010184 char *pos;
10185 const char *ifname;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010186
10187 if (!enabled) {
10188 if (wpa_s->l2_test) {
10189 l2_packet_deinit(wpa_s->l2_test);
10190 wpa_s->l2_test = NULL;
10191 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
10192 }
10193 return 0;
10194 }
10195
10196 if (wpa_s->l2_test)
10197 return 0;
10198
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080010199 pos = os_strstr(cmd, " ifname=");
10200 if (pos)
10201 ifname = pos + 8;
10202 else
10203 ifname = wpa_s->ifname;
10204
10205 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010206 ETHERTYPE_IP, wpas_data_test_rx,
10207 wpa_s, 1);
10208 if (wpa_s->l2_test == NULL)
10209 return -1;
10210
10211 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
10212
10213 return 0;
10214}
10215
10216
10217static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
10218{
10219 u8 dst[ETH_ALEN], src[ETH_ALEN];
Hai Shalom74f70d42019-02-11 14:42:39 -080010220 char *pos, *pos2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010221 int used;
10222 long int val;
10223 u8 tos;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010224 u8 buf[2 + HWSIM_PACKETLEN];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010225 struct ether_header *eth;
Hai Shalomfdcde762020-04-02 11:19:20 -070010226 struct ip *ip;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010227 u8 *dpos;
10228 unsigned int i;
Hai Shalom74f70d42019-02-11 14:42:39 -080010229 size_t send_len = HWSIM_IP_LEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010230
10231 if (wpa_s->l2_test == NULL)
10232 return -1;
10233
Hai Shalom74f70d42019-02-11 14:42:39 -080010234 /* format: <dst> <src> <tos> [len=<length>] */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010235
10236 pos = cmd;
10237 used = hwaddr_aton2(pos, dst);
10238 if (used < 0)
10239 return -1;
10240 pos += used;
10241 while (*pos == ' ')
10242 pos++;
10243 used = hwaddr_aton2(pos, src);
10244 if (used < 0)
10245 return -1;
10246 pos += used;
10247
Hai Shalom74f70d42019-02-11 14:42:39 -080010248 val = strtol(pos, &pos2, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010249 if (val < 0 || val > 0xff)
10250 return -1;
10251 tos = val;
10252
Hai Shalom74f70d42019-02-11 14:42:39 -080010253 pos = os_strstr(pos2, " len=");
10254 if (pos) {
10255 i = atoi(pos + 5);
10256 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
10257 return -1;
10258 send_len = i;
10259 }
10260
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010261 eth = (struct ether_header *) &buf[2];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010262 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
10263 os_memcpy(eth->ether_shost, src, ETH_ALEN);
10264 eth->ether_type = htons(ETHERTYPE_IP);
Hai Shalomfdcde762020-04-02 11:19:20 -070010265 ip = (struct ip *) (eth + 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010266 os_memset(ip, 0, sizeof(*ip));
Hai Shalomfdcde762020-04-02 11:19:20 -070010267 ip->ip_hl = 5;
10268 ip->ip_v = 4;
10269 ip->ip_ttl = 64;
10270 ip->ip_tos = tos;
10271 ip->ip_len = htons(send_len);
10272 ip->ip_p = 1;
10273 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
10274 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
10275 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010276 dpos = (u8 *) (ip + 1);
Hai Shalom74f70d42019-02-11 14:42:39 -080010277 for (i = 0; i < send_len - sizeof(*ip); i++)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010278 *dpos++ = i;
10279
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010280 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
Hai Shalom74f70d42019-02-11 14:42:39 -080010281 sizeof(struct ether_header) + send_len) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010282 return -1;
10283
10284 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
10285 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
10286
10287 return 0;
10288}
10289
10290
10291static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
10292 char *cmd)
10293{
10294 u8 *buf;
10295 struct ether_header *eth;
10296 struct l2_packet_data *l2 = NULL;
10297 size_t len;
10298 u16 ethertype;
10299 int res = -1;
10300
10301 len = os_strlen(cmd);
10302 if (len & 1 || len < ETH_HLEN * 2)
10303 return -1;
10304 len /= 2;
10305
10306 buf = os_malloc(len);
10307 if (buf == NULL)
10308 return -1;
10309
10310 if (hexstr2bin(cmd, buf, len) < 0)
10311 goto done;
10312
10313 eth = (struct ether_header *) buf;
10314 ethertype = ntohs(eth->ether_type);
10315
10316 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
10317 wpas_data_test_rx, wpa_s, 1);
10318 if (l2 == NULL)
10319 goto done;
10320
10321 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
10322 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
10323done:
10324 if (l2)
10325 l2_packet_deinit(l2);
10326 os_free(buf);
10327
10328 return res < 0 ? -1 : 0;
10329}
10330
Dmitry Shmidtff787d52015-01-12 13:01:47 -080010331
Jouni Malinenc4818362015-10-04 11:45:13 +030010332static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
10333{
10334 struct wpa_supplicant *wpa_s = eloop_ctx;
10335 int i, count = (intptr_t) timeout_ctx;
10336
10337 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
10338 count);
10339 for (i = 0; i < count; i++) {
10340 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
10341 i + 1, count);
10342 }
10343}
10344
10345
10346static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
10347{
10348 int count;
10349
10350 count = atoi(cmd);
10351 if (count <= 0)
10352 return -1;
10353
10354 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
10355 (void *) (intptr_t) count);
10356}
10357
Dmitry Shmidt818ea482014-03-10 13:15:21 -070010358
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010359static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010360{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010361 struct wpabuf *buf;
10362 size_t len;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010363
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010364 len = os_strlen(val);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010365 if (len & 1)
10366 return -1;
10367 len /= 2;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010368
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010369 if (len == 0) {
10370 buf = NULL;
10371 } else {
10372 buf = wpabuf_alloc(len);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010373 if (!buf)
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010374 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010375
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010376 if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010377 wpabuf_free(buf);
10378 return -1;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010379 }
10380 }
10381
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010382 *ret = buf;
10383 return 0;
10384}
10385
10386
10387static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
10388 const char *cmd)
10389{
10390 struct wpabuf *buf;
10391
10392 if (wpas_get_hex_buf(cmd, &buf) < 0)
10393 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010394 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
10395 return 0;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010396}
10397
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010398
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010399static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
10400 const char *cmd)
10401{
10402 struct wpabuf *buf;
10403
10404 if (wpas_get_hex_buf(cmd, &buf) < 0)
10405 return -1;
10406 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
10407 return 0;
10408}
10409
10410
10411static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
10412 const char *cmd)
10413{
10414 struct wpabuf *buf;
10415
10416 if (wpas_get_hex_buf(cmd, &buf) < 0)
10417 return -1;
10418 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
10419 return 0;
10420}
10421
10422
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000010423static int wpas_ctrl_test_rsnxe_data(struct wpa_supplicant *wpa_s,
10424 const char *cmd)
10425{
10426 struct wpabuf *data = NULL, *mask = NULL;
10427 char *pos;
10428
10429 pos = os_strchr(cmd, ' ');
10430 if (!pos)
10431 return -1;
10432 *pos++ = '\0';
10433
10434 if (wpas_get_hex_buf(cmd, &data) < 0 ||
10435 wpas_get_hex_buf(pos, &mask) < 0 ||
10436 wpa_sm_set_test_rsnxe_data(wpa_s->wpa, data, mask) < 0) {
10437 wpabuf_free(data);
10438 wpabuf_free(mask);
10439 return -1;
10440 }
10441
10442 return 0;
10443}
10444
10445
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010446static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
10447{
10448 u8 zero[WPA_TK_MAX_LEN];
10449
10450 if (wpa_s->last_tk_alg == WPA_ALG_NONE)
10451 return -1;
10452
10453 wpa_printf(MSG_INFO, "TESTING: Reset PN");
10454 os_memset(zero, 0, sizeof(zero));
10455
10456 /* First, use a zero key to avoid any possible duplicate key avoidance
10457 * in the driver. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000010458 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 -070010459 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -070010460 zero, wpa_s->last_tk_len,
10461 KEY_FLAG_PAIRWISE_RX_TX) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010462 return -1;
10463
10464 /* Set the previously configured key to reset its TSC/RSC */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000010465 return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg,
10466 wpa_s->last_tk_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010467 wpa_s->last_tk_key_idx, 1, zero, 6,
Hai Shalomfdcde762020-04-02 11:19:20 -070010468 wpa_s->last_tk, wpa_s->last_tk_len,
10469 KEY_FLAG_PAIRWISE_RX_TX);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010470}
10471
10472
10473static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
10474{
10475 const char *pos = cmd;
10476 int error, pairwise;
10477
10478 error = atoi(pos);
10479 pos = os_strchr(pos, ' ');
10480 if (!pos)
10481 return -1;
10482 pairwise = atoi(pos);
10483 wpa_sm_key_request(wpa_s->wpa, error, pairwise);
10484 return 0;
10485}
10486
10487
10488static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
10489{
10490#ifdef CONFIG_SME
10491 struct wpa_driver_associate_params params;
10492 int ret;
10493
10494 os_memset(&params, 0, sizeof(params));
10495 params.bssid = wpa_s->bssid;
10496 params.ssid = wpa_s->sme.ssid;
10497 params.ssid_len = wpa_s->sme.ssid_len;
10498 params.freq.freq = wpa_s->sme.freq;
10499 if (wpa_s->last_assoc_req_wpa_ie) {
10500 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
10501 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
10502 }
10503 params.pairwise_suite = wpa_s->pairwise_cipher;
10504 params.group_suite = wpa_s->group_cipher;
10505 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
10506 params.key_mgmt_suite = wpa_s->key_mgmt;
10507 params.wpa_proto = wpa_s->wpa_proto;
10508 params.mgmt_frame_protection = wpa_s->sme.mfp;
10509 params.rrm_used = wpa_s->rrm.rrm_used;
10510 if (wpa_s->sme.prev_bssid_set)
10511 params.prev_bssid = wpa_s->sme.prev_bssid;
10512 wpa_printf(MSG_INFO, "TESTING: Resend association request");
10513 ret = wpa_drv_associate(wpa_s, &params);
10514 wpa_s->testing_resend_assoc = 1;
10515 return ret;
10516#else /* CONFIG_SME */
10517 return -1;
10518#endif /* CONFIG_SME */
10519}
10520
Hai Shaloma20dcd72022-02-04 13:43:00 -080010521
10522static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
10523 const char *cmd)
10524{
10525 u8 dtok = 1;
10526 int exponent = 10;
10527 int mantissa = 8192;
10528 u8 min_twt = 255;
10529 unsigned long long twt = 0;
10530 bool requestor = true;
10531 int setup_cmd = 0;
10532 bool trigger = true;
10533 bool implicit = true;
10534 bool flow_type = true;
10535 int flow_id = 0;
10536 bool protection = false;
10537 u8 twt_channel = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -070010538 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021,
10539 * Figure 9-687 - Control field format):
10540 * B4 = TWT Information Frame Disabled */
Hai Shaloma20dcd72022-02-04 13:43:00 -080010541 const char *tok_s;
10542
10543 tok_s = os_strstr(cmd, " dialog=");
10544 if (tok_s)
10545 dtok = atoi(tok_s + os_strlen(" dialog="));
10546
10547 tok_s = os_strstr(cmd, " exponent=");
10548 if (tok_s)
10549 exponent = atoi(tok_s + os_strlen(" exponent="));
10550
10551 tok_s = os_strstr(cmd, " mantissa=");
10552 if (tok_s)
10553 mantissa = atoi(tok_s + os_strlen(" mantissa="));
10554
10555 tok_s = os_strstr(cmd, " min_twt=");
10556 if (tok_s)
10557 min_twt = atoi(tok_s + os_strlen(" min_twt="));
10558
10559 tok_s = os_strstr(cmd, " setup_cmd=");
10560 if (tok_s)
10561 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
10562
10563 tok_s = os_strstr(cmd, " twt=");
Sunil8cd6f4d2022-06-28 18:40:46 +000010564 if (tok_s &&
10565 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1)
10566 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080010567
10568 tok_s = os_strstr(cmd, " requestor=");
10569 if (tok_s)
10570 requestor = atoi(tok_s + os_strlen(" requestor="));
10571
10572 tok_s = os_strstr(cmd, " trigger=");
10573 if (tok_s)
10574 trigger = atoi(tok_s + os_strlen(" trigger="));
10575
10576 tok_s = os_strstr(cmd, " implicit=");
10577 if (tok_s)
10578 implicit = atoi(tok_s + os_strlen(" implicit="));
10579
10580 tok_s = os_strstr(cmd, " flow_type=");
10581 if (tok_s)
10582 flow_type = atoi(tok_s + os_strlen(" flow_type="));
10583
10584 tok_s = os_strstr(cmd, " flow_id=");
10585 if (tok_s)
10586 flow_id = atoi(tok_s + os_strlen(" flow_id="));
10587
10588 tok_s = os_strstr(cmd, " protection=");
10589 if (tok_s)
10590 protection = atoi(tok_s + os_strlen(" protection="));
10591
10592 tok_s = os_strstr(cmd, " twt_channel=");
10593 if (tok_s)
10594 twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
10595
10596 tok_s = os_strstr(cmd, " control=");
10597 if (tok_s)
10598 control = atoi(tok_s + os_strlen(" control="));
10599
10600 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
10601 setup_cmd, twt, requestor, trigger, implicit,
10602 flow_type, flow_id, protection, twt_channel,
10603 control);
10604}
10605
10606
10607static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
10608 const char *cmd)
10609{
10610 u8 flags = 0x1;
10611 const char *tok_s;
10612
10613 tok_s = os_strstr(cmd, " flags=");
10614 if (tok_s)
10615 flags = atoi(tok_s + os_strlen(" flags="));
10616
10617 return wpas_twt_send_teardown(wpa_s, flags);
10618}
10619
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010620#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010621
10622
10623static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
10624{
10625 char *pos = cmd;
10626 int frame;
10627 size_t len;
10628 struct wpabuf *buf;
10629 struct ieee802_11_elems elems;
10630
10631 frame = atoi(pos);
10632 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10633 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010634 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010635
10636 pos = os_strchr(pos, ' ');
10637 if (pos == NULL)
10638 return -1;
10639 pos++;
10640
10641 len = os_strlen(pos);
10642 if (len == 0)
10643 return 0;
10644 if (len & 1)
10645 return -1;
10646 len /= 2;
10647
10648 buf = wpabuf_alloc(len);
10649 if (buf == NULL)
10650 return -1;
10651
10652 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
10653 wpabuf_free(buf);
10654 return -1;
10655 }
10656
10657 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
10658 ParseFailed) {
10659 wpabuf_free(buf);
10660 return -1;
10661 }
10662
10663 if (wpa_s->vendor_elem[frame] == NULL) {
10664 wpa_s->vendor_elem[frame] = buf;
Hai Shalom60840252021-02-19 19:02:11 -080010665 goto update_ies;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010666 }
10667
10668 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
10669 wpabuf_free(buf);
10670 return -1;
10671 }
10672
10673 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
10674 wpabuf_free(buf);
Hai Shalom60840252021-02-19 19:02:11 -080010675
10676update_ies:
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010677 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010678
Hai Shalom60840252021-02-19 19:02:11 -080010679 if (frame == VENDOR_ELEM_PROBE_REQ ||
10680 frame == VENDOR_ELEM_PROBE_REQ_P2P)
10681 wpa_supplicant_set_default_scan_ies(wpa_s);
10682
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010683 return 0;
10684}
10685
10686
10687static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
10688 char *buf, size_t buflen)
10689{
10690 int frame = atoi(cmd);
10691
10692 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10693 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010694 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010695
10696 if (wpa_s->vendor_elem[frame] == NULL)
10697 return 0;
10698
10699 return wpa_snprintf_hex(buf, buflen,
10700 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
10701 wpabuf_len(wpa_s->vendor_elem[frame]));
10702}
10703
10704
10705static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
10706{
10707 char *pos = cmd;
10708 int frame;
10709 size_t len;
10710 u8 *buf;
10711 struct ieee802_11_elems elems;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010712 int res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010713
10714 frame = atoi(pos);
10715 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
10716 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010717 wpa_s = wpas_vendor_elem(wpa_s, frame);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010718
10719 pos = os_strchr(pos, ' ');
10720 if (pos == NULL)
10721 return -1;
10722 pos++;
10723
10724 if (*pos == '*') {
10725 wpabuf_free(wpa_s->vendor_elem[frame]);
10726 wpa_s->vendor_elem[frame] = NULL;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010727 wpas_vendor_elem_update(wpa_s);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010728 return 0;
10729 }
10730
10731 if (wpa_s->vendor_elem[frame] == NULL)
10732 return -1;
10733
10734 len = os_strlen(pos);
10735 if (len == 0)
10736 return 0;
10737 if (len & 1)
10738 return -1;
10739 len /= 2;
10740
10741 buf = os_malloc(len);
10742 if (buf == NULL)
10743 return -1;
10744
10745 if (hexstr2bin(pos, buf, len) < 0) {
10746 os_free(buf);
10747 return -1;
10748 }
10749
10750 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
10751 os_free(buf);
10752 return -1;
10753 }
10754
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010755 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010756 os_free(buf);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080010757 return res;
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070010758}
10759
10760
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010761#ifndef CONFIG_NO_RRM
10762
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010763static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
10764{
10765 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010766 size_t len;
10767 const u8 *data;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010768
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010769 /*
10770 * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
10771 * BSSID[6]
10772 * BSSID Information[4]
10773 * Operating Class[1]
10774 * Channel Number[1]
10775 * PHY Type[1]
10776 * Optional Subelements[variable]
10777 */
10778#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
10779
10780 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010781 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010782 goto out;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010783 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010784
10785 data = wpabuf_head_u8(neighbor_rep);
10786 len = wpabuf_len(neighbor_rep);
10787
10788 while (len >= 2 + NR_IE_MIN_LEN) {
10789 const u8 *nr;
10790 char lci[256 * 2 + 1];
10791 char civic[256 * 2 + 1];
10792 u8 nr_len = data[1];
10793 const u8 *pos = data, *end;
10794
10795 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
10796 nr_len < NR_IE_MIN_LEN) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010797 wpa_dbg(wpa_s, MSG_DEBUG,
10798 "CTRL: Invalid Neighbor Report element: id=%u len=%u",
10799 data[0], nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010800 goto out;
10801 }
10802
10803 if (2U + nr_len > len) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010804 wpa_dbg(wpa_s, MSG_DEBUG,
10805 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
10806 data[0], len, nr_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010807 goto out;
10808 }
10809 pos += 2;
10810 end = pos + nr_len;
10811
10812 nr = pos;
10813 pos += NR_IE_MIN_LEN;
10814
10815 lci[0] = '\0';
10816 civic[0] = '\0';
10817 while (end - pos > 2) {
10818 u8 s_id, s_len;
10819
10820 s_id = *pos++;
10821 s_len = *pos++;
10822 if (s_len > end - pos)
10823 goto out;
10824 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
10825 /* Measurement Token[1] */
10826 /* Measurement Report Mode[1] */
10827 /* Measurement Type[1] */
10828 /* Measurement Report[variable] */
10829 switch (pos[2]) {
10830 case MEASURE_TYPE_LCI:
10831 if (lci[0])
10832 break;
10833 wpa_snprintf_hex(lci, sizeof(lci),
10834 pos, s_len);
10835 break;
10836 case MEASURE_TYPE_LOCATION_CIVIC:
10837 if (civic[0])
10838 break;
10839 wpa_snprintf_hex(civic, sizeof(civic),
10840 pos, s_len);
10841 break;
10842 }
10843 }
10844
10845 pos += s_len;
10846 }
10847
10848 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
10849 "bssid=" MACSTR
10850 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
10851 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
10852 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
10853 nr[ETH_ALEN + 6],
10854 lci[0] ? " lci=" : "", lci,
10855 civic[0] ? " civic=" : "", civic);
10856
10857 data = end;
10858 len -= 2 + nr_len;
10859 }
10860
10861out:
10862 wpabuf_free(neighbor_rep);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010863}
10864
10865
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010866static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
10867 char *cmd)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010868{
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010869 struct wpa_ssid_value ssid, *ssid_p = NULL;
10870 int ret, lci = 0, civic = 0;
10871 char *ssid_s;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010872
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010873 ssid_s = os_strstr(cmd, "ssid=");
10874 if (ssid_s) {
10875 if (ssid_parse(ssid_s + 5, &ssid)) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080010876 wpa_msg(wpa_s, MSG_INFO,
10877 "CTRL: Send Neighbor Report: bad SSID");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010878 return -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010879 }
10880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010881 ssid_p = &ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010882
10883 /*
10884 * Move cmd after the SSID text that may include "lci" or
10885 * "civic".
10886 */
10887 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
10888 if (cmd)
10889 cmd++;
10890
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010891 }
10892
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010893 if (cmd && os_strstr(cmd, "lci"))
10894 lci = 1;
10895
10896 if (cmd && os_strstr(cmd, "civic"))
10897 civic = 1;
10898
10899 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010900 wpas_ctrl_neighbor_rep_cb,
10901 wpa_s);
10902
10903 return ret;
10904}
10905
Sunil Ravib0ac25f2024-07-12 01:42:03 +000010906#endif /* CONFIG_NO_RRM */
10907
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010908
10909static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
10910{
10911 eapol_sm_erp_flush(wpa_s->eapol);
10912 return 0;
10913}
10914
10915
10916static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
10917 char *cmd)
10918{
10919 char *token, *context = NULL;
10920 unsigned int enable = ~0, type = 0;
10921 u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
10922 u8 *addr = NULL, *mask = NULL;
10923
10924 while ((token = str_token(cmd, " ", &context))) {
10925 if (os_strcasecmp(token, "scan") == 0) {
10926 type |= MAC_ADDR_RAND_SCAN;
10927 } else if (os_strcasecmp(token, "sched") == 0) {
10928 type |= MAC_ADDR_RAND_SCHED_SCAN;
10929 } else if (os_strcasecmp(token, "pno") == 0) {
10930 type |= MAC_ADDR_RAND_PNO;
10931 } else if (os_strcasecmp(token, "all") == 0) {
10932 type = wpa_s->mac_addr_rand_supported;
10933 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
10934 enable = atoi(token + 7);
10935 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
10936 addr = _addr;
10937 if (hwaddr_aton(token + 5, addr)) {
10938 wpa_printf(MSG_INFO,
10939 "CTRL: Invalid MAC address: %s",
10940 token);
10941 return -1;
10942 }
10943 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
10944 mask = _mask;
10945 if (hwaddr_aton(token + 5, mask)) {
10946 wpa_printf(MSG_INFO,
10947 "CTRL: Invalid MAC address mask: %s",
10948 token);
10949 return -1;
10950 }
10951 } else {
10952 wpa_printf(MSG_INFO,
10953 "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
10954 token);
10955 return -1;
10956 }
10957 }
10958
10959 if (!type) {
10960 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
10961 return -1;
10962 }
10963
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010964 if (enable > 1) {
10965 wpa_printf(MSG_INFO,
10966 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
10967 return -1;
10968 }
10969
Hai Shalom81f62d82019-07-22 12:10:00 -070010970 if (!enable)
10971 return wpas_disable_mac_addr_randomization(wpa_s, type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010972
Hai Shalom81f62d82019-07-22 12:10:00 -070010973 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010974}
10975
10976
Dmitry Shmidte4663042016-04-04 10:07:49 -070010977static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
10978 char *buf, size_t buflen)
10979{
10980 size_t reply_len;
10981
10982 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
10983#ifdef CONFIG_AP
10984 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
10985 buflen - reply_len);
10986#endif /* CONFIG_AP */
10987 return reply_len;
10988}
10989
10990
10991static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
10992{
Hai Shalom60840252021-02-19 19:02:11 -080010993 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
Dmitry Shmidte4663042016-04-04 10:07:49 -070010994 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
10995#ifdef CONFIG_AP
10996 wpas_ap_pmksa_cache_flush(wpa_s);
10997#endif /* CONFIG_AP */
10998}
10999
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000011000#ifdef CONFIG_P2P
11001#ifdef CONFIG_PASN
11002
11003#ifdef CONFIG_TESTING_OPTIONS
11004static int p2p_ctrl_get_pasn_ptk(struct wpa_supplicant *wpa_s, char *buf,
11005 size_t buflen)
11006{
11007 const u8 *ptk;
11008 size_t ptk_len;
11009
11010 if (wpas_p2p_get_pasn_ptk(wpa_s, &ptk, &ptk_len))
11011 return -1;
11012 return wpa_snprintf_hex(buf, buflen, ptk, ptk_len);
11013}
11014#endif /* CONFIG_TESTING_OPTIONS */
11015
11016#endif /* CONFIG_PASN */
11017#endif /* CONFIG_P2P */
Dmitry Shmidte4663042016-04-04 10:07:49 -070011018
Dmitry Shmidt29333592017-01-09 12:27:11 -080011019#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
11020
11021static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
11022 const char *cmd, char *buf, size_t buflen)
11023{
11024 struct rsn_pmksa_cache_entry *entry;
11025 struct wpa_ssid *ssid;
11026 char *pos, *pos2, *end;
11027 int ret;
11028 struct os_reltime now;
11029
11030 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11031 if (!ssid)
11032 return -1;
11033
11034 pos = buf;
11035 end = buf + buflen;
11036
11037 os_get_reltime(&now);
11038
11039 /*
11040 * Entry format:
11041 * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11042 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011043 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080011044 */
11045
11046 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
11047 entry = entry->next) {
11048 if (entry->network_ctx != ssid)
11049 continue;
11050
11051 pos2 = pos;
11052 ret = os_snprintf(pos2, end - pos2, MACSTR " ",
11053 MAC2STR(entry->aa));
11054 if (os_snprintf_error(end - pos2, ret))
11055 break;
11056 pos2 += ret;
11057
11058 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
11059 PMKID_LEN);
11060
11061 ret = os_snprintf(pos2, end - pos2, " ");
11062 if (os_snprintf_error(end - pos2, ret))
11063 break;
11064 pos2 += ret;
11065
11066 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
11067 entry->pmk_len);
11068
11069 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
11070 (int) (entry->reauth_time - now.sec),
11071 (int) (entry->expiration - now.sec),
11072 entry->akmp,
11073 entry->opportunistic);
11074 if (os_snprintf_error(end - pos2, ret))
11075 break;
11076 pos2 += ret;
11077
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011078 if (entry->fils_cache_id_set) {
11079 ret = os_snprintf(pos2, end - pos2, " %02x%02x",
11080 entry->fils_cache_id[0],
11081 entry->fils_cache_id[1]);
11082 if (os_snprintf_error(end - pos2, ret))
11083 break;
11084 pos2 += ret;
11085 }
11086
Dmitry Shmidt29333592017-01-09 12:27:11 -080011087 ret = os_snprintf(pos2, end - pos2, "\n");
11088 if (os_snprintf_error(end - pos2, ret))
11089 break;
11090 pos2 += ret;
11091
11092 pos = pos2;
11093 }
11094
11095 return pos - buf;
11096}
11097
11098
11099static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
11100 char *cmd)
11101{
11102 struct rsn_pmksa_cache_entry *entry;
11103 struct wpa_ssid *ssid;
11104 char *pos, *pos2;
11105 int ret = -1;
11106 struct os_reltime now;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011107 int reauth_time = 0, expiration = 0, i;
Dmitry Shmidt29333592017-01-09 12:27:11 -080011108
11109 /*
11110 * Entry format:
11111 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
11112 * <expiration in seconds> <akmp> <opportunistic>
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011113 * [FILS Cache Identifier]
Dmitry Shmidt29333592017-01-09 12:27:11 -080011114 */
11115
11116 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
11117 if (!ssid)
11118 return -1;
11119
11120 pos = os_strchr(cmd, ' ');
11121 if (!pos)
11122 return -1;
11123 pos++;
11124
11125 entry = os_zalloc(sizeof(*entry));
11126 if (!entry)
11127 return -1;
11128
11129 if (hwaddr_aton(pos, entry->aa))
11130 goto fail;
11131
11132 pos = os_strchr(pos, ' ');
11133 if (!pos)
11134 goto fail;
11135 pos++;
11136
11137 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
11138 goto fail;
11139
11140 pos = os_strchr(pos, ' ');
11141 if (!pos)
11142 goto fail;
11143 pos++;
11144
11145 pos2 = os_strchr(pos, ' ');
11146 if (!pos2)
11147 goto fail;
11148 entry->pmk_len = (pos2 - pos) / 2;
11149 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
11150 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
11151 goto fail;
11152
11153 pos = os_strchr(pos, ' ');
11154 if (!pos)
11155 goto fail;
11156 pos++;
11157
11158 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
11159 &entry->akmp, &entry->opportunistic) != 4)
11160 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011161 if (reauth_time > expiration)
11162 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070011163 for (i = 0; i < 4; i++) {
11164 pos = os_strchr(pos, ' ');
11165 if (!pos) {
11166 if (i < 3)
11167 goto fail;
11168 break;
11169 }
11170 pos++;
11171 }
11172 if (pos) {
11173 if (hexstr2bin(pos, entry->fils_cache_id,
11174 FILS_CACHE_ID_LEN) < 0)
11175 goto fail;
11176 entry->fils_cache_id_set = 1;
11177 }
Dmitry Shmidt29333592017-01-09 12:27:11 -080011178 os_get_reltime(&now);
11179 entry->expiration = now.sec + expiration;
11180 entry->reauth_time = now.sec + reauth_time;
11181
11182 entry->network_ctx = ssid;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000011183 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt29333592017-01-09 12:27:11 -080011184
Hai Shaloma20dcd72022-02-04 13:43:00 -080011185 entry->external = true;
11186
Dmitry Shmidt29333592017-01-09 12:27:11 -080011187 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
11188 entry = NULL;
11189 ret = 0;
11190fail:
11191 os_free(entry);
11192 return ret;
11193}
11194
Paul Stewart092955c2017-02-06 09:13:09 -080011195
11196#ifdef CONFIG_MESH
11197
11198static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
11199 const char *cmd, char *buf,
11200 size_t buflen)
11201{
11202 u8 spa[ETH_ALEN];
11203
11204 if (!wpa_s->ifmsh)
11205 return -1;
11206
11207 if (os_strcasecmp(cmd, "any") == 0)
11208 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
11209
11210 if (hwaddr_aton(cmd, spa))
11211 return -1;
11212
11213 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
11214}
11215
11216
11217static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
11218 char *cmd)
11219{
11220 /*
Hai Shalom60840252021-02-19 19:02:11 -080011221 * We do not check mesh interface existence because PMKSA should be
Paul Stewart092955c2017-02-06 09:13:09 -080011222 * stored before wpa_s->ifmsh creation to suppress commit message
11223 * creation.
11224 */
11225 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
11226}
11227
11228#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080011229#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
11230
11231
Paul Stewart092955c2017-02-06 09:13:09 -080011232#ifdef CONFIG_FILS
11233static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
11234 const char *cmd)
11235{
11236 struct fils_hlp_req *req;
11237 const char *pos;
11238
11239 /* format: <dst> <packet starting from ethertype> */
11240
11241 req = os_zalloc(sizeof(*req));
11242 if (!req)
11243 return -1;
11244
11245 if (hwaddr_aton(cmd, req->dst))
11246 goto fail;
11247
11248 pos = os_strchr(cmd, ' ');
11249 if (!pos)
11250 goto fail;
11251 pos++;
11252 req->pkt = wpabuf_parse_bin(pos);
11253 if (!req->pkt)
11254 goto fail;
11255
11256 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
11257 return 0;
11258fail:
11259 wpabuf_free(req->pkt);
11260 os_free(req);
11261 return -1;
11262}
11263#endif /* CONFIG_FILS */
11264
11265
Sunil Ravia04bd252022-05-02 22:54:18 -070011266int wpas_ctrl_cmd_debug_level(const char *cmd)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080011267{
11268 if (os_strcmp(cmd, "PING") == 0 ||
11269 os_strncmp(cmd, "BSS ", 4) == 0 ||
11270 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
11271 os_strncmp(cmd, "STATUS", 6) == 0 ||
11272 os_strncmp(cmd, "STA ", 4) == 0 ||
11273 os_strncmp(cmd, "STA-", 4) == 0)
11274 return MSG_EXCESSIVE;
11275 return MSG_DEBUG;
11276}
11277
11278
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011279#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -070011280static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
11281 const char *cmd)
11282{
11283 size_t frame_classifier_len;
11284 const char *pos, *end;
11285 struct robust_av_data *robust_av = &wpa_s->robust_av;
11286 int val;
11287
11288 /*
11289 * format:
11290 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
11291 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
11292 */
11293 os_memset(robust_av, 0, sizeof(struct robust_av_data));
11294 if (os_strncmp(cmd, "add ", 4) == 0) {
11295 robust_av->request_type = SCS_REQ_ADD;
11296 } else if (os_strcmp(cmd, "remove") == 0) {
11297 robust_av->request_type = SCS_REQ_REMOVE;
11298 robust_av->valid_config = false;
11299 return wpas_send_mscs_req(wpa_s);
11300 } else if (os_strncmp(cmd, "change ", 7) == 0) {
11301 robust_av->request_type = SCS_REQ_CHANGE;
11302 } else {
11303 return -1;
11304 }
11305
11306 pos = os_strstr(cmd, "up_bitmap=");
11307 if (!pos)
11308 return -1;
11309
11310 val = hex2byte(pos + 10);
11311 if (val < 0)
11312 return -1;
11313 robust_av->up_bitmap = val;
11314
11315 pos = os_strstr(cmd, "up_limit=");
11316 if (!pos)
11317 return -1;
11318
11319 robust_av->up_limit = atoi(pos + 9);
11320
11321 pos = os_strstr(cmd, "stream_timeout=");
11322 if (!pos)
11323 return -1;
11324
11325 robust_av->stream_timeout = atoi(pos + 15);
11326 if (robust_av->stream_timeout == 0)
11327 return -1;
11328
11329 pos = os_strstr(cmd, "frame_classifier=");
11330 if (!pos)
11331 return -1;
11332
11333 pos += 17;
11334 end = os_strchr(pos, ' ');
11335 if (!end)
11336 end = pos + os_strlen(pos);
11337
11338 frame_classifier_len = (end - pos) / 2;
11339 if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
11340 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
11341 return -1;
11342
11343 robust_av->frame_classifier_len = frame_classifier_len;
11344 robust_av->valid_config = true;
11345
11346 return wpas_send_mscs_req(wpa_s);
11347}
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011348#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -070011349
11350
Hai Shalom60840252021-02-19 19:02:11 -080011351#ifdef CONFIG_PASN
11352static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
11353{
11354 char *token, *context = NULL;
11355 u8 bssid[ETH_ALEN];
11356 int akmp = -1, cipher = -1, got_bssid = 0;
11357 u16 group = 0xFFFF;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011358 u8 *comeback = NULL;
11359 size_t comeback_len = 0;
11360 int id = 0, ret = -1;
Hai Shalom60840252021-02-19 19:02:11 -080011361
11362 /*
11363 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
Hai Shaloma20dcd72022-02-04 13:43:00 -080011364 * [comeback=<hexdump>]
Hai Shalom60840252021-02-19 19:02:11 -080011365 */
11366 while ((token = str_token(cmd, " ", &context))) {
11367 if (os_strncmp(token, "bssid=", 6) == 0) {
11368 if (hwaddr_aton(token + 6, bssid))
Hai Shaloma20dcd72022-02-04 13:43:00 -080011369 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011370 got_bssid = 1;
11371 } else if (os_strcmp(token, "akmp=PASN") == 0) {
11372 akmp = WPA_KEY_MGMT_PASN;
11373#ifdef CONFIG_IEEE80211R
11374 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
11375 akmp = WPA_KEY_MGMT_FT_PSK;
11376 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
11377 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
11378 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
11379 akmp = WPA_KEY_MGMT_FT_IEEE8021X;
11380#endif /* CONFIG_IEEE80211R */
11381#ifdef CONFIG_SAE
11382 } else if (os_strcmp(token, "akmp=SAE") == 0) {
11383 akmp = WPA_KEY_MGMT_SAE;
Sunil Ravi89eba102022-09-13 21:04:37 -070011384 } else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) {
11385 akmp = WPA_KEY_MGMT_SAE_EXT_KEY;
Hai Shalom60840252021-02-19 19:02:11 -080011386#endif /* CONFIG_SAE */
11387#ifdef CONFIG_FILS
11388 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
11389 akmp = WPA_KEY_MGMT_FILS_SHA256;
11390 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
11391 akmp = WPA_KEY_MGMT_FILS_SHA384;
11392#endif /* CONFIG_FILS */
11393 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
11394 cipher = WPA_CIPHER_CCMP_256;
11395 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
11396 cipher = WPA_CIPHER_GCMP_256;
11397 } else if (os_strcmp(token, "cipher=CCMP") == 0) {
11398 cipher = WPA_CIPHER_CCMP;
11399 } else if (os_strcmp(token, "cipher=GCMP") == 0) {
11400 cipher = WPA_CIPHER_GCMP;
11401 } else if (os_strncmp(token, "group=", 6) == 0) {
11402 group = atoi(token + 6);
11403 } else if (os_strncmp(token, "nid=", 4) == 0) {
11404 id = atoi(token + 4);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011405 } else if (os_strncmp(token, "comeback=", 9) == 0) {
11406 comeback_len = os_strlen(token + 9);
11407 if (comeback || !comeback_len || comeback_len % 2)
11408 goto out;
11409
11410 comeback_len /= 2;
11411 comeback = os_malloc(comeback_len);
11412 if (!comeback ||
11413 hexstr2bin(token + 9, comeback, comeback_len))
11414 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011415 } else {
11416 wpa_printf(MSG_DEBUG,
11417 "CTRL: PASN Invalid parameter: '%s'",
11418 token);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011419 goto out;
Hai Shalom60840252021-02-19 19:02:11 -080011420 }
11421 }
11422
11423 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
11424 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
Hai Shaloma20dcd72022-02-04 13:43:00 -080011425 goto out;
11426 }
11427
Sunil Ravi89eba102022-09-13 21:04:37 -070011428 ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher,
11429 group, id, comeback, comeback_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -080011430out:
11431 os_free(comeback);
11432 return ret;
11433}
11434
11435
11436static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
11437 const char *cmd)
11438{
11439 u8 bssid[ETH_ALEN];
11440
11441 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
11442 wpa_printf(MSG_DEBUG,
11443 "CTRL: PASN_DEAUTH without valid BSSID");
Hai Shalom60840252021-02-19 19:02:11 -080011444 return -1;
11445 }
11446
Sunil Ravi89eba102022-09-13 21:04:37 -070011447 return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid);
Hai Shalom60840252021-02-19 19:02:11 -080011448}
Hai Shaloma20dcd72022-02-04 13:43:00 -080011449
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011450
11451#ifdef CONFIG_TESTING_OPTIONS
11452static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s,
11453 const char *cmd)
11454{
11455 union wpa_event_data event;
11456 const char *pos = cmd;
11457 u8 addr[ETH_ALEN];
11458
11459 os_memset(&event, 0, sizeof(event));
11460
11461 if (os_strncmp(pos, "auth ", 5) == 0)
11462 event.pasn_auth.action = PASN_ACTION_AUTH;
11463 else if (os_strncmp(pos, "del ", 4) == 0)
11464 event.pasn_auth.action =
11465 PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
11466 else
11467 return -1;
11468
11469 pos = os_strchr(pos, ' ');
11470 if (!pos)
11471 return -1;
11472 pos++;
11473 while (hwaddr_aton(pos, addr) == 0) {
11474 struct pasn_peer *peer;
11475
11476 if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS)
11477 return -1;
11478 peer = &event.pasn_auth.peer[event.pasn_auth.num_peers];
11479 os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN);
11480 os_memcpy(peer->peer_addr, addr, ETH_ALEN);
11481 event.pasn_auth.num_peers++;
11482
11483 pos = os_strchr(pos, ' ');
11484 if (!pos)
11485 break;
11486 pos++;
11487 }
11488
11489 wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event);
11490 return 0;
11491}
11492#endif /* CONFIG_TESTING_OPTIONS */
11493
Hai Shalom60840252021-02-19 19:02:11 -080011494#endif /* CONFIG_PASN */
11495
11496
Sunil Ravib0ac25f2024-07-12 01:42:03 +000011497#ifndef CONFIG_NO_ROBUST_AV
11498
Hai Shaloma20dcd72022-02-04 13:43:00 -080011499static int set_type4_frame_classifier(const char *cmd,
11500 struct type4_params *param)
11501{
11502 const char *pos, *end;
11503 u8 classifier_mask = 0;
11504 int ret;
11505 char addr[INET6_ADDRSTRLEN];
11506 size_t alen;
11507
11508 if (os_strstr(cmd, "ip_version=ipv4")) {
11509 param->ip_version = IPV4;
11510 } else if (os_strstr(cmd, "ip_version=ipv6")) {
11511 param->ip_version = IPV6;
11512 } else {
11513 wpa_printf(MSG_ERROR, "IP version missing/invalid");
11514 return -1;
11515 }
11516
11517 classifier_mask |= BIT(0);
11518
11519 pos = os_strstr(cmd, "src_ip=");
11520 if (pos) {
11521 pos += 7;
11522 end = os_strchr(pos, ' ');
11523 if (!end)
11524 end = pos + os_strlen(pos);
11525
11526 alen = end - pos;
11527 if (alen >= INET6_ADDRSTRLEN)
11528 return -1;
11529 os_memcpy(addr, pos, alen);
11530 addr[alen] = '\0';
11531 if (param->ip_version == IPV4)
11532 ret = inet_pton(AF_INET, addr,
11533 &param->ip_params.v4.src_ip);
11534 else
11535 ret = inet_pton(AF_INET6, addr,
11536 &param->ip_params.v6.src_ip);
11537
11538 if (ret != 1) {
11539 wpa_printf(MSG_ERROR,
11540 "Error converting src IP address to binary ret=%d",
11541 ret);
11542 return -1;
11543 }
11544
11545 classifier_mask |= BIT(1);
11546 }
11547
11548 pos = os_strstr(cmd, "dst_ip=");
11549 if (pos) {
11550 pos += 7;
11551 end = os_strchr(pos, ' ');
11552 if (!end)
11553 end = pos + os_strlen(pos);
11554
11555 alen = end - pos;
11556 if (alen >= INET6_ADDRSTRLEN)
11557 return -1;
11558 os_memcpy(addr, pos, alen);
11559 addr[alen] = '\0';
11560 if (param->ip_version == IPV4)
11561 ret = inet_pton(AF_INET, addr,
11562 &param->ip_params.v4.dst_ip);
11563 else
11564 ret = inet_pton(AF_INET6, addr,
11565 &param->ip_params.v6.dst_ip);
11566
11567 if (ret != 1) {
11568 wpa_printf(MSG_ERROR,
11569 "Error converting dst IP address to binary ret=%d",
11570 ret);
11571 return -1;
11572 }
11573
11574 classifier_mask |= BIT(2);
11575 }
11576
11577 pos = os_strstr(cmd, "src_port=");
11578 if (pos && atoi(pos + 9) > 0) {
11579 if (param->ip_version == IPV4)
11580 param->ip_params.v4.src_port = atoi(pos + 9);
11581 else
11582 param->ip_params.v6.src_port = atoi(pos + 9);
11583 classifier_mask |= BIT(3);
11584 }
11585
11586 pos = os_strstr(cmd, "dst_port=");
11587 if (pos && atoi(pos + 9) > 0) {
11588 if (param->ip_version == IPV4)
11589 param->ip_params.v4.dst_port = atoi(pos + 9);
11590 else
11591 param->ip_params.v6.dst_port = atoi(pos + 9);
11592 classifier_mask |= BIT(4);
11593 }
11594
11595 pos = os_strstr(cmd, "dscp=");
11596 if (pos && atoi(pos + 5) > 0) {
11597 if (param->ip_version == IPV4)
11598 param->ip_params.v4.dscp = atoi(pos + 5);
11599 else
11600 param->ip_params.v6.dscp = atoi(pos + 5);
11601 classifier_mask |= BIT(5);
11602 }
11603
11604 if (param->ip_version == IPV4) {
11605 pos = os_strstr(cmd, "protocol=");
11606 if (pos) {
11607 if (os_strstr(pos, "udp")) {
11608 param->ip_params.v4.protocol = 17;
11609 } else if (os_strstr(pos, "tcp")) {
11610 param->ip_params.v4.protocol = 6;
11611 } else if (os_strstr(pos, "esp")) {
11612 param->ip_params.v4.protocol = 50;
11613 } else {
11614 wpa_printf(MSG_ERROR, "Invalid protocol");
11615 return -1;
11616 }
11617 classifier_mask |= BIT(6);
11618 }
11619 } else {
11620 pos = os_strstr(cmd, "next_header=");
11621 if (pos) {
11622 if (os_strstr(pos, "udp")) {
11623 param->ip_params.v6.next_header = 17;
11624 } else if (os_strstr(pos, "tcp")) {
11625 param->ip_params.v6.next_header = 6;
11626 } else if (os_strstr(pos, "esp")) {
11627 param->ip_params.v6.next_header = 50;
11628 } else {
11629 wpa_printf(MSG_ERROR, "Invalid next header");
11630 return -1;
11631 }
11632
11633 classifier_mask |= BIT(6);
11634 }
11635
11636 pos = os_strstr(cmd, "flow_label=");
11637 if (pos) {
11638 pos += 11;
11639 end = os_strchr(pos, ' ');
11640 if (!end)
11641 end = pos + os_strlen(pos);
11642
11643 if (end - pos != 6 ||
11644 hexstr2bin(pos, param->ip_params.v6.flow_label,
11645 3) ||
11646 param->ip_params.v6.flow_label[0] > 0x0F) {
11647 wpa_printf(MSG_ERROR, "Invalid flow label");
11648 return -1;
11649 }
11650
11651 classifier_mask |= BIT(7);
11652 }
11653 }
11654
11655 param->classifier_mask = classifier_mask;
11656 return 0;
11657}
11658
11659
11660static int set_type10_frame_classifier(const char *cmd,
11661 struct type10_params *param)
11662{
11663 const char *pos, *end;
11664 size_t filter_len;
11665
11666 pos = os_strstr(cmd, "prot_instance=");
11667 if (!pos) {
11668 wpa_printf(MSG_ERROR, "Protocol instance missing");
11669 return -1;
11670 }
11671 param->prot_instance = atoi(pos + 14);
11672
11673 pos = os_strstr(cmd, "prot_number=");
11674 if (!pos) {
11675 wpa_printf(MSG_ERROR, "Protocol number missing");
11676 return -1;
11677 }
11678 if (os_strstr(pos, "udp")) {
11679 param->prot_number = 17;
11680 } else if (os_strstr(pos, "tcp")) {
11681 param->prot_number = 6;
11682 } else if (os_strstr(pos, "esp")) {
11683 param->prot_number = 50;
11684 } else {
11685 wpa_printf(MSG_ERROR, "Invalid protocol number");
11686 return -1;
11687 }
11688
11689 pos = os_strstr(cmd, "filter_value=");
11690 if (!pos) {
11691 wpa_printf(MSG_ERROR,
11692 "Classifier parameter filter_value missing");
11693 return -1;
11694 }
11695
11696 pos += 13;
11697 end = os_strchr(pos, ' ');
11698 if (!end)
11699 end = pos + os_strlen(pos);
11700
11701 filter_len = (end - pos) / 2;
11702 param->filter_value = os_malloc(filter_len);
11703 if (!param->filter_value)
11704 return -1;
11705
11706 if (hexstr2bin(pos, param->filter_value, filter_len)) {
11707 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
11708 goto free;
11709 }
11710
11711 pos = os_strstr(cmd, "filter_mask=");
11712 if (!pos) {
11713 wpa_printf(MSG_ERROR,
11714 "Classifier parameter filter_mask missing");
11715 goto free;
11716 }
11717
11718 pos += 12;
11719 end = os_strchr(pos, ' ');
11720 if (!end)
11721 end = pos + os_strlen(pos);
11722
11723 if (filter_len != (size_t) (end - pos) / 2) {
11724 wpa_printf(MSG_ERROR,
11725 "Filter mask length mismatch expected=%zu received=%zu",
11726 filter_len, (size_t) (end - pos) / 2);
11727 goto free;
11728 }
11729
11730 param->filter_mask = os_malloc(filter_len);
11731 if (!param->filter_mask)
11732 goto free;
11733
11734 if (hexstr2bin(pos, param->filter_mask, filter_len)) {
11735 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
11736 os_free(param->filter_mask);
11737 param->filter_mask = NULL;
11738 goto free;
11739 }
11740
11741 param->filter_len = filter_len;
11742 return 0;
11743free:
11744 os_free(param->filter_value);
11745 param->filter_value = NULL;
11746 return -1;
11747}
11748
11749
11750static int scs_parse_type4(struct tclas_element *elem, const char *pos)
11751{
11752 struct type4_params type4_param = { 0 };
11753
11754 if (set_type4_frame_classifier(pos, &type4_param) == -1) {
11755 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
11756 return -1;
11757 }
11758
11759 os_memcpy(&elem->frame_classifier.type4_param,
11760 &type4_param, sizeof(struct type4_params));
11761 return 0;
11762}
11763
11764
11765static int scs_parse_type10(struct tclas_element *elem, const char *pos)
11766{
11767 struct type10_params type10_param = { 0 };
11768
11769 if (set_type10_frame_classifier(pos, &type10_param) == -1) {
11770 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
11771 return -1;
11772 }
11773
11774 os_memcpy(&elem->frame_classifier.type10_param,
11775 &type10_param, sizeof(struct type10_params));
11776 return 0;
11777}
11778
11779
11780static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
11781 char *cmd)
11782{
11783 char *pos1, *pos;
11784 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
11785 struct scs_desc_elem desc_elem = { 0 };
11786 int val;
11787 unsigned int num_scs_desc = 0;
11788
11789 if (wpa_s->ongoing_scs_req) {
11790 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
11791 __func__);
11792 return -1;
11793 }
11794
11795 /**
11796 * format:
11797 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
11798 * [classifier_type=<4|10>]
11799 * [classifier params based on classifier type]
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011800 * [tclas_processing=<0|1>]
11801 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>]
11802 * [max_si=<decimal number>] [min_data_rate=<decimal number>]
11803 * [delay_bound=<decimal number>] [max_msdu=<decimal number>]
11804 * [service_start_time=<decimal number>]
11805 * [service_start_time_link_id=<decimal number>]
11806 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>]
11807 * [msdu_lifetime=<decimal number>]
11808 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>]
11809 * [scs_id=<decimal number>] ...
Hai Shaloma20dcd72022-02-04 13:43:00 -080011810 */
11811 pos1 = os_strstr(cmd, "scs_id=");
11812 if (!pos1) {
11813 wpa_printf(MSG_ERROR, "SCSID not present");
11814 return -1;
11815 }
11816
11817 free_up_scs_desc(scs_data);
11818
11819 while (pos1) {
11820 struct scs_desc_elem *n1;
11821 struct active_scs_elem *active_scs_desc;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011822 char *next_scs_desc, *pos2;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011823 unsigned int num_tclas_elem = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011824 bool scsid_active = false, tclas_present = false;
11825 struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011826
11827 desc_elem.scs_id = atoi(pos1 + 7);
11828 pos1 += 7;
11829
11830 next_scs_desc = os_strstr(pos1, "scs_id=");
11831 if (next_scs_desc) {
11832 char temp[20];
11833
11834 os_snprintf(temp, sizeof(temp), "scs_id=%d ",
11835 desc_elem.scs_id);
11836 if (os_strstr(next_scs_desc, temp)) {
11837 wpa_printf(MSG_ERROR,
11838 "Multiple SCS descriptors configured with same SCSID(=%d)",
11839 desc_elem.scs_id);
11840 goto free_scs_desc;
11841 }
11842 pos1[next_scs_desc - pos1 - 1] = '\0';
11843 }
11844
11845 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
11846 struct active_scs_elem, list) {
11847 if (desc_elem.scs_id == active_scs_desc->scs_id) {
11848 scsid_active = true;
11849 break;
11850 }
11851 }
11852
11853 if (os_strstr(pos1, "add ")) {
11854 desc_elem.request_type = SCS_REQ_ADD;
11855 if (scsid_active) {
11856 wpa_printf(MSG_ERROR, "SCSID %d already active",
11857 desc_elem.scs_id);
11858 return -1;
11859 }
11860 } else if (os_strstr(pos1, "remove")) {
11861 desc_elem.request_type = SCS_REQ_REMOVE;
11862 if (!scsid_active) {
11863 wpa_printf(MSG_ERROR, "SCSID %d not active",
11864 desc_elem.scs_id);
11865 return -1;
11866 }
11867 goto scs_desc_end;
11868 } else if (os_strstr(pos1, "change ")) {
11869 desc_elem.request_type = SCS_REQ_CHANGE;
11870 if (!scsid_active) {
11871 wpa_printf(MSG_ERROR, "SCSID %d not active",
11872 desc_elem.scs_id);
11873 return -1;
11874 }
11875 } else {
11876 wpa_printf(MSG_ERROR, "SCS Request type invalid");
11877 goto free_scs_desc;
11878 }
11879
11880 pos1 = os_strstr(pos1, "scs_up=");
11881 if (!pos1) {
11882 wpa_printf(MSG_ERROR,
11883 "Intra-Access user priority not present");
11884 goto free_scs_desc;
11885 }
11886
11887 val = atoi(pos1 + 7);
11888 if (val < 0 || val > 7) {
11889 wpa_printf(MSG_ERROR,
11890 "Intra-Access user priority invalid %d",
11891 val);
11892 goto free_scs_desc;
11893 }
11894
11895 desc_elem.intra_access_priority = val;
11896 desc_elem.scs_up_avail = true;
11897
11898 pos = os_strstr(pos1, "classifier_type=");
11899 if (!pos) {
11900 wpa_printf(MSG_ERROR, "classifier type empty");
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011901 goto qos_characteristics;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011902 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011903 tclas_present = true;
Hai Shaloma20dcd72022-02-04 13:43:00 -080011904
11905 while (pos) {
11906 struct tclas_element elem = { 0 }, *n;
11907 char *next_tclas_elem;
11908
11909 val = atoi(pos + 16);
11910 if (val != 4 && val != 10) {
11911 wpa_printf(MSG_ERROR,
11912 "classifier type invalid %d", val);
11913 goto free_scs_desc;
11914 }
11915
11916 elem.classifier_type = val;
11917 pos += 16;
11918
11919 next_tclas_elem = os_strstr(pos, "classifier_type=");
11920 if (next_tclas_elem) {
11921 pos1 = next_tclas_elem;
11922 pos[next_tclas_elem - pos - 1] = '\0';
11923 }
11924
11925 switch (val) {
11926 case 4:
11927 if (scs_parse_type4(&elem, pos) < 0)
11928 goto free_scs_desc;
11929 break;
11930 case 10:
11931 if (scs_parse_type10(&elem, pos) < 0)
11932 goto free_scs_desc;
11933 break;
11934 }
11935
11936 n = os_realloc(desc_elem.tclas_elems,
11937 (num_tclas_elem + 1) * sizeof(elem));
11938 if (!n)
11939 goto free_scs_desc;
11940
11941 desc_elem.tclas_elems = n;
11942 os_memcpy((u8 *) desc_elem.tclas_elems +
11943 num_tclas_elem * sizeof(elem),
11944 &elem, sizeof(elem));
11945 num_tclas_elem++;
11946 desc_elem.num_tclas_elem = num_tclas_elem;
11947 pos = next_tclas_elem;
11948 }
11949
11950 if (desc_elem.num_tclas_elem > 1) {
11951 pos1 = os_strstr(pos1, "tclas_processing=");
11952 if (!pos1) {
11953 wpa_printf(MSG_ERROR, "tclas_processing empty");
11954 goto free_scs_desc;
11955 }
11956
11957 val = atoi(pos1 + 17);
11958 if (val != 0 && val != 1) {
11959 wpa_printf(MSG_ERROR,
11960 "tclas_processing invalid");
11961 goto free_scs_desc;
11962 }
11963
11964 desc_elem.tclas_processing = val;
11965 }
11966
Sunil Ravi2a14cf12023-11-21 00:54:38 +000011967 qos_characteristics:
11968 pos1 = os_strstr(pos1, "qos_characteristics");
11969 if (!pos1 && !tclas_present)
11970 goto free_scs_desc;
11971 if (!pos1)
11972 goto scs_desc_end;
11973
11974 qos_elem->available = true;
11975 if (os_strstr(pos1, "up ")) {
11976 qos_elem->direction = SCS_DIRECTION_UP;
11977 if (tclas_present) {
11978 wpa_printf(MSG_ERROR,
11979 "TCLAS with direction:UP not allowed");
11980 goto free_scs_desc;
11981 }
11982 } else if (os_strstr(pos1, "down ")) {
11983 qos_elem->direction = SCS_DIRECTION_DOWN;
11984 } else if (os_strstr(pos1, "direct ")) {
11985 qos_elem->direction = SCS_DIRECTION_DIRECT;
11986 }
11987
11988 pos1 = os_strstr(pos1, "min_si=");
11989 if (!pos1) {
11990 wpa_printf(MSG_ERROR, "Min SI is required");
11991 goto free_scs_desc;
11992 }
11993 qos_elem->min_si = atoi(pos1 + 7);
11994
11995 pos1 = os_strstr(pos1, "max_si=");
11996 if (!pos1) {
11997 wpa_printf(MSG_ERROR, "Max SI is required");
11998 goto free_scs_desc;
11999 }
12000 qos_elem->max_si = atoi(pos1 + 7);
12001
12002 if (qos_elem->min_si && qos_elem->max_si &&
12003 qos_elem->max_si < qos_elem->min_si) {
12004 wpa_printf(MSG_ERROR, "Invalid Max SI");
12005 goto free_scs_desc;
12006 }
12007
12008 pos1 = os_strstr(pos1, "min_data_rate=");
12009 if (!pos1) {
12010 wpa_printf(MSG_ERROR, "Min data rate is required");
12011 goto free_scs_desc;
12012 }
12013 qos_elem->min_data_rate = atoi(pos1 + 14);
12014
12015 pos1 = os_strstr(pos1, "delay_bound=");
12016 if (!pos1) {
12017 wpa_printf(MSG_ERROR, "Delay Bound is required");
12018 goto free_scs_desc;
12019 }
12020 qos_elem->delay_bound = atoi(pos1 + 12);
12021
12022 if (qos_elem->min_data_rate >= BIT(24) ||
12023 qos_elem->delay_bound >= BIT(24)) {
12024 wpa_printf(MSG_ERROR,
12025 "Invalid min_data_rate or delay_bound");
12026 goto free_scs_desc;
12027 }
12028
12029 pos2 = os_strstr(pos1, "max_msdu=");
12030 if (pos2) {
12031 qos_elem->max_msdu_size = atoi(pos2 + 9);
12032 qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE;
12033 }
12034
12035 pos2 = os_strstr(pos1, "service_start_time=");
12036 if (pos2) {
12037 qos_elem->service_start_time = atoi(pos2 + 19);
12038 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME;
12039 }
12040
12041 pos2 = os_strstr(pos1, "service_start_time_link_id=");
12042 if (pos2) {
12043 qos_elem->service_start_time_link_id = atoi(pos2 + 27);
12044 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
12045 }
12046
12047 pos2 = os_strstr(pos1, "mean_data_rate=");
12048 if (pos2) {
12049 qos_elem->mean_data_rate = atoi(pos2 + 15);
12050 qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE;
12051 }
12052
12053 pos2 = os_strstr(pos1, "burst_size=");
12054 if (pos2) {
12055 qos_elem->burst_size = atoi(pos2 + 11);
12056 qos_elem->mask |=
12057 SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE;
12058 }
12059
12060 pos2 = os_strstr(pos1, "msdu_lifetime=");
12061 if (pos2) {
12062 qos_elem->msdu_lifetime = atoi(pos2 + 14);
12063 qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME;
12064 }
12065
12066 pos2 = os_strstr(pos1, "msdu_delivery_info=");
12067 if (pos2) {
12068 qos_elem->msdu_delivery_info = atoi(pos2 + 19);
12069 qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO;
12070 }
12071
12072 pos2 = os_strstr(pos1, "medium_time=");
12073 if (pos2) {
12074 qos_elem->medium_time = atoi(pos2 + 12);
12075 qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME;
12076 }
12077
Hai Shaloma20dcd72022-02-04 13:43:00 -080012078scs_desc_end:
12079 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
12080 sizeof(struct scs_desc_elem));
12081 if (!n1)
12082 goto free_scs_desc;
12083
12084 scs_data->scs_desc_elems = n1;
12085 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
12086 sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
12087 num_scs_desc++;
12088 scs_data->num_scs_desc = num_scs_desc;
12089 pos1 = next_scs_desc;
12090 os_memset(&desc_elem, 0, sizeof(desc_elem));
12091 }
12092
12093 return wpas_send_scs_req(wpa_s);
12094
12095free_scs_desc:
12096 free_up_tclas_elem(&desc_elem);
12097 free_up_scs_desc(scs_data);
12098 return -1;
12099}
12100
12101
12102static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
12103 const char *cmd)
12104{
12105 char *pos;
12106 struct dscp_policy_status *policy = NULL, *n;
12107 int num_policies = 0, ret = -1;
12108 struct dscp_resp_data resp_data;
12109
12110 /*
12111 * format:
12112 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
12113 */
12114
12115 os_memset(&resp_data, 0, sizeof(resp_data));
12116
12117 resp_data.more = os_strstr(cmd, "more") != NULL;
12118
12119 if (os_strstr(cmd, "reset")) {
12120 resp_data.reset = true;
12121 resp_data.solicited = false;
12122 goto send_resp;
12123 }
12124
12125 resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
12126
12127 pos = os_strstr(cmd, "policy_id=");
12128 while (pos) {
12129 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
12130 if (!n)
12131 goto fail;
12132
12133 policy = n;
12134 pos += 10;
12135 policy[num_policies].id = atoi(pos);
12136 if (policy[num_policies].id == 0) {
12137 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
12138 goto fail;
12139 }
12140
12141 pos = os_strstr(pos, "status=");
12142 if (!pos) {
12143 wpa_printf(MSG_ERROR,
12144 "DSCP: Status is not found for a policy");
12145 goto fail;
12146 }
12147
12148 pos += 7;
12149 policy[num_policies].status = atoi(pos);
12150 num_policies++;
12151
12152 pos = os_strstr(pos, "policy_id");
12153 }
12154
12155 resp_data.policy = policy;
12156 resp_data.num_policies = num_policies;
12157send_resp:
12158 ret = wpas_send_dscp_response(wpa_s, &resp_data);
12159 if (ret)
12160 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
12161fail:
12162 os_free(policy);
12163 return ret;
12164}
12165
12166
12167static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
12168 const char *cmd)
12169{
12170 char *pos;
12171
12172 /*
12173 * format:
12174 * Wildcard DSCP query
12175 * <wildcard>
12176 *
12177 * DSCP query with a domain name attribute:
12178 * [domain_name=<string>]
12179 */
12180
12181 if (os_strstr(cmd, "wildcard")) {
12182 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
12183 return wpas_send_dscp_query(wpa_s, NULL, 0);
12184 }
12185
12186 pos = os_strstr(cmd, "domain_name=");
12187 if (!pos || !os_strlen(pos + 12)) {
12188 wpa_printf(MSG_ERROR, "QM: Domain name not preset");
12189 return -1;
12190 }
12191
12192 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
12193}
12194
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012195#endif /* CONFIG_NO_ROBUST_AV */
12196
Hai Shaloma20dcd72022-02-04 13:43:00 -080012197
Sunil Ravi89eba102022-09-13 21:04:37 -070012198static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
12199 char *buf, size_t buflen)
12200{
12201 int ret, i;
12202 char *pos, *end;
12203 struct wpa_mlo_signal_info mlo_si;
12204
12205 if (!wpa_s->valid_links)
12206 return -1;
12207
12208 ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si);
12209 if (ret)
12210 return -1;
12211
12212 pos = buf;
12213 end = buf + buflen;
12214
Sunil Ravi99c035e2024-07-12 01:42:03 +000012215 for_each_link(mlo_si.valid_links, i) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012216 ret = os_snprintf(pos, end - pos,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012217 "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
Sunil Ravi89eba102022-09-13 21:04:37 -070012218 "NOISE=%d\nFREQUENCY=%u\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012219 i, mlo_si.links[i].data.signal,
12220 mlo_si.links[i].data.current_tx_rate / 1000,
Sunil Ravi89eba102022-09-13 21:04:37 -070012221 mlo_si.links[i].current_noise,
12222 mlo_si.links[i].frequency);
12223 if (os_snprintf_error(end - pos, ret))
12224 return -1;
12225 pos += ret;
12226
12227 if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) {
12228 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
12229 channel_width_to_string(
12230 mlo_si.links[i].chanwidth));
12231 if (os_snprintf_error(end - pos, ret))
12232 return -1;
12233 pos += ret;
12234 }
12235
12236 if (mlo_si.links[i].center_frq1 > 0) {
12237 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
12238 mlo_si.links[i].center_frq1);
12239 if (os_snprintf_error(end - pos, ret))
12240 return -1;
12241 pos += ret;
12242 }
12243
12244 if (mlo_si.links[i].center_frq2 > 0) {
12245 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
12246 mlo_si.links[i].center_frq2);
12247 if (os_snprintf_error(end - pos, ret))
12248 return -1;
12249 pos += ret;
12250 }
12251
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012252 if (mlo_si.links[i].data.avg_signal) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012253 ret = os_snprintf(pos, end - pos,
12254 "AVG_RSSI=%d\n",
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012255 mlo_si.links[i].data.avg_signal);
Sunil Ravi89eba102022-09-13 21:04:37 -070012256 if (os_snprintf_error(end - pos, ret))
12257 return -1;
12258 pos += ret;
12259 }
12260
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000012261 if (mlo_si.links[i].data.avg_beacon_signal) {
12262 ret = os_snprintf(
12263 pos, end - pos, "AVG_BEACON_RSSI=%d\n",
12264 mlo_si.links[i].data.avg_beacon_signal);
Sunil Ravi89eba102022-09-13 21:04:37 -070012265 if (os_snprintf_error(end - pos, ret))
12266 return -1;
12267 pos += ret;
12268 }
12269 }
12270
12271 return pos - buf;
12272}
12273
12274
12275static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s,
12276 char *buf, size_t buflen)
12277{
12278 int ret, i;
12279 char *pos, *end;
12280
12281 if (!wpa_s->valid_links)
12282 return -1;
12283
12284 pos = buf;
12285 end = buf + buflen;
12286
Sunil Ravi99c035e2024-07-12 01:42:03 +000012287 for_each_link(wpa_s->valid_links, i) {
Sunil Ravi89eba102022-09-13 21:04:37 -070012288 ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n"
12289 "ap_link_addr=" MACSTR
12290 "\nsta_link_addr=" MACSTR "\n",
12291 i, wpa_s->links[i].freq,
12292 MAC2STR(wpa_s->links[i].bssid),
12293 MAC2STR(wpa_s->links[i].addr));
12294 if (os_snprintf_error(end - pos, ret))
12295 return pos - buf;
12296 pos += ret;
12297 }
12298
12299 return pos - buf;
12300}
12301
12302
Sunil Ravi2a14cf12023-11-21 00:54:38 +000012303#ifdef CONFIG_TESTING_OPTIONS
12304static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd)
12305{
12306 char *token, *context = NULL;
12307 u8 bssid[ETH_ALEN];
12308 int mld_id = -1, link_id = -1;
12309 struct wpa_bss *bss;
12310 int *freqs;
12311
12312 os_memset(bssid, 0, sizeof(bssid));
12313
12314 while ((token = str_token(cmd, " ", &context))) {
12315 if (os_strncmp(token, "bssid=", 6) == 0) {
12316 if (hwaddr_aton(token + 6, bssid))
12317 return -1;
12318 } else if (os_strncmp(token, "mld_id=", 7) == 0) {
12319 mld_id = atoi(token + 7);
12320 } else if (os_strncmp(token, "link_id=", 8) == 0) {
12321 link_id = atoi(token + 8);
12322 }
12323 }
12324
Sunil Ravi7f769292024-07-23 22:21:32 +000012325 if (is_zero_ether_addr(bssid)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +000012326 wpa_printf(MSG_DEBUG,
12327 "MLD: Failed parsing ML probe request arguments");
12328 return -1;
12329 }
12330
12331 bss = wpa_bss_get_bssid(wpa_s, bssid);
12332 if (!bss) {
12333 wpa_printf(MSG_DEBUG,
12334 "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid));
12335 return -1;
12336 }
12337
12338 if (wpa_s->sched_scanning || wpa_s->scanning ||
12339 (wpa_s->wpa_state > WPA_SCANNING &&
12340 wpa_s->wpa_state != WPA_COMPLETED)) {
12341 wpa_printf(MSG_DEBUG,
12342 "MLO: Ongoing scan: Reject ML probe request");
12343 return -1;
12344 }
12345
12346 freqs = os_malloc(sizeof(int) * 2);
12347 if (!freqs)
12348 return -1;
12349
12350 freqs[0] = bss->freq;
12351 freqs[1] = 0;
12352
12353 wpa_s->manual_scan_passive = 0;
12354 wpa_s->manual_scan_use_id = 0;
12355 wpa_s->manual_scan_only_new = 0;
12356 wpa_s->scan_id_count = 0;
12357 wpa_s->scan_res_handler = scan_only_handler;
12358 os_free(wpa_s->manual_scan_freqs);
12359 wpa_s->manual_scan_freqs = freqs;
12360
12361 os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN);
12362 wpa_s->ml_probe_mld_id = mld_id;
12363 if (link_id >= 0)
12364 wpa_s->ml_probe_links = BIT(link_id);
12365
12366 wpa_s->normal_scans = 0;
12367 wpa_s->scan_req = MANUAL_SCAN_REQ;
12368 wpa_s->after_wps = 0;
12369 wpa_s->known_wps_freq = 0;
12370 wpa_supplicant_req_scan(wpa_s, 0, 0);
12371
12372 return 0;
12373}
12374#endif /* CONFIG_TESTING_OPTIONS */
12375
12376
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012377#ifdef CONFIG_NAN_USD
12378
12379static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
12380 char *buf, size_t buflen)
12381{
12382 char *token, *context = NULL;
12383 int publish_id;
12384 struct nan_publish_params params;
12385 const char *service_name = NULL;
12386 struct wpabuf *ssi = NULL;
12387 int ret = -1;
12388 enum nan_service_protocol_type srv_proto_type = 0;
12389 int *freq_list = NULL;
Sunil Ravic0f5d412024-09-11 22:12:49 +000012390 bool p2p = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012391
12392 os_memset(&params, 0, sizeof(params));
12393 /* USD shall use both solicited and unsolicited transmissions */
12394 params.unsolicited = true;
12395 params.solicited = true;
12396 /* USD shall require FSD without GAS */
12397 params.fsd = true;
12398 params.freq = NAN_USD_DEFAULT_FREQ;
12399
12400 while ((token = str_token(cmd, " ", &context))) {
12401 if (os_strncmp(token, "service_name=", 13) == 0) {
12402 service_name = token + 13;
12403 continue;
12404 }
12405
12406 if (os_strncmp(token, "ttl=", 4) == 0) {
12407 params.ttl = atoi(token + 4);
12408 continue;
12409 }
12410
12411 if (os_strncmp(token, "freq=", 5) == 0) {
12412 params.freq = atoi(token + 5);
12413 continue;
12414 }
12415
12416 if (os_strncmp(token, "freq_list=", 10) == 0) {
12417 char *pos = token + 10;
12418
12419 if (os_strcmp(pos, "all") == 0) {
12420 os_free(freq_list);
12421 freq_list = wpas_nan_usd_all_freqs(wpa_s);
12422 params.freq_list = freq_list;
12423 continue;
12424 }
12425
12426 while (pos && pos[0]) {
12427 int_array_add_unique(&freq_list, atoi(pos));
12428 pos = os_strchr(pos, ',');
12429 if (pos)
12430 pos++;
12431 }
12432
12433 params.freq_list = freq_list;
12434 continue;
12435 }
12436
12437 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12438 srv_proto_type = atoi(token + 15);
12439 continue;
12440 }
12441
12442 if (os_strncmp(token, "ssi=", 4) == 0) {
12443 if (ssi)
12444 goto fail;
12445 ssi = wpabuf_parse_bin(token + 4);
12446 if (!ssi)
12447 goto fail;
12448 continue;
12449 }
12450
Sunil Ravic0f5d412024-09-11 22:12:49 +000012451 if (os_strcmp(token, "p2p=1") == 0) {
12452 p2p = true;
12453 continue;
12454 }
12455
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012456 if (os_strcmp(token, "solicited=0") == 0) {
12457 params.solicited = false;
12458 continue;
12459 }
12460
12461 if (os_strcmp(token, "unsolicited=0") == 0) {
12462 params.unsolicited = false;
12463 continue;
12464 }
12465
12466 if (os_strcmp(token, "fsd=0") == 0) {
12467 params.fsd = false;
12468 continue;
12469 }
12470
12471 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
12472 token);
12473 goto fail;
12474 }
12475
12476 publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
Sunil Ravic0f5d412024-09-11 22:12:49 +000012477 ssi, &params, p2p);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012478 if (publish_id > 0)
12479 ret = os_snprintf(buf, buflen, "%d", publish_id);
12480fail:
12481 wpabuf_free(ssi);
12482 os_free(freq_list);
12483 return ret;
12484}
12485
12486
12487static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
12488 char *cmd)
12489{
12490 char *token, *context = NULL;
12491 int publish_id = 0;
12492
12493 while ((token = str_token(cmd, " ", &context))) {
12494 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12495 continue;
12496 wpa_printf(MSG_INFO,
12497 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
12498 token);
12499 return -1;
12500 }
12501
12502 if (publish_id <= 0) {
12503 wpa_printf(MSG_INFO,
12504 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
12505 return -1;
12506 }
12507
12508 wpas_nan_usd_cancel_publish(wpa_s, publish_id);
12509 return 0;
12510}
12511
12512
12513static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
12514 char *cmd)
12515{
12516 char *token, *context = NULL;
12517 int publish_id = 0;
12518 struct wpabuf *ssi = NULL;
12519 int ret = -1;
12520
12521 while ((token = str_token(cmd, " ", &context))) {
12522 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
12523 continue;
12524 if (os_strncmp(token, "ssi=", 4) == 0) {
12525 if (ssi)
12526 goto fail;
12527 ssi = wpabuf_parse_bin(token + 4);
12528 if (!ssi)
12529 goto fail;
12530 continue;
12531 }
12532 wpa_printf(MSG_INFO,
12533 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
12534 token);
12535 goto fail;
12536 }
12537
12538 if (publish_id <= 0) {
12539 wpa_printf(MSG_INFO,
12540 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
12541 goto fail;
12542 }
12543
12544 ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
12545fail:
12546 wpabuf_free(ssi);
12547 return ret;
12548}
12549
12550
12551static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
12552 char *buf, size_t buflen)
12553{
12554 char *token, *context = NULL;
12555 int subscribe_id;
12556 struct nan_subscribe_params params;
12557 const char *service_name = NULL;
12558 struct wpabuf *ssi = NULL;
12559 int ret = -1;
12560 enum nan_service_protocol_type srv_proto_type = 0;
Sunil Ravic0f5d412024-09-11 22:12:49 +000012561 int *freq_list = NULL;
12562 bool p2p = false;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012563
12564 os_memset(&params, 0, sizeof(params));
12565 params.freq = NAN_USD_DEFAULT_FREQ;
12566
12567 while ((token = str_token(cmd, " ", &context))) {
12568 if (os_strncmp(token, "service_name=", 13) == 0) {
12569 service_name = token + 13;
12570 continue;
12571 }
12572
12573 if (os_strcmp(token, "active=1") == 0) {
12574 params.active = true;
12575 continue;
12576 }
12577
12578 if (os_strncmp(token, "ttl=", 4) == 0) {
12579 params.ttl = atoi(token + 4);
12580 continue;
12581 }
12582
12583 if (os_strncmp(token, "freq=", 5) == 0) {
12584 params.freq = atoi(token + 5);
12585 continue;
12586 }
12587
Sunil Ravic0f5d412024-09-11 22:12:49 +000012588 if (os_strncmp(token, "freq_list=", 10) == 0) {
12589 char *pos = token + 10;
12590
12591 if (os_strcmp(pos, "all") == 0) {
12592 os_free(freq_list);
12593 freq_list = wpas_nan_usd_all_freqs(wpa_s);
12594 params.freq_list = freq_list;
12595 continue;
12596 }
12597
12598 while (pos && pos[0]) {
12599 int_array_add_unique(&freq_list, atoi(pos));
12600 pos = os_strchr(pos, ',');
12601 if (pos)
12602 pos++;
12603 }
12604
12605 params.freq_list = freq_list;
12606 continue;
12607 }
12608
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012609 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
12610 srv_proto_type = atoi(token + 15);
12611 continue;
12612 }
12613
12614 if (os_strncmp(token, "ssi=", 4) == 0) {
12615 if (ssi)
12616 goto fail;
12617 ssi = wpabuf_parse_bin(token + 4);
12618 if (!ssi)
12619 goto fail;
12620 continue;
12621 }
12622
Sunil Ravic0f5d412024-09-11 22:12:49 +000012623 if (os_strcmp(token, "p2p=1") == 0) {
12624 p2p = true;
12625 continue;
12626 }
12627
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012628 wpa_printf(MSG_INFO,
12629 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
12630 token);
12631 goto fail;
12632 }
12633
12634 subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
12635 srv_proto_type, ssi,
Sunil Ravic0f5d412024-09-11 22:12:49 +000012636 &params, p2p);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012637 if (subscribe_id > 0)
12638 ret = os_snprintf(buf, buflen, "%d", subscribe_id);
12639fail:
12640 wpabuf_free(ssi);
Sunil Ravic0f5d412024-09-11 22:12:49 +000012641 os_free(freq_list);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000012642 return ret;
12643}
12644
12645
12646static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
12647 char *cmd)
12648{
12649 char *token, *context = NULL;
12650 int subscribe_id = 0;
12651
12652 while ((token = str_token(cmd, " ", &context))) {
12653 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
12654 continue;
12655 wpa_printf(MSG_INFO,
12656 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
12657 token);
12658 return -1;
12659 }
12660
12661 if (subscribe_id <= 0) {
12662 wpa_printf(MSG_INFO,
12663 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
12664 return -1;
12665 }
12666
12667 wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
12668 return 0;
12669}
12670
12671
12672static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
12673{
12674 char *token, *context = NULL;
12675 int handle = 0;
12676 int req_instance_id = 0;
12677 struct wpabuf *ssi = NULL;
12678 u8 peer_addr[ETH_ALEN];
12679 int ret = -1;
12680
12681 os_memset(peer_addr, 0, ETH_ALEN);
12682
12683 while ((token = str_token(cmd, " ", &context))) {
12684 if (sscanf(token, "handle=%i", &handle) == 1)
12685 continue;
12686
12687 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
12688 continue;
12689
12690 if (os_strncmp(token, "address=", 8) == 0) {
12691 if (hwaddr_aton(token + 8, peer_addr) < 0)
12692 return -1;
12693 continue;
12694 }
12695
12696 if (os_strncmp(token, "ssi=", 4) == 0) {
12697 if (ssi)
12698 goto fail;
12699 ssi = wpabuf_parse_bin(token + 4);
12700 if (!ssi)
12701 goto fail;
12702 continue;
12703 }
12704
12705 wpa_printf(MSG_INFO,
12706 "CTRL: Invalid NAN_TRANSMIT parameter: %s",
12707 token);
12708 goto fail;
12709 }
12710
12711 if (handle <= 0) {
12712 wpa_printf(MSG_INFO,
12713 "CTRL: Invalid or missing NAN_TRANSMIT handle");
12714 goto fail;
12715 }
12716
12717 if (is_zero_ether_addr(peer_addr)) {
12718 wpa_printf(MSG_INFO,
12719 "CTRL: Invalid or missing NAN_TRANSMIT address");
12720 goto fail;
12721 }
12722
12723 ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
12724 req_instance_id);
12725fail:
12726 wpabuf_free(ssi);
12727 return ret;
12728}
12729
12730#endif /* CONFIG_NAN_USD */
12731
12732
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012733char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
12734 char *buf, size_t *resp_len)
12735{
12736 char *reply;
12737 const int reply_size = 4096;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012738 int reply_len;
12739
12740 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012741 os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
12742 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
12743 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012744 if (wpa_debug_show_keys)
12745 wpa_dbg(wpa_s, MSG_DEBUG,
12746 "Control interface command '%s'", buf);
12747 else
12748 wpa_dbg(wpa_s, MSG_DEBUG,
12749 "Control interface command '%s [REMOVED]'",
12750 os_strncmp(buf, WPA_CTRL_RSP,
12751 os_strlen(WPA_CTRL_RSP)) == 0 ?
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070012752 WPA_CTRL_RSP :
12753 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
12754 "SET_NETWORK" : "key-add"));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012755 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
Dmitry Shmidt21de2142014-04-08 10:50:52 -070012756 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012757 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
12758 (const u8 *) buf, os_strlen(buf));
12759 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080012760 int level = wpas_ctrl_cmd_debug_level(buf);
Dmitry Shmidtaa532512012-09-24 10:35:31 -070012761 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012762 }
12763
12764 reply = os_malloc(reply_size);
12765 if (reply == NULL) {
12766 *resp_len = 1;
12767 return NULL;
12768 }
12769
12770 os_memcpy(reply, "OK\n", 3);
12771 reply_len = 3;
12772
12773 if (os_strcmp(buf, "PING") == 0) {
12774 os_memcpy(reply, "PONG\n", 5);
12775 reply_len = 5;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070012776 } else if (os_strcmp(buf, "IFNAME") == 0) {
12777 reply_len = os_strlen(wpa_s->ifname);
12778 os_memcpy(reply, wpa_s->ifname, reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012779 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
12780 if (wpa_debug_reopen_file() < 0)
12781 reply_len = -1;
12782 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
12783 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
12784 } else if (os_strcmp(buf, "MIB") == 0) {
12785 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
12786 if (reply_len >= 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012787 reply_len += eapol_sm_get_mib(wpa_s->eapol,
12788 reply + reply_len,
12789 reply_size - reply_len);
Hai Shalom74f70d42019-02-11 14:42:39 -080012790#ifdef CONFIG_MACSEC
12791 reply_len += ieee802_1x_kay_get_mib(
12792 wpa_s->kay, reply + reply_len,
12793 reply_size - reply_len);
12794#endif /* CONFIG_MACSEC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012795 }
12796 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
12797 reply_len = wpa_supplicant_ctrl_iface_status(
12798 wpa_s, buf + 6, reply, reply_size);
12799 } else if (os_strcmp(buf, "PMKSA") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070012800 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070012801 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070012802 wpas_ctrl_iface_pmksa_flush(wpa_s);
Dmitry Shmidt29333592017-01-09 12:27:11 -080012803#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
12804 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
12805 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
12806 reply, reply_size);
12807 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
12808 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
12809 reply_len = -1;
Paul Stewart092955c2017-02-06 09:13:09 -080012810#ifdef CONFIG_MESH
12811 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
12812 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
12813 reply, reply_size);
12814 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
12815 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
12816 reply_len = -1;
12817#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -080012818#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012819 } else if (os_strncmp(buf, "SET ", 4) == 0) {
12820 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
12821 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080012822 } else if (os_strncmp(buf, "DUMP", 4) == 0) {
12823 reply_len = wpa_config_dump_values(wpa_s->conf,
12824 reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012825 } else if (os_strncmp(buf, "GET ", 4) == 0) {
12826 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
12827 reply, reply_size);
12828 } else if (os_strcmp(buf, "LOGON") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070012829 eapol_sm_notify_logoff(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012830 } else if (os_strcmp(buf, "LOGOFF") == 0) {
Hai Shalome21d4e82020-04-29 16:34:06 -070012831 eapol_sm_notify_logoff(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012832 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
12833 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12834 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012835 else
12836 wpas_request_connection(wpa_s);
Dmitry Shmidt98660862014-03-11 17:26:21 -070012837 } else if (os_strcmp(buf, "REATTACH") == 0) {
12838 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
12839 !wpa_s->current_ssid)
12840 reply_len = -1;
12841 else {
12842 wpa_s->reattach = 1;
12843 wpas_request_connection(wpa_s);
12844 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012845 } else if (os_strcmp(buf, "RECONNECT") == 0) {
12846 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
12847 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012848 else if (wpa_s->disconnected)
12849 wpas_request_connection(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012850#ifdef IEEE8021X_EAPOL
12851 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
12852 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
12853 reply_len = -1;
12854#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012855#ifdef CONFIG_IEEE80211R
12856 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
12857 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
12858 reply_len = -1;
12859#endif /* CONFIG_IEEE80211R */
12860#ifdef CONFIG_WPS
12861 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
12862 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
12863 if (res == -2) {
12864 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12865 reply_len = 17;
12866 } else if (res)
12867 reply_len = -1;
12868 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
12869 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
12870 if (res == -2) {
12871 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12872 reply_len = 17;
12873 } else if (res)
12874 reply_len = -1;
12875 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
12876 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
12877 reply,
12878 reply_size);
12879 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
12880 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
12881 wpa_s, buf + 14, reply, reply_size);
12882 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
12883 if (wpas_wps_cancel(wpa_s))
12884 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012885#ifdef CONFIG_WPS_NFC
12886 } else if (os_strcmp(buf, "WPS_NFC") == 0) {
12887 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
12888 reply_len = -1;
12889 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
12890 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
12891 reply_len = -1;
Dmitry Shmidtf8623282013-02-20 14:34:59 -080012892 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
12893 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
12894 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070012895 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
12896 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
12897 wpa_s, buf + 14, reply, reply_size);
12898 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
12899 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
12900 buf + 17))
12901 reply_len = -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080012902 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
12903 reply_len = wpas_ctrl_nfc_get_handover_req(
12904 wpa_s, buf + 21, reply, reply_size);
12905 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
12906 reply_len = wpas_ctrl_nfc_get_handover_sel(
12907 wpa_s, buf + 21, reply, reply_size);
Dmitry Shmidtf8623282013-02-20 14:34:59 -080012908 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
12909 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
12910 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012911#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012912 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
12913 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
12914 reply_len = -1;
12915#ifdef CONFIG_AP
12916 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
12917 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
12918 wpa_s, buf + 11, reply, reply_size);
12919#endif /* CONFIG_AP */
12920#ifdef CONFIG_WPS_ER
12921 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
12922 if (wpas_wps_er_start(wpa_s, NULL))
12923 reply_len = -1;
12924 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
12925 if (wpas_wps_er_start(wpa_s, buf + 13))
12926 reply_len = -1;
12927 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012928 wpas_wps_er_stop(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012929 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
12930 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
12931 reply_len = -1;
12932 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
12933 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
12934 if (ret == -2) {
12935 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
12936 reply_len = 17;
12937 } else if (ret == -3) {
12938 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
12939 reply_len = 18;
12940 } else if (ret == -4) {
12941 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
12942 reply_len = 20;
12943 } else if (ret)
12944 reply_len = -1;
12945 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
12946 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
12947 reply_len = -1;
12948 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
12949 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
12950 buf + 18))
12951 reply_len = -1;
12952 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
12953 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
12954 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070012955#ifdef CONFIG_WPS_NFC
12956 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
12957 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
12958 wpa_s, buf + 24, reply, reply_size);
12959#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012960#endif /* CONFIG_WPS_ER */
12961#endif /* CONFIG_WPS */
12962#ifdef CONFIG_IBSS_RSN
12963 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
12964 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
12965 reply_len = -1;
12966#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012967#ifdef CONFIG_MESH
12968 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
12969 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12970 wpa_s, buf + 19, reply, reply_size);
12971 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
12972 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
12973 wpa_s, "", reply, reply_size);
12974 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
12975 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
12976 reply_len = -1;
12977 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
12978 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
12979 buf + 18))
12980 reply_len = -1;
Dmitry Shmidte4663042016-04-04 10:07:49 -070012981 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
12982 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
12983 reply_len = -1;
12984 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
12985 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
12986 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070012987 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) {
12988 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16))
12989 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080012990#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012991#ifdef CONFIG_P2P
12992 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -080012993 if (p2p_ctrl_find(wpa_s, buf + 8))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012994 reply_len = -1;
12995 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
12996 if (p2p_ctrl_find(wpa_s, ""))
12997 reply_len = -1;
12998 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
12999 wpas_p2p_stop_find(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -080013000 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
13001 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
13002 reply_len = -1;
13003 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
13004 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
13005 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013006 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
13007 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
13008 reply_size);
13009 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
13010 if (p2p_ctrl_listen(wpa_s, buf + 11))
13011 reply_len = -1;
13012 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
13013 if (p2p_ctrl_listen(wpa_s, ""))
13014 reply_len = -1;
13015 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
13016 if (wpas_p2p_group_remove(wpa_s, buf + 17))
13017 reply_len = -1;
13018 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -070013019 if (p2p_ctrl_group_add(wpa_s, ""))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013020 reply_len = -1;
13021 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
13022 if (p2p_ctrl_group_add(wpa_s, buf + 14))
13023 reply_len = -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013024 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
13025 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
13026 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013027 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
13028 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
13029 reply_len = -1;
13030 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
13031 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000013032#ifdef CONFIG_PASN
13033#ifdef CONFIG_TESTING_OPTIONS
13034 } else if (os_strcmp(buf, "P2P_GET_PASNPTK") == 0) {
13035 reply_len = p2p_ctrl_get_pasn_ptk(wpa_s, reply, reply_size);
13036#endif /* CONFIG_TESTING_OPTIONS */
13037#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013038 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
13039 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
13040 reply_size);
13041 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
13042 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
13043 reply_len = -1;
13044 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
13045 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
13046 reply_len = -1;
13047 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
13048 wpas_p2p_sd_service_update(wpa_s);
13049 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
13050 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
13051 reply_len = -1;
13052 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
13053 wpas_p2p_service_flush(wpa_s);
13054 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
13055 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
13056 reply_len = -1;
13057 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
13058 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
13059 reply_len = -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -080013060 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
13061 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
13062 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013063 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
13064 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
13065 reply_len = -1;
13066 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
13067 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
13068 reply_len = -1;
13069 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
13070 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
13071 reply_size);
13072 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
13073 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
13074 reply_len = -1;
13075 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
Dmitry Shmidt444d5672013-04-01 13:08:44 -070013076 p2p_ctrl_flush(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013077 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
13078 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
13079 reply_len = -1;
13080 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
13081 if (wpas_p2p_cancel(wpa_s))
13082 reply_len = -1;
13083 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
13084 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
13085 reply_len = -1;
13086 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
13087 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
13088 reply_len = -1;
13089 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
13090 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
13091 reply_len = -1;
13092 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
13093 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
13094 reply_len = -1;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070013095 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
13096 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
13097 reply_len = -1;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070013098 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
13099 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
13100 reply_len = -1;
13101 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
13102 if (wpas_p2p_lo_stop(wpa_s))
13103 reply_len = -1;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000013104 } else if (os_strcmp(buf, "P2P_REMOVE_IDENTITY") == 0) {
13105 if (wpas_p2p_remove_all_identity(wpa_s))
13106 reply_len = -1;
13107#ifdef CONFIG_TESTING_OPTIONS
13108 } else if (os_strncmp(buf, "P2P_PMK_GET", 12) == 0) {
13109 reply_len = p2p_ctrl_pmk_get(wpa_s, reply, reply_size);
13110#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013111#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070013112#ifdef CONFIG_WIFI_DISPLAY
13113 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
13114 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
13115 reply_len = -1;
13116 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
13117 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
13118 reply, reply_size);
13119#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013120#ifdef CONFIG_INTERWORKING
13121 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
13122 if (interworking_fetch_anqp(wpa_s) < 0)
13123 reply_len = -1;
13124 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
13125 interworking_stop_fetch_anqp(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080013126 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
13127 if (ctrl_interworking_select(wpa_s, NULL) < 0)
13128 reply_len = -1;
13129 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
13130 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013131 reply_len = -1;
13132 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -080013133 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013134 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080013135 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
13136 int id;
13137
13138 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
13139 if (id < 0)
13140 reply_len = -1;
13141 else {
13142 reply_len = os_snprintf(reply, reply_size, "%d\n", id);
13143 if (os_snprintf_error(reply_size, reply_len))
13144 reply_len = -1;
13145 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013146 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
13147 if (get_anqp(wpa_s, buf + 9) < 0)
13148 reply_len = -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070013149 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
13150 if (gas_request(wpa_s, buf + 12) < 0)
13151 reply_len = -1;
13152 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
13153 reply_len = gas_response_get(wpa_s, buf + 17, reply,
13154 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013155#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -070013156#ifdef CONFIG_HS20
13157 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
13158 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
13159 reply_len = -1;
13160 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
13161 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
13162 reply_len = -1;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080013163 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080013164 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
13165 reply_len = -1;
13166 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
13167 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
13168 reply_len = -1;
13169 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
13170 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
13171 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
13172 if (del_hs20_icon(wpa_s, buf + 14) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080013173 reply_len = -1;
13174 } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070013175 if (hs20_fetch_osu(wpa_s, 0) < 0)
13176 reply_len = -1;
13177 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
13178 if (hs20_fetch_osu(wpa_s, 1) < 0)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080013179 reply_len = -1;
13180 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
13181 hs20_cancel_fetch_osu(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -070013182#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013183 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
13184 {
13185 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
13186 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
13187 reply_len = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -070013188 else {
13189 /*
13190 * Notify response from timeout to allow the control
13191 * interface response to be sent first.
13192 */
13193 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
13194 wpa_s, NULL);
13195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013196 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
13197 if (wpa_supplicant_reload_configuration(wpa_s))
13198 reply_len = -1;
13199 } else if (os_strcmp(buf, "TERMINATE") == 0) {
13200 wpa_supplicant_terminate_proc(wpa_s->global);
13201 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
13202 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
13203 reply_len = -1;
Hai Shalom60840252021-02-19 19:02:11 -080013204 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
13205 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
13206 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidte19501d2011-03-16 14:32:18 -070013207 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
Hai Shalom60840252021-02-19 19:02:11 -080013208 /* deprecated backwards compatibility alias for BSSID_IGNORE */
13209 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013210 wpa_s, buf + 9, reply, reply_size);
13211 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
13212 reply_len = wpa_supplicant_ctrl_iface_log_level(
13213 wpa_s, buf + 9, reply, reply_size);
Vinit Deshpandeda134e92014-12-02 10:59:29 -080013214 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
13215 reply_len = wpa_supplicant_ctrl_iface_list_networks(
13216 wpa_s, buf + 14, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013217 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
13218 reply_len = wpa_supplicant_ctrl_iface_list_networks(
Vinit Deshpandeda134e92014-12-02 10:59:29 -080013219 wpa_s, NULL, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013220 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070013221 wpas_request_disconnection(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080013222 } else if (os_strcmp(buf, "SCAN") == 0) {
13223 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
13224 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
13225 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013226 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
13227 reply_len = wpa_supplicant_ctrl_iface_scan_results(
13228 wpa_s, reply, reply_size);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013229 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
13230 if (wpas_abort_ongoing_scan(wpa_s) < 0)
13231 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013232 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
13233 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
13234 reply_len = -1;
13235 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
13236 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
13237 reply_len = -1;
13238 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
13239 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
13240 reply_len = -1;
13241 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
13242 reply_len = wpa_supplicant_ctrl_iface_add_network(
13243 wpa_s, reply, reply_size);
13244 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
13245 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
13246 reply_len = -1;
13247 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
13248 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
13249 reply_len = -1;
13250 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
13251 reply_len = wpa_supplicant_ctrl_iface_get_network(
13252 wpa_s, buf + 12, reply, reply_size);
Dmitry Shmidt684785c2014-05-12 13:34:29 -070013253 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013254 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12,
13255 wpa_s))
Dmitry Shmidt684785c2014-05-12 13:34:29 -070013256 reply_len = -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -070013257 } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
13258 reply_len = wpa_supplicant_ctrl_iface_list_creds(
13259 wpa_s, reply, reply_size);
13260 } else if (os_strcmp(buf, "ADD_CRED") == 0) {
13261 reply_len = wpa_supplicant_ctrl_iface_add_cred(
13262 wpa_s, reply, reply_size);
13263 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
13264 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
13265 reply_len = -1;
13266 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
13267 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
13268 reply_len = -1;
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -070013269 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
13270 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
13271 reply,
13272 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013273#ifndef CONFIG_NO_CONFIG_WRITE
13274 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
13275 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
13276 reply_len = -1;
13277#endif /* CONFIG_NO_CONFIG_WRITE */
13278 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
13279 reply_len = wpa_supplicant_ctrl_iface_get_capability(
13280 wpa_s, buf + 15, reply, reply_size);
13281 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
13282 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
13283 reply_len = -1;
13284 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
13285 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
13286 reply_len = -1;
13287 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
13288 reply_len = wpa_supplicant_global_iface_list(
13289 wpa_s->global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013290 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013291 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080013292 wpa_s->global, buf + 10, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013293 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
13294 reply_len = wpa_supplicant_ctrl_iface_bss(
13295 wpa_s, buf + 4, reply, reply_size);
13296#ifdef CONFIG_AP
13297 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
13298 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13299 } else if (os_strncmp(buf, "STA ", 4) == 0) {
13300 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
13301 reply_size);
13302 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13303 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13304 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070013305 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13306 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13307 reply_len = -1;
13308 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13309 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13310 reply_len = -1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080013311 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13312 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13313 reply_len = -1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -080013314 } else if (os_strcmp(buf, "STOP_AP") == 0) {
13315 if (wpas_ap_stop_ap(wpa_s))
13316 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013317 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
13318 if (wpas_ap_update_beacon(wpa_s))
13319 reply_len = -1;
Sunil Ravia04bd252022-05-02 22:54:18 -070013320 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
13321 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
13322 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13323 DENY_UNLESS_ACCEPTED,
13324 buf + 19) ||
13325 ap_ctrl_iface_set_acl(wpa_s))
13326 reply_len = -1;
13327 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
13328 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13329 DENY_UNLESS_ACCEPTED,
13330 buf + 19) ||
13331 ap_ctrl_iface_set_acl(wpa_s) ||
13332 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13333 reply_len = -1;
13334 } else if (os_strcmp(buf + 11, "SHOW") == 0) {
13335 reply_len = ap_ctrl_iface_acl_show_mac(
13336 wpa_s, DENY_UNLESS_ACCEPTED,
13337 reply, reply_size);
13338 } else if (os_strcmp(buf + 11, "CLEAR") == 0) {
13339 ap_ctrl_iface_acl_clear_list(wpa_s,
13340 DENY_UNLESS_ACCEPTED);
13341 if (ap_ctrl_iface_set_acl(wpa_s) ||
13342 ap_ctrl_iface_disassoc_accept_mac(wpa_s))
13343 reply_len = -1;
13344 } else {
13345 reply_len = -1;
13346 }
13347 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
13348 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
13349 if (ap_ctrl_iface_acl_add_mac(wpa_s,
13350 ACCEPT_UNLESS_DENIED,
13351 buf + 17) ||
13352 ap_ctrl_iface_set_acl(wpa_s) ||
13353 ap_ctrl_iface_disassoc_deny_mac(wpa_s))
13354 reply_len = -1;
13355 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
13356 if (ap_ctrl_iface_acl_del_mac(wpa_s,
13357 ACCEPT_UNLESS_DENIED,
13358 buf + 17) ||
13359 ap_ctrl_iface_set_acl(wpa_s))
13360 reply_len = -1;
13361 } else if (os_strcmp(buf + 9, "SHOW") == 0) {
13362 reply_len = ap_ctrl_iface_acl_show_mac(
13363 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size);
13364 } else if (os_strcmp(buf + 9, "CLEAR") == 0) {
13365 ap_ctrl_iface_acl_clear_list(wpa_s,
13366 ACCEPT_UNLESS_DENIED);
13367 if (ap_ctrl_iface_set_acl(wpa_s))
13368 reply_len = -1;
13369 } else {
13370 reply_len = -1;
13371 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013372#endif /* CONFIG_AP */
13373 } else if (os_strcmp(buf, "SUSPEND") == 0) {
13374 wpas_notify_suspend(wpa_s->global);
13375 } else if (os_strcmp(buf, "RESUME") == 0) {
13376 wpas_notify_resume(wpa_s->global);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070013377#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013378 } else if (os_strcmp(buf, "DROP_SA") == 0) {
13379 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
Dmitry Shmidt21de2142014-04-08 10:50:52 -070013380#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013381 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
13382 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
13383 reply_len = -1;
13384 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013385 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013386 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
13387 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
13388 reply_len = -1;
13389 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
13390 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
13391 buf + 17))
13392 reply_len = -1;
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -070013393 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013394 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013395#ifdef CONFIG_TDLS
13396 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
13397 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
13398 reply_len = -1;
13399 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
13400 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
13401 reply_len = -1;
13402 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
13403 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
13404 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013405 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
13406 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
13407 buf + 17))
13408 reply_len = -1;
13409 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
13410 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
13411 buf + 24))
13412 reply_len = -1;
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -070013413 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) {
13414 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status(
13415 wpa_s, buf + 17, reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013416#endif /* CONFIG_TDLS */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013417#ifndef CONFIG_NO_WMM_AC
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013418 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
13419 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
13420 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
13421 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
13422 reply_len = -1;
13423 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
13424 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
13425 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013426#endif /* CONFIG_NO_WMM_AC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013427 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
13428 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
13429 reply_size);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -080013430 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
13431 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
13432 reply_len = -1;
Yuhao Zhengfcd6f212012-07-27 10:37:52 -070013433 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
13434 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
13435 reply_size);
Dmitry Shmidt04949592012-07-19 12:16:46 -070013436#ifdef CONFIG_AUTOSCAN
13437 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
13438 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
13439 reply_len = -1;
13440#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070013441 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
13442 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
13443 reply_size);
Hai Shalomb755a2a2020-04-23 21:49:02 -070013444 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
13445 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply,
13446 reply_size);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080013447#ifdef ANDROID
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -070013448 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
13449 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
13450 reply_size);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080013451#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080013452 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
13453 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
13454 reply_size);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013455 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080013456 pmksa_cache_clear_current(wpa_s->wpa);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013457 eapol_sm_request_reauth(wpa_s->eapol);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080013458#ifdef CONFIG_WNM
13459 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
13460 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
13461 reply_len = -1;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080013462 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
13463 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
Dmitry Shmidt44c95782013-05-17 09:51:35 -070013464 reply_len = -1;
Hai Shalom39ba6fc2019-01-22 12:40:38 -080013465 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
13466 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13467 reply_len = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080013468#endif /* CONFIG_WNM */
Sunil Ravia04bd252022-05-02 22:54:18 -070013469#ifdef CONFIG_WNM_AP
13470 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13471 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13472 reply_len = -1;
13473 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
13474 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13))
13475 reply_len = -1;
13476 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13477 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13478 reply_len = -1;
13479#endif /* CONFIG_WNM_AP */
Dmitry Shmidt444d5672013-04-01 13:08:44 -070013480 } else if (os_strcmp(buf, "FLUSH") == 0) {
13481 wpa_supplicant_ctrl_iface_flush(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080013482 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13483 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
13484 reply_size);
Dmitry Shmidt818ea482014-03-10 13:15:21 -070013485#ifdef CONFIG_TESTING_OPTIONS
13486 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
13487 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
13488 reply_len = -1;
13489 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
13490 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013491 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
13492 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
13493 reply_len = -1;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -070013494 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
13495 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
13496 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013497 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
13498 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
13499 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013500 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
13501 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
13502 reply_len = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013503 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
13504 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
13505 reply_len = -1;
13506 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
13507 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
13508 reply_len = -1;
13509 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
13510 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
13511 reply_len = -1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080013512 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013513 if (testing_set_fail_pattern(true, buf + 16) < 0)
Dmitry Shmidtff787d52015-01-12 13:01:47 -080013514 reply_len = -1;
13515 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013516 reply_len = testing_get_fail_pattern(true, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013517 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013518 if (testing_set_fail_pattern(false, buf + 10) < 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013519 reply_len = -1;
13520 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013521 reply_len = testing_get_fail_pattern(false, reply, reply_size);
Jouni Malinenc4818362015-10-04 11:45:13 +030013522 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
13523 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
13524 reply_len = -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -080013525 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
13526 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
13527 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013528 } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
13529 if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
13530 reply_len = -1;
13531 } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
13532 if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
13533 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013534 } else if (os_strcmp(buf, "RESET_PN") == 0) {
13535 if (wpas_ctrl_reset_pn(wpa_s) < 0)
13536 reply_len = -1;
13537 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
13538 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
13539 reply_len = -1;
13540 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
13541 if (wpas_ctrl_resend_assoc(wpa_s) < 0)
13542 reply_len = -1;
Hai Shalom74f70d42019-02-11 14:42:39 -080013543 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
13544 sme_event_unprot_disconnect(
13545 wpa_s, wpa_s->bssid, NULL,
13546 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
Hai Shaloma20dcd72022-02-04 13:43:00 -080013547 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
13548 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
13549 reply_len = -1;
13550 } else if (os_strcmp(buf, "TWT_SETUP") == 0) {
13551 if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
13552 reply_len = -1;
13553 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
13554 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
13555 reply_len = -1;
13556 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
13557 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
13558 reply_len = -1;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000013559 } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
13560 if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
13561 reply_len = -1;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000013562 } else if (os_strncmp(buf, "TEST_RSNXE_DATA ", 16) == 0) {
13563 if (wpas_ctrl_test_rsnxe_data(wpa_s, buf + 16) < 0)
13564 reply_len = -1;
Dmitry Shmidt818ea482014-03-10 13:15:21 -070013565#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070013566 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
13567 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
13568 reply_len = -1;
13569 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
13570 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
13571 reply_size);
13572 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
13573 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
13574 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013575#ifndef CONFIG_NO_RRM
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013576 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
Dmitry Shmidt849734c2016-05-27 09:59:01 -070013577 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013578 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013579#endif /* CONFIG_NO_RRM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080013580 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
13581 wpas_ctrl_iface_erp_flush(wpa_s);
13582 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
13583 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
13584 reply_len = -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080013585 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
13586 reply_len = wpas_ctrl_iface_get_pref_freq_list(
13587 wpa_s, buf + 19, reply, reply_size);
Paul Stewart092955c2017-02-06 09:13:09 -080013588#ifdef CONFIG_FILS
13589 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
13590 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
13591 reply_len = -1;
13592 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
13593 wpas_flush_fils_hlp_req(wpa_s);
13594#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013595#ifdef CONFIG_DPP
13596 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
13597 int res;
13598
13599 res = wpas_dpp_qr_code(wpa_s, buf + 12);
13600 if (res < 0) {
13601 reply_len = -1;
13602 } else {
13603 reply_len = os_snprintf(reply, reply_size, "%d", res);
13604 if (os_snprintf_error(reply_size, reply_len))
13605 reply_len = -1;
13606 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080013607 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
13608 int res;
13609
13610 res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
13611 if (res < 0) {
13612 reply_len = -1;
13613 } else {
13614 reply_len = os_snprintf(reply, reply_size, "%d", res);
13615 if (os_snprintf_error(reply_size, reply_len))
13616 reply_len = -1;
13617 }
Hai Shalomfdcde762020-04-02 11:19:20 -070013618 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
13619 int res;
13620
13621 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
13622 if (res < 0) {
13623 reply_len = -1;
13624 } else {
13625 reply_len = os_snprintf(reply, reply_size, "%d", res);
13626 if (os_snprintf_error(reply_size, reply_len))
13627 reply_len = -1;
13628 }
13629 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
13630 int res;
13631
13632 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
13633 if (res < 0) {
13634 reply_len = -1;
13635 } else {
13636 reply_len = os_snprintf(reply, reply_size, "%d", res);
13637 if (os_snprintf_error(reply_size, reply_len))
13638 reply_len = -1;
13639 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013640 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
13641 int res;
13642
Hai Shalom021b0b52019-04-10 11:17:58 -070013643 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013644 if (res < 0) {
13645 reply_len = -1;
13646 } else {
13647 reply_len = os_snprintf(reply, reply_size, "%d", res);
13648 if (os_snprintf_error(reply_size, reply_len))
13649 reply_len = -1;
13650 }
13651 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013652 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013653 reply_len = -1;
13654 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
13655 const char *uri;
13656
Hai Shalom021b0b52019-04-10 11:17:58 -070013657 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013658 if (!uri) {
13659 reply_len = -1;
13660 } else {
13661 reply_len = os_snprintf(reply, reply_size, "%s", uri);
13662 if (os_snprintf_error(reply_size, reply_len))
13663 reply_len = -1;
13664 }
13665 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013666 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
13667 reply, reply_size);
Hai Shalomfdcde762020-04-02 11:19:20 -070013668 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
13669 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18),
13670 os_strchr(buf + 18, ' ')) < 0)
13671 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013672 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
13673 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
13674 reply_len = -1;
13675 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
13676 if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
13677 reply_len = -1;
13678 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -070013679 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013680 wpas_dpp_listen_stop(wpa_s);
13681 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
13682 int res;
13683
Hai Shalom021b0b52019-04-10 11:17:58 -070013684 res = dpp_configurator_add(wpa_s->dpp, buf + 20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013685 if (res < 0) {
13686 reply_len = -1;
13687 } else {
13688 reply_len = os_snprintf(reply, reply_size, "%d", res);
13689 if (os_snprintf_error(reply_size, reply_len))
13690 reply_len = -1;
13691 }
Sunil Ravia04bd252022-05-02 22:54:18 -070013692 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
13693 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0)
13694 reply_len = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013695 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013696 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013697 reply_len = -1;
13698 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -080013699 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013700 reply_len = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -070013701 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -070013702 reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
13703 atoi(buf + 25),
13704 reply, reply_size);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013705 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
13706 int res;
13707
13708 res = wpas_dpp_pkex_add(wpa_s, buf + 12);
13709 if (res < 0) {
13710 reply_len = -1;
13711 } else {
13712 reply_len = os_snprintf(reply, reply_size, "%d", res);
13713 if (os_snprintf_error(reply_size, reply_len))
13714 reply_len = -1;
13715 }
13716 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
13717 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
13718 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013719 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
13720 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
13721 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070013722#ifdef CONFIG_DPP2
13723 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
13724 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
13725 reply_len = -1;
13726 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
13727 if (wpas_dpp_controller_start(wpa_s, NULL) < 0)
13728 reply_len = -1;
13729 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
13730 dpp_controller_stop(wpa_s->dpp);
Hai Shalomfdcde762020-04-02 11:19:20 -070013731 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
13732 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0)
13733 reply_len = -1;
13734 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
13735 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070013736 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
Hai Shalom899fcc72020-10-19 14:38:18 -070013737 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0)
13738 reply_len = -1;
13739 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) {
13740 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -070013741 reply_len = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -070013742#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -070013743#ifdef CONFIG_DPP3
13744 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
13745 if (wpas_dpp_push_button(wpa_s, NULL) < 0)
13746 reply_len = -1;
13747 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
13748 if (wpas_dpp_push_button(wpa_s, buf + 15) < 0)
13749 reply_len = -1;
13750#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070013751#endif /* CONFIG_DPP */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013752#ifdef CONFIG_NAN_USD
13753 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
13754 reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
13755 reply_size);
13756 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
13757 if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
Hai Shalom899fcc72020-10-19 14:38:18 -070013758 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013759 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
13760 if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
13761 reply_len = -1;
13762 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
13763 reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
13764 reply_size);
13765 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
13766 if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
13767 reply_len = -1;
13768 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
13769 if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
13770 reply_len = -1;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000013771 } else if (os_strcmp(buf, "NAN_FLUSH") == 0) {
13772 wpas_nan_usd_flush(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013773#endif /* CONFIG_NAN_USD */
Hai Shalom60840252021-02-19 19:02:11 -080013774#ifdef CONFIG_PASN
13775 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
13776 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
13777 reply_len = -1;
13778 } else if (os_strcmp(buf, "PASN_STOP") == 0) {
13779 wpas_pasn_auth_stop(wpa_s);
13780 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
13781 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
Hai Shaloma20dcd72022-02-04 13:43:00 -080013782 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
13783 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
13784 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013785#ifdef CONFIG_TESTING_OPTIONS
13786 } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) {
13787 if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0)
13788 reply_len = -1;
13789#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -080013790#endif /* CONFIG_PASN */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013791#ifndef CONFIG_NO_ROBUST_AV
13792 } else if (os_strncmp(buf, "MSCS ", 5) == 0) {
13793 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
13794 reply_len = -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -080013795 } else if (os_strncmp(buf, "SCS ", 4) == 0) {
13796 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
13797 reply_len = -1;
13798 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
13799 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
13800 reply_len = -1;
13801 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
13802 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
13803 reply_len = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000013804#endif /* CONFIG_NO_ROBUST_AV */
Sunil Ravi89eba102022-09-13 21:04:37 -070013805 } else if (os_strcmp(buf, "MLO_STATUS") == 0) {
13806 reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply,
13807 reply_size);
13808 } else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) {
13809 reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply,
13810 reply_size);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000013811 } else if (os_strcmp(buf, "NEW_RANDOM_MAC_ADDRESS") == 0) {
13812 enum wpas_mac_addr_style mac_addr_style =
13813 wpa_s->conf->preassoc_mac_addr;
13814
13815 wpa_s->conf->preassoc_mac_addr = WPAS_MAC_ADDR_STYLE_RANDOM;
13816 if (wpas_update_random_addr_disassoc(wpa_s) != 1)
13817 reply_len = -1;
13818 wpa_s->conf->preassoc_mac_addr = mac_addr_style;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013819 } else {
13820 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
13821 reply_len = 16;
13822 }
13823
13824 if (reply_len < 0) {
13825 os_memcpy(reply, "FAIL\n", 5);
13826 reply_len = 5;
13827 }
13828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013829 *resp_len = reply_len;
13830 return reply;
13831}
13832
13833
13834static int wpa_supplicant_global_iface_add(struct wpa_global *global,
13835 char *cmd)
13836{
13837 struct wpa_interface iface;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013838 char *pos, *extra;
13839 struct wpa_supplicant *wpa_s;
13840 unsigned int create_iface = 0;
13841 u8 mac_addr[ETH_ALEN];
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013842 enum wpa_driver_if_type type = WPA_IF_STATION;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013843
13844 /*
13845 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013846 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013847 */
13848 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
13849
13850 os_memset(&iface, 0, sizeof(iface));
13851
13852 do {
13853 iface.ifname = pos = cmd;
13854 pos = os_strchr(pos, '\t');
13855 if (pos)
13856 *pos++ = '\0';
13857 if (iface.ifname[0] == '\0')
13858 return -1;
13859 if (pos == NULL)
13860 break;
13861
13862 iface.confname = pos;
13863 pos = os_strchr(pos, '\t');
13864 if (pos)
13865 *pos++ = '\0';
13866 if (iface.confname[0] == '\0')
13867 iface.confname = NULL;
13868 if (pos == NULL)
13869 break;
13870
13871 iface.driver = pos;
13872 pos = os_strchr(pos, '\t');
13873 if (pos)
13874 *pos++ = '\0';
13875 if (iface.driver[0] == '\0')
13876 iface.driver = NULL;
13877 if (pos == NULL)
13878 break;
13879
13880 iface.ctrl_interface = pos;
13881 pos = os_strchr(pos, '\t');
13882 if (pos)
13883 *pos++ = '\0';
13884 if (iface.ctrl_interface[0] == '\0')
13885 iface.ctrl_interface = NULL;
13886 if (pos == NULL)
13887 break;
13888
13889 iface.driver_param = pos;
13890 pos = os_strchr(pos, '\t');
13891 if (pos)
13892 *pos++ = '\0';
13893 if (iface.driver_param[0] == '\0')
13894 iface.driver_param = NULL;
13895 if (pos == NULL)
13896 break;
13897
13898 iface.bridge_ifname = pos;
13899 pos = os_strchr(pos, '\t');
13900 if (pos)
13901 *pos++ = '\0';
13902 if (iface.bridge_ifname[0] == '\0')
13903 iface.bridge_ifname = NULL;
13904 if (pos == NULL)
13905 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013906
13907 extra = pos;
13908 pos = os_strchr(pos, '\t');
13909 if (pos)
13910 *pos++ = '\0';
Dmitry Shmidt83474442015-04-15 13:47:09 -070013911 if (!extra[0])
13912 break;
13913
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013914 if (os_strcmp(extra, "create") == 0) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013915 create_iface = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013916 if (!pos)
13917 break;
13918
13919 if (os_strcmp(pos, "sta") == 0) {
13920 type = WPA_IF_STATION;
13921 } else if (os_strcmp(pos, "ap") == 0) {
13922 type = WPA_IF_AP_BSS;
13923 } else {
13924 wpa_printf(MSG_DEBUG,
13925 "INTERFACE_ADD unsupported interface type: '%s'",
13926 pos);
13927 return -1;
13928 }
13929 } else {
Dmitry Shmidt83474442015-04-15 13:47:09 -070013930 wpa_printf(MSG_DEBUG,
13931 "INTERFACE_ADD unsupported extra parameter: '%s'",
13932 extra);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013933 return -1;
Dmitry Shmidt83474442015-04-15 13:47:09 -070013934 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013935 } while (0);
13936
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013937 if (create_iface) {
13938 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
13939 iface.ifname);
13940 if (!global->ifaces)
13941 return -1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080013942 if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013943 NULL, NULL, NULL, mac_addr, NULL) < 0) {
13944 wpa_printf(MSG_ERROR,
13945 "CTRL_IFACE interface creation failed");
13946 return -1;
13947 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013948
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013949 wpa_printf(MSG_DEBUG,
13950 "CTRL_IFACE interface '%s' created with MAC addr: "
13951 MACSTR, iface.ifname, MAC2STR(mac_addr));
13952 }
13953
13954 if (wpa_supplicant_get_iface(global, iface.ifname))
13955 goto fail;
13956
13957 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
13958 if (!wpa_s)
13959 goto fail;
13960 wpa_s->added_vif = create_iface;
13961 return 0;
13962
13963fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013964 if (create_iface) {
13965 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13966 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013967 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013968 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013969 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013970}
13971
13972
13973static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
13974 char *cmd)
13975{
13976 struct wpa_supplicant *wpa_s;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013977 int ret;
13978 unsigned int delete_iface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013979
13980 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
13981
13982 wpa_s = wpa_supplicant_get_iface(global, cmd);
13983 if (wpa_s == NULL)
13984 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013985 delete_iface = wpa_s->added_vif;
13986 ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
13987 if (!ret && delete_iface) {
13988 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
13989 cmd);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000013990 /* wpa_supplicant does not create multi-BSS AP, so collapse to
13991 * WPA_IF_STATION to avoid unwanted clean up in the driver. */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070013992 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
13993 }
13994 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070013995}
13996
13997
13998static void wpa_free_iface_info(struct wpa_interface_info *iface)
13999{
14000 struct wpa_interface_info *prev;
14001
14002 while (iface) {
14003 prev = iface;
14004 iface = iface->next;
14005
14006 os_free(prev->ifname);
14007 os_free(prev->desc);
14008 os_free(prev);
14009 }
14010}
14011
14012
14013static int wpa_supplicant_global_iface_list(struct wpa_global *global,
14014 char *buf, int len)
14015{
14016 int i, res;
14017 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
14018 char *pos, *end;
14019
14020 for (i = 0; wpa_drivers[i]; i++) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070014021 const struct wpa_driver_ops *drv = wpa_drivers[i];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014022 if (drv->get_interfaces == NULL)
14023 continue;
14024 tmp = drv->get_interfaces(global->drv_priv[i]);
14025 if (tmp == NULL)
14026 continue;
14027
14028 if (last == NULL)
14029 iface = last = tmp;
14030 else
14031 last->next = tmp;
14032 while (last->next)
14033 last = last->next;
14034 }
14035
14036 pos = buf;
14037 end = buf + len;
14038 for (tmp = iface; tmp; tmp = tmp->next) {
14039 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
14040 tmp->drv_name, tmp->ifname,
14041 tmp->desc ? tmp->desc : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014042 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014043 *pos = '\0';
14044 break;
14045 }
14046 pos += res;
14047 }
14048
14049 wpa_free_iface_info(iface);
14050
14051 return pos - buf;
14052}
14053
14054
14055static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014056 const char *input,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014057 char *buf, int len)
14058{
14059 int res;
14060 char *pos, *end;
14061 struct wpa_supplicant *wpa_s;
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014062 int show_ctrl = 0;
14063
14064 if (input)
14065 show_ctrl = !!os_strstr(input, "ctrl");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014066
14067 wpa_s = global->ifaces;
14068 pos = buf;
14069 end = buf + len;
14070
14071 while (wpa_s) {
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014072 if (show_ctrl)
14073 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
14074 wpa_s->ifname,
14075 wpa_s->conf->ctrl_interface ?
14076 wpa_s->conf->ctrl_interface : "N/A");
14077 else
14078 res = os_snprintf(pos, end - pos, "%s\n",
14079 wpa_s->ifname);
14080
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014081 if (os_snprintf_error(end - pos, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014082 *pos = '\0';
14083 break;
14084 }
14085 pos += res;
14086 wpa_s = wpa_s->next;
14087 }
14088 return pos - buf;
14089}
14090
14091
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014092static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
14093 const char *ifname,
14094 char *cmd, size_t *resp_len)
14095{
14096 struct wpa_supplicant *wpa_s;
14097
14098 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14099 if (os_strcmp(ifname, wpa_s->ifname) == 0)
14100 break;
14101 }
14102
14103 if (wpa_s == NULL) {
14104 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
14105 if (resp)
14106 *resp_len = os_strlen(resp);
14107 else
14108 *resp_len = 1;
14109 return resp;
14110 }
14111
14112 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
14113}
14114
14115
14116static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
14117 char *buf, size_t *resp_len)
14118{
14119#ifdef CONFIG_P2P
14120 static const char * cmd[] = {
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070014121 "LIST_NETWORKS",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014122 "P2P_FIND",
14123 "P2P_STOP_FIND",
14124 "P2P_LISTEN",
14125 "P2P_GROUP_ADD",
14126 "P2P_GET_PASSPHRASE",
14127 "P2P_SERVICE_UPDATE",
14128 "P2P_SERVICE_FLUSH",
14129 "P2P_FLUSH",
14130 "P2P_CANCEL",
14131 "P2P_PRESENCE_REQ",
14132 "P2P_EXT_LISTEN",
Paul Stewart092955c2017-02-06 09:13:09 -080014133#ifdef CONFIG_AP
14134 "STA-FIRST",
14135#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014136 NULL
14137 };
14138 static const char * prefix[] = {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080014139#ifdef ANDROID
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070014140 "DRIVER ",
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -080014141#endif /* ANDROID */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070014142 "GET_CAPABILITY ",
Dmitry Shmidt0c18dcd2013-08-16 15:29:47 -070014143 "GET_NETWORK ",
14144 "REMOVE_NETWORK ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014145 "P2P_FIND ",
14146 "P2P_CONNECT ",
14147 "P2P_LISTEN ",
14148 "P2P_GROUP_REMOVE ",
14149 "P2P_GROUP_ADD ",
Dmitry Shmidt849734c2016-05-27 09:59:01 -070014150 "P2P_GROUP_MEMBER ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014151 "P2P_PROV_DISC ",
14152 "P2P_SERV_DISC_REQ ",
14153 "P2P_SERV_DISC_CANCEL_REQ ",
14154 "P2P_SERV_DISC_RESP ",
14155 "P2P_SERV_DISC_EXTERNAL ",
14156 "P2P_SERVICE_ADD ",
14157 "P2P_SERVICE_DEL ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080014158 "P2P_SERVICE_REP ",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014159 "P2P_REJECT ",
14160 "P2P_INVITE ",
14161 "P2P_PEER ",
14162 "P2P_SET ",
14163 "P2P_UNAUTHORIZE ",
14164 "P2P_PRESENCE_REQ ",
14165 "P2P_EXT_LISTEN ",
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070014166 "P2P_REMOVE_CLIENT ",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080014167 "WPS_NFC_TOKEN ",
14168 "WPS_NFC_TAG_READ ",
Dmitry Shmidt413dde72014-04-11 10:23:22 -070014169 "NFC_GET_HANDOVER_SEL ",
14170 "NFC_GET_HANDOVER_REQ ",
14171 "NFC_REPORT_HANDOVER ",
Dmitry Shmidt216983b2015-02-06 10:50:36 -080014172 "P2P_ASP_PROVISION ",
14173 "P2P_ASP_PROVISION_RESP ",
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000014174 "NAN_",
Paul Stewart092955c2017-02-06 09:13:09 -080014175#ifdef CONFIG_AP
14176 "STA ",
14177 "STA-NEXT ",
14178#endif /* CONFIG_AP */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014179 NULL
14180 };
14181 int found = 0;
14182 int i;
14183
14184 if (global->p2p_init_wpa_s == NULL)
14185 return NULL;
14186
14187 for (i = 0; !found && cmd[i]; i++) {
14188 if (os_strcmp(buf, cmd[i]) == 0)
14189 found = 1;
14190 }
14191
14192 for (i = 0; !found && prefix[i]; i++) {
14193 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
14194 found = 1;
14195 }
14196
14197 if (found)
14198 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
14199 buf, resp_len);
14200#endif /* CONFIG_P2P */
14201 return NULL;
14202}
14203
14204
14205static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
14206 char *buf, size_t *resp_len)
14207{
14208#ifdef CONFIG_WIFI_DISPLAY
14209 if (global->p2p_init_wpa_s == NULL)
14210 return NULL;
14211 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
14212 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
14213 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
14214 buf, resp_len);
14215#endif /* CONFIG_WIFI_DISPLAY */
14216 return NULL;
14217}
14218
14219
14220static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
14221 char *buf, size_t *resp_len)
14222{
14223 char *ret;
14224
14225 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
14226 if (ret)
14227 return ret;
14228
14229 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
14230 if (ret)
14231 return ret;
14232
14233 return NULL;
14234}
14235
14236
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014237static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
14238{
14239 char *value;
14240
14241 value = os_strchr(cmd, ' ');
14242 if (value == NULL)
14243 return -1;
14244 *value++ = '\0';
14245
14246 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
14247
14248#ifdef CONFIG_WIFI_DISPLAY
14249 if (os_strcasecmp(cmd, "wifi_display") == 0) {
14250 wifi_display_enable(global, !!atoi(value));
14251 return 0;
14252 }
14253#endif /* CONFIG_WIFI_DISPLAY */
14254
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014255 /* Restore cmd to its original value to allow redirection */
14256 value[-1] = ' ';
14257
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014258 return -1;
14259}
14260
14261
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014262static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global,
14263 char *cmd)
14264{
14265 struct wpa_supplicant *wpa_s[2]; /* src, dst */
14266 char *p;
14267 unsigned int i;
14268
14269 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id>
14270 * <variable name> */
14271
14272 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) {
14273 p = os_strchr(cmd, ' ');
14274 if (p == NULL)
14275 return -1;
14276 *p = '\0';
14277
14278 wpa_s[i] = global->ifaces;
14279 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) {
14280 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0)
14281 break;
14282 }
14283
14284 if (!wpa_s[i]) {
14285 wpa_printf(MSG_DEBUG,
14286 "CTRL_IFACE: Could not find iface=%s", cmd);
14287 return -1;
14288 }
14289
14290 cmd = p + 1;
14291 }
14292
14293 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]);
14294}
14295
14296
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014297#ifndef CONFIG_NO_CONFIG_WRITE
14298static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
14299{
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014300 int ret = 0, saved = 0;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014301 struct wpa_supplicant *wpa_s;
14302
14303 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14304 if (!wpa_s->conf->update_config) {
14305 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
14306 continue;
14307 }
14308
14309 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
14310 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
14311 ret = 1;
14312 } else {
14313 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014314 saved++;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014315 }
14316 }
14317
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014318 if (!saved && !ret) {
14319 wpa_dbg(wpa_s, MSG_DEBUG,
14320 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
14321 ret = 1;
14322 }
14323
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014324 return ret;
14325}
14326#endif /* CONFIG_NO_CONFIG_WRITE */
14327
14328
14329static int wpas_global_ctrl_iface_status(struct wpa_global *global,
14330 char *buf, size_t buflen)
14331{
14332 char *pos, *end;
14333 int ret;
14334 struct wpa_supplicant *wpa_s;
14335
14336 pos = buf;
14337 end = buf + buflen;
14338
14339#ifdef CONFIG_P2P
14340 if (global->p2p && !global->p2p_disabled) {
14341 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
14342 "\n"
14343 "p2p_state=%s\n",
14344 MAC2STR(global->p2p_dev_addr),
14345 p2p_get_state_txt(global->p2p));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014346 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014347 return pos - buf;
14348 pos += ret;
14349 } else if (global->p2p) {
14350 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014351 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014352 return pos - buf;
14353 pos += ret;
14354 }
14355#endif /* CONFIG_P2P */
14356
14357#ifdef CONFIG_WIFI_DISPLAY
14358 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
14359 !!global->wifi_display);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014360 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014361 return pos - buf;
14362 pos += ret;
14363#endif /* CONFIG_WIFI_DISPLAY */
14364
14365 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
14366 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
14367 "address=" MACSTR "\n",
14368 wpa_s->ifname, MAC2STR(wpa_s->own_addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014369 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014370 return pos - buf;
14371 pos += ret;
14372 }
14373
14374 return pos - buf;
14375}
14376
14377
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014378#ifdef CONFIG_FST
14379
14380static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
14381 char *cmd, char *buf,
14382 size_t reply_size)
14383{
14384 char ifname[IFNAMSIZ + 1];
14385 struct fst_iface_cfg cfg;
14386 struct wpa_supplicant *wpa_s;
14387 struct fst_wpa_obj iface_obj;
14388
14389 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
14390 wpa_s = wpa_supplicant_get_iface(global, ifname);
14391 if (wpa_s) {
14392 if (wpa_s->fst) {
14393 wpa_printf(MSG_INFO, "FST: Already attached");
14394 return -1;
14395 }
14396 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
14397 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
14398 &iface_obj, &cfg);
14399 if (wpa_s->fst)
14400 return os_snprintf(buf, reply_size, "OK\n");
14401 }
14402 }
14403
14404 return -1;
14405}
14406
14407
14408static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global,
14409 char *cmd, char *buf,
14410 size_t reply_size)
14411{
14412 char ifname[IFNAMSIZ + 1];
14413 struct wpa_supplicant *wpa_s;
14414
14415 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
14416 wpa_s = wpa_supplicant_get_iface(global, ifname);
14417 if (wpa_s) {
14418 if (!fst_iface_detach(ifname)) {
14419 wpa_s->fst = NULL;
14420 return os_snprintf(buf, reply_size, "OK\n");
14421 }
14422 }
14423 }
14424
14425 return -1;
14426}
14427
14428#endif /* CONFIG_FST */
14429
14430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014431char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
14432 char *buf, size_t *resp_len)
14433{
14434 char *reply;
14435 const int reply_size = 2048;
14436 int reply_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080014437 int level = MSG_DEBUG;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014438
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -070014439 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
14440 char *pos = os_strchr(buf + 7, ' ');
14441 if (pos) {
14442 *pos++ = '\0';
14443 return wpas_global_ctrl_iface_ifname(global,
14444 buf + 7, pos,
14445 resp_len);
14446 }
14447 }
14448
14449 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
14450 if (reply)
14451 return reply;
14452
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080014453 if (os_strcmp(buf, "PING") == 0)
14454 level = MSG_EXCESSIVE;
14455 wpa_hexdump_ascii(level, "RX global ctrl_iface",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014456 (const u8 *) buf, os_strlen(buf));
14457
14458 reply = os_malloc(reply_size);
14459 if (reply == NULL) {
14460 *resp_len = 1;
14461 return NULL;
14462 }
14463
14464 os_memcpy(reply, "OK\n", 3);
14465 reply_len = 3;
14466
14467 if (os_strcmp(buf, "PING") == 0) {
14468 os_memcpy(reply, "PONG\n", 5);
14469 reply_len = 5;
14470 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
14471 if (wpa_supplicant_global_iface_add(global, buf + 14))
14472 reply_len = -1;
14473 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
14474 if (wpa_supplicant_global_iface_remove(global, buf + 17))
14475 reply_len = -1;
14476 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
14477 reply_len = wpa_supplicant_global_iface_list(
14478 global, reply, reply_size);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014479 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014480 reply_len = wpa_supplicant_global_iface_interfaces(
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -080014481 global, buf + 10, reply, reply_size);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014482#ifdef CONFIG_FST
14483 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
14484 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
14485 reply,
14486 reply_size);
14487 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
14488 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11,
14489 reply,
14490 reply_size);
14491 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
14492 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
14493#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014494 } else if (os_strcmp(buf, "TERMINATE") == 0) {
14495 wpa_supplicant_terminate_proc(global);
14496 } else if (os_strcmp(buf, "SUSPEND") == 0) {
14497 wpas_notify_suspend(global);
14498 } else if (os_strcmp(buf, "RESUME") == 0) {
14499 wpas_notify_resume(global);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014500 } else if (os_strncmp(buf, "SET ", 4) == 0) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014501 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
14502#ifdef CONFIG_P2P
14503 if (global->p2p_init_wpa_s) {
14504 os_free(reply);
14505 /* Check if P2P redirection would work for this
14506 * command. */
14507 return wpa_supplicant_ctrl_iface_process(
14508 global->p2p_init_wpa_s,
14509 buf, resp_len);
14510 }
14511#endif /* CONFIG_P2P */
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014512 reply_len = -1;
Dmitry Shmidt61593f02014-04-21 16:27:35 -070014513 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080014514 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
14515 if (wpas_global_ctrl_iface_dup_network(global, buf + 12))
14516 reply_len = -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070014517#ifndef CONFIG_NO_CONFIG_WRITE
14518 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
14519 if (wpas_global_ctrl_iface_save_config(global))
14520 reply_len = -1;
14521#endif /* CONFIG_NO_CONFIG_WRITE */
14522 } else if (os_strcmp(buf, "STATUS") == 0) {
14523 reply_len = wpas_global_ctrl_iface_status(global, reply,
14524 reply_size);
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080014525#ifdef CONFIG_MODULE_TESTS
14526 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -080014527 if (wpas_module_tests() < 0)
14528 reply_len = -1;
14529#endif /* CONFIG_MODULE_TESTS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080014530 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
14531 if (wpa_debug_reopen_file() < 0)
14532 reply_len = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014533 } else {
14534 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
14535 reply_len = 16;
14536 }
14537
14538 if (reply_len < 0) {
14539 os_memcpy(reply, "FAIL\n", 5);
14540 reply_len = 5;
14541 }
14542
14543 *resp_len = reply_len;
14544 return reply;
14545}