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