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