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