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