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