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