]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Check for driver's DFS offload capability before handling DFS
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
13b11ba7 3 * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
6fc6879b 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
6fc6879b
JM
7 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
6fc6879b 16
90973fb2 17#include "common/wpa_ctrl.h"
cd101567
JM
18#include "utils/common.h"
19#include "utils/eloop.h"
82a855bd 20#include "utils/edit.h"
a624f20b 21#include "utils/list.h"
90973fb2 22#include "common/version.h"
a8918e86 23#include "common/ieee802_11_defs.h"
b1001e4c
DS
24#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
6fc6879b
JM
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
090b8e3d 31"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
6fc6879b
JM
32
33
34static const char *wpa_cli_license =
331f89ff
JM
35"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
6fc6879b
JM
37
38static const char *wpa_cli_full_license =
331f89ff 39"This software may be distributed under the terms of the BSD license.\n"
6fc6879b
JM
40"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
6fc6879b 69static struct wpa_ctrl *ctrl_conn;
4a3ade4e 70static struct wpa_ctrl *mon_conn;
6fc6879b
JM
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
02a3e5c0 73static int wpa_cli_connected = -1;
6fc6879b 74static int wpa_cli_last_id = 0;
c5c5817c
JM
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
6fc6879b
JM
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
1cc84c1c 82static int ping_interval = 5;
4a3ade4e 83static int interactive = 0;
13b11ba7 84static char *ifname_prefix = NULL;
6fc6879b 85
a624f20b
JM
86struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
76788542 93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
37620493 94static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
a624f20b 95
6fc6879b 96
2af4d404 97static void print_help(const char *cmd);
cd101567 98static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
d62aaa7d 99static void wpa_cli_close_connection(void);
8e897ae3 100static char * wpa_cli_get_default_ifname(void);
2af4d404 101static char ** wpa_list_cmd_list(void);
dfa141b1
ER
102
103
6fc6879b
JM
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
1cc84c1c
JM
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
6fc6879b
JM
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
c5c5817c 116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
dfa141b1 117 " default interface: first interface found in socket path\n");
2af4d404 118 print_help(NULL);
6fc6879b
JM
119}
120
121
a624f20b
JM
122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
4877e1fc 170#ifdef CONFIG_P2P
76788542
JM
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
5e24dc8a 178 buf = dup_binstr(txt, end - txt);
76788542
JM
179 if (buf == NULL)
180 return;
76788542
JM
181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
4877e1fc 184#endif /* CONFIG_P2P */
76788542
JM
185
186
a624f20b
JM
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
4877e1fc 206#ifdef CONFIG_P2P
a624f20b
JM
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
76788542
JM
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
5e24dc8a 226 buf = dup_binstr(txt, end - txt);
76788542
JM
227 if (buf == NULL)
228 return -1;
76788542
JM
229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
4877e1fc 233#endif /* CONFIG_P2P */
76788542
JM
234
235
a624f20b
JM
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
f9884c09 242 res = os_calloc(count + 1, sizeof(char *));
a624f20b
JM
243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
f3f0f648
JM
276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
4a3ade4e 303static int wpa_cli_open_connection(const char *ifname, int attach)
6fc6879b
JM
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
4a3ade4e
JM
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
6fc6879b 314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
b1001e4c 315 char *cfile = NULL;
6fc6879b
JM
316 int flen, res;
317
318 if (ifname == NULL)
4a3ade4e 319 return -1;
6fc6879b 320
b1001e4c
DS
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
6fc6879b
JM
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
4a3ade4e
JM
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
6fc6879b 352 os_free(cfile);
6fc6879b 353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
4a3ade4e
JM
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
cd101567
JM
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
4a3ade4e
JM
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
d62aaa7d 365 wpa_cli_close_connection();
4a3ade4e
JM
366 return -1;
367 }
368 }
369
370 return 0;
6fc6879b
JM
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
4a3ade4e 380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
6fc6879b
JM
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
4a3ade4e 385 if (mon_conn) {
cd101567 386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
4a3ade4e
JM
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
6fc6879b
JM
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
aec309c4 401 char buf[4096];
6fc6879b
JM
402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
13b11ba7
JM
409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
6fc6879b
JM
415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
a432bafb
JM
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
6fc6879b
JM
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
0076869c
JM
441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
28fcfb67 474 char buf[4096];
0076869c
JM
475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
0eed2a8d
JD
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
6fc6879b
JM
493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
0bc13468
JM
495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
a771c07d
JM
499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
0bc13468 501 return wpa_ctrl_command(ctrl, "STATUS");
6fc6879b
JM
502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
ac6912b5
BG
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
77895cd9
JM
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
0076869c 519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
77895cd9
JM
520}
521
522
6fc6879b
JM
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
2af4d404 537 print_help(argc > 0 ? argv[0] : NULL);
6fc6879b
JM
538 return 0;
539}
540
541
2af4d404
JM
542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
6fc6879b
JM
557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
cd101567
JM
567 if (interactive)
568 eloop_terminate();
6fc6879b
JM
569 return 0;
570}
571
572
6fc6879b
JM
573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
f1fb042c 578 if (argc == 1) {
40eac890 579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
f1fb042c
JM
580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
6fc6879b 585 }
f1fb042c
JM
586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
6fc6879b
JM
588}
589
590
21565872
JM
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
556b30da 618 "p2p_no_go_freq",
21565872 619 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
20ea1ca4 620 "p2p_go_vht",
21565872
JM
621 "p2p_ignore_shared_freq", "country", "bss_max_count",
622 "bss_expiration_age", "bss_expiration_scan_count",
623 "filter_ssids", "filter_rssi", "max_num_sta",
624 "disassoc_low_ack", "hs20", "interworking", "hessid",
625 "access_network_type", "pbc_in_m1", "autoscan",
626 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
627 "wps_nfc_dev_pw", "ext_password_backend",
628 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
629 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
4701f379 630 "ignore_old_scan_res", "freq_list", "external_sim",
d3b20469 631 "tdls_external_control", "p2p_search_delay"
21565872 632 };
e7ecab4a 633 int i, num_fields = ARRAY_SIZE(fields);
21565872
JM
634
635 if (arg == 1) {
636 char **res = os_calloc(num_fields + 1, sizeof(char *));
637 if (res == NULL)
638 return NULL;
639 for (i = 0; i < num_fields; i++) {
640 res[i] = os_strdup(fields[i]);
641 if (res[i] == NULL)
642 return res;
643 }
644 return res;
645 }
646
69aa3341
JM
647 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
648 return cli_txt_list_array(&bsses);
649
21565872
JM
650 return NULL;
651}
652
653
acec8d32
JM
654static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
87c7ba84 656 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
acec8d32
JM
657}
658
659
6fc6879b
JM
660static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
661{
662 return wpa_ctrl_command(ctrl, "LOGOFF");
663}
664
665
666static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
668 return wpa_ctrl_command(ctrl, "LOGON");
669}
670
671
672static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "REASSOCIATE");
676}
677
678
0f44ec8e
PQ
679static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
680{
681 return wpa_ctrl_command(ctrl, "REATTACH");
682}
683
684
6fc6879b
JM
685static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
686 char *argv[])
687{
87c7ba84 688 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
6fc6879b
JM
689}
690
691
692static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
87c7ba84 694 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
6fc6879b
JM
695}
696
697
67b9bd08
DS
698static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700{
87c7ba84 701 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
67b9bd08
DS
702}
703
704
78633c37
SL
705static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
706 char *argv[])
707{
87c7ba84 708 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
78633c37
SL
709}
710
711
712static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
713 char *argv[])
714{
87c7ba84 715 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
78633c37
SL
716}
717
718
39ee845f
DS
719static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
720{
721 char cmd[256];
722 int res;
723
724 if (argc < 1)
725 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
726 else
727 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
728 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
729 printf("Too long BSS_FLUSH command.\n");
730 return -1;
731 }
732 return wpa_ctrl_command(ctrl, cmd);
733}
734
735
6fc6879b
JM
736static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
737 char *argv[])
738{
87c7ba84 739 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
6fc6879b
JM
740}
741
742
743static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
87c7ba84 745 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
6fc6879b
JM
746}
747
748
fcc60db4
JM
749static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
87c7ba84 751 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
fcc60db4
JM
752}
753
754
755static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
fcc60db4
JM
757 if (argc == 0) {
758 printf("Invalid WPS_PIN command: need one or two arguments:\n"
759 "- BSSID: use 'any' to select any\n"
760 "- PIN: optional, used only with devices that have no "
761 "display\n");
762 return -1;
763 }
764
87c7ba84 765 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
fcc60db4
JM
766}
767
768
3981cb3c
JM
769static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
771{
87c7ba84 772 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
3981cb3c
JM
773}
774
775
2f9929ff
AC
776static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
777 char *argv[])
778{
779 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
780}
781
782
71892384 783#ifdef CONFIG_WPS_NFC
3f2c8ba6
JM
784
785static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
786{
87c7ba84 787 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
3f2c8ba6
JM
788}
789
790
bbf41865
JM
791static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
792 char *argv[])
793{
794 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
795}
796
797
3f2c8ba6
JM
798static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
799 char *argv[])
800{
87c7ba84 801 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
3f2c8ba6 802}
d7645d23
JM
803
804
805static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
808 int ret;
809 char *buf;
810 size_t buflen;
811
812 if (argc != 1) {
813 printf("Invalid 'wps_nfc_tag_read' command - one argument "
814 "is required.\n");
815 return -1;
816 }
817
818 buflen = 18 + os_strlen(argv[0]);
819 buf = os_malloc(buflen);
820 if (buf == NULL)
821 return -1;
822 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
823
824 ret = wpa_ctrl_command(ctrl, buf);
825 os_free(buf);
826
827 return ret;
828}
71892384 829
e65552dd
JM
830
831static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
832 char *argv[])
833{
834 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
835}
836
837
838static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
839 char *argv[])
840{
841 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
842}
843
844
e4758827
JM
845static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
849}
850
71892384 851#endif /* CONFIG_WPS_NFC */
46bdb83a
MH
852
853
fcc60db4
JM
854static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
855{
856 char cmd[256];
857 int res;
858
52eb293d
JM
859 if (argc == 2)
860 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
861 argv[0], argv[1]);
7d6640a6 862 else if (argc == 5 || argc == 6) {
52eb293d
JM
863 char ssid_hex[2 * 32 + 1];
864 char key_hex[2 * 64 + 1];
865 int i;
866
867 ssid_hex[0] = '\0';
868 for (i = 0; i < 32; i++) {
869 if (argv[2][i] == '\0')
870 break;
871 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
872 }
873
874 key_hex[0] = '\0';
7d6640a6
JM
875 if (argc == 6) {
876 for (i = 0; i < 64; i++) {
877 if (argv[5][i] == '\0')
878 break;
879 os_snprintf(&key_hex[i * 2], 3, "%02x",
880 argv[5][i]);
881 }
52eb293d
JM
882 }
883
884 res = os_snprintf(cmd, sizeof(cmd),
885 "WPS_REG %s %s %s %s %s %s",
886 argv[0], argv[1], ssid_hex, argv[3], argv[4],
887 key_hex);
888 } else {
fcc60db4 889 printf("Invalid WPS_REG command: need two arguments:\n"
129eb428 890 "- BSSID of the target AP\n"
fcc60db4 891 "- AP PIN\n");
52eb293d
JM
892 printf("Alternatively, six arguments can be used to "
893 "reconfigure the AP:\n"
129eb428 894 "- BSSID of the target AP\n"
52eb293d
JM
895 "- AP PIN\n"
896 "- new SSID\n"
897 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
898 "- new encr (NONE, WEP, TKIP, CCMP)\n"
899 "- new key\n");
fcc60db4
JM
900 return -1;
901 }
902
fcc60db4
JM
903 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
904 printf("Too long WPS_REG command.\n");
905 return -1;
906 }
907 return wpa_ctrl_command(ctrl, cmd);
908}
909
910
70d84f11
JM
911static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913{
87c7ba84 914 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
70d84f11
JM
915}
916
917
e9bcfebf
JM
918static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
87c7ba84 921 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
e9bcfebf
JM
922}
923
924
925static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
927{
928 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
929
930}
931
932
72df2f5f
JM
933static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
934 char *argv[])
935{
31fcea93
JM
936 if (argc < 2) {
937 printf("Invalid WPS_ER_PIN command: need at least two "
938 "arguments:\n"
72df2f5f 939 "- UUID: use 'any' to select any\n"
31fcea93
JM
940 "- PIN: Enrollee PIN\n"
941 "optional: - Enrollee MAC address\n");
72df2f5f
JM
942 return -1;
943 }
944
87c7ba84 945 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
72df2f5f
JM
946}
947
948
564cd7fa
JM
949static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
950 char *argv[])
951{
87c7ba84 952 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
564cd7fa
JM
953}
954
955
e64dcfd5
JM
956static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
957 char *argv[])
958{
e64dcfd5
JM
959 if (argc != 2) {
960 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
961 "- UUID: specify which AP to use\n"
962 "- PIN: AP PIN\n");
963 return -1;
964 }
965
87c7ba84 966 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
e64dcfd5
JM
967}
968
969
ef10f473
JM
970static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
971 char *argv[])
972{
ef10f473
JM
973 if (argc != 2) {
974 printf("Invalid WPS_ER_SET_CONFIG command: need two "
975 "arguments:\n"
976 "- UUID: specify which AP to use\n"
977 "- Network configuration id\n");
978 return -1;
979 }
980
87c7ba84 981 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
ef10f473
JM
982}
983
984
7d6640a6
JM
985static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
986 char *argv[])
987{
988 char cmd[256];
989 int res;
990
991 if (argc == 5 || argc == 6) {
992 char ssid_hex[2 * 32 + 1];
993 char key_hex[2 * 64 + 1];
994 int i;
995
996 ssid_hex[0] = '\0';
997 for (i = 0; i < 32; i++) {
998 if (argv[2][i] == '\0')
999 break;
1000 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1001 }
1002
1003 key_hex[0] = '\0';
1004 if (argc == 6) {
1005 for (i = 0; i < 64; i++) {
1006 if (argv[5][i] == '\0')
1007 break;
1008 os_snprintf(&key_hex[i * 2], 3, "%02x",
1009 argv[5][i]);
1010 }
1011 }
1012
1013 res = os_snprintf(cmd, sizeof(cmd),
1014 "WPS_ER_CONFIG %s %s %s %s %s %s",
1015 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1016 key_hex);
1017 } else {
1018 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1019 "- AP UUID\n"
1020 "- AP PIN\n"
1021 "- new SSID\n"
1022 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1023 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1024 "- new key\n");
1025 return -1;
1026 }
1027
1028 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029 printf("Too long WPS_ER_CONFIG command.\n");
1030 return -1;
1031 }
1032 return wpa_ctrl_command(ctrl, cmd);
1033}
1034
1035
1cea09a9
JM
1036#ifdef CONFIG_WPS_NFC
1037static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1038 char *argv[])
1039{
1cea09a9
JM
1040 if (argc != 2) {
1041 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1042 "arguments:\n"
1043 "- WPS/NDEF: token format\n"
1044 "- UUID: specify which AP to use\n");
1045 return -1;
1046 }
1047
87c7ba84 1048 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1cea09a9
JM
1049}
1050#endif /* CONFIG_WPS_NFC */
1051
1052
11ef8d35
JM
1053static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1054{
87c7ba84 1055 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
11ef8d35
JM
1056}
1057
1058
6fc6879b
JM
1059static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060{
87c7ba84 1061 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
6fc6879b
JM
1062}
1063
1064
1065static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1066{
1067 char cmd[256], *pos, *end;
1068 int i, ret;
1069
1070 if (argc < 2) {
1071 printf("Invalid IDENTITY command: needs two arguments "
1072 "(network id and identity)\n");
1073 return -1;
1074 }
1075
1076 end = cmd + sizeof(cmd);
1077 pos = cmd;
1078 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1079 argv[0], argv[1]);
1080 if (ret < 0 || ret >= end - pos) {
1081 printf("Too long IDENTITY command.\n");
1082 return -1;
1083 }
1084 pos += ret;
1085 for (i = 2; i < argc; i++) {
1086 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1087 if (ret < 0 || ret >= end - pos) {
1088 printf("Too long IDENTITY command.\n");
1089 return -1;
1090 }
1091 pos += ret;
1092 }
1093
1094 return wpa_ctrl_command(ctrl, cmd);
1095}
1096
1097
1098static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099{
1100 char cmd[256], *pos, *end;
1101 int i, ret;
1102
1103 if (argc < 2) {
1104 printf("Invalid PASSWORD command: needs two arguments "
1105 "(network id and password)\n");
1106 return -1;
1107 }
1108
1109 end = cmd + sizeof(cmd);
1110 pos = cmd;
1111 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1112 argv[0], argv[1]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long PASSWORD command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 for (i = 2; i < argc; i++) {
1119 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1120 if (ret < 0 || ret >= end - pos) {
1121 printf("Too long PASSWORD command.\n");
1122 return -1;
1123 }
1124 pos += ret;
1125 }
1126
1127 return wpa_ctrl_command(ctrl, cmd);
1128}
1129
1130
1131static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1132 char *argv[])
1133{
1134 char cmd[256], *pos, *end;
1135 int i, ret;
1136
1137 if (argc < 2) {
1138 printf("Invalid NEW_PASSWORD command: needs two arguments "
1139 "(network id and password)\n");
1140 return -1;
1141 }
1142
1143 end = cmd + sizeof(cmd);
1144 pos = cmd;
1145 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1146 argv[0], argv[1]);
1147 if (ret < 0 || ret >= end - pos) {
1148 printf("Too long NEW_PASSWORD command.\n");
1149 return -1;
1150 }
1151 pos += ret;
1152 for (i = 2; i < argc; i++) {
1153 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long NEW_PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 }
1160
1161 return wpa_ctrl_command(ctrl, cmd);
1162}
1163
1164
1165static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1166{
1167 char cmd[256], *pos, *end;
1168 int i, ret;
1169
1170 if (argc < 2) {
1171 printf("Invalid PIN command: needs two arguments "
1172 "(network id and pin)\n");
1173 return -1;
1174 }
1175
1176 end = cmd + sizeof(cmd);
1177 pos = cmd;
1178 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1179 argv[0], argv[1]);
1180 if (ret < 0 || ret >= end - pos) {
1181 printf("Too long PIN command.\n");
1182 return -1;
1183 }
1184 pos += ret;
1185 for (i = 2; i < argc; i++) {
1186 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1187 if (ret < 0 || ret >= end - pos) {
1188 printf("Too long PIN command.\n");
1189 return -1;
1190 }
1191 pos += ret;
1192 }
1193 return wpa_ctrl_command(ctrl, cmd);
1194}
1195
1196
1197static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1198{
1199 char cmd[256], *pos, *end;
1200 int i, ret;
1201
1202 if (argc < 2) {
1203 printf("Invalid OTP command: needs two arguments (network "
1204 "id and password)\n");
1205 return -1;
1206 }
1207
1208 end = cmd + sizeof(cmd);
1209 pos = cmd;
1210 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1211 argv[0], argv[1]);
1212 if (ret < 0 || ret >= end - pos) {
1213 printf("Too long OTP command.\n");
1214 return -1;
1215 }
1216 pos += ret;
1217 for (i = 2; i < argc; i++) {
1218 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1219 if (ret < 0 || ret >= end - pos) {
1220 printf("Too long OTP command.\n");
1221 return -1;
1222 }
1223 pos += ret;
1224 }
1225
1226 return wpa_ctrl_command(ctrl, cmd);
1227}
1228
1229
a5d44ac0
JM
1230static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1231{
1232 char cmd[256], *pos, *end;
1233 int i, ret;
1234
1235 if (argc < 2) {
1236 printf("Invalid SIM command: needs two arguments "
1237 "(network id and SIM operation response)\n");
1238 return -1;
1239 }
1240
1241 end = cmd + sizeof(cmd);
1242 pos = cmd;
1243 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1244 argv[0], argv[1]);
1245 if (ret < 0 || ret >= end - pos) {
1246 printf("Too long SIM command.\n");
1247 return -1;
1248 }
1249 pos += ret;
1250 for (i = 2; i < argc; i++) {
1251 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1252 if (ret < 0 || ret >= end - pos) {
1253 printf("Too long SIM command.\n");
1254 return -1;
1255 }
1256 pos += ret;
1257 }
1258 return wpa_ctrl_command(ctrl, cmd);
1259}
1260
1261
6fc6879b
JM
1262static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1263 char *argv[])
1264{
1265 char cmd[256], *pos, *end;
1266 int i, ret;
1267
1268 if (argc < 2) {
1269 printf("Invalid PASSPHRASE command: needs two arguments "
1270 "(network id and passphrase)\n");
1271 return -1;
1272 }
1273
1274 end = cmd + sizeof(cmd);
1275 pos = cmd;
1276 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1277 argv[0], argv[1]);
1278 if (ret < 0 || ret >= end - pos) {
1279 printf("Too long PASSPHRASE command.\n");
1280 return -1;
1281 }
1282 pos += ret;
1283 for (i = 2; i < argc; i++) {
1284 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1285 if (ret < 0 || ret >= end - pos) {
1286 printf("Too long PASSPHRASE command.\n");
1287 return -1;
1288 }
1289 pos += ret;
1290 }
1291
1292 return wpa_ctrl_command(ctrl, cmd);
1293}
1294
1295
1296static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
6fc6879b
JM
1298 if (argc < 2) {
1299 printf("Invalid BSSID command: needs two arguments (network "
1300 "id and BSSID)\n");
1301 return -1;
1302 }
1303
87c7ba84 1304 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
6fc6879b
JM
1305}
1306
1307
9aa10e2b
DS
1308static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1309{
87c7ba84
JM
1310 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1311}
9aa10e2b
DS
1312
1313
0597a5b5
DS
1314static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1315{
87c7ba84 1316 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
0597a5b5
DS
1317}
1318
1319
6fc6879b
JM
1320static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1321 char *argv[])
1322{
1323 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1324}
1325
1326
1327static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329{
87c7ba84 1330 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
6fc6879b
JM
1331}
1332
1333
1334static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1335 char *argv[])
1336{
87c7ba84 1337 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
6fc6879b
JM
1338}
1339
1340
1341static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1342 char *argv[])
1343{
87c7ba84 1344 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
6fc6879b
JM
1345}
1346
1347
1348static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1349 char *argv[])
1350{
1351 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1352}
1353
1354
1355static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1356 char *argv[])
1357{
87c7ba84 1358 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
6fc6879b
JM
1359}
1360
1361
1362static void wpa_cli_show_network_variables(void)
1363{
1364 printf("set_network variables:\n"
1365 " ssid (network name, SSID)\n"
1366 " psk (WPA passphrase or pre-shared key)\n"
1367 " key_mgmt (key management protocol)\n"
1368 " identity (EAP identity)\n"
1369 " password (EAP password)\n"
1370 " ...\n"
1371 "\n"
1372 "Note: Values are entered in the same format as the "
1373 "configuration file is using,\n"
1374 "i.e., strings values need to be inside double quotation "
1375 "marks.\n"
1376 "For example: set_network 1 ssid \"network name\"\n"
1377 "\n"
1378 "Please see wpa_supplicant.conf documentation for full list "
1379 "of\navailable variables.\n");
1380}
1381
1382
1383static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1384 char *argv[])
1385{
6fc6879b
JM
1386 if (argc == 0) {
1387 wpa_cli_show_network_variables();
1388 return 0;
1389 }
1390
af1dff8c 1391 if (argc < 3) {
6fc6879b
JM
1392 printf("Invalid SET_NETWORK command: needs three arguments\n"
1393 "(network id, variable name, and value)\n");
1394 return -1;
1395 }
1396
87c7ba84 1397 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
6fc6879b
JM
1398}
1399
1400
1401static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1402 char *argv[])
1403{
6fc6879b
JM
1404 if (argc == 0) {
1405 wpa_cli_show_network_variables();
1406 return 0;
1407 }
1408
1409 if (argc != 2) {
1410 printf("Invalid GET_NETWORK command: needs two arguments\n"
1411 "(network id and variable name)\n");
1412 return -1;
1413 }
1414
87c7ba84 1415 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
6fc6879b
JM
1416}
1417
1418
1c330a2f
DS
1419static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1420 char *argv[])
1421{
1422 if (argc == 0) {
1423 wpa_cli_show_network_variables();
1424 return 0;
1425 }
1426
1427 if (argc < 3) {
1428 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1429 "(src netid, dest netid, and variable name)\n");
1430 return -1;
1431 }
1432
1433 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1434}
1435
1436
d94c9ee6
JM
1437static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1438 char *argv[])
1439{
1440 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1441}
1442
1443
1444static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1445{
1446 return wpa_ctrl_command(ctrl, "ADD_CRED");
1447}
1448
1449
1450static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1451 char *argv[])
1452{
87c7ba84 1453 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
d94c9ee6
JM
1454}
1455
1456
1457static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458{
d94c9ee6
JM
1459 if (argc != 3) {
1460 printf("Invalid SET_CRED command: needs three arguments\n"
1461 "(cred id, variable name, and value)\n");
1462 return -1;
1463 }
1464
87c7ba84 1465 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
d94c9ee6
JM
1466}
1467
1468
c880ab87
JM
1469static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1470{
1471 if (argc != 2) {
1472 printf("Invalid GET_CRED command: needs two arguments\n"
1473 "(cred id, variable name)\n");
1474 return -1;
1475 }
1476
1477 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1478}
1479
1480
6fc6879b
JM
1481static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1482 char *argv[])
1483{
1484 return wpa_ctrl_command(ctrl, "DISCONNECT");
1485}
1486
1487
1488static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1489 char *argv[])
1490{
1491 return wpa_ctrl_command(ctrl, "RECONNECT");
1492}
1493
1494
1495static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1496 char *argv[])
1497{
1498 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1499}
1500
1501
1502static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1503{
66fe0f70 1504 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
6fc6879b
JM
1505}
1506
1507
1508static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1509 char *argv[])
1510{
1511 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1512}
1513
1514
1515static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516{
87c7ba84 1517 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
6fc6879b
JM
1518}
1519
1520
a624f20b
JM
1521static char ** wpa_cli_complete_bss(const char *str, int pos)
1522{
1523 int arg = get_cmd_arg_num(str, pos);
1524 char **res = NULL;
1525
1526 switch (arg) {
1527 case 1:
1528 res = cli_txt_list_array(&bsses);
1529 break;
1530 }
1531
1532 return res;
1533}
1534
1535
6fc6879b
JM
1536static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1537 char *argv[])
1538{
6fc6879b
JM
1539 if (argc < 1 || argc > 2) {
1540 printf("Invalid GET_CAPABILITY command: need either one or "
1541 "two arguments\n");
1542 return -1;
1543 }
1544
1545 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1546 printf("Invalid GET_CAPABILITY command: second argument, "
1547 "if any, must be 'strict'\n");
1548 return -1;
1549 }
1550
87c7ba84 1551 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
6fc6879b
JM
1552}
1553
1554
1555static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1556{
1557 printf("Available interfaces:\n");
1558 return wpa_ctrl_command(ctrl, "INTERFACES");
1559}
1560
1561
1562static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1563{
1564 if (argc < 1) {
1565 wpa_cli_list_interfaces(ctrl);
1566 return 0;
1567 }
1568
1569 wpa_cli_close_connection();
1570 os_free(ctrl_ifname);
1571 ctrl_ifname = os_strdup(argv[0]);
1572
2150c333 1573 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
6fc6879b 1574 printf("Connected to interface '%s.\n", ctrl_ifname);
6fc6879b
JM
1575 } else {
1576 printf("Could not connect to interface '%s' - re-trying\n",
1577 ctrl_ifname);
1578 }
1579 return 0;
1580}
1581
1582
1583static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1584 char *argv[])
1585{
1586 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1587}
1588
1589
1590static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1591 char *argv[])
1592{
1593 return wpa_ctrl_command(ctrl, "TERMINATE");
1594}
1595
1596
1597static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1598 char *argv[])
1599{
1600 char cmd[256];
1601 int res;
1602
1603 if (argc < 1) {
1604 printf("Invalid INTERFACE_ADD command: needs at least one "
1605 "argument (interface name)\n"
1606 "All arguments: ifname confname driver ctrl_interface "
1607 "driver_param bridge_name\n");
1608 return -1;
1609 }
1610
1611 /*
1612 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1613 * <driver_param>TAB<bridge_name>
1614 */
1615 res = os_snprintf(cmd, sizeof(cmd),
1616 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1617 argv[0],
1618 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1619 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1620 argc > 5 ? argv[5] : "");
1621 if (res < 0 || (size_t) res >= sizeof(cmd))
1622 return -1;
1623 cmd[sizeof(cmd) - 1] = '\0';
1624 return wpa_ctrl_command(ctrl, cmd);
1625}
1626
1627
1628static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1629 char *argv[])
1630{
87c7ba84 1631 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
6fc6879b
JM
1632}
1633
1634
4b4a8ae5
JM
1635static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1636 char *argv[])
1637{
1638 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1639}
1640
1641
e653b622
JM
1642#ifdef CONFIG_AP
1643static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1644{
87c7ba84 1645 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
e653b622
JM
1646}
1647
1648
1649static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1650 char *addr, size_t addr_len)
1651{
1652 char buf[4096], *pos;
1653 size_t len;
1654 int ret;
1655
1656 if (ctrl_conn == NULL) {
1657 printf("Not connected to hostapd - command dropped.\n");
1658 return -1;
1659 }
1660 len = sizeof(buf) - 1;
024d018b 1661 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
e653b622
JM
1662 wpa_cli_msg_cb);
1663 if (ret == -2) {
1664 printf("'%s' command timed out.\n", cmd);
1665 return -2;
1666 } else if (ret < 0) {
1667 printf("'%s' command failed.\n", cmd);
1668 return -1;
1669 }
1670
1671 buf[len] = '\0';
024d018b 1672 if (os_memcmp(buf, "FAIL", 4) == 0)
e653b622
JM
1673 return -1;
1674 printf("%s", buf);
1675
1676 pos = buf;
1677 while (*pos != '\0' && *pos != '\n')
1678 pos++;
1679 *pos = '\0';
1680 os_strlcpy(addr, buf, addr_len);
1681 return 0;
1682}
1683
1684
1685static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1686{
1687 char addr[32], cmd[64];
1688
1689 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1690 return 0;
1691 do {
e824cc46 1692 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
e653b622
JM
1693 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1694
1695 return -1;
1696}
e60b2951
JJ
1697
1698
1699static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1700 char *argv[])
1701{
87c7ba84 1702 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
e60b2951
JJ
1703}
1704
1705
1706static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1707 char *argv[])
1708{
87c7ba84 1709 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
e60b2951 1710}
334bf36a
AO
1711
1712static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1713 char *argv[])
1714{
1715 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1716}
1717
e653b622
JM
1718#endif /* CONFIG_AP */
1719
1720
207ef3fb
JM
1721static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722{
1723 return wpa_ctrl_command(ctrl, "SUSPEND");
1724}
1725
1726
1727static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728{
1729 return wpa_ctrl_command(ctrl, "RESUME");
1730}
1731
1732
9ff4de6d 1733#ifdef CONFIG_TESTING_OPTIONS
32d5295f
JM
1734static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1735{
1736 return wpa_ctrl_command(ctrl, "DROP_SA");
1737}
9ff4de6d 1738#endif /* CONFIG_TESTING_OPTIONS */
32d5295f
JM
1739
1740
86d4f806
JM
1741static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
87c7ba84 1743 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
86d4f806
JM
1744}
1745
1746
57faa1ce
JM
1747#ifdef CONFIG_P2P
1748
1749static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1750{
87c7ba84 1751 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
57faa1ce
JM
1752}
1753
1754
01335e2c
JM
1755static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1756{
1757 char **res = NULL;
1758 int arg = get_cmd_arg_num(str, pos);
1759
1760 res = os_calloc(6, sizeof(char *));
1761 if (res == NULL)
1762 return NULL;
1763 res[0] = os_strdup("type=social");
1764 if (res[0] == NULL) {
1765 os_free(res);
1766 return NULL;
1767 }
1768 res[1] = os_strdup("type=progressive");
1769 if (res[1] == NULL)
1770 return res;
1771 res[2] = os_strdup("delay=");
1772 if (res[2] == NULL)
1773 return res;
1774 res[3] = os_strdup("dev_id=");
1775 if (res[3] == NULL)
1776 return res;
1777 if (arg == 1)
1778 res[4] = os_strdup("[timeout]");
1779
1780 return res;
1781}
1782
1783
57faa1ce
JM
1784static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1785 char *argv[])
1786{
1787 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1788}
1789
1790
1791static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1792 char *argv[])
1793{
87c7ba84 1794 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
57faa1ce
JM
1795}
1796
1797
a624f20b
JM
1798static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1799{
1800 int arg = get_cmd_arg_num(str, pos);
1801 char **res = NULL;
1802
1803 switch (arg) {
1804 case 1:
1805 res = cli_txt_list_array(&p2p_peers);
1806 break;
1807 }
1808
1809 return res;
1810}
1811
1812
57faa1ce
JM
1813static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1814 char *argv[])
1815{
87c7ba84 1816 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
57faa1ce
JM
1817}
1818
1819
1820static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1821 char *argv[])
1822{
87c7ba84 1823 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
57faa1ce
JM
1824}
1825
1826
76788542
JM
1827static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1828{
1829 int arg = get_cmd_arg_num(str, pos);
1830 char **res = NULL;
1831
1832 switch (arg) {
1833 case 1:
1834 res = cli_txt_list_array(&p2p_groups);
1835 break;
1836 }
1837
1838 return res;
1839}
1840
1841
57faa1ce
JM
1842static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1843 char *argv[])
1844{
87c7ba84 1845 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
57faa1ce
JM
1846}
1847
1848
1849static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1850 char *argv[])
1851{
8c5f7309
JJ
1852 if (argc != 2 && argc != 3) {
1853 printf("Invalid P2P_PROV_DISC command: needs at least "
1854 "two arguments, address and config method\n"
1855 "(display, keypad, or pbc) and an optional join\n");
57faa1ce
JM
1856 return -1;
1857 }
1858
87c7ba84 1859 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
57faa1ce
JM
1860}
1861
1862
1863static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1864 char *argv[])
1865{
1866 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1867}
1868
1869
1870static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1871 char *argv[])
1872{
1873 char cmd[4096];
57faa1ce
JM
1874
1875 if (argc != 2 && argc != 4) {
1876 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1877 "arguments (address and TLVs) or four arguments "
1878 "(address, \"upnp\", version, search target "
1879 "(SSDP ST:)\n");
1880 return -1;
1881 }
1882
87c7ba84 1883 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
57faa1ce 1884 return -1;
57faa1ce
JM
1885 return wpa_ctrl_command(ctrl, cmd);
1886}
1887
1888
1889static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1890 int argc, char *argv[])
1891{
87c7ba84 1892 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
57faa1ce
JM
1893}
1894
1895
1896static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1897 char *argv[])
1898{
1899 char cmd[4096];
1900 int res;
1901
1902 if (argc != 4) {
1903 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1904 "arguments (freq, address, dialog token, and TLVs)\n");
1905 return -1;
1906 }
1907
1908 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1909 argv[0], argv[1], argv[2], argv[3]);
1910 if (res < 0 || (size_t) res >= sizeof(cmd))
1911 return -1;
1912 cmd[sizeof(cmd) - 1] = '\0';
1913 return wpa_ctrl_command(ctrl, cmd);
1914}
1915
1916
1917static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1918 char *argv[])
1919{
1920 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1921}
1922
1923
1924static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1925 int argc, char *argv[])
1926{
87c7ba84 1927 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
57faa1ce
JM
1928}
1929
1930
1931static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1932 char *argv[])
1933{
1934 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1935}
1936
1937
1938static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1939 char *argv[])
1940{
1941 char cmd[4096];
1942 int res;
1943
1944 if (argc != 3 && argc != 4) {
1945 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1946 "arguments\n");
1947 return -1;
1948 }
1949
1950 if (argc == 4)
1951 res = os_snprintf(cmd, sizeof(cmd),
1952 "P2P_SERVICE_ADD %s %s %s %s",
1953 argv[0], argv[1], argv[2], argv[3]);
1954 else
1955 res = os_snprintf(cmd, sizeof(cmd),
1956 "P2P_SERVICE_ADD %s %s %s",
1957 argv[0], argv[1], argv[2]);
1958 if (res < 0 || (size_t) res >= sizeof(cmd))
1959 return -1;
1960 cmd[sizeof(cmd) - 1] = '\0';
1961 return wpa_ctrl_command(ctrl, cmd);
1962}
1963
1964
1965static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1966 char *argv[])
1967{
1968 char cmd[4096];
1969 int res;
1970
1971 if (argc != 2 && argc != 3) {
1972 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1973 "arguments\n");
1974 return -1;
1975 }
1976
1977 if (argc == 3)
1978 res = os_snprintf(cmd, sizeof(cmd),
1979 "P2P_SERVICE_DEL %s %s %s",
1980 argv[0], argv[1], argv[2]);
1981 else
1982 res = os_snprintf(cmd, sizeof(cmd),
1983 "P2P_SERVICE_DEL %s %s",
1984 argv[0], argv[1]);
1985 if (res < 0 || (size_t) res >= sizeof(cmd))
1986 return -1;
1987 cmd[sizeof(cmd) - 1] = '\0';
1988 return wpa_ctrl_command(ctrl, cmd);
1989}
1990
1991
1992static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1993 int argc, char *argv[])
1994{
87c7ba84 1995 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
57faa1ce
JM
1996}
1997
1998
1999static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2000 int argc, char *argv[])
2001{
87c7ba84 2002 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
57faa1ce
JM
2003}
2004
2005
2006static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2007{
87c7ba84 2008 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
57faa1ce
JM
2009}
2010
2011
a624f20b
JM
2012static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2013{
2014 int arg = get_cmd_arg_num(str, pos);
2015 char **res = NULL;
2016
2017 switch (arg) {
2018 case 1:
2019 res = cli_txt_list_array(&p2p_peers);
2020 break;
2021 }
2022
2023 return res;
2024}
2025
2026
57faa1ce
JM
2027static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2028 char *addr, size_t addr_len,
2029 int discovered)
2030{
2031 char buf[4096], *pos;
2032 size_t len;
2033 int ret;
2034
2035 if (ctrl_conn == NULL)
2036 return -1;
2037 len = sizeof(buf) - 1;
024d018b 2038 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
57faa1ce
JM
2039 wpa_cli_msg_cb);
2040 if (ret == -2) {
2041 printf("'%s' command timed out.\n", cmd);
2042 return -2;
2043 } else if (ret < 0) {
2044 printf("'%s' command failed.\n", cmd);
2045 return -1;
2046 }
2047
2048 buf[len] = '\0';
024d018b 2049 if (os_memcmp(buf, "FAIL", 4) == 0)
57faa1ce
JM
2050 return -1;
2051
2052 pos = buf;
2053 while (*pos != '\0' && *pos != '\n')
2054 pos++;
2055 *pos++ = '\0';
2056 os_strlcpy(addr, buf, addr_len);
2057 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2058 printf("%s\n", addr);
2059 return 0;
2060}
2061
2062
2063static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2064{
2065 char addr[32], cmd[64];
2066 int discovered;
2067
2068 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2069
2070 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2071 addr, sizeof(addr), discovered))
9a6ade33 2072 return -1;
57faa1ce
JM
2073 do {
2074 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2075 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2076 discovered) == 0);
2077
9a6ade33 2078 return 0;
57faa1ce
JM
2079}
2080
2081
2082static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2083{
87c7ba84 2084 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
57faa1ce
JM
2085}
2086
2087
698e921b
JM
2088static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2089{
2090 int arg = get_cmd_arg_num(str, pos);
2091 const char *fields[] = {
2092 "discoverability",
2093 "managed",
2094 "listen_channel",
2095 "ssid_postfix",
2096 "noa",
2097 "ps",
2098 "oppps",
2099 "ctwindow",
2100 "disabled",
2101 "conc_pref",
2102 "force_long_sd",
2103 "peer_filter",
2104 "cross_connect",
2105 "go_apsd",
2106 "client_apsd",
2107 "disallow_freq",
2108 "disc_int",
05766ed8 2109 "per_sta_psk",
698e921b 2110 };
e7ecab4a 2111 int i, num_fields = ARRAY_SIZE(fields);
698e921b
JM
2112
2113 if (arg == 1) {
2114 char **res = os_calloc(num_fields + 1, sizeof(char *));
2115 if (res == NULL)
2116 return NULL;
2117 for (i = 0; i < num_fields; i++) {
2118 res[i] = os_strdup(fields[i]);
2119 if (res[i] == NULL)
2120 return res;
2121 }
2122 return res;
2123 }
2124
2125 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2126 return cli_txt_list_array(&p2p_peers);
2127
2128 return NULL;
2129}
2130
2131
57faa1ce
JM
2132static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2133{
2134 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2135}
2136
2137
59eba7a2
JM
2138static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2139 char *argv[])
2140{
2141 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2142}
2143
2144
9d562b79
SS
2145static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2146 char *argv[])
2147{
87c7ba84 2148 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
9d562b79
SS
2149}
2150
2151
57faa1ce
JM
2152static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2153 char *argv[])
2154{
57faa1ce
JM
2155 if (argc != 0 && argc != 2 && argc != 4) {
2156 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2157 "(preferred duration, interval; in microsecods).\n"
2158 "Optional second pair can be used to provide "
2159 "acceptable values.\n");
2160 return -1;
2161 }
2162
87c7ba84 2163 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
57faa1ce
JM
2164}
2165
2166
2167static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2168 char *argv[])
2169{
57faa1ce
JM
2170 if (argc != 0 && argc != 2) {
2171 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2172 "(availability period, availability interval; in "
2173 "millisecods).\n"
2174 "Extended Listen Timing can be cancelled with this "
2175 "command when used without parameters.\n");
2176 return -1;
2177 }
2178
87c7ba84 2179 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
57faa1ce
JM
2180}
2181
f2c56602
JM
2182
2183static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2184 char *argv[])
2185{
2186 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2187}
2188
57faa1ce
JM
2189#endif /* CONFIG_P2P */
2190
9675ce35
JM
2191#ifdef CONFIG_WIFI_DISPLAY
2192
2193static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195{
2196 char cmd[100];
2197 int res;
2198
2199 if (argc != 1 && argc != 2) {
2200 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2201 "arguments (subelem, hexdump)\n");
2202 return -1;
2203 }
2204
2205 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2206 argv[0], argc > 1 ? argv[1] : "");
2207 if (res < 0 || (size_t) res >= sizeof(cmd))
2208 return -1;
2209 cmd[sizeof(cmd) - 1] = '\0';
2210 return wpa_ctrl_command(ctrl, cmd);
2211}
2212
2213
2214static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
2217 char cmd[100];
2218 int res;
2219
2220 if (argc != 1) {
2221 printf("Invalid WFD_SUBELEM_GET command: needs one "
2222 "argument (subelem)\n");
2223 return -1;
2224 }
2225
2226 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2227 argv[0]);
2228 if (res < 0 || (size_t) res >= sizeof(cmd))
2229 return -1;
2230 cmd[sizeof(cmd) - 1] = '\0';
2231 return wpa_ctrl_command(ctrl, cmd);
2232}
2233#endif /* CONFIG_WIFI_DISPLAY */
2234
57faa1ce 2235
afc064fe
JM
2236#ifdef CONFIG_INTERWORKING
2237static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2238 char *argv[])
2239{
2240 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2241}
2242
2243
2244static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2245 char *argv[])
2246{
2247 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2248}
2249
2250
b02fe7ff
JM
2251static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2252 char *argv[])
2253{
87c7ba84 2254 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
b02fe7ff
JM
2255}
2256
2257
2258static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
87c7ba84 2261 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
b02fe7ff
JM
2262}
2263
2264
afc064fe
JM
2265static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2266{
87c7ba84 2267 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
afc064fe 2268}
b1f12296
JM
2269
2270
2271static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2272 char *argv[])
2273{
2274 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2275}
2276
2277
2278static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280{
2281 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2282}
afc064fe
JM
2283#endif /* CONFIG_INTERWORKING */
2284
2285
a8918e86
JK
2286#ifdef CONFIG_HS20
2287
2288static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2289 char *argv[])
2290{
87c7ba84 2291 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
a8918e86
JK
2292}
2293
2294
2295static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2296 char *argv[])
2297{
2298 char cmd[512];
a8918e86
JK
2299
2300 if (argc == 0) {
2301 printf("Command needs one or two arguments (dst mac addr and "
2302 "optional home realm)\n");
2303 return -1;
2304 }
2305
87c7ba84
JM
2306 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2307 argc, argv) < 0)
a8918e86 2308 return -1;
a8918e86
JK
2309
2310 return wpa_ctrl_command(ctrl, cmd);
2311}
2312
184e110c
JM
2313
2314static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2315 char *argv[])
2316{
2317 char cmd[512];
2318
2319 if (argc < 2) {
2320 printf("Command needs two arguments (dst mac addr and "
2321 "icon name)\n");
2322 return -1;
2323 }
2324
2325 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2326 return -1;
2327
2328 return wpa_ctrl_command(ctrl, cmd);
2329}
2330
b572df86
JM
2331
2332static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2333{
2334 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2335}
2336
2337
2338static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2339 char *argv[])
2340{
2341 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2342}
2343
a8918e86
JK
2344#endif /* CONFIG_HS20 */
2345
2346
0d0a8ca1
AC
2347static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2348 char *argv[])
2349{
87c7ba84 2350 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
0d0a8ca1
AC
2351}
2352
2353
281ff0aa
GP
2354static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2355 char *argv[])
2356{
87c7ba84 2357 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
281ff0aa
GP
2358}
2359
2360
2361static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2362 char *argv[])
2363{
87c7ba84 2364 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
281ff0aa
GP
2365}
2366
2367
2368static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2369 char *argv[])
2370{
87c7ba84 2371 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
281ff0aa
GP
2372}
2373
2374
60b24b0d
DS
2375static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2376 char *argv[])
2377{
2378 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2379}
2380
2381
dc7785f8
YZ
2382static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2383 char *argv[])
2384{
2385 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2386}
2387
2388
9482426e
JM
2389static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2390 char *argv[])
2391{
2392 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2393}
2394
2395
2bdd8342
TB
2396#ifdef CONFIG_AUTOSCAN
2397
2398static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2399{
2bdd8342
TB
2400 if (argc == 0)
2401 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2402
87c7ba84 2403 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2bdd8342
TB
2404}
2405
2406#endif /* CONFIG_AUTOSCAN */
2407
2408
e9199e31
JM
2409#ifdef CONFIG_WNM
2410
2411static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2412{
2413 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2414}
2415
65bcd0a9
VK
2416
2417static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2418{
2419 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2420}
2421
e9199e31
JM
2422#endif /* CONFIG_WNM */
2423
2424
27b80b5b
JM
2425static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2426{
2427 if (argc == 0)
2428 return -1;
2429 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2430}
2431
2432
5e2c3490
JM
2433#ifdef ANDROID
2434static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2435{
2436 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2437}
2438#endif /* ANDROID */
2439
2440
adef8948
BL
2441static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2442{
2443 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2444}
2445
2446
acb54643
JM
2447static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2448{
2449 return wpa_ctrl_command(ctrl, "FLUSH");
2450}
2451
2452
1f965e62
JM
2453static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2454{
2455 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2456}
2457
2458
40fd868c
ER
2459enum wpa_cli_cmd_flags {
2460 cli_cmd_flag_none = 0x00,
2461 cli_cmd_flag_sensitive = 0x01
2462};
2463
6fc6879b
JM
2464struct wpa_cli_cmd {
2465 const char *cmd;
2466 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
b49039bd 2467 char ** (*completion)(const char *str, int pos);
40fd868c 2468 enum wpa_cli_cmd_flags flags;
dfa141b1 2469 const char *usage;
6fc6879b
JM
2470};
2471
2472static struct wpa_cli_cmd wpa_cli_commands[] = {
b49039bd 2473 { "status", wpa_cli_cmd_status, NULL,
dfa141b1
ER
2474 cli_cmd_flag_none,
2475 "[verbose] = get current WPA/EAPOL/EAP status" },
b49039bd 2476 { "ifname", wpa_cli_cmd_ifname, NULL,
0eed2a8d
JD
2477 cli_cmd_flag_none,
2478 "= get current interface name" },
b49039bd 2479 { "ping", wpa_cli_cmd_ping, NULL,
dfa141b1
ER
2480 cli_cmd_flag_none,
2481 "= pings wpa_supplicant" },
b49039bd 2482 { "relog", wpa_cli_cmd_relog, NULL,
ac6912b5
BG
2483 cli_cmd_flag_none,
2484 "= re-open log-file (allow rolling logs)" },
b49039bd 2485 { "note", wpa_cli_cmd_note, NULL,
77895cd9
JM
2486 cli_cmd_flag_none,
2487 "<text> = add a note to wpa_supplicant debug log" },
b49039bd 2488 { "mib", wpa_cli_cmd_mib, NULL,
dfa141b1
ER
2489 cli_cmd_flag_none,
2490 "= get MIB variables (dot1x, dot11)" },
2af4d404 2491 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
dfa141b1 2492 cli_cmd_flag_none,
2af4d404 2493 "[command] = show usage help" },
b49039bd 2494 { "interface", wpa_cli_cmd_interface, NULL,
dfa141b1
ER
2495 cli_cmd_flag_none,
2496 "[ifname] = show interfaces/select interface" },
b49039bd 2497 { "level", wpa_cli_cmd_level, NULL,
dfa141b1
ER
2498 cli_cmd_flag_none,
2499 "<debug level> = change debug level" },
b49039bd 2500 { "license", wpa_cli_cmd_license, NULL,
dfa141b1
ER
2501 cli_cmd_flag_none,
2502 "= show full wpa_cli license" },
b49039bd 2503 { "quit", wpa_cli_cmd_quit, NULL,
dfa141b1
ER
2504 cli_cmd_flag_none,
2505 "= exit wpa_cli" },
21565872 2506 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
dfa141b1
ER
2507 cli_cmd_flag_none,
2508 "= set variables (shows list of variables when run without "
2509 "arguments)" },
b49039bd 2510 { "get", wpa_cli_cmd_get, NULL,
acec8d32
JM
2511 cli_cmd_flag_none,
2512 "<name> = get information" },
b49039bd 2513 { "logon", wpa_cli_cmd_logon, NULL,
dfa141b1
ER
2514 cli_cmd_flag_none,
2515 "= IEEE 802.1X EAPOL state machine logon" },
b49039bd 2516 { "logoff", wpa_cli_cmd_logoff, NULL,
dfa141b1
ER
2517 cli_cmd_flag_none,
2518 "= IEEE 802.1X EAPOL state machine logoff" },
b49039bd 2519 { "pmksa", wpa_cli_cmd_pmksa, NULL,
dfa141b1
ER
2520 cli_cmd_flag_none,
2521 "= show PMKSA cache" },
b49039bd 2522 { "reassociate", wpa_cli_cmd_reassociate, NULL,
dfa141b1
ER
2523 cli_cmd_flag_none,
2524 "= force reassociation" },
0f44ec8e
PQ
2525 { "reattach", wpa_cli_cmd_reattach, NULL,
2526 cli_cmd_flag_none,
2527 "= force reassociation back to the same BSS" },
b49039bd 2528 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
dfa141b1
ER
2529 cli_cmd_flag_none,
2530 "<BSSID> = force preauthentication" },
b49039bd 2531 { "identity", wpa_cli_cmd_identity, NULL,
dfa141b1
ER
2532 cli_cmd_flag_none,
2533 "<network id> <identity> = configure identity for an SSID" },
b49039bd 2534 { "password", wpa_cli_cmd_password, NULL,
dfa141b1
ER
2535 cli_cmd_flag_sensitive,
2536 "<network id> <password> = configure password for an SSID" },
b49039bd 2537 { "new_password", wpa_cli_cmd_new_password, NULL,
dfa141b1
ER
2538 cli_cmd_flag_sensitive,
2539 "<network id> <password> = change password for an SSID" },
b49039bd 2540 { "pin", wpa_cli_cmd_pin, NULL,
dfa141b1
ER
2541 cli_cmd_flag_sensitive,
2542 "<network id> <pin> = configure pin for an SSID" },
b49039bd 2543 { "otp", wpa_cli_cmd_otp, NULL,
dfa141b1
ER
2544 cli_cmd_flag_sensitive,
2545 "<network id> <password> = configure one-time-password for an SSID"
2546 },
b49039bd 2547 { "passphrase", wpa_cli_cmd_passphrase, NULL,
dfa141b1
ER
2548 cli_cmd_flag_sensitive,
2549 "<network id> <passphrase> = configure private key passphrase\n"
2550 " for an SSID" },
a5d44ac0
JM
2551 { "sim", wpa_cli_cmd_sim, NULL,
2552 cli_cmd_flag_sensitive,
2553 "<network id> <pin> = report SIM operation result" },
b49039bd 2554 { "bssid", wpa_cli_cmd_bssid, NULL,
dfa141b1
ER
2555 cli_cmd_flag_none,
2556 "<network id> <BSSID> = set preferred BSSID for an SSID" },
b49039bd 2557 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
9aa10e2b
DS
2558 cli_cmd_flag_none,
2559 "<BSSID> = add a BSSID to the blacklist\n"
2560 "blacklist clear = clear the blacklist\n"
2561 "blacklist = display the blacklist" },
b49039bd 2562 { "log_level", wpa_cli_cmd_log_level, NULL,
0597a5b5
DS
2563 cli_cmd_flag_none,
2564 "<level> [<timestamp>] = update the log level/timestamp\n"
2565 "log_level = display the current log level and log options" },
b49039bd 2566 { "list_networks", wpa_cli_cmd_list_networks, NULL,
dfa141b1
ER
2567 cli_cmd_flag_none,
2568 "= list configured networks" },
b49039bd 2569 { "select_network", wpa_cli_cmd_select_network, NULL,
dfa141b1
ER
2570 cli_cmd_flag_none,
2571 "<network id> = select a network (disable others)" },
b49039bd 2572 { "enable_network", wpa_cli_cmd_enable_network, NULL,
dfa141b1
ER
2573 cli_cmd_flag_none,
2574 "<network id> = enable a network" },
b49039bd 2575 { "disable_network", wpa_cli_cmd_disable_network, NULL,
dfa141b1
ER
2576 cli_cmd_flag_none,
2577 "<network id> = disable a network" },
b49039bd 2578 { "add_network", wpa_cli_cmd_add_network, NULL,
dfa141b1
ER
2579 cli_cmd_flag_none,
2580 "= add a network" },
b49039bd 2581 { "remove_network", wpa_cli_cmd_remove_network, NULL,
dfa141b1
ER
2582 cli_cmd_flag_none,
2583 "<network id> = remove a network" },
b49039bd 2584 { "set_network", wpa_cli_cmd_set_network, NULL,
dfa141b1
ER
2585 cli_cmd_flag_sensitive,
2586 "<network id> <variable> <value> = set network variables (shows\n"
2587 " list of variables when run without arguments)" },
b49039bd 2588 { "get_network", wpa_cli_cmd_get_network, NULL,
dfa141b1
ER
2589 cli_cmd_flag_none,
2590 "<network id> <variable> = get network variables" },
1c330a2f
DS
2591 { "dup_network", wpa_cli_cmd_dup_network, NULL,
2592 cli_cmd_flag_none,
2593 "<src network id> <dst network id> <variable> = duplicate network variables"
2594 },
b49039bd 2595 { "list_creds", wpa_cli_cmd_list_creds, NULL,
d94c9ee6
JM
2596 cli_cmd_flag_none,
2597 "= list configured credentials" },
b49039bd 2598 { "add_cred", wpa_cli_cmd_add_cred, NULL,
d94c9ee6
JM
2599 cli_cmd_flag_none,
2600 "= add a credential" },
b49039bd 2601 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
d94c9ee6
JM
2602 cli_cmd_flag_none,
2603 "<cred id> = remove a credential" },
b49039bd 2604 { "set_cred", wpa_cli_cmd_set_cred, NULL,
d94c9ee6
JM
2605 cli_cmd_flag_sensitive,
2606 "<cred id> <variable> <value> = set credential variables" },
c880ab87
JM
2607 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2608 cli_cmd_flag_none,
2609 "<cred id> <variable> = get credential variables" },
b49039bd 2610 { "save_config", wpa_cli_cmd_save_config, NULL,
dfa141b1
ER
2611 cli_cmd_flag_none,
2612 "= save the current configuration" },
b49039bd 2613 { "disconnect", wpa_cli_cmd_disconnect, NULL,
dfa141b1
ER
2614 cli_cmd_flag_none,
2615 "= disconnect and wait for reassociate/reconnect command before\n"
2616 " connecting" },
b49039bd 2617 { "reconnect", wpa_cli_cmd_reconnect, NULL,
dfa141b1
ER
2618 cli_cmd_flag_none,
2619 "= like reassociate, but only takes effect if already disconnected"
2620 },
b49039bd 2621 { "scan", wpa_cli_cmd_scan, NULL,
dfa141b1
ER
2622 cli_cmd_flag_none,
2623 "= request new BSS scan" },
b49039bd 2624 { "scan_results", wpa_cli_cmd_scan_results, NULL,
dfa141b1
ER
2625 cli_cmd_flag_none,
2626 "= get latest scan results" },
b49039bd 2627 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
dfa141b1
ER
2628 cli_cmd_flag_none,
2629 "<<idx> | <bssid>> = get detailed scan result info" },
b49039bd 2630 { "get_capability", wpa_cli_cmd_get_capability, NULL,
dfa141b1 2631 cli_cmd_flag_none,
06060522 2632 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
35aa088a 2633 "= get capabilies" },
b49039bd 2634 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
dfa141b1
ER
2635 cli_cmd_flag_none,
2636 "= force wpa_supplicant to re-read its configuration file" },
b49039bd 2637 { "terminate", wpa_cli_cmd_terminate, NULL,
dfa141b1
ER
2638 cli_cmd_flag_none,
2639 "= terminate wpa_supplicant" },
b49039bd 2640 { "interface_add", wpa_cli_cmd_interface_add, NULL,
dfa141b1
ER
2641 cli_cmd_flag_none,
2642 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2643 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2644 " are optional" },
b49039bd 2645 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
dfa141b1
ER
2646 cli_cmd_flag_none,
2647 "<ifname> = removes the interface" },
b49039bd 2648 { "interface_list", wpa_cli_cmd_interface_list, NULL,
dfa141b1
ER
2649 cli_cmd_flag_none,
2650 "= list available interfaces" },
b49039bd 2651 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
dfa141b1
ER
2652 cli_cmd_flag_none,
2653 "<value> = set ap_scan parameter" },
b49039bd 2654 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
67b9bd08
DS
2655 cli_cmd_flag_none,
2656 "<value> = set scan_interval parameter (in seconds)" },
b49039bd 2657 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
78633c37
SL
2658 cli_cmd_flag_none,
2659 "<value> = set BSS expiration age parameter" },
b49039bd 2660 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
78633c37
SL
2661 cli_cmd_flag_none,
2662 "<value> = set BSS expiration scan count parameter" },
b49039bd 2663 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
39ee845f
DS
2664 cli_cmd_flag_none,
2665 "<value> = set BSS flush age (0 by default)" },
b49039bd 2666 { "stkstart", wpa_cli_cmd_stkstart, NULL,
dfa141b1
ER
2667 cli_cmd_flag_none,
2668 "<addr> = request STK negotiation with <addr>" },
b49039bd 2669 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
dfa141b1
ER
2670 cli_cmd_flag_none,
2671 "<addr> = request over-the-DS FT with <addr>" },
b49039bd 2672 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
dfa141b1
ER
2673 cli_cmd_flag_none,
2674 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
b49039bd 2675 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
dfa141b1
ER
2676 cli_cmd_flag_sensitive,
2677 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2678 "hardcoded)" },
b49039bd 2679 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
3981cb3c
JM
2680 cli_cmd_flag_sensitive,
2681 "<PIN> = verify PIN checksum" },
b49039bd 2682 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2f9929ff 2683 "Cancels the pending WPS operation" },
71892384 2684#ifdef CONFIG_WPS_NFC
b49039bd 2685 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3f2c8ba6
JM
2686 cli_cmd_flag_none,
2687 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
bbf41865
JM
2688 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2689 cli_cmd_flag_none,
2690 "<WPS|NDEF> = build configuration token" },
b49039bd 2691 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3f2c8ba6
JM
2692 cli_cmd_flag_none,
2693 "<WPS|NDEF> = create password token" },
b49039bd 2694 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
d7645d23
JM
2695 cli_cmd_flag_sensitive,
2696 "<hexdump of payload> = report read NFC tag with WPS data" },
e65552dd
JM
2697 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2698 cli_cmd_flag_none,
2699 "<NDEF> <WPS> = create NFC handover request" },
2700 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2701 cli_cmd_flag_none,
2702 "<NDEF> <WPS> = create NFC handover select" },
e4758827
JM
2703 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2704 cli_cmd_flag_none,
2705 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2706 "NFC handover" },
71892384 2707#endif /* CONFIG_WPS_NFC */
b49039bd 2708 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
dfa141b1
ER
2709 cli_cmd_flag_sensitive,
2710 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
b49039bd 2711 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
70d84f11
JM
2712 cli_cmd_flag_sensitive,
2713 "[params..] = enable/disable AP PIN" },
b49039bd 2714 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
e9bcfebf 2715 cli_cmd_flag_none,
08486685 2716 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
b49039bd 2717 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
e9bcfebf
JM
2718 cli_cmd_flag_none,
2719 "= stop Wi-Fi Protected Setup External Registrar" },
b49039bd 2720 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
72df2f5f
JM
2721 cli_cmd_flag_sensitive,
2722 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
b49039bd 2723 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
564cd7fa
JM
2724 cli_cmd_flag_none,
2725 "<UUID> = accept an Enrollee PBC using External Registrar" },
b49039bd 2726 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
e64dcfd5
JM
2727 cli_cmd_flag_sensitive,
2728 "<UUID> <PIN> = learn AP configuration" },
b49039bd 2729 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
ef10f473
JM
2730 cli_cmd_flag_none,
2731 "<UUID> <network id> = set AP configuration for enrolling" },
b49039bd 2732 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
7d6640a6
JM
2733 cli_cmd_flag_sensitive,
2734 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
1cea09a9 2735#ifdef CONFIG_WPS_NFC
b49039bd 2736 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
1cea09a9
JM
2737 cli_cmd_flag_none,
2738 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2739#endif /* CONFIG_WPS_NFC */
b49039bd 2740 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
11ef8d35
JM
2741 cli_cmd_flag_none,
2742 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622 2743#ifdef CONFIG_AP
b49039bd 2744 { "sta", wpa_cli_cmd_sta, NULL,
e653b622
JM
2745 cli_cmd_flag_none,
2746 "<addr> = get information about an associated station (AP)" },
b49039bd 2747 { "all_sta", wpa_cli_cmd_all_sta, NULL,
e653b622
JM
2748 cli_cmd_flag_none,
2749 "= get information about all associated stations (AP)" },
b49039bd 2750 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
e60b2951
JJ
2751 cli_cmd_flag_none,
2752 "<addr> = deauthenticate a station" },
b49039bd 2753 { "disassociate", wpa_cli_cmd_disassociate, NULL,
e60b2951
JJ
2754 cli_cmd_flag_none,
2755 "<addr> = disassociate a station" },
334bf36a
AO
2756 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2757 cli_cmd_flag_none,
2758 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2759 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2760 " = CSA parameters" },
e653b622 2761#endif /* CONFIG_AP */
b49039bd 2762 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
207ef3fb 2763 "= notification of suspend/hibernate" },
b49039bd 2764 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
207ef3fb 2765 "= notification of resume/thaw" },
9ff4de6d 2766#ifdef CONFIG_TESTING_OPTIONS
b49039bd 2767 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
32d5295f 2768 "= drop SA without deauth/disassoc (test command)" },
9ff4de6d 2769#endif /* CONFIG_TESTING_OPTIONS */
b49039bd 2770 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
86d4f806
JM
2771 cli_cmd_flag_none,
2772 "<addr> = roam to the specified BSS" },
57faa1ce 2773#ifdef CONFIG_P2P
01335e2c
JM
2774 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2775 cli_cmd_flag_none,
57faa1ce 2776 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
b49039bd 2777 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
57faa1ce 2778 "= stop P2P Devices search" },
b49039bd
JM
2779 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2780 cli_cmd_flag_none,
e2308e4b 2781 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
b49039bd 2782 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
57faa1ce 2783 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
b49039bd
JM
2784 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2785 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
4d2ea6a6 2786 "<ifname> = remove P2P group interface (terminate group if GO)" },
b49039bd 2787 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
7aeac985 2788 "[ht40] = add a new P2P group (local end as GO)" },
b49039bd
JM
2789 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2790 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
57faa1ce 2791 "<addr> <method> = request provisioning discovery" },
b49039bd 2792 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
57faa1ce
JM
2793 cli_cmd_flag_none,
2794 "= get the passphrase for a group (GO only)" },
2795 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
b49039bd 2796 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
57faa1ce
JM
2797 "<addr> <TLVs> = schedule service discovery request" },
2798 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
b49039bd 2799 NULL, cli_cmd_flag_none,
57faa1ce 2800 "<id> = cancel pending service discovery request" },
b49039bd 2801 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
57faa1ce
JM
2802 cli_cmd_flag_none,
2803 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
b49039bd 2804 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
57faa1ce
JM
2805 cli_cmd_flag_none,
2806 "= indicate change in local services" },
b49039bd 2807 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
57faa1ce
JM
2808 cli_cmd_flag_none,
2809 "<external> = set external processing of service discovery" },
b49039bd 2810 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
57faa1ce
JM
2811 cli_cmd_flag_none,
2812 "= remove all stored service entries" },
b49039bd 2813 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
57faa1ce
JM
2814 cli_cmd_flag_none,
2815 "<bonjour|upnp> <query|version> <response|service> = add a local "
2816 "service" },
b49039bd 2817 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
57faa1ce
JM
2818 cli_cmd_flag_none,
2819 "<bonjour|upnp> <query|version> [|service] = remove a local "
2820 "service" },
b49039bd 2821 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
57faa1ce
JM
2822 cli_cmd_flag_none,
2823 "<addr> = reject connection attempts from a specific peer" },
b49039bd 2824 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
57faa1ce
JM
2825 cli_cmd_flag_none,
2826 "<cmd> [peer=addr] = invite peer" },
b49039bd 2827 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
57faa1ce
JM
2828 "[discovered] = list known (optionally, only fully discovered) P2P "
2829 "peers" },
b49039bd
JM
2830 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2831 cli_cmd_flag_none,
57faa1ce 2832 "<address> = show information about known P2P peer" },
698e921b
JM
2833 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2834 cli_cmd_flag_none,
57faa1ce 2835 "<field> <value> = set a P2P parameter" },
b49039bd 2836 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
57faa1ce 2837 "= flush P2P state" },
b49039bd 2838 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
59eba7a2 2839 "= cancel P2P group formation" },
b49039bd
JM
2840 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2841 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
9d562b79 2842 "<address> = unauthorize a peer" },
b49039bd
JM
2843 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2844 cli_cmd_flag_none,
57faa1ce
JM
2845 "[<duration> <interval>] [<duration> <interval>] = request GO "
2846 "presence" },
b49039bd
JM
2847 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2848 cli_cmd_flag_none,
57faa1ce 2849 "[<period> <interval>] = set extended listen timing" },
f2c56602
JM
2850 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2851 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2852 "<address|iface=address> = remove a peer from all groups" },
57faa1ce 2853#endif /* CONFIG_P2P */
9675ce35
JM
2854#ifdef CONFIG_WIFI_DISPLAY
2855 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2856 cli_cmd_flag_none,
2857 "<subelem> [contents] = set Wi-Fi Display subelement" },
2858 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2859 cli_cmd_flag_none,
2860 "<subelem> = get Wi-Fi Display subelement" },
2861#endif /* CONFIG_WIFI_DISPLAY */
afc064fe 2862#ifdef CONFIG_INTERWORKING
b49039bd 2863 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
afc064fe 2864 "= fetch ANQP information for all APs" },
b49039bd
JM
2865 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2866 cli_cmd_flag_none,
afc064fe 2867 "= stop fetch_anqp operation" },
b49039bd 2868 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
b02fe7ff
JM
2869 cli_cmd_flag_none,
2870 "[auto] = perform Interworking network selection" },
2871 { "interworking_connect", wpa_cli_cmd_interworking_connect,
b49039bd 2872 wpa_cli_complete_bss, cli_cmd_flag_none,
b02fe7ff 2873 "<BSSID> = connect using Interworking credentials" },
b49039bd
JM
2874 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2875 cli_cmd_flag_none,
afc064fe 2876 "<addr> <info id>[,<info id>]... = request ANQP information" },
b1f12296
JM
2877 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2878 cli_cmd_flag_none,
2879 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2880 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2881 wpa_cli_complete_bss, cli_cmd_flag_none,
2882 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
afc064fe 2883#endif /* CONFIG_INTERWORKING */
a8918e86 2884#ifdef CONFIG_HS20
b49039bd
JM
2885 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2886 cli_cmd_flag_none,
a8918e86
JK
2887 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2888 },
2889 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
b49039bd 2890 wpa_cli_complete_bss, cli_cmd_flag_none,
a8918e86 2891 "<addr> <home realm> = get HS20 nai home realm list" },
184e110c
JM
2892 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2893 wpa_cli_complete_bss, cli_cmd_flag_none,
2894 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
b572df86
JM
2895 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2896 "= fetch OSU provider information from all APs" },
2897 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2898 cli_cmd_flag_none,
2899 "= cancel fetch_osu command" },
a8918e86 2900#endif /* CONFIG_HS20 */
b49039bd
JM
2901 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2902 cli_cmd_flag_none,
0d0a8ca1 2903 "<0/1> = disable/enable automatic reconnection" },
b49039bd 2904 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
281ff0aa
GP
2905 cli_cmd_flag_none,
2906 "<addr> = request TDLS discovery with <addr>" },
b49039bd 2907 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
281ff0aa
GP
2908 cli_cmd_flag_none,
2909 "<addr> = request TDLS setup with <addr>" },
b49039bd 2910 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
281ff0aa
GP
2911 cli_cmd_flag_none,
2912 "<addr> = tear down TDLS with <addr>" },
b49039bd 2913 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
60b24b0d
DS
2914 cli_cmd_flag_none,
2915 "= get signal parameters" },
dc7785f8
YZ
2916 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2917 cli_cmd_flag_none,
2918 "= get TX/RX packet counters" },
b49039bd
JM
2919 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2920 cli_cmd_flag_none,
9482426e 2921 "= trigger IEEE 802.1X/EAPOL reauthentication" },
2bdd8342 2922#ifdef CONFIG_AUTOSCAN
b49039bd 2923 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2bdd8342
TB
2924 "[params] = Set or unset (if none) autoscan parameters" },
2925#endif /* CONFIG_AUTOSCAN */
e9199e31
JM
2926#ifdef CONFIG_WNM
2927 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2928 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
65bcd0a9
VK
2929 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2930 "<query reason> = Send BSS Transition Management Query" },
e9199e31 2931#endif /* CONFIG_WNM */
b49039bd 2932 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
27b80b5b 2933 "<params..> = Sent unprocessed command" },
acb54643
JM
2934 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2935 "= flush wpa_supplicant state" },
5e2c3490
JM
2936#ifdef ANDROID
2937 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
2938 "<command> = driver private commands" },
2939#endif /* ANDROID */
1f965e62
JM
2940 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2941 "= radio_work <show/add/done>" },
adef8948
BL
2942 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2943 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2944 },
b49039bd 2945 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
2946};
2947
2948
dfa141b1
ER
2949/*
2950 * Prints command usage, lines are padded with the specified string.
2951 */
2952static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2953{
2954 char c;
2955 size_t n;
2956
2957 printf("%s%s ", pad, cmd->cmd);
2958 for (n = 0; (c = cmd->usage[n]); n++) {
2959 printf("%c", c);
2960 if (c == '\n')
2961 printf("%s", pad);
2962 }
2963 printf("\n");
2964}
2965
2966
2af4d404 2967static void print_help(const char *cmd)
dfa141b1
ER
2968{
2969 int n;
2970 printf("commands:\n");
2af4d404
JM
2971 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2972 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2973 print_cmd_help(&wpa_cli_commands[n], " ");
2974 }
dfa141b1
ER
2975}
2976
2977
e8ecb5fb 2978static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
40fd868c
ER
2979{
2980 const char *c, *delim;
2981 int n;
2982 size_t len;
2983
2984 delim = os_strchr(cmd, ' ');
2985 if (delim)
2986 len = delim - cmd;
2987 else
2988 len = os_strlen(cmd);
2989
2990 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2991 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2992 return (wpa_cli_commands[n].flags &
2993 cli_cmd_flag_sensitive);
2994 }
2995 return 0;
2996}
e8ecb5fb
JM
2997
2998
2999static char ** wpa_list_cmd_list(void)
3000{
3001 char **res;
3002 int i, count;
37620493 3003 struct cli_txt_entry *e;
e8ecb5fb 3004
e7ecab4a 3005 count = ARRAY_SIZE(wpa_cli_commands);
37620493
JM
3006 count += dl_list_len(&p2p_groups);
3007 count += dl_list_len(&ifnames);
3008 res = os_calloc(count + 1, sizeof(char *));
e8ecb5fb
JM
3009 if (res == NULL)
3010 return NULL;
3011
3012 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3013 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3014 if (res[i] == NULL)
3015 break;
3016 }
3017
37620493
JM
3018 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3019 size_t len = 8 + os_strlen(e->txt);
3020 res[i] = os_malloc(len);
3021 if (res[i] == NULL)
3022 break;
3023 os_snprintf(res[i], len, "ifname=%s", e->txt);
3024 i++;
3025 }
3026
3027 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3028 res[i] = os_strdup(e->txt);
3029 if (res[i] == NULL)
3030 break;
3031 i++;
3032 }
3033
e8ecb5fb
JM
3034 return res;
3035}
3036
3037
3038static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3039 int pos)
3040{
3041 int i;
3042
3043 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3044 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
e4f6873c
JM
3045 if (wpa_cli_commands[i].completion)
3046 return wpa_cli_commands[i].completion(str,
3047 pos);
e8ecb5fb
JM
3048 edit_clear_line();
3049 printf("\r%s\n", wpa_cli_commands[i].usage);
3050 edit_redraw();
3051 break;
3052 }
3053 }
3054
3055 return NULL;
3056}
3057
3058
3059static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3060{
3061 char **res;
3062 const char *end;
3063 char *cmd;
3064
37620493
JM
3065 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3066 end = os_strchr(str, ' ');
3067 if (end && pos > end - str) {
3068 pos -= end - str + 1;
3069 str = end + 1;
3070 }
3071 }
3072
e8ecb5fb
JM
3073 end = os_strchr(str, ' ');
3074 if (end == NULL || str + pos < end)
3075 return wpa_list_cmd_list();
3076
3077 cmd = os_malloc(pos + 1);
3078 if (cmd == NULL)
3079 return NULL;
3080 os_memcpy(cmd, str, pos);
3081 cmd[end - str] = '\0';
3082 res = wpa_cli_cmd_completion(cmd, str, pos);
3083 os_free(cmd);
3084 return res;
3085}
40fd868c
ER
3086
3087
6fc6879b
JM
3088static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3089{
3090 struct wpa_cli_cmd *cmd, *match = NULL;
3091 int count;
3092 int ret = 0;
3093
13b11ba7
JM
3094 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3095 ifname_prefix = argv[0] + 7;
3096 argv = &argv[1];
3097 argc--;
3098 } else
3099 ifname_prefix = NULL;
3100
3101 if (argc == 0)
3102 return -1;
3103
6fc6879b
JM
3104 count = 0;
3105 cmd = wpa_cli_commands;
3106 while (cmd->cmd) {
3107 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3108 {
3109 match = cmd;
3110 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3111 /* we have an exact match */
3112 count = 1;
3113 break;
3114 }
3115 count++;
3116 }
3117 cmd++;
3118 }
3119
3120 if (count > 1) {
3121 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3122 cmd = wpa_cli_commands;
3123 while (cmd->cmd) {
3124 if (os_strncasecmp(cmd->cmd, argv[0],
3125 os_strlen(argv[0])) == 0) {
3126 printf(" %s", cmd->cmd);
3127 }
3128 cmd++;
3129 }
3130 printf("\n");
3131 ret = 1;
3132 } else if (count == 0) {
3133 printf("Unknown command '%s'\n", argv[0]);
3134 ret = 1;
3135 } else {
3136 ret = match->handler(ctrl, argc - 1, &argv[1]);
3137 }
3138
3139 return ret;
3140}
3141
3142
3143static int str_match(const char *a, const char *b)
3144{
3145 return os_strncmp(a, b, os_strlen(b)) == 0;
3146}
3147
3148
3149static int wpa_cli_exec(const char *program, const char *arg1,
3150 const char *arg2)
3151{
3152 char *cmd;
3153 size_t len;
3154 int res;
308a4ec8 3155 int ret = 0;
6fc6879b
JM
3156
3157 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3158 cmd = os_malloc(len);
3159 if (cmd == NULL)
3160 return -1;
3161 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3162 if (res < 0 || (size_t) res >= len) {
3163 os_free(cmd);
3164 return -1;
3165 }
3166 cmd[len - 1] = '\0';
3167#ifndef _WIN32_WCE
308a4ec8
JM
3168 if (system(cmd) < 0)
3169 ret = -1;
6fc6879b
JM
3170#endif /* _WIN32_WCE */
3171 os_free(cmd);
3172
308a4ec8 3173 return ret;
6fc6879b
JM
3174}
3175
3176
3177static void wpa_cli_action_process(const char *msg)
3178{
3179 const char *pos;
3180 char *copy = NULL, *id, *pos2;
3181
3182 pos = msg;
3183 if (*pos == '<') {
3184 /* skip priority */
3185 pos = os_strchr(pos, '>');
3186 if (pos)
3187 pos++;
3188 else
3189 pos = msg;
3190 }
3191
3192 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3193 int new_id = -1;
3194 os_unsetenv("WPA_ID");
3195 os_unsetenv("WPA_ID_STR");
3196 os_unsetenv("WPA_CTRL_DIR");
3197
3198 pos = os_strstr(pos, "[id=");
3199 if (pos)
3200 copy = os_strdup(pos + 4);
3201
3202 if (copy) {
3203 pos2 = id = copy;
3204 while (*pos2 && *pos2 != ' ')
3205 pos2++;
3206 *pos2++ = '\0';
3207 new_id = atoi(id);
3208 os_setenv("WPA_ID", id, 1);
3209 while (*pos2 && *pos2 != '=')
3210 pos2++;
3211 if (*pos2 == '=')
3212 pos2++;
3213 id = pos2;
3214 while (*pos2 && *pos2 != ']')
3215 pos2++;
3216 *pos2 = '\0';
3217 os_setenv("WPA_ID_STR", id, 1);
3218 os_free(copy);
3219 }
3220
3221 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3222
02a3e5c0 3223 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
6fc6879b
JM
3224 wpa_cli_connected = 1;
3225 wpa_cli_last_id = new_id;
3226 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3227 }
3228 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3229 if (wpa_cli_connected) {
3230 wpa_cli_connected = 0;
3231 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3232 }
42f0101b
JM
3233 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3234 wpa_cli_exec(action_file, ctrl_ifname, pos);
3235 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3236 wpa_cli_exec(action_file, ctrl_ifname, pos);
72044390
JM
3237 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3238 wpa_cli_exec(action_file, ctrl_ifname, pos);
3239 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3240 wpa_cli_exec(action_file, ctrl_ifname, pos);
e670738a
DS
3241 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3242 wpa_cli_exec(action_file, ctrl_ifname, pos);
876103dc
AC
3243 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3244 wpa_cli_exec(action_file, ctrl_ifname, pos);
3245 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3246 wpa_cli_exec(action_file, ctrl_ifname, pos);
653c4893
NKG
3247 } else if (str_match(pos, AP_STA_CONNECTED)) {
3248 wpa_cli_exec(action_file, ctrl_ifname, pos);
3249 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3250 wpa_cli_exec(action_file, ctrl_ifname, pos);
ae8535b6
JM
3251 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3252 wpa_cli_exec(action_file, ctrl_ifname, pos);
95a3ea94
JM
3253 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3254 wpa_cli_exec(action_file, ctrl_ifname, pos);
7ef69479
JM
3255 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3256 wpa_cli_exec(action_file, ctrl_ifname, pos);
6fc6879b
JM
3257 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3258 printf("wpa_supplicant is terminating - stop monitoring\n");
3259 wpa_cli_quit = 1;
3260 }
3261}
3262
3263
3264#ifndef CONFIG_ANSI_C_EXTRA
3265static void wpa_cli_action_cb(char *msg, size_t len)
3266{
3267 wpa_cli_action_process(msg);
3268}
3269#endif /* CONFIG_ANSI_C_EXTRA */
3270
3271
3272static void wpa_cli_reconnect(void)
3273{
3274 wpa_cli_close_connection();
059d3a90
JM
3275 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3276 return;
3277
3278 if (interactive) {
3279 edit_clear_line();
3280 printf("\rConnection to wpa_supplicant re-established\n");
3281 edit_redraw();
3282 }
6fc6879b
JM
3283}
3284
3285
a624f20b
JM
3286static void cli_event(const char *str)
3287{
3288 const char *start, *s;
3289
3290 start = os_strchr(str, '>');
3291 if (start == NULL)
3292 return;
3293
3294 start++;
3295
3296 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3297 s = os_strchr(start, ' ');
3298 if (s == NULL)
3299 return;
3300 s = os_strchr(s + 1, ' ');
3301 if (s == NULL)
3302 return;
3303 cli_txt_list_add(&bsses, s + 1);
3304 return;
3305 }
3306
3307 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3308 s = os_strchr(start, ' ');
3309 if (s == NULL)
3310 return;
3311 s = os_strchr(s + 1, ' ');
3312 if (s == NULL)
3313 return;
3314 cli_txt_list_del_addr(&bsses, s + 1);
3315 return;
3316 }
3317
3318#ifdef CONFIG_P2P
3319 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3320 s = os_strstr(start, " p2p_dev_addr=");
3321 if (s == NULL)
3322 return;
3323 cli_txt_list_add_addr(&p2p_peers, s + 14);
3324 return;
3325 }
3326
3327 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3328 s = os_strstr(start, " p2p_dev_addr=");
3329 if (s == NULL)
3330 return;
3331 cli_txt_list_del_addr(&p2p_peers, s + 14);
3332 return;
3333 }
76788542
JM
3334
3335 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3336 s = os_strchr(start, ' ');
3337 if (s == NULL)
3338 return;
3339 cli_txt_list_add_word(&p2p_groups, s + 1);
3340 return;
3341 }
3342
3343 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3344 s = os_strchr(start, ' ');
3345 if (s == NULL)
3346 return;
3347 cli_txt_list_del_word(&p2p_groups, s + 1);
3348 return;
3349 }
a624f20b
JM
3350#endif /* CONFIG_P2P */
3351}
3352
3353
059d3a90
JM
3354static int check_terminating(const char *msg)
3355{
3356 const char *pos = msg;
3357
3358 if (*pos == '<') {
3359 /* skip priority */
3360 pos = os_strchr(pos, '>');
3361 if (pos)
3362 pos++;
3363 else
3364 pos = msg;
3365 }
3366
3367 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3368 edit_clear_line();
3369 printf("\rConnection to wpa_supplicant lost - trying to "
3370 "reconnect\n");
3371 edit_redraw();
3372 wpa_cli_attached = 0;
3373 wpa_cli_close_connection();
3374 return 1;
3375 }
3376
3377 return 0;
3378}
3379
3380
cd101567 3381static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
6fc6879b 3382{
6fc6879b
JM
3383 if (ctrl_conn == NULL) {
3384 wpa_cli_reconnect();
3385 return;
3386 }
3387 while (wpa_ctrl_pending(ctrl) > 0) {
3388 char buf[256];
3389 size_t len = sizeof(buf) - 1;
3390 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3391 buf[len] = '\0';
3392 if (action_monitor)
3393 wpa_cli_action_process(buf);
3394 else {
a624f20b 3395 cli_event(buf);
f3f0f648 3396 if (wpa_cli_show_event(buf)) {
82a855bd 3397 edit_clear_line();
cd101567 3398 printf("\r%s\n", buf);
bdc45634 3399 edit_redraw();
f3f0f648 3400 }
059d3a90
JM
3401
3402 if (interactive && check_terminating(buf) > 0)
3403 return;
6fc6879b
JM
3404 }
3405 } else {
3406 printf("Could not read pending message.\n");
3407 break;
3408 }
3409 }
3410
3411 if (wpa_ctrl_pending(ctrl) < 0) {
3412 printf("Connection to wpa_supplicant lost - trying to "
3413 "reconnect\n");
3414 wpa_cli_reconnect();
3415 }
3416}
3417
6f1c6549
JM
3418#define max_args 10
3419
3420static int tokenize_cmd(char *cmd, char *argv[])
3421{
3422 char *pos;
3423 int argc = 0;
3424
3425 pos = cmd;
3426 for (;;) {
3427 while (*pos == ' ')
3428 pos++;
3429 if (*pos == '\0')
3430 break;
3431 argv[argc] = pos;
3432 argc++;
3433 if (argc == max_args)
3434 break;
3435 if (*pos == '"') {
3436 char *pos2 = os_strrchr(pos, '"');
3437 if (pos2)
3438 pos = pos2 + 1;
3439 }
3440 while (*pos != '\0' && *pos != ' ')
3441 pos++;
3442 if (*pos == ' ')
3443 *pos++ = '\0';
3444 }
3445
3446 return argc;
3447}
3448
3449
cd101567
JM
3450static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3451{
3452 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3453 printf("Connection to wpa_supplicant lost - trying to "
3454 "reconnect\n");
3455 wpa_cli_close_connection();
3456 }
3457 if (!ctrl_conn)
3458 wpa_cli_reconnect();
3459 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3460}
3461
3462
cd101567
JM
3463static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3464{
3465 wpa_cli_recv_pending(mon_conn, 0);
3466}
3467
3468
82a855bd 3469static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
aee680e8
JM
3470{
3471 char *argv[max_args];
3472 int argc;
82a855bd 3473 argc = tokenize_cmd(cmd, argv);
aee680e8
JM
3474 if (argc)
3475 wpa_request(ctrl_conn, argc, argv);
aee680e8
JM
3476}
3477
3478
82a855bd 3479static void wpa_cli_edit_eof_cb(void *ctx)
6f1c6549 3480{
82a855bd 3481 eloop_terminate();
cd101567
JM
3482}
3483
3484
4be9f275
JM
3485static int warning_displayed = 0;
3486static char *hfile = NULL;
3487static int edit_started = 0;
aee680e8 3488
4be9f275
JM
3489static void start_edit(void)
3490{
3491 char *home;
db3a0322
JM
3492 char *ps = NULL;
3493
3494#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3495 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3496#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
cd101567 3497
8953e968
JM
3498 home = getenv("HOME");
3499 if (home) {
3500 const char *fname = ".wpa_cli_history";
3501 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3502 hfile = os_malloc(hfile_len);
3503 if (hfile)
3504 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3505 }
3506
4be9f275 3507 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
db3a0322 3508 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4be9f275
JM
3509 eloop_terminate();
3510 return;
3511 }
3512
3513 edit_started = 1;
cd101567 3514 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4be9f275
JM
3515}
3516
3517
9be37143
JM
3518static void update_bssid_list(struct wpa_ctrl *ctrl)
3519{
3520 char buf[4096];
3521 size_t len = sizeof(buf);
3522 int ret;
3523 char *cmd = "BSS RANGE=ALL MASK=0x2";
3524 char *pos, *end;
3525
3526 if (ctrl == NULL)
3527 return;
3528 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3529 if (ret < 0)
3530 return;
3531 buf[len] = '\0';
3532
3533 pos = buf;
3534 while (pos) {
3535 pos = os_strstr(pos, "bssid=");
3536 if (pos == NULL)
3537 break;
3538 pos += 6;
3539 end = os_strchr(pos, '\n');
3540 if (end == NULL)
3541 break;
3542 *end = '\0';
3543 cli_txt_list_add(&bsses, pos);
3544 pos = end + 1;
3545 }
3546}
3547
3548
37620493
JM
3549static void update_ifnames(struct wpa_ctrl *ctrl)
3550{
3551 char buf[4096];
3552 size_t len = sizeof(buf);
3553 int ret;
3554 char *cmd = "INTERFACES";
3555 char *pos, *end;
3556 char txt[200];
3557
3558 cli_txt_list_flush(&ifnames);
3559
3560 if (ctrl == NULL)
3561 return;
3562 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3563 if (ret < 0)
3564 return;
3565 buf[len] = '\0';
3566
3567 pos = buf;
3568 while (pos) {
3569 end = os_strchr(pos, '\n');
3570 if (end == NULL)
3571 break;
3572 *end = '\0';
3573 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3574 if (ret > 0 && ret < (int) sizeof(txt))
3575 cli_txt_list_add(&ifnames, txt);
3576 pos = end + 1;
3577 }
3578}
3579
3580
4be9f275
JM
3581static void try_connection(void *eloop_ctx, void *timeout_ctx)
3582{
6fd5ceaf
JM
3583 if (ctrl_conn)
3584 goto done;
3585
8e897ae3
JM
3586 if (ctrl_ifname == NULL)
3587 ctrl_ifname = wpa_cli_get_default_ifname();
3588
4be9f275
JM
3589 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3590 if (!warning_displayed) {
3591 printf("Could not connect to wpa_supplicant: "
3592 "%s - re-trying\n", ctrl_ifname);
3593 warning_displayed = 1;
3594 }
3595 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3596 return;
3597 }
3598
9be37143
JM
3599 update_bssid_list(ctrl_conn);
3600
4be9f275
JM
3601 if (warning_displayed)
3602 printf("Connection established.\n");
3603
6fd5ceaf 3604done:
4be9f275
JM
3605 start_edit();
3606}
3607
cd101567 3608
4be9f275
JM
3609static void wpa_cli_interactive(void)
3610{
3611 printf("\nInteractive mode\n\n");
3612
3613 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
cd101567 3614 eloop_run();
4be9f275 3615 eloop_cancel_timeout(try_connection, NULL, NULL);
cd101567 3616
a624f20b 3617 cli_txt_list_flush(&p2p_peers);
76788542 3618 cli_txt_list_flush(&p2p_groups);
a624f20b 3619 cli_txt_list_flush(&bsses);
37620493 3620 cli_txt_list_flush(&ifnames);
4be9f275
JM
3621 if (edit_started)
3622 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
8953e968 3623 os_free(hfile);
cd101567
JM
3624 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3625 wpa_cli_close_connection();
6f1c6549
JM
3626}
3627
6fc6879b
JM
3628
3629static void wpa_cli_action(struct wpa_ctrl *ctrl)
3630{
3631#ifdef CONFIG_ANSI_C_EXTRA
3632 /* TODO: ANSI C version(?) */
3633 printf("Action processing not supported in ANSI C build.\n");
3634#else /* CONFIG_ANSI_C_EXTRA */
3635 fd_set rfds;
3636 int fd, res;
3637 struct timeval tv;
3638 char buf[256]; /* note: large enough to fit in unsolicited messages */
3639 size_t len;
3640
3641 fd = wpa_ctrl_get_fd(ctrl);
3642
3643 while (!wpa_cli_quit) {
3644 FD_ZERO(&rfds);
3645 FD_SET(fd, &rfds);
1cc84c1c 3646 tv.tv_sec = ping_interval;
6fc6879b
JM
3647 tv.tv_usec = 0;
3648 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3649 if (res < 0 && errno != EINTR) {
3650 perror("select");
3651 break;
3652 }
3653
3654 if (FD_ISSET(fd, &rfds))
cd101567 3655 wpa_cli_recv_pending(ctrl, 1);
6fc6879b
JM
3656 else {
3657 /* verify that connection is still working */
3658 len = sizeof(buf) - 1;
3659 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3660 wpa_cli_action_cb) < 0 ||
3661 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3662 printf("wpa_supplicant did not reply to PING "
3663 "command - exiting\n");
3664 break;
3665 }
3666 }
3667 }
3668#endif /* CONFIG_ANSI_C_EXTRA */
3669}
3670
3671
3672static void wpa_cli_cleanup(void)
3673{
3674 wpa_cli_close_connection();
3675 if (pid_file)
3676 os_daemonize_terminate(pid_file);
3677
3678 os_program_deinit();
3679}
3680
4be9f275
JM
3681
3682static void wpa_cli_terminate(int sig, void *ctx)
6fc6879b 3683{
4be9f275 3684 eloop_terminate();
6fc6879b
JM
3685}
3686
3687
6fc6879b
JM
3688static char * wpa_cli_get_default_ifname(void)
3689{
3690 char *ifname = NULL;
3691
3692#ifdef CONFIG_CTRL_IFACE_UNIX
3693 struct dirent *dent;
3694 DIR *dir = opendir(ctrl_iface_dir);
b1001e4c
DS
3695 if (!dir) {
3696#ifdef ANDROID
3697 char ifprop[PROPERTY_VALUE_MAX];
3698 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3699 ifname = os_strdup(ifprop);
3700 printf("Using interface '%s'\n", ifname);
3701 return ifname;
3702 }
3703#endif /* ANDROID */
6fc6879b 3704 return NULL;
b1001e4c 3705 }
6fc6879b
JM
3706 while ((dent = readdir(dir))) {
3707#ifdef _DIRENT_HAVE_D_TYPE
3708 /*
3709 * Skip the file if it is not a socket. Also accept
3710 * DT_UNKNOWN (0) in case the C library or underlying
3711 * file system does not support d_type.
3712 */
3713 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3714 continue;
3715#endif /* _DIRENT_HAVE_D_TYPE */
3716 if (os_strcmp(dent->d_name, ".") == 0 ||
3717 os_strcmp(dent->d_name, "..") == 0)
3718 continue;
3719 printf("Selected interface '%s'\n", dent->d_name);
3720 ifname = os_strdup(dent->d_name);
3721 break;
3722 }
3723 closedir(dir);
3724#endif /* CONFIG_CTRL_IFACE_UNIX */
3725
3726#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
89c7ac57 3727 char buf[4096], *pos;
6fc6879b
JM
3728 size_t len;
3729 struct wpa_ctrl *ctrl;
3730 int ret;
3731
3732 ctrl = wpa_ctrl_open(NULL);
3733 if (ctrl == NULL)
3734 return NULL;
3735
3736 len = sizeof(buf) - 1;
3737 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3738 if (ret >= 0) {
3739 buf[len] = '\0';
3740 pos = os_strchr(buf, '\n');
3741 if (pos)
3742 *pos = '\0';
3743 ifname = os_strdup(buf);
3744 }
3745 wpa_ctrl_close(ctrl);
3746#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3747
3748 return ifname;
3749}
3750
3751
3752int main(int argc, char *argv[])
3753{
6fc6879b
JM
3754 int c;
3755 int daemonize = 0;
3756 int ret = 0;
3757 const char *global = NULL;
3758
3759 if (os_program_init())
3760 return -1;
3761
3762 for (;;) {
1cc84c1c 3763 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
3764 if (c < 0)
3765 break;
3766 switch (c) {
3767 case 'a':
3768 action_file = optarg;
3769 break;
3770 case 'B':
3771 daemonize = 1;
3772 break;
3773 case 'g':
3774 global = optarg;
3775 break;
1cc84c1c
JM
3776 case 'G':
3777 ping_interval = atoi(optarg);
3778 break;
6fc6879b
JM
3779 case 'h':
3780 usage();
3781 return 0;
3782 case 'v':
3783 printf("%s\n", wpa_cli_version);
3784 return 0;
3785 case 'i':
3786 os_free(ctrl_ifname);
3787 ctrl_ifname = os_strdup(optarg);
3788 break;
3789 case 'p':
3790 ctrl_iface_dir = optarg;
3791 break;
3792 case 'P':
3793 pid_file = optarg;
3794 break;
3795 default:
3796 usage();
3797 return -1;
3798 }
3799 }
3800
3801 interactive = (argc == optind) && (action_file == NULL);
3802
3803 if (interactive)
3804 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3805
cd101567
JM
3806 if (eloop_init())
3807 return -1;
3808
6fc6879b
JM
3809 if (global) {
3810#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3811 ctrl_conn = wpa_ctrl_open(NULL);
3812#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3813 ctrl_conn = wpa_ctrl_open(global);
3814#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3815 if (ctrl_conn == NULL) {
5a49459e
BG
3816 fprintf(stderr, "Failed to connect to wpa_supplicant "
3817 "global interface: %s error: %s\n",
3818 global, strerror(errno));
6fc6879b
JM
3819 return -1;
3820 }
214e428b
JM
3821
3822 if (interactive) {
37620493 3823 update_ifnames(ctrl_conn);
214e428b
JM
3824 mon_conn = wpa_ctrl_open(global);
3825 if (mon_conn) {
3826 if (wpa_ctrl_attach(mon_conn) == 0) {
3827 wpa_cli_attached = 1;
3828 eloop_register_read_sock(
3829 wpa_ctrl_get_fd(mon_conn),
3830 wpa_cli_mon_receive,
3831 NULL, NULL);
3832 } else {
3833 printf("Failed to open monitor "
3834 "connection through global "
3835 "control interface\n");
3836 }
3837 }
3838 }
6fc6879b
JM
3839 }
3840
4be9f275 3841 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
6fc6879b 3842
4a3ade4e
JM
3843 if (ctrl_ifname == NULL)
3844 ctrl_ifname = wpa_cli_get_default_ifname();
3845
3846 if (interactive) {
4be9f275 3847 wpa_cli_interactive();
4a3ade4e
JM
3848 } else {
3849 if (!global &&
3850 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
5a49459e
BG
3851 fprintf(stderr, "Failed to connect to non-global "
3852 "ctrl_ifname: %s error: %s\n",
3853 ctrl_ifname, strerror(errno));
4a3ade4e
JM
3854 return -1;
3855 }
3856
3857 if (action_file) {
3858 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3859 wpa_cli_attached = 1;
3860 } else {
3861 printf("Warning: Failed to attach to "
3862 "wpa_supplicant.\n");
6fc6879b 3863 return -1;
4a3ade4e 3864 }
6fc6879b 3865 }
6fc6879b 3866
4be9f275
JM
3867 if (daemonize && os_daemonize(pid_file))
3868 return -1;
6fc6879b 3869
4be9f275
JM
3870 if (action_file)
3871 wpa_cli_action(ctrl_conn);
3872 else
3873 ret = wpa_request(ctrl_conn, argc - optind,
3874 &argv[optind]);
3875 }
6fc6879b
JM
3876
3877 os_free(ctrl_ifname);
cd101567 3878 eloop_destroy();
6fc6879b
JM
3879 wpa_cli_cleanup();
3880
3881 return ret;
3882}
3883
3884#else /* CONFIG_CTRL_IFACE */
3885int main(int argc, char *argv[])
3886{
3887 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3888 return -1;
3889}
3890#endif /* CONFIG_CTRL_IFACE */