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