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