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