]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Add ctrl iface command for autoscan
[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
40fd868c
ER
2814enum wpa_cli_cmd_flags {
2815 cli_cmd_flag_none = 0x00,
2816 cli_cmd_flag_sensitive = 0x01
2817};
2818
6fc6879b
JM
2819struct wpa_cli_cmd {
2820 const char *cmd;
2821 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 2822 enum wpa_cli_cmd_flags flags;
dfa141b1 2823 const char *usage;
6fc6879b
JM
2824};
2825
2826static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 2827 { "status", wpa_cli_cmd_status,
dfa141b1
ER
2828 cli_cmd_flag_none,
2829 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 2830 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
2831 cli_cmd_flag_none,
2832 "= pings wpa_supplicant" },
ac6912b5
BG
2833 { "relog", wpa_cli_cmd_relog,
2834 cli_cmd_flag_none,
2835 "= re-open log-file (allow rolling logs)" },
77895cd9
JM
2836 { "note", wpa_cli_cmd_note,
2837 cli_cmd_flag_none,
2838 "<text> = add a note to wpa_supplicant debug log" },
40fd868c 2839 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
2840 cli_cmd_flag_none,
2841 "= get MIB variables (dot1x, dot11)" },
40fd868c 2842 { "help", wpa_cli_cmd_help,
dfa141b1
ER
2843 cli_cmd_flag_none,
2844 "= show this usage help" },
40fd868c 2845 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
2846 cli_cmd_flag_none,
2847 "[ifname] = show interfaces/select interface" },
40fd868c 2848 { "level", wpa_cli_cmd_level,
dfa141b1
ER
2849 cli_cmd_flag_none,
2850 "<debug level> = change debug level" },
40fd868c 2851 { "license", wpa_cli_cmd_license,
dfa141b1
ER
2852 cli_cmd_flag_none,
2853 "= show full wpa_cli license" },
40fd868c 2854 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
2855 cli_cmd_flag_none,
2856 "= exit wpa_cli" },
40fd868c 2857 { "set", wpa_cli_cmd_set,
dfa141b1
ER
2858 cli_cmd_flag_none,
2859 "= set variables (shows list of variables when run without "
2860 "arguments)" },
acec8d32
JM
2861 { "get", wpa_cli_cmd_get,
2862 cli_cmd_flag_none,
2863 "<name> = get information" },
40fd868c 2864 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
2865 cli_cmd_flag_none,
2866 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 2867 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
2868 cli_cmd_flag_none,
2869 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 2870 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
2871 cli_cmd_flag_none,
2872 "= show PMKSA cache" },
40fd868c 2873 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
2874 cli_cmd_flag_none,
2875 "= force reassociation" },
40fd868c 2876 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
2877 cli_cmd_flag_none,
2878 "<BSSID> = force preauthentication" },
40fd868c 2879 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
2880 cli_cmd_flag_none,
2881 "<network id> <identity> = configure identity for an SSID" },
40fd868c 2882 { "password", wpa_cli_cmd_password,
dfa141b1
ER
2883 cli_cmd_flag_sensitive,
2884 "<network id> <password> = configure password for an SSID" },
40fd868c 2885 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
2886 cli_cmd_flag_sensitive,
2887 "<network id> <password> = change password for an SSID" },
40fd868c 2888 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
2889 cli_cmd_flag_sensitive,
2890 "<network id> <pin> = configure pin for an SSID" },
40fd868c 2891 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
2892 cli_cmd_flag_sensitive,
2893 "<network id> <password> = configure one-time-password for an SSID"
2894 },
40fd868c 2895 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
2896 cli_cmd_flag_sensitive,
2897 "<network id> <passphrase> = configure private key passphrase\n"
2898 " for an SSID" },
40fd868c 2899 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
2900 cli_cmd_flag_none,
2901 "<network id> <BSSID> = set preferred BSSID for an SSID" },
9aa10e2b
DS
2902 { "blacklist", wpa_cli_cmd_blacklist,
2903 cli_cmd_flag_none,
2904 "<BSSID> = add a BSSID to the blacklist\n"
2905 "blacklist clear = clear the blacklist\n"
2906 "blacklist = display the blacklist" },
0597a5b5
DS
2907 { "log_level", wpa_cli_cmd_log_level,
2908 cli_cmd_flag_none,
2909 "<level> [<timestamp>] = update the log level/timestamp\n"
2910 "log_level = display the current log level and log options" },
40fd868c 2911 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
2912 cli_cmd_flag_none,
2913 "= list configured networks" },
40fd868c 2914 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
2915 cli_cmd_flag_none,
2916 "<network id> = select a network (disable others)" },
40fd868c 2917 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
2918 cli_cmd_flag_none,
2919 "<network id> = enable a network" },
40fd868c 2920 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
2921 cli_cmd_flag_none,
2922 "<network id> = disable a network" },
40fd868c 2923 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
2924 cli_cmd_flag_none,
2925 "= add a network" },
40fd868c 2926 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
2927 cli_cmd_flag_none,
2928 "<network id> = remove a network" },
40fd868c 2929 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
2930 cli_cmd_flag_sensitive,
2931 "<network id> <variable> <value> = set network variables (shows\n"
2932 " list of variables when run without arguments)" },
40fd868c 2933 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
2934 cli_cmd_flag_none,
2935 "<network id> <variable> = get network variables" },
d94c9ee6
JM
2936 { "list_creds", wpa_cli_cmd_list_creds,
2937 cli_cmd_flag_none,
2938 "= list configured credentials" },
2939 { "add_cred", wpa_cli_cmd_add_cred,
2940 cli_cmd_flag_none,
2941 "= add a credential" },
2942 { "remove_cred", wpa_cli_cmd_remove_cred,
2943 cli_cmd_flag_none,
2944 "<cred id> = remove a credential" },
2945 { "set_cred", wpa_cli_cmd_set_cred,
2946 cli_cmd_flag_sensitive,
2947 "<cred id> <variable> <value> = set credential variables" },
40fd868c 2948 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
2949 cli_cmd_flag_none,
2950 "= save the current configuration" },
40fd868c 2951 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
2952 cli_cmd_flag_none,
2953 "= disconnect and wait for reassociate/reconnect command before\n"
2954 " connecting" },
40fd868c 2955 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
2956 cli_cmd_flag_none,
2957 "= like reassociate, but only takes effect if already disconnected"
2958 },
40fd868c 2959 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
2960 cli_cmd_flag_none,
2961 "= request new BSS scan" },
40fd868c 2962 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
2963 cli_cmd_flag_none,
2964 "= get latest scan results" },
40fd868c 2965 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
2966 cli_cmd_flag_none,
2967 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 2968 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
2969 cli_cmd_flag_none,
2970 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 2971 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
2972 cli_cmd_flag_none,
2973 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 2974 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
2975 cli_cmd_flag_none,
2976 "= terminate wpa_supplicant" },
40fd868c 2977 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
2978 cli_cmd_flag_none,
2979 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2980 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2981 " are optional" },
40fd868c 2982 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
2983 cli_cmd_flag_none,
2984 "<ifname> = removes the interface" },
40fd868c 2985 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
2986 cli_cmd_flag_none,
2987 "= list available interfaces" },
40fd868c 2988 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
2989 cli_cmd_flag_none,
2990 "<value> = set ap_scan parameter" },
67b9bd08
DS
2991 { "scan_interval", wpa_cli_cmd_scan_interval,
2992 cli_cmd_flag_none,
2993 "<value> = set scan_interval parameter (in seconds)" },
78633c37
SL
2994 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2995 cli_cmd_flag_none,
2996 "<value> = set BSS expiration age parameter" },
2997 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2998 cli_cmd_flag_none,
2999 "<value> = set BSS expiration scan count parameter" },
40fd868c 3000 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
3001 cli_cmd_flag_none,
3002 "<addr> = request STK negotiation with <addr>" },
40fd868c 3003 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
3004 cli_cmd_flag_none,
3005 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 3006 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
3007 cli_cmd_flag_none,
3008 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 3009 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
3010 cli_cmd_flag_sensitive,
3011 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3012 "hardcoded)" },
3981cb3c
JM
3013 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
3014 cli_cmd_flag_sensitive,
3015 "<PIN> = verify PIN checksum" },
2f9929ff
AC
3016 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
3017 "Cancels the pending WPS operation" },
116f7bb0 3018#ifdef CONFIG_WPS_OOB
46bdb83a
MH
3019 { "wps_oob", wpa_cli_cmd_wps_oob,
3020 cli_cmd_flag_sensitive,
e1ee6b60 3021 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 3022#endif /* CONFIG_WPS_OOB */
40fd868c 3023 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
3024 cli_cmd_flag_sensitive,
3025 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
70d84f11
JM
3026 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
3027 cli_cmd_flag_sensitive,
3028 "[params..] = enable/disable AP PIN" },
e9bcfebf
JM
3029 { "wps_er_start", wpa_cli_cmd_wps_er_start,
3030 cli_cmd_flag_none,
08486685 3031 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
e9bcfebf
JM
3032 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
3033 cli_cmd_flag_none,
3034 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
3035 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
3036 cli_cmd_flag_sensitive,
3037 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
3038 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
3039 cli_cmd_flag_none,
3040 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
3041 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
3042 cli_cmd_flag_sensitive,
3043 "<UUID> <PIN> = learn AP configuration" },
ef10f473
JM
3044 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
3045 cli_cmd_flag_none,
3046 "<UUID> <network id> = set AP configuration for enrolling" },
7d6640a6
JM
3047 { "wps_er_config", wpa_cli_cmd_wps_er_config,
3048 cli_cmd_flag_sensitive,
3049 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
11ef8d35
JM
3050 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
3051 cli_cmd_flag_none,
3052 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
3053#ifdef CONFIG_AP
3054 { "sta", wpa_cli_cmd_sta,
3055 cli_cmd_flag_none,
3056 "<addr> = get information about an associated station (AP)" },
3057 { "all_sta", wpa_cli_cmd_all_sta,
3058 cli_cmd_flag_none,
3059 "= get information about all associated stations (AP)" },
e60b2951
JJ
3060 { "deauthenticate", wpa_cli_cmd_deauthenticate,
3061 cli_cmd_flag_none,
3062 "<addr> = deauthenticate a station" },
3063 { "disassociate", wpa_cli_cmd_disassociate,
3064 cli_cmd_flag_none,
3065 "<addr> = disassociate a station" },
e653b622 3066#endif /* CONFIG_AP */
207ef3fb
JM
3067 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
3068 "= notification of suspend/hibernate" },
3069 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
3070 "= notification of resume/thaw" },
32d5295f
JM
3071 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
3072 "= drop SA without deauth/disassoc (test command)" },
86d4f806
JM
3073 { "roam", wpa_cli_cmd_roam,
3074 cli_cmd_flag_none,
3075 "<addr> = roam to the specified BSS" },
57faa1ce
JM
3076#ifdef CONFIG_P2P
3077 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
3078 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3079 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
3080 "= stop P2P Devices search" },
3081 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
3082 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
3083 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
3084 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3085 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
4d2ea6a6 3086 "<ifname> = remove P2P group interface (terminate group if GO)" },
57faa1ce
JM
3087 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
3088 "= add a new P2P group (local end as GO)" },
3089 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
3090 "<addr> <method> = request provisioning discovery" },
3091 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
3092 cli_cmd_flag_none,
3093 "= get the passphrase for a group (GO only)" },
3094 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3095 cli_cmd_flag_none,
3096 "<addr> <TLVs> = schedule service discovery request" },
3097 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3098 cli_cmd_flag_none,
3099 "<id> = cancel pending service discovery request" },
3100 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
3101 cli_cmd_flag_none,
3102 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3103 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
3104 cli_cmd_flag_none,
3105 "= indicate change in local services" },
3106 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
3107 cli_cmd_flag_none,
3108 "<external> = set external processing of service discovery" },
3109 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
3110 cli_cmd_flag_none,
3111 "= remove all stored service entries" },
3112 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
3113 cli_cmd_flag_none,
3114 "<bonjour|upnp> <query|version> <response|service> = add a local "
3115 "service" },
3116 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
3117 cli_cmd_flag_none,
3118 "<bonjour|upnp> <query|version> [|service] = remove a local "
3119 "service" },
3120 { "p2p_reject", wpa_cli_cmd_p2p_reject,
3121 cli_cmd_flag_none,
3122 "<addr> = reject connection attempts from a specific peer" },
3123 { "p2p_invite", wpa_cli_cmd_p2p_invite,
3124 cli_cmd_flag_none,
3125 "<cmd> [peer=addr] = invite peer" },
3126 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
3127 "[discovered] = list known (optionally, only fully discovered) P2P "
3128 "peers" },
3129 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
3130 "<address> = show information about known P2P peer" },
3131 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
3132 "<field> <value> = set a P2P parameter" },
3133 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
3134 "= flush P2P state" },
59eba7a2
JM
3135 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
3136 "= cancel P2P group formation" },
9d562b79
SS
3137 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
3138 "<address> = unauthorize a peer" },
57faa1ce
JM
3139 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
3140 "[<duration> <interval>] [<duration> <interval>] = request GO "
3141 "presence" },
3142 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
3143 "[<period> <interval>] = set extended listen timing" },
3144#endif /* CONFIG_P2P */
afc064fe
JM
3145
3146#ifdef CONFIG_INTERWORKING
3147 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
3148 "= fetch ANQP information for all APs" },
3149 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
3150 "= stop fetch_anqp operation" },
b02fe7ff
JM
3151 { "interworking_select", wpa_cli_cmd_interworking_select,
3152 cli_cmd_flag_none,
3153 "[auto] = perform Interworking network selection" },
3154 { "interworking_connect", wpa_cli_cmd_interworking_connect,
3155 cli_cmd_flag_none,
3156 "<BSSID> = connect using Interworking credentials" },
afc064fe
JM
3157 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
3158 "<addr> <info id>[,<info id>]... = request ANQP information" },
3159#endif /* CONFIG_INTERWORKING */
a8918e86
JK
3160#ifdef CONFIG_HS20
3161 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, cli_cmd_flag_none,
3162 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3163 },
3164 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3165 cli_cmd_flag_none,
3166 "<addr> <home realm> = get HS20 nai home realm list" },
3167#endif /* CONFIG_HS20 */
0d0a8ca1
AC
3168 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
3169 "<0/1> = disable/enable automatic reconnection" },
281ff0aa
GP
3170 { "tdls_discover", wpa_cli_cmd_tdls_discover,
3171 cli_cmd_flag_none,
3172 "<addr> = request TDLS discovery with <addr>" },
3173 { "tdls_setup", wpa_cli_cmd_tdls_setup,
3174 cli_cmd_flag_none,
3175 "<addr> = request TDLS setup with <addr>" },
3176 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
3177 cli_cmd_flag_none,
3178 "<addr> = tear down TDLS with <addr>" },
60b24b0d
DS
3179 { "signal_poll", wpa_cli_cmd_signal_poll,
3180 cli_cmd_flag_none,
3181 "= get signal parameters" },
9482426e
JM
3182 { "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none,
3183 "= trigger IEEE 802.1X/EAPOL reauthentication" },
dfa141b1 3184 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
3185};
3186
3187
dfa141b1
ER
3188/*
3189 * Prints command usage, lines are padded with the specified string.
3190 */
3191static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3192{
3193 char c;
3194 size_t n;
3195
3196 printf("%s%s ", pad, cmd->cmd);
3197 for (n = 0; (c = cmd->usage[n]); n++) {
3198 printf("%c", c);
3199 if (c == '\n')
3200 printf("%s", pad);
3201 }
3202 printf("\n");
3203}
3204
3205
3206static void print_help(void)
3207{
3208 int n;
3209 printf("commands:\n");
3210 for (n = 0; wpa_cli_commands[n].cmd; n++)
3211 print_cmd_help(&wpa_cli_commands[n], " ");
3212}
3213
3214
e8ecb5fb 3215static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
40fd868c
ER
3216{
3217 const char *c, *delim;
3218 int n;
3219 size_t len;
3220
3221 delim = os_strchr(cmd, ' ');
3222 if (delim)
3223 len = delim - cmd;
3224 else
3225 len = os_strlen(cmd);
3226
3227 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3228 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3229 return (wpa_cli_commands[n].flags &
3230 cli_cmd_flag_sensitive);
3231 }
3232 return 0;
3233}
e8ecb5fb
JM
3234
3235
3236static char ** wpa_list_cmd_list(void)
3237{
3238 char **res;
3239 int i, count;
3240
3241 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3242 res = os_zalloc(count * sizeof(char *));
3243 if (res == NULL)
3244 return NULL;
3245
3246 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3247 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3248 if (res[i] == NULL)
3249 break;
3250 }
3251
3252 return res;
3253}
3254
3255
3256static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3257 int pos)
3258{
3259 int i;
3260
a624f20b
JM
3261 if (os_strcasecmp(cmd, "bss") == 0)
3262 return wpa_cli_complete_bss(str, pos);
3263#ifdef CONFIG_P2P
3264 if (os_strcasecmp(cmd, "p2p_connect") == 0)
3265 return wpa_cli_complete_p2p_connect(str, pos);
3266 if (os_strcasecmp(cmd, "p2p_peer") == 0)
3267 return wpa_cli_complete_p2p_peer(str, pos);
76788542
JM
3268 if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3269 return wpa_cli_complete_p2p_group_remove(str, pos);
a624f20b
JM
3270#endif /* CONFIG_P2P */
3271
e8ecb5fb
JM
3272 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3273 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3274 edit_clear_line();
3275 printf("\r%s\n", wpa_cli_commands[i].usage);
3276 edit_redraw();
3277 break;
3278 }
3279 }
3280
3281 return NULL;
3282}
3283
3284
3285static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3286{
3287 char **res;
3288 const char *end;
3289 char *cmd;
3290
3291 end = os_strchr(str, ' ');
3292 if (end == NULL || str + pos < end)
3293 return wpa_list_cmd_list();
3294
3295 cmd = os_malloc(pos + 1);
3296 if (cmd == NULL)
3297 return NULL;
3298 os_memcpy(cmd, str, pos);
3299 cmd[end - str] = '\0';
3300 res = wpa_cli_cmd_completion(cmd, str, pos);
3301 os_free(cmd);
3302 return res;
3303}
40fd868c
ER
3304
3305
6fc6879b
JM
3306static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3307{
3308 struct wpa_cli_cmd *cmd, *match = NULL;
3309 int count;
3310 int ret = 0;
3311
3312 count = 0;
3313 cmd = wpa_cli_commands;
3314 while (cmd->cmd) {
3315 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3316 {
3317 match = cmd;
3318 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3319 /* we have an exact match */
3320 count = 1;
3321 break;
3322 }
3323 count++;
3324 }
3325 cmd++;
3326 }
3327
3328 if (count > 1) {
3329 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3330 cmd = wpa_cli_commands;
3331 while (cmd->cmd) {
3332 if (os_strncasecmp(cmd->cmd, argv[0],
3333 os_strlen(argv[0])) == 0) {
3334 printf(" %s", cmd->cmd);
3335 }
3336 cmd++;
3337 }
3338 printf("\n");
3339 ret = 1;
3340 } else if (count == 0) {
3341 printf("Unknown command '%s'\n", argv[0]);
3342 ret = 1;
3343 } else {
3344 ret = match->handler(ctrl, argc - 1, &argv[1]);
3345 }
3346
3347 return ret;
3348}
3349
3350
3351static int str_match(const char *a, const char *b)
3352{
3353 return os_strncmp(a, b, os_strlen(b)) == 0;
3354}
3355
3356
3357static int wpa_cli_exec(const char *program, const char *arg1,
3358 const char *arg2)
3359{
3360 char *cmd;
3361 size_t len;
3362 int res;
308a4ec8 3363 int ret = 0;
6fc6879b
JM
3364
3365 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3366 cmd = os_malloc(len);
3367 if (cmd == NULL)
3368 return -1;
3369 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3370 if (res < 0 || (size_t) res >= len) {
3371 os_free(cmd);
3372 return -1;
3373 }
3374 cmd[len - 1] = '\0';
3375#ifndef _WIN32_WCE
308a4ec8
JM
3376 if (system(cmd) < 0)
3377 ret = -1;
6fc6879b
JM
3378#endif /* _WIN32_WCE */
3379 os_free(cmd);
3380
308a4ec8 3381 return ret;
6fc6879b
JM
3382}
3383
3384
3385static void wpa_cli_action_process(const char *msg)
3386{
3387 const char *pos;
3388 char *copy = NULL, *id, *pos2;
3389
3390 pos = msg;
3391 if (*pos == '<') {
3392 /* skip priority */
3393 pos = os_strchr(pos, '>');
3394 if (pos)
3395 pos++;
3396 else
3397 pos = msg;
3398 }
3399
3400 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3401 int new_id = -1;
3402 os_unsetenv("WPA_ID");
3403 os_unsetenv("WPA_ID_STR");
3404 os_unsetenv("WPA_CTRL_DIR");
3405
3406 pos = os_strstr(pos, "[id=");
3407 if (pos)
3408 copy = os_strdup(pos + 4);
3409
3410 if (copy) {
3411 pos2 = id = copy;
3412 while (*pos2 && *pos2 != ' ')
3413 pos2++;
3414 *pos2++ = '\0';
3415 new_id = atoi(id);
3416 os_setenv("WPA_ID", id, 1);
3417 while (*pos2 && *pos2 != '=')
3418 pos2++;
3419 if (*pos2 == '=')
3420 pos2++;
3421 id = pos2;
3422 while (*pos2 && *pos2 != ']')
3423 pos2++;
3424 *pos2 = '\0';
3425 os_setenv("WPA_ID_STR", id, 1);
3426 os_free(copy);
3427 }
3428
3429 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3430
3431 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3432 wpa_cli_connected = 1;
3433 wpa_cli_last_id = new_id;
3434 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3435 }
3436 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3437 if (wpa_cli_connected) {
3438 wpa_cli_connected = 0;
3439 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3440 }
42f0101b
JM
3441 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3442 wpa_cli_exec(action_file, ctrl_ifname, pos);
3443 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3444 wpa_cli_exec(action_file, ctrl_ifname, pos);
72044390
JM
3445 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3446 wpa_cli_exec(action_file, ctrl_ifname, pos);
3447 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3448 wpa_cli_exec(action_file, ctrl_ifname, pos);
e670738a
DS
3449 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3450 wpa_cli_exec(action_file, ctrl_ifname, pos);
876103dc
AC
3451 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3452 wpa_cli_exec(action_file, ctrl_ifname, pos);
3453 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3454 wpa_cli_exec(action_file, ctrl_ifname, pos);
653c4893
NKG
3455 } else if (str_match(pos, AP_STA_CONNECTED)) {
3456 wpa_cli_exec(action_file, ctrl_ifname, pos);
3457 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3458 wpa_cli_exec(action_file, ctrl_ifname, pos);
6fc6879b
JM
3459 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3460 printf("wpa_supplicant is terminating - stop monitoring\n");
3461 wpa_cli_quit = 1;
3462 }
3463}
3464
3465
3466#ifndef CONFIG_ANSI_C_EXTRA
3467static void wpa_cli_action_cb(char *msg, size_t len)
3468{
3469 wpa_cli_action_process(msg);
3470}
3471#endif /* CONFIG_ANSI_C_EXTRA */
3472
3473
3474static void wpa_cli_reconnect(void)
3475{
3476 wpa_cli_close_connection();
4a3ade4e 3477 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
3478}
3479
3480
a624f20b
JM
3481static void cli_event(const char *str)
3482{
3483 const char *start, *s;
3484
3485 start = os_strchr(str, '>');
3486 if (start == NULL)
3487 return;
3488
3489 start++;
3490
3491 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3492 s = os_strchr(start, ' ');
3493 if (s == NULL)
3494 return;
3495 s = os_strchr(s + 1, ' ');
3496 if (s == NULL)
3497 return;
3498 cli_txt_list_add(&bsses, s + 1);
3499 return;
3500 }
3501
3502 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3503 s = os_strchr(start, ' ');
3504 if (s == NULL)
3505 return;
3506 s = os_strchr(s + 1, ' ');
3507 if (s == NULL)
3508 return;
3509 cli_txt_list_del_addr(&bsses, s + 1);
3510 return;
3511 }
3512
3513#ifdef CONFIG_P2P
3514 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3515 s = os_strstr(start, " p2p_dev_addr=");
3516 if (s == NULL)
3517 return;
3518 cli_txt_list_add_addr(&p2p_peers, s + 14);
3519 return;
3520 }
3521
3522 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3523 s = os_strstr(start, " p2p_dev_addr=");
3524 if (s == NULL)
3525 return;
3526 cli_txt_list_del_addr(&p2p_peers, s + 14);
3527 return;
3528 }
76788542
JM
3529
3530 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3531 s = os_strchr(start, ' ');
3532 if (s == NULL)
3533 return;
3534 cli_txt_list_add_word(&p2p_groups, s + 1);
3535 return;
3536 }
3537
3538 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3539 s = os_strchr(start, ' ');
3540 if (s == NULL)
3541 return;
3542 cli_txt_list_del_word(&p2p_groups, s + 1);
3543 return;
3544 }
a624f20b
JM
3545#endif /* CONFIG_P2P */
3546}
3547
3548
cd101567 3549static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
6fc6879b 3550{
6fc6879b
JM
3551 if (ctrl_conn == NULL) {
3552 wpa_cli_reconnect();
3553 return;
3554 }
3555 while (wpa_ctrl_pending(ctrl) > 0) {
3556 char buf[256];
3557 size_t len = sizeof(buf) - 1;
3558 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3559 buf[len] = '\0';
3560 if (action_monitor)
3561 wpa_cli_action_process(buf);
3562 else {
a624f20b 3563 cli_event(buf);
f3f0f648 3564 if (wpa_cli_show_event(buf)) {
82a855bd 3565 edit_clear_line();
cd101567 3566 printf("\r%s\n", buf);
bdc45634 3567 edit_redraw();
f3f0f648 3568 }
6fc6879b
JM
3569 }
3570 } else {
3571 printf("Could not read pending message.\n");
3572 break;
3573 }
3574 }
3575
3576 if (wpa_ctrl_pending(ctrl) < 0) {
3577 printf("Connection to wpa_supplicant lost - trying to "
3578 "reconnect\n");
3579 wpa_cli_reconnect();
3580 }
3581}
3582
6f1c6549
JM
3583#define max_args 10
3584
3585static int tokenize_cmd(char *cmd, char *argv[])
3586{
3587 char *pos;
3588 int argc = 0;
3589
3590 pos = cmd;
3591 for (;;) {
3592 while (*pos == ' ')
3593 pos++;
3594 if (*pos == '\0')
3595 break;
3596 argv[argc] = pos;
3597 argc++;
3598 if (argc == max_args)
3599 break;
3600 if (*pos == '"') {
3601 char *pos2 = os_strrchr(pos, '"');
3602 if (pos2)
3603 pos = pos2 + 1;
3604 }
3605 while (*pos != '\0' && *pos != ' ')
3606 pos++;
3607 if (*pos == ' ')
3608 *pos++ = '\0';
3609 }
3610
3611 return argc;
3612}
3613
3614
cd101567
JM
3615static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3616{
3617 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3618 printf("Connection to wpa_supplicant lost - trying to "
3619 "reconnect\n");
3620 wpa_cli_close_connection();
3621 }
3622 if (!ctrl_conn)
3623 wpa_cli_reconnect();
3624 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3625}
3626
3627
3628static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3629{
3630 eloop_terminate();
3631}
3632
3633
3634static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3635{
3636 wpa_cli_recv_pending(mon_conn, 0);
3637}
3638
3639
82a855bd 3640static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
aee680e8
JM
3641{
3642 char *argv[max_args];
3643 int argc;
82a855bd 3644 argc = tokenize_cmd(cmd, argv);
aee680e8
JM
3645 if (argc)
3646 wpa_request(ctrl_conn, argc, argv);
aee680e8
JM
3647}
3648
3649
82a855bd 3650static void wpa_cli_edit_eof_cb(void *ctx)
6f1c6549 3651{
82a855bd 3652 eloop_terminate();
cd101567
JM
3653}
3654
3655
3656static void wpa_cli_interactive(void)
3657{
8953e968 3658 char *home, *hfile = NULL;
aee680e8 3659
cd101567 3660 printf("\nInteractive mode\n\n");
cd101567 3661
8953e968
JM
3662 home = getenv("HOME");
3663 if (home) {
3664 const char *fname = ".wpa_cli_history";
3665 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3666 hfile = os_malloc(hfile_len);
3667 if (hfile)
3668 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3669 }
3670
cd101567 3671 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
8953e968
JM
3672 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3673 wpa_cli_edit_completion_cb, NULL, hfile);
cd101567
JM
3674 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3675
cd101567
JM
3676 eloop_run();
3677
a624f20b 3678 cli_txt_list_flush(&p2p_peers);
76788542 3679 cli_txt_list_flush(&p2p_groups);
a624f20b 3680 cli_txt_list_flush(&bsses);
8953e968
JM
3681 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3682 os_free(hfile);
cd101567
JM
3683 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3684 wpa_cli_close_connection();
6f1c6549
JM
3685}
3686
6fc6879b
JM
3687
3688static void wpa_cli_action(struct wpa_ctrl *ctrl)
3689{
3690#ifdef CONFIG_ANSI_C_EXTRA
3691 /* TODO: ANSI C version(?) */
3692 printf("Action processing not supported in ANSI C build.\n");
3693#else /* CONFIG_ANSI_C_EXTRA */
3694 fd_set rfds;
3695 int fd, res;
3696 struct timeval tv;
3697 char buf[256]; /* note: large enough to fit in unsolicited messages */
3698 size_t len;
3699
3700 fd = wpa_ctrl_get_fd(ctrl);
3701
3702 while (!wpa_cli_quit) {
3703 FD_ZERO(&rfds);
3704 FD_SET(fd, &rfds);
1cc84c1c 3705 tv.tv_sec = ping_interval;
6fc6879b
JM
3706 tv.tv_usec = 0;
3707 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3708 if (res < 0 && errno != EINTR) {
3709 perror("select");
3710 break;
3711 }
3712
3713 if (FD_ISSET(fd, &rfds))
cd101567 3714 wpa_cli_recv_pending(ctrl, 1);
6fc6879b
JM
3715 else {
3716 /* verify that connection is still working */
3717 len = sizeof(buf) - 1;
3718 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3719 wpa_cli_action_cb) < 0 ||
3720 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3721 printf("wpa_supplicant did not reply to PING "
3722 "command - exiting\n");
3723 break;
3724 }
3725 }
3726 }
3727#endif /* CONFIG_ANSI_C_EXTRA */
3728}
3729
3730
3731static void wpa_cli_cleanup(void)
3732{
3733 wpa_cli_close_connection();
3734 if (pid_file)
3735 os_daemonize_terminate(pid_file);
3736
3737 os_program_deinit();
3738}
3739
3740static void wpa_cli_terminate(int sig)
3741{
3742 wpa_cli_cleanup();
3743 exit(0);
3744}
3745
3746
6fc6879b
JM
3747static char * wpa_cli_get_default_ifname(void)
3748{
3749 char *ifname = NULL;
3750
3751#ifdef CONFIG_CTRL_IFACE_UNIX
3752 struct dirent *dent;
3753 DIR *dir = opendir(ctrl_iface_dir);
b1001e4c
DS
3754 if (!dir) {
3755#ifdef ANDROID
3756 char ifprop[PROPERTY_VALUE_MAX];
3757 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3758 ifname = os_strdup(ifprop);
3759 printf("Using interface '%s'\n", ifname);
3760 return ifname;
3761 }
3762#endif /* ANDROID */
6fc6879b 3763 return NULL;
b1001e4c 3764 }
6fc6879b
JM
3765 while ((dent = readdir(dir))) {
3766#ifdef _DIRENT_HAVE_D_TYPE
3767 /*
3768 * Skip the file if it is not a socket. Also accept
3769 * DT_UNKNOWN (0) in case the C library or underlying
3770 * file system does not support d_type.
3771 */
3772 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3773 continue;
3774#endif /* _DIRENT_HAVE_D_TYPE */
3775 if (os_strcmp(dent->d_name, ".") == 0 ||
3776 os_strcmp(dent->d_name, "..") == 0)
3777 continue;
3778 printf("Selected interface '%s'\n", dent->d_name);
3779 ifname = os_strdup(dent->d_name);
3780 break;
3781 }
3782 closedir(dir);
3783#endif /* CONFIG_CTRL_IFACE_UNIX */
3784
3785#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3786 char buf[2048], *pos;
3787 size_t len;
3788 struct wpa_ctrl *ctrl;
3789 int ret;
3790
3791 ctrl = wpa_ctrl_open(NULL);
3792 if (ctrl == NULL)
3793 return NULL;
3794
3795 len = sizeof(buf) - 1;
3796 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3797 if (ret >= 0) {
3798 buf[len] = '\0';
3799 pos = os_strchr(buf, '\n');
3800 if (pos)
3801 *pos = '\0';
3802 ifname = os_strdup(buf);
3803 }
3804 wpa_ctrl_close(ctrl);
3805#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3806
3807 return ifname;
3808}
3809
3810
3811int main(int argc, char *argv[])
3812{
6fc6879b
JM
3813 int warning_displayed = 0;
3814 int c;
3815 int daemonize = 0;
3816 int ret = 0;
3817 const char *global = NULL;
3818
3819 if (os_program_init())
3820 return -1;
3821
3822 for (;;) {
1cc84c1c 3823 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
3824 if (c < 0)
3825 break;
3826 switch (c) {
3827 case 'a':
3828 action_file = optarg;
3829 break;
3830 case 'B':
3831 daemonize = 1;
3832 break;
3833 case 'g':
3834 global = optarg;
3835 break;
1cc84c1c
JM
3836 case 'G':
3837 ping_interval = atoi(optarg);
3838 break;
6fc6879b
JM
3839 case 'h':
3840 usage();
3841 return 0;
3842 case 'v':
3843 printf("%s\n", wpa_cli_version);
3844 return 0;
3845 case 'i':
3846 os_free(ctrl_ifname);
3847 ctrl_ifname = os_strdup(optarg);
3848 break;
3849 case 'p':
3850 ctrl_iface_dir = optarg;
3851 break;
3852 case 'P':
3853 pid_file = optarg;
3854 break;
3855 default:
3856 usage();
3857 return -1;
3858 }
3859 }
3860
3861 interactive = (argc == optind) && (action_file == NULL);
3862
3863 if (interactive)
3864 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3865
cd101567
JM
3866 if (eloop_init())
3867 return -1;
3868
6fc6879b
JM
3869 if (global) {
3870#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3871 ctrl_conn = wpa_ctrl_open(NULL);
3872#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3873 ctrl_conn = wpa_ctrl_open(global);
3874#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3875 if (ctrl_conn == NULL) {
5a49459e
BG
3876 fprintf(stderr, "Failed to connect to wpa_supplicant "
3877 "global interface: %s error: %s\n",
3878 global, strerror(errno));
6fc6879b
JM
3879 return -1;
3880 }
3881 }
3882
6fc6879b
JM
3883#ifndef _WIN32_WCE
3884 signal(SIGINT, wpa_cli_terminate);
3885 signal(SIGTERM, wpa_cli_terminate);
3886#endif /* _WIN32_WCE */
6fc6879b 3887
4a3ade4e
JM
3888 if (ctrl_ifname == NULL)
3889 ctrl_ifname = wpa_cli_get_default_ifname();
3890
3891 if (interactive) {
3892 for (; !global;) {
3893 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3894 if (warning_displayed)
3895 printf("Connection established.\n");
3896 break;
3897 }
3898
3899 if (!warning_displayed) {
5a49459e
BG
3900 printf("Could not connect to wpa_supplicant: "
3901 "%s - re-trying\n", ctrl_ifname);
4a3ade4e
JM
3902 warning_displayed = 1;
3903 }
3904 os_sleep(1, 0);
3905 continue;
3906 }
3907 } else {
3908 if (!global &&
3909 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
5a49459e
BG
3910 fprintf(stderr, "Failed to connect to non-global "
3911 "ctrl_ifname: %s error: %s\n",
3912 ctrl_ifname, strerror(errno));
4a3ade4e
JM
3913 return -1;
3914 }
3915
3916 if (action_file) {
3917 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3918 wpa_cli_attached = 1;
3919 } else {
3920 printf("Warning: Failed to attach to "
3921 "wpa_supplicant.\n");
6fc6879b 3922 return -1;
4a3ade4e 3923 }
6fc6879b
JM
3924 }
3925 }
3926
3927 if (daemonize && os_daemonize(pid_file))
3928 return -1;
3929
3930 if (interactive)
3931 wpa_cli_interactive();
3932 else if (action_file)
3933 wpa_cli_action(ctrl_conn);
3934 else
3935 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3936
3937 os_free(ctrl_ifname);
cd101567 3938 eloop_destroy();
6fc6879b
JM
3939 wpa_cli_cleanup();
3940
3941 return ret;
3942}
3943
3944#else /* CONFIG_CTRL_IFACE */
3945int main(int argc, char *argv[])
3946{
3947 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3948 return -1;
3949}
3950#endif /* CONFIG_CTRL_IFACE */