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