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