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