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