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