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