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