]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
HS 2.0: Add runtime configuration of Hotspot 2.0 station
[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
5f97dd1c
DS
1699 if (argc < 1) {
1700 printf("Invalid BSS command: need at least one argument"
1701 "(index or BSSID)\n");
6fc6879b
JM
1702 return -1;
1703 }
1704
5f97dd1c
DS
1705 res = os_snprintf(cmd, sizeof(cmd), "BSS %s%s%s%s%s", argv[0],
1706 argc > 1 ? " " : "", argc > 1 ? argv[1] : "",
1707 argc > 2 ? " " : "", argc > 2 ? argv[2] : "");
1708
6fc6879b
JM
1709 if (res < 0 || (size_t) res >= sizeof(cmd))
1710 return -1;
1711 cmd[sizeof(cmd) - 1] = '\0';
1712
1713 return wpa_ctrl_command(ctrl, cmd);
1714}
1715
1716
a624f20b
JM
1717static char ** wpa_cli_complete_bss(const char *str, int pos)
1718{
1719 int arg = get_cmd_arg_num(str, pos);
1720 char **res = NULL;
1721
1722 switch (arg) {
1723 case 1:
1724 res = cli_txt_list_array(&bsses);
1725 break;
1726 }
1727
1728 return res;
1729}
1730
1731
6fc6879b
JM
1732static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1733 char *argv[])
1734{
1735 char cmd[64];
1736 int res;
1737
1738 if (argc < 1 || argc > 2) {
1739 printf("Invalid GET_CAPABILITY command: need either one or "
1740 "two arguments\n");
1741 return -1;
1742 }
1743
1744 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1745 printf("Invalid GET_CAPABILITY command: second argument, "
1746 "if any, must be 'strict'\n");
1747 return -1;
1748 }
1749
1750 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1751 (argc == 2) ? " strict" : "");
1752 if (res < 0 || (size_t) res >= sizeof(cmd))
1753 return -1;
1754 cmd[sizeof(cmd) - 1] = '\0';
1755
1756 return wpa_ctrl_command(ctrl, cmd);
1757}
1758
1759
1760static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1761{
1762 printf("Available interfaces:\n");
1763 return wpa_ctrl_command(ctrl, "INTERFACES");
1764}
1765
1766
1767static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1768{
1769 if (argc < 1) {
1770 wpa_cli_list_interfaces(ctrl);
1771 return 0;
1772 }
1773
1774 wpa_cli_close_connection();
1775 os_free(ctrl_ifname);
1776 ctrl_ifname = os_strdup(argv[0]);
1777
4a3ade4e 1778 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
6fc6879b 1779 printf("Connected to interface '%s.\n", ctrl_ifname);
6fc6879b
JM
1780 } else {
1781 printf("Could not connect to interface '%s' - re-trying\n",
1782 ctrl_ifname);
1783 }
1784 return 0;
1785}
1786
1787
1788static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1789 char *argv[])
1790{
1791 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1792}
1793
1794
1795static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1796 char *argv[])
1797{
1798 return wpa_ctrl_command(ctrl, "TERMINATE");
1799}
1800
1801
1802static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1803 char *argv[])
1804{
1805 char cmd[256];
1806 int res;
1807
1808 if (argc < 1) {
1809 printf("Invalid INTERFACE_ADD command: needs at least one "
1810 "argument (interface name)\n"
1811 "All arguments: ifname confname driver ctrl_interface "
1812 "driver_param bridge_name\n");
1813 return -1;
1814 }
1815
1816 /*
1817 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1818 * <driver_param>TAB<bridge_name>
1819 */
1820 res = os_snprintf(cmd, sizeof(cmd),
1821 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1822 argv[0],
1823 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1824 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1825 argc > 5 ? argv[5] : "");
1826 if (res < 0 || (size_t) res >= sizeof(cmd))
1827 return -1;
1828 cmd[sizeof(cmd) - 1] = '\0';
1829 return wpa_ctrl_command(ctrl, cmd);
1830}
1831
1832
1833static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1834 char *argv[])
1835{
1836 char cmd[128];
1837 int res;
1838
1839 if (argc != 1) {
1840 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1841 "(interface name)\n");
1842 return -1;
1843 }
1844
1845 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1846 if (res < 0 || (size_t) res >= sizeof(cmd))
1847 return -1;
1848 cmd[sizeof(cmd) - 1] = '\0';
1849 return wpa_ctrl_command(ctrl, cmd);
1850}
1851
1852
4b4a8ae5
JM
1853static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1854 char *argv[])
1855{
1856 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1857}
1858
1859
e653b622
JM
1860#ifdef CONFIG_AP
1861static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1862{
1863 char buf[64];
1864 if (argc != 1) {
1865 printf("Invalid 'sta' command - exactly one argument, STA "
1866 "address, is required.\n");
1867 return -1;
1868 }
e824cc46 1869 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
e653b622
JM
1870 return wpa_ctrl_command(ctrl, buf);
1871}
1872
1873
1874static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1875 char *addr, size_t addr_len)
1876{
1877 char buf[4096], *pos;
1878 size_t len;
1879 int ret;
1880
1881 if (ctrl_conn == NULL) {
1882 printf("Not connected to hostapd - command dropped.\n");
1883 return -1;
1884 }
1885 len = sizeof(buf) - 1;
024d018b 1886 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
e653b622
JM
1887 wpa_cli_msg_cb);
1888 if (ret == -2) {
1889 printf("'%s' command timed out.\n", cmd);
1890 return -2;
1891 } else if (ret < 0) {
1892 printf("'%s' command failed.\n", cmd);
1893 return -1;
1894 }
1895
1896 buf[len] = '\0';
024d018b 1897 if (os_memcmp(buf, "FAIL", 4) == 0)
e653b622
JM
1898 return -1;
1899 printf("%s", buf);
1900
1901 pos = buf;
1902 while (*pos != '\0' && *pos != '\n')
1903 pos++;
1904 *pos = '\0';
1905 os_strlcpy(addr, buf, addr_len);
1906 return 0;
1907}
1908
1909
1910static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1911{
1912 char addr[32], cmd[64];
1913
1914 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1915 return 0;
1916 do {
e824cc46 1917 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
e653b622
JM
1918 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1919
1920 return -1;
1921}
e60b2951
JJ
1922
1923
1924static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1925 char *argv[])
1926{
1927 char buf[64];
1928 if (argc < 1) {
1929 printf("Invalid 'deauthenticate' command - exactly one "
1930 "argument, STA address, is required.\n");
1931 return -1;
1932 }
1933 if (argc > 1)
1934 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
1935 argv[0], argv[1]);
1936 else
1937 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
1938 return wpa_ctrl_command(ctrl, buf);
1939}
1940
1941
1942static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1943 char *argv[])
1944{
1945 char buf[64];
1946 if (argc < 1) {
1947 printf("Invalid 'disassociate' command - exactly one "
1948 "argument, STA address, is required.\n");
1949 return -1;
1950 }
1951 if (argc > 1)
1952 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
1953 argv[0], argv[1]);
1954 else
1955 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
1956 return wpa_ctrl_command(ctrl, buf);
1957}
e653b622
JM
1958#endif /* CONFIG_AP */
1959
1960
207ef3fb
JM
1961static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1962{
1963 return wpa_ctrl_command(ctrl, "SUSPEND");
1964}
1965
1966
1967static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1968{
1969 return wpa_ctrl_command(ctrl, "RESUME");
1970}
1971
1972
32d5295f
JM
1973static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1974{
1975 return wpa_ctrl_command(ctrl, "DROP_SA");
1976}
1977
1978
86d4f806
JM
1979static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1980{
1981 char cmd[128];
1982 int res;
1983
1984 if (argc != 1) {
1985 printf("Invalid ROAM command: needs one argument "
1986 "(target AP's BSSID)\n");
1987 return -1;
1988 }
1989
1990 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1991 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1992 printf("Too long ROAM command.\n");
1993 return -1;
1994 }
1995 return wpa_ctrl_command(ctrl, cmd);
1996}
1997
1998
57faa1ce
JM
1999#ifdef CONFIG_P2P
2000
2001static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2002{
2003 char cmd[128];
2004 int res;
2005
2006 if (argc == 0)
2007 return wpa_ctrl_command(ctrl, "P2P_FIND");
2008
6d92fa6e
JM
2009 if (argc > 2)
2010 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s %s",
2011 argv[0], argv[1], argv[2]);
2012 else if (argc > 1)
57faa1ce
JM
2013 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
2014 argv[0], argv[1]);
2015 else
2016 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
2017 if (res < 0 || (size_t) res >= sizeof(cmd))
2018 return -1;
2019 cmd[sizeof(cmd) - 1] = '\0';
2020 return wpa_ctrl_command(ctrl, cmd);
2021}
2022
2023
2024static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2025 char *argv[])
2026{
2027 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2028}
2029
2030
2031static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2032 char *argv[])
2033{
2034 char cmd[128];
2035 int res;
2036
2037 if (argc < 2) {
2038 printf("Invalid P2P_CONNECT command: needs at least two "
2039 "arguments (address and pbc/PIN)\n");
2040 return -1;
2041 }
2042
2043 if (argc > 4)
2044 res = os_snprintf(cmd, sizeof(cmd),
2045 "P2P_CONNECT %s %s %s %s %s",
2046 argv[0], argv[1], argv[2], argv[3],
2047 argv[4]);
2048 else if (argc > 3)
2049 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
2050 argv[0], argv[1], argv[2], argv[3]);
2051 else if (argc > 2)
2052 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
2053 argv[0], argv[1], argv[2]);
2054 else
2055 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
2056 argv[0], argv[1]);
2057 if (res < 0 || (size_t) res >= sizeof(cmd))
2058 return -1;
2059 cmd[sizeof(cmd) - 1] = '\0';
2060 return wpa_ctrl_command(ctrl, cmd);
2061}
2062
2063
a624f20b
JM
2064static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2065{
2066 int arg = get_cmd_arg_num(str, pos);
2067 char **res = NULL;
2068
2069 switch (arg) {
2070 case 1:
2071 res = cli_txt_list_array(&p2p_peers);
2072 break;
2073 }
2074
2075 return res;
2076}
2077
2078
57faa1ce
JM
2079static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2080 char *argv[])
2081{
2082 char cmd[128];
2083 int res;
2084
2085 if (argc == 0)
2086 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
2087
2088 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
2089 if (res < 0 || (size_t) res >= sizeof(cmd))
2090 return -1;
2091 cmd[sizeof(cmd) - 1] = '\0';
2092 return wpa_ctrl_command(ctrl, cmd);
2093}
2094
2095
2096static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2097 char *argv[])
2098{
2099 char cmd[128];
2100 int res;
2101
2102 if (argc != 1) {
2103 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
2104 "(interface name)\n");
2105 return -1;
2106 }
2107
2108 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
2109 if (res < 0 || (size_t) res >= sizeof(cmd))
2110 return -1;
2111 cmd[sizeof(cmd) - 1] = '\0';
2112 return wpa_ctrl_command(ctrl, cmd);
2113}
2114
2115
76788542
JM
2116static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2117{
2118 int arg = get_cmd_arg_num(str, pos);
2119 char **res = NULL;
2120
2121 switch (arg) {
2122 case 1:
2123 res = cli_txt_list_array(&p2p_groups);
2124 break;
2125 }
2126
2127 return res;
2128}
2129
2130
57faa1ce
JM
2131static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2132 char *argv[])
2133{
2134 char cmd[128];
2135 int res;
2136
2137 if (argc == 0)
2138 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
2139
751bc722
MK
2140 if (argc > 1)
2141 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s %s",
2142 argv[0], argv[1]);
2143 else
2144 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s",
2145 argv[0]);
57faa1ce
JM
2146 if (res < 0 || (size_t) res >= sizeof(cmd))
2147 return -1;
2148 cmd[sizeof(cmd) - 1] = '\0';
2149 return wpa_ctrl_command(ctrl, cmd);
2150}
2151
2152
2153static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2154 char *argv[])
2155{
2156 char cmd[128];
2157 int res;
2158
8c5f7309
JJ
2159 if (argc != 2 && argc != 3) {
2160 printf("Invalid P2P_PROV_DISC command: needs at least "
2161 "two arguments, address and config method\n"
2162 "(display, keypad, or pbc) and an optional join\n");
57faa1ce
JM
2163 return -1;
2164 }
2165
8c5f7309
JJ
2166 if (argc == 3)
2167 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s %s",
2168 argv[0], argv[1], argv[2]);
2169 else
2170 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
2171 argv[0], argv[1]);
57faa1ce
JM
2172 if (res < 0 || (size_t) res >= sizeof(cmd))
2173 return -1;
2174 cmd[sizeof(cmd) - 1] = '\0';
2175 return wpa_ctrl_command(ctrl, cmd);
2176}
2177
2178
2179static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2180 char *argv[])
2181{
2182 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2183}
2184
2185
2186static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2187 char *argv[])
2188{
2189 char cmd[4096];
2190 int res;
2191
2192 if (argc != 2 && argc != 4) {
2193 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2194 "arguments (address and TLVs) or four arguments "
2195 "(address, \"upnp\", version, search target "
2196 "(SSDP ST:)\n");
2197 return -1;
2198 }
2199
2200 if (argc == 4)
2201 res = os_snprintf(cmd, sizeof(cmd),
2202 "P2P_SERV_DISC_REQ %s %s %s %s",
2203 argv[0], argv[1], argv[2], argv[3]);
2204 else
2205 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
2206 argv[0], argv[1]);
2207 if (res < 0 || (size_t) res >= sizeof(cmd))
2208 return -1;
2209 cmd[sizeof(cmd) - 1] = '\0';
2210 return wpa_ctrl_command(ctrl, cmd);
2211}
2212
2213
2214static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2215 int argc, char *argv[])
2216{
2217 char cmd[128];
2218 int res;
2219
2220 if (argc != 1) {
2221 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
2222 "argument (pending request identifier)\n");
2223 return -1;
2224 }
2225
2226 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
2227 argv[0]);
2228 if (res < 0 || (size_t) res >= sizeof(cmd))
2229 return -1;
2230 cmd[sizeof(cmd) - 1] = '\0';
2231 return wpa_ctrl_command(ctrl, cmd);
2232}
2233
2234
2235static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
2238 char cmd[4096];
2239 int res;
2240
2241 if (argc != 4) {
2242 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2243 "arguments (freq, address, dialog token, and TLVs)\n");
2244 return -1;
2245 }
2246
2247 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2248 argv[0], argv[1], argv[2], argv[3]);
2249 if (res < 0 || (size_t) res >= sizeof(cmd))
2250 return -1;
2251 cmd[sizeof(cmd) - 1] = '\0';
2252 return wpa_ctrl_command(ctrl, cmd);
2253}
2254
2255
2256static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
2259 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2260}
2261
2262
2263static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2264 int argc, char *argv[])
2265{
2266 char cmd[128];
2267 int res;
2268
2269 if (argc != 1) {
2270 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
2271 "argument (external processing: 0/1)\n");
2272 return -1;
2273 }
2274
2275 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
2276 argv[0]);
2277 if (res < 0 || (size_t) res >= sizeof(cmd))
2278 return -1;
2279 cmd[sizeof(cmd) - 1] = '\0';
2280 return wpa_ctrl_command(ctrl, cmd);
2281}
2282
2283
2284static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2285 char *argv[])
2286{
2287 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2288}
2289
2290
2291static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2292 char *argv[])
2293{
2294 char cmd[4096];
2295 int res;
2296
2297 if (argc != 3 && argc != 4) {
2298 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
2299 "arguments\n");
2300 return -1;
2301 }
2302
2303 if (argc == 4)
2304 res = os_snprintf(cmd, sizeof(cmd),
2305 "P2P_SERVICE_ADD %s %s %s %s",
2306 argv[0], argv[1], argv[2], argv[3]);
2307 else
2308 res = os_snprintf(cmd, sizeof(cmd),
2309 "P2P_SERVICE_ADD %s %s %s",
2310 argv[0], argv[1], argv[2]);
2311 if (res < 0 || (size_t) res >= sizeof(cmd))
2312 return -1;
2313 cmd[sizeof(cmd) - 1] = '\0';
2314 return wpa_ctrl_command(ctrl, cmd);
2315}
2316
2317
2318static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2319 char *argv[])
2320{
2321 char cmd[4096];
2322 int res;
2323
2324 if (argc != 2 && argc != 3) {
2325 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2326 "arguments\n");
2327 return -1;
2328 }
2329
2330 if (argc == 3)
2331 res = os_snprintf(cmd, sizeof(cmd),
2332 "P2P_SERVICE_DEL %s %s %s",
2333 argv[0], argv[1], argv[2]);
2334 else
2335 res = os_snprintf(cmd, sizeof(cmd),
2336 "P2P_SERVICE_DEL %s %s",
2337 argv[0], argv[1]);
2338 if (res < 0 || (size_t) res >= sizeof(cmd))
2339 return -1;
2340 cmd[sizeof(cmd) - 1] = '\0';
2341 return wpa_ctrl_command(ctrl, cmd);
2342}
2343
2344
2345static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2346 int argc, char *argv[])
2347{
2348 char cmd[128];
2349 int res;
2350
2351 if (argc != 1) {
2352 printf("Invalid P2P_REJECT command: needs one argument "
2353 "(peer address)\n");
2354 return -1;
2355 }
2356
2357 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
2358 if (res < 0 || (size_t) res >= sizeof(cmd))
2359 return -1;
2360 cmd[sizeof(cmd) - 1] = '\0';
2361 return wpa_ctrl_command(ctrl, cmd);
2362}
2363
2364
2365static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2366 int argc, char *argv[])
2367{
2368 char cmd[128];
2369 int res;
2370
2371 if (argc < 1) {
2372 printf("Invalid P2P_INVITE command: needs at least one "
2373 "argument\n");
2374 return -1;
2375 }
2376
2377 if (argc > 2)
2378 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
2379 argv[0], argv[1], argv[2]);
2380 else if (argc > 1)
2381 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
2382 argv[0], argv[1]);
2383 else
2384 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
2385 if (res < 0 || (size_t) res >= sizeof(cmd))
2386 return -1;
2387 cmd[sizeof(cmd) - 1] = '\0';
2388 return wpa_ctrl_command(ctrl, cmd);
2389}
2390
2391
2392static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2393{
2394 char buf[64];
2395 if (argc != 1) {
2396 printf("Invalid 'p2p_peer' command - exactly one argument, "
2397 "P2P peer device address, is required.\n");
2398 return -1;
2399 }
2400 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
2401 return wpa_ctrl_command(ctrl, buf);
2402}
2403
2404
a624f20b
JM
2405static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2406{
2407 int arg = get_cmd_arg_num(str, pos);
2408 char **res = NULL;
2409
2410 switch (arg) {
2411 case 1:
2412 res = cli_txt_list_array(&p2p_peers);
2413 break;
2414 }
2415
2416 return res;
2417}
2418
2419
57faa1ce
JM
2420static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2421 char *addr, size_t addr_len,
2422 int discovered)
2423{
2424 char buf[4096], *pos;
2425 size_t len;
2426 int ret;
2427
2428 if (ctrl_conn == NULL)
2429 return -1;
2430 len = sizeof(buf) - 1;
024d018b 2431 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
57faa1ce
JM
2432 wpa_cli_msg_cb);
2433 if (ret == -2) {
2434 printf("'%s' command timed out.\n", cmd);
2435 return -2;
2436 } else if (ret < 0) {
2437 printf("'%s' command failed.\n", cmd);
2438 return -1;
2439 }
2440
2441 buf[len] = '\0';
024d018b 2442 if (os_memcmp(buf, "FAIL", 4) == 0)
57faa1ce
JM
2443 return -1;
2444
2445 pos = buf;
2446 while (*pos != '\0' && *pos != '\n')
2447 pos++;
2448 *pos++ = '\0';
2449 os_strlcpy(addr, buf, addr_len);
2450 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2451 printf("%s\n", addr);
2452 return 0;
2453}
2454
2455
2456static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2457{
2458 char addr[32], cmd[64];
2459 int discovered;
2460
2461 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2462
2463 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2464 addr, sizeof(addr), discovered))
9a6ade33 2465 return -1;
57faa1ce
JM
2466 do {
2467 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2468 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2469 discovered) == 0);
2470
9a6ade33 2471 return 0;
57faa1ce
JM
2472}
2473
2474
2475static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2476{
2477 char cmd[100];
2478 int res;
2479
2480 if (argc != 2) {
2481 printf("Invalid P2P_SET command: needs two arguments (field, "
2482 "value)\n");
2483 return -1;
2484 }
2485
2486 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2487 if (res < 0 || (size_t) res >= sizeof(cmd))
2488 return -1;
2489 cmd[sizeof(cmd) - 1] = '\0';
2490 return wpa_ctrl_command(ctrl, cmd);
2491}
2492
2493
2494static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2495{
2496 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2497}
2498
2499
59eba7a2
JM
2500static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2501 char *argv[])
2502{
2503 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2504}
2505
2506
9d562b79
SS
2507static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2508 char *argv[])
2509{
2510 char cmd[100];
2511 int res;
2512
2513 if (argc != 1) {
2514 printf("Invalid P2P_UNAUTHORIZE command: needs one argument "
2515 "(peer address)\n");
2516 return -1;
2517 }
2518
2519 res = os_snprintf(cmd, sizeof(cmd), "P2P_UNAUTHORIZE %s", argv[0]);
2520
2521 if (res < 0 || (size_t) res >= sizeof(cmd))
2522 return -1;
2523
2524 cmd[sizeof(cmd) - 1] = '\0';
2525 return wpa_ctrl_command(ctrl, cmd);
2526}
2527
2528
57faa1ce
JM
2529static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2530 char *argv[])
2531{
2532 char cmd[100];
2533 int res;
2534
2535 if (argc != 0 && argc != 2 && argc != 4) {
2536 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2537 "(preferred duration, interval; in microsecods).\n"
2538 "Optional second pair can be used to provide "
2539 "acceptable values.\n");
2540 return -1;
2541 }
2542
2543 if (argc == 4)
2544 res = os_snprintf(cmd, sizeof(cmd),
2545 "P2P_PRESENCE_REQ %s %s %s %s",
2546 argv[0], argv[1], argv[2], argv[3]);
2547 else if (argc == 2)
2548 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2549 argv[0], argv[1]);
2550 else
2551 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2552 if (res < 0 || (size_t) res >= sizeof(cmd))
2553 return -1;
2554 cmd[sizeof(cmd) - 1] = '\0';
2555 return wpa_ctrl_command(ctrl, cmd);
2556}
2557
2558
2559static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2560 char *argv[])
2561{
2562 char cmd[100];
2563 int res;
2564
2565 if (argc != 0 && argc != 2) {
2566 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2567 "(availability period, availability interval; in "
2568 "millisecods).\n"
2569 "Extended Listen Timing can be cancelled with this "
2570 "command when used without parameters.\n");
2571 return -1;
2572 }
2573
2574 if (argc == 2)
2575 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2576 argv[0], argv[1]);
2577 else
2578 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2579 if (res < 0 || (size_t) res >= sizeof(cmd))
2580 return -1;
2581 cmd[sizeof(cmd) - 1] = '\0';
2582 return wpa_ctrl_command(ctrl, cmd);
2583}
2584
2585#endif /* CONFIG_P2P */
2586
2587
afc064fe
JM
2588#ifdef CONFIG_INTERWORKING
2589static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2590 char *argv[])
2591{
2592 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2593}
2594
2595
2596static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2597 char *argv[])
2598{
2599 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2600}
2601
2602
b02fe7ff
JM
2603static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2604 char *argv[])
2605{
2606 char cmd[100];
2607 int res;
2608
2609 if (argc == 0)
2610 return wpa_ctrl_command(ctrl, "INTERWORKING_SELECT");
2611
2612 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_SELECT %s", argv[0]);
2613 if (res < 0 || (size_t) res >= sizeof(cmd))
2614 return -1;
2615 cmd[sizeof(cmd) - 1] = '\0';
2616 return wpa_ctrl_command(ctrl, cmd);
2617}
2618
2619
2620static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2621 char *argv[])
2622{
2623 char cmd[100];
2624 int res;
2625
2626 if (argc != 1) {
2627 printf("Invalid INTERWORKING_CONNECT commands: needs one "
2628 "argument (BSSID)\n");
2629 return -1;
2630 }
2631
2632 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_CONNECT %s",
2633 argv[0]);
2634 if (res < 0 || (size_t) res >= sizeof(cmd))
2635 return -1;
2636 cmd[sizeof(cmd) - 1] = '\0';
2637 return wpa_ctrl_command(ctrl, cmd);
2638}
2639
2640
afc064fe
JM
2641static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2642{
2643 char cmd[100];
2644 int res;
2645
2646 if (argc != 2) {
2647 printf("Invalid ANQP_GET command: needs two arguments "
2648 "(addr and info id list)\n");
2649 return -1;
2650 }
2651
2652 res = os_snprintf(cmd, sizeof(cmd), "ANQP_GET %s %s",
2653 argv[0], argv[1]);
2654 if (res < 0 || (size_t) res >= sizeof(cmd))
2655 return -1;
2656 cmd[sizeof(cmd) - 1] = '\0';
2657 return wpa_ctrl_command(ctrl, cmd);
2658}
2659#endif /* CONFIG_INTERWORKING */
2660
2661
0d0a8ca1
AC
2662static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2663 char *argv[])
2664{
2665 char cmd[256];
2666 int res;
2667
2668 if (argc != 1) {
2669 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2670 "(0/1 = disable/enable automatic reconnection)\n");
2671 return -1;
2672 }
2673 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2674 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2675 printf("Too long STA_AUTOCONNECT command.\n");
2676 return -1;
2677 }
2678 return wpa_ctrl_command(ctrl, cmd);
2679}
2680
2681
281ff0aa
GP
2682static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2683 char *argv[])
2684{
2685 char cmd[256];
2686 int res;
2687
2688 if (argc != 1) {
2689 printf("Invalid TDLS_DISCOVER command: needs one argument "
2690 "(Peer STA MAC address)\n");
2691 return -1;
2692 }
2693
2694 res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
2695 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2696 printf("Too long TDLS_DISCOVER command.\n");
2697 return -1;
2698 }
2699 return wpa_ctrl_command(ctrl, cmd);
2700}
2701
2702
2703static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2704 char *argv[])
2705{
2706 char cmd[256];
2707 int res;
2708
2709 if (argc != 1) {
2710 printf("Invalid TDLS_SETUP command: needs one argument "
2711 "(Peer STA MAC address)\n");
2712 return -1;
2713 }
2714
2715 res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
2716 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2717 printf("Too long TDLS_SETUP command.\n");
2718 return -1;
2719 }
2720 return wpa_ctrl_command(ctrl, cmd);
2721}
2722
2723
2724static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2725 char *argv[])
2726{
2727 char cmd[256];
2728 int res;
2729
2730 if (argc != 1) {
2731 printf("Invalid TDLS_TEARDOWN command: needs one argument "
2732 "(Peer STA MAC address)\n");
2733 return -1;
2734 }
2735
2736 res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
2737 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2738 printf("Too long TDLS_TEARDOWN command.\n");
2739 return -1;
2740 }
2741 return wpa_ctrl_command(ctrl, cmd);
2742}
2743
2744
60b24b0d
DS
2745static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2746 char *argv[])
2747{
2748 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2749}
2750
2751
9482426e
JM
2752static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2753 char *argv[])
2754{
2755 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2756}
2757
2758
40fd868c
ER
2759enum wpa_cli_cmd_flags {
2760 cli_cmd_flag_none = 0x00,
2761 cli_cmd_flag_sensitive = 0x01
2762};
2763
6fc6879b
JM
2764struct wpa_cli_cmd {
2765 const char *cmd;
2766 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 2767 enum wpa_cli_cmd_flags flags;
dfa141b1 2768 const char *usage;
6fc6879b
JM
2769};
2770
2771static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 2772 { "status", wpa_cli_cmd_status,
dfa141b1
ER
2773 cli_cmd_flag_none,
2774 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 2775 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
2776 cli_cmd_flag_none,
2777 "= pings wpa_supplicant" },
ac6912b5
BG
2778 { "relog", wpa_cli_cmd_relog,
2779 cli_cmd_flag_none,
2780 "= re-open log-file (allow rolling logs)" },
77895cd9
JM
2781 { "note", wpa_cli_cmd_note,
2782 cli_cmd_flag_none,
2783 "<text> = add a note to wpa_supplicant debug log" },
40fd868c 2784 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
2785 cli_cmd_flag_none,
2786 "= get MIB variables (dot1x, dot11)" },
40fd868c 2787 { "help", wpa_cli_cmd_help,
dfa141b1
ER
2788 cli_cmd_flag_none,
2789 "= show this usage help" },
40fd868c 2790 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
2791 cli_cmd_flag_none,
2792 "[ifname] = show interfaces/select interface" },
40fd868c 2793 { "level", wpa_cli_cmd_level,
dfa141b1
ER
2794 cli_cmd_flag_none,
2795 "<debug level> = change debug level" },
40fd868c 2796 { "license", wpa_cli_cmd_license,
dfa141b1
ER
2797 cli_cmd_flag_none,
2798 "= show full wpa_cli license" },
40fd868c 2799 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
2800 cli_cmd_flag_none,
2801 "= exit wpa_cli" },
40fd868c 2802 { "set", wpa_cli_cmd_set,
dfa141b1
ER
2803 cli_cmd_flag_none,
2804 "= set variables (shows list of variables when run without "
2805 "arguments)" },
acec8d32
JM
2806 { "get", wpa_cli_cmd_get,
2807 cli_cmd_flag_none,
2808 "<name> = get information" },
40fd868c 2809 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
2810 cli_cmd_flag_none,
2811 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 2812 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
2813 cli_cmd_flag_none,
2814 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 2815 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
2816 cli_cmd_flag_none,
2817 "= show PMKSA cache" },
40fd868c 2818 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
2819 cli_cmd_flag_none,
2820 "= force reassociation" },
40fd868c 2821 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
2822 cli_cmd_flag_none,
2823 "<BSSID> = force preauthentication" },
40fd868c 2824 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
2825 cli_cmd_flag_none,
2826 "<network id> <identity> = configure identity for an SSID" },
40fd868c 2827 { "password", wpa_cli_cmd_password,
dfa141b1
ER
2828 cli_cmd_flag_sensitive,
2829 "<network id> <password> = configure password for an SSID" },
40fd868c 2830 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
2831 cli_cmd_flag_sensitive,
2832 "<network id> <password> = change password for an SSID" },
40fd868c 2833 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
2834 cli_cmd_flag_sensitive,
2835 "<network id> <pin> = configure pin for an SSID" },
40fd868c 2836 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
2837 cli_cmd_flag_sensitive,
2838 "<network id> <password> = configure one-time-password for an SSID"
2839 },
40fd868c 2840 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
2841 cli_cmd_flag_sensitive,
2842 "<network id> <passphrase> = configure private key passphrase\n"
2843 " for an SSID" },
40fd868c 2844 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
2845 cli_cmd_flag_none,
2846 "<network id> <BSSID> = set preferred BSSID for an SSID" },
9aa10e2b
DS
2847 { "blacklist", wpa_cli_cmd_blacklist,
2848 cli_cmd_flag_none,
2849 "<BSSID> = add a BSSID to the blacklist\n"
2850 "blacklist clear = clear the blacklist\n"
2851 "blacklist = display the blacklist" },
0597a5b5
DS
2852 { "log_level", wpa_cli_cmd_log_level,
2853 cli_cmd_flag_none,
2854 "<level> [<timestamp>] = update the log level/timestamp\n"
2855 "log_level = display the current log level and log options" },
40fd868c 2856 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
2857 cli_cmd_flag_none,
2858 "= list configured networks" },
40fd868c 2859 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
2860 cli_cmd_flag_none,
2861 "<network id> = select a network (disable others)" },
40fd868c 2862 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
2863 cli_cmd_flag_none,
2864 "<network id> = enable a network" },
40fd868c 2865 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
2866 cli_cmd_flag_none,
2867 "<network id> = disable a network" },
40fd868c 2868 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
2869 cli_cmd_flag_none,
2870 "= add a network" },
40fd868c 2871 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
2872 cli_cmd_flag_none,
2873 "<network id> = remove a network" },
40fd868c 2874 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
2875 cli_cmd_flag_sensitive,
2876 "<network id> <variable> <value> = set network variables (shows\n"
2877 " list of variables when run without arguments)" },
40fd868c 2878 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
2879 cli_cmd_flag_none,
2880 "<network id> <variable> = get network variables" },
d94c9ee6
JM
2881 { "list_creds", wpa_cli_cmd_list_creds,
2882 cli_cmd_flag_none,
2883 "= list configured credentials" },
2884 { "add_cred", wpa_cli_cmd_add_cred,
2885 cli_cmd_flag_none,
2886 "= add a credential" },
2887 { "remove_cred", wpa_cli_cmd_remove_cred,
2888 cli_cmd_flag_none,
2889 "<cred id> = remove a credential" },
2890 { "set_cred", wpa_cli_cmd_set_cred,
2891 cli_cmd_flag_sensitive,
2892 "<cred id> <variable> <value> = set credential variables" },
40fd868c 2893 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
2894 cli_cmd_flag_none,
2895 "= save the current configuration" },
40fd868c 2896 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
2897 cli_cmd_flag_none,
2898 "= disconnect and wait for reassociate/reconnect command before\n"
2899 " connecting" },
40fd868c 2900 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
2901 cli_cmd_flag_none,
2902 "= like reassociate, but only takes effect if already disconnected"
2903 },
40fd868c 2904 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
2905 cli_cmd_flag_none,
2906 "= request new BSS scan" },
40fd868c 2907 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
2908 cli_cmd_flag_none,
2909 "= get latest scan results" },
40fd868c 2910 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
2911 cli_cmd_flag_none,
2912 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 2913 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
2914 cli_cmd_flag_none,
2915 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 2916 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
2917 cli_cmd_flag_none,
2918 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 2919 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
2920 cli_cmd_flag_none,
2921 "= terminate wpa_supplicant" },
40fd868c 2922 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
2923 cli_cmd_flag_none,
2924 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2925 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2926 " are optional" },
40fd868c 2927 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
2928 cli_cmd_flag_none,
2929 "<ifname> = removes the interface" },
40fd868c 2930 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
2931 cli_cmd_flag_none,
2932 "= list available interfaces" },
40fd868c 2933 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
2934 cli_cmd_flag_none,
2935 "<value> = set ap_scan parameter" },
67b9bd08
DS
2936 { "scan_interval", wpa_cli_cmd_scan_interval,
2937 cli_cmd_flag_none,
2938 "<value> = set scan_interval parameter (in seconds)" },
78633c37
SL
2939 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2940 cli_cmd_flag_none,
2941 "<value> = set BSS expiration age parameter" },
2942 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2943 cli_cmd_flag_none,
2944 "<value> = set BSS expiration scan count parameter" },
40fd868c 2945 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
2946 cli_cmd_flag_none,
2947 "<addr> = request STK negotiation with <addr>" },
40fd868c 2948 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
2949 cli_cmd_flag_none,
2950 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 2951 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
2952 cli_cmd_flag_none,
2953 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 2954 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
2955 cli_cmd_flag_sensitive,
2956 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2957 "hardcoded)" },
3981cb3c
JM
2958 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2959 cli_cmd_flag_sensitive,
2960 "<PIN> = verify PIN checksum" },
2f9929ff
AC
2961 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2962 "Cancels the pending WPS operation" },
116f7bb0 2963#ifdef CONFIG_WPS_OOB
46bdb83a
MH
2964 { "wps_oob", wpa_cli_cmd_wps_oob,
2965 cli_cmd_flag_sensitive,
e1ee6b60 2966 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 2967#endif /* CONFIG_WPS_OOB */
40fd868c 2968 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
2969 cli_cmd_flag_sensitive,
2970 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
70d84f11
JM
2971 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
2972 cli_cmd_flag_sensitive,
2973 "[params..] = enable/disable AP PIN" },
e9bcfebf
JM
2974 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2975 cli_cmd_flag_none,
08486685 2976 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
e9bcfebf
JM
2977 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2978 cli_cmd_flag_none,
2979 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
2980 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2981 cli_cmd_flag_sensitive,
2982 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
2983 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2984 cli_cmd_flag_none,
2985 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
2986 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2987 cli_cmd_flag_sensitive,
2988 "<UUID> <PIN> = learn AP configuration" },
ef10f473
JM
2989 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2990 cli_cmd_flag_none,
2991 "<UUID> <network id> = set AP configuration for enrolling" },
7d6640a6
JM
2992 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2993 cli_cmd_flag_sensitive,
2994 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
11ef8d35
JM
2995 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2996 cli_cmd_flag_none,
2997 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
2998#ifdef CONFIG_AP
2999 { "sta", wpa_cli_cmd_sta,
3000 cli_cmd_flag_none,
3001 "<addr> = get information about an associated station (AP)" },
3002 { "all_sta", wpa_cli_cmd_all_sta,
3003 cli_cmd_flag_none,
3004 "= get information about all associated stations (AP)" },
e60b2951
JJ
3005 { "deauthenticate", wpa_cli_cmd_deauthenticate,
3006 cli_cmd_flag_none,
3007 "<addr> = deauthenticate a station" },
3008 { "disassociate", wpa_cli_cmd_disassociate,
3009 cli_cmd_flag_none,
3010 "<addr> = disassociate a station" },
e653b622 3011#endif /* CONFIG_AP */
207ef3fb
JM
3012 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
3013 "= notification of suspend/hibernate" },
3014 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
3015 "= notification of resume/thaw" },
32d5295f
JM
3016 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
3017 "= drop SA without deauth/disassoc (test command)" },
86d4f806
JM
3018 { "roam", wpa_cli_cmd_roam,
3019 cli_cmd_flag_none,
3020 "<addr> = roam to the specified BSS" },
57faa1ce
JM
3021#ifdef CONFIG_P2P
3022 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
3023 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3024 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
3025 "= stop P2P Devices search" },
3026 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
3027 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
3028 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
3029 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3030 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
4d2ea6a6 3031 "<ifname> = remove P2P group interface (terminate group if GO)" },
57faa1ce
JM
3032 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
3033 "= add a new P2P group (local end as GO)" },
3034 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
3035 "<addr> <method> = request provisioning discovery" },
3036 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
3037 cli_cmd_flag_none,
3038 "= get the passphrase for a group (GO only)" },
3039 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3040 cli_cmd_flag_none,
3041 "<addr> <TLVs> = schedule service discovery request" },
3042 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3043 cli_cmd_flag_none,
3044 "<id> = cancel pending service discovery request" },
3045 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
3046 cli_cmd_flag_none,
3047 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3048 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
3049 cli_cmd_flag_none,
3050 "= indicate change in local services" },
3051 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
3052 cli_cmd_flag_none,
3053 "<external> = set external processing of service discovery" },
3054 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
3055 cli_cmd_flag_none,
3056 "= remove all stored service entries" },
3057 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
3058 cli_cmd_flag_none,
3059 "<bonjour|upnp> <query|version> <response|service> = add a local "
3060 "service" },
3061 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
3062 cli_cmd_flag_none,
3063 "<bonjour|upnp> <query|version> [|service] = remove a local "
3064 "service" },
3065 { "p2p_reject", wpa_cli_cmd_p2p_reject,
3066 cli_cmd_flag_none,
3067 "<addr> = reject connection attempts from a specific peer" },
3068 { "p2p_invite", wpa_cli_cmd_p2p_invite,
3069 cli_cmd_flag_none,
3070 "<cmd> [peer=addr] = invite peer" },
3071 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
3072 "[discovered] = list known (optionally, only fully discovered) P2P "
3073 "peers" },
3074 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
3075 "<address> = show information about known P2P peer" },
3076 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
3077 "<field> <value> = set a P2P parameter" },
3078 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
3079 "= flush P2P state" },
59eba7a2
JM
3080 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
3081 "= cancel P2P group formation" },
9d562b79
SS
3082 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
3083 "<address> = unauthorize a peer" },
57faa1ce
JM
3084 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
3085 "[<duration> <interval>] [<duration> <interval>] = request GO "
3086 "presence" },
3087 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
3088 "[<period> <interval>] = set extended listen timing" },
3089#endif /* CONFIG_P2P */
afc064fe
JM
3090
3091#ifdef CONFIG_INTERWORKING
3092 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
3093 "= fetch ANQP information for all APs" },
3094 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
3095 "= stop fetch_anqp operation" },
b02fe7ff
JM
3096 { "interworking_select", wpa_cli_cmd_interworking_select,
3097 cli_cmd_flag_none,
3098 "[auto] = perform Interworking network selection" },
3099 { "interworking_connect", wpa_cli_cmd_interworking_connect,
3100 cli_cmd_flag_none,
3101 "<BSSID> = connect using Interworking credentials" },
afc064fe
JM
3102 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
3103 "<addr> <info id>[,<info id>]... = request ANQP information" },
3104#endif /* CONFIG_INTERWORKING */
0d0a8ca1
AC
3105 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
3106 "<0/1> = disable/enable automatic reconnection" },
281ff0aa
GP
3107 { "tdls_discover", wpa_cli_cmd_tdls_discover,
3108 cli_cmd_flag_none,
3109 "<addr> = request TDLS discovery with <addr>" },
3110 { "tdls_setup", wpa_cli_cmd_tdls_setup,
3111 cli_cmd_flag_none,
3112 "<addr> = request TDLS setup with <addr>" },
3113 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
3114 cli_cmd_flag_none,
3115 "<addr> = tear down TDLS with <addr>" },
60b24b0d
DS
3116 { "signal_poll", wpa_cli_cmd_signal_poll,
3117 cli_cmd_flag_none,
3118 "= get signal parameters" },
9482426e
JM
3119 { "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none,
3120 "= trigger IEEE 802.1X/EAPOL reauthentication" },
dfa141b1 3121 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
3122};
3123
3124
dfa141b1
ER
3125/*
3126 * Prints command usage, lines are padded with the specified string.
3127 */
3128static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3129{
3130 char c;
3131 size_t n;
3132
3133 printf("%s%s ", pad, cmd->cmd);
3134 for (n = 0; (c = cmd->usage[n]); n++) {
3135 printf("%c", c);
3136 if (c == '\n')
3137 printf("%s", pad);
3138 }
3139 printf("\n");
3140}
3141
3142
3143static void print_help(void)
3144{
3145 int n;
3146 printf("commands:\n");
3147 for (n = 0; wpa_cli_commands[n].cmd; n++)
3148 print_cmd_help(&wpa_cli_commands[n], " ");
3149}
3150
3151
e8ecb5fb 3152static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
40fd868c
ER
3153{
3154 const char *c, *delim;
3155 int n;
3156 size_t len;
3157
3158 delim = os_strchr(cmd, ' ');
3159 if (delim)
3160 len = delim - cmd;
3161 else
3162 len = os_strlen(cmd);
3163
3164 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3165 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3166 return (wpa_cli_commands[n].flags &
3167 cli_cmd_flag_sensitive);
3168 }
3169 return 0;
3170}
e8ecb5fb
JM
3171
3172
3173static char ** wpa_list_cmd_list(void)
3174{
3175 char **res;
3176 int i, count;
3177
3178 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3179 res = os_zalloc(count * sizeof(char *));
3180 if (res == NULL)
3181 return NULL;
3182
3183 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3184 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3185 if (res[i] == NULL)
3186 break;
3187 }
3188
3189 return res;
3190}
3191
3192
3193static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3194 int pos)
3195{
3196 int i;
3197
a624f20b
JM
3198 if (os_strcasecmp(cmd, "bss") == 0)
3199 return wpa_cli_complete_bss(str, pos);
3200#ifdef CONFIG_P2P
3201 if (os_strcasecmp(cmd, "p2p_connect") == 0)
3202 return wpa_cli_complete_p2p_connect(str, pos);
3203 if (os_strcasecmp(cmd, "p2p_peer") == 0)
3204 return wpa_cli_complete_p2p_peer(str, pos);
76788542
JM
3205 if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3206 return wpa_cli_complete_p2p_group_remove(str, pos);
a624f20b
JM
3207#endif /* CONFIG_P2P */
3208
e8ecb5fb
JM
3209 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3210 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3211 edit_clear_line();
3212 printf("\r%s\n", wpa_cli_commands[i].usage);
3213 edit_redraw();
3214 break;
3215 }
3216 }
3217
3218 return NULL;
3219}
3220
3221
3222static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3223{
3224 char **res;
3225 const char *end;
3226 char *cmd;
3227
3228 end = os_strchr(str, ' ');
3229 if (end == NULL || str + pos < end)
3230 return wpa_list_cmd_list();
3231
3232 cmd = os_malloc(pos + 1);
3233 if (cmd == NULL)
3234 return NULL;
3235 os_memcpy(cmd, str, pos);
3236 cmd[end - str] = '\0';
3237 res = wpa_cli_cmd_completion(cmd, str, pos);
3238 os_free(cmd);
3239 return res;
3240}
40fd868c
ER
3241
3242
6fc6879b
JM
3243static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3244{
3245 struct wpa_cli_cmd *cmd, *match = NULL;
3246 int count;
3247 int ret = 0;
3248
3249 count = 0;
3250 cmd = wpa_cli_commands;
3251 while (cmd->cmd) {
3252 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3253 {
3254 match = cmd;
3255 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3256 /* we have an exact match */
3257 count = 1;
3258 break;
3259 }
3260 count++;
3261 }
3262 cmd++;
3263 }
3264
3265 if (count > 1) {
3266 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3267 cmd = wpa_cli_commands;
3268 while (cmd->cmd) {
3269 if (os_strncasecmp(cmd->cmd, argv[0],
3270 os_strlen(argv[0])) == 0) {
3271 printf(" %s", cmd->cmd);
3272 }
3273 cmd++;
3274 }
3275 printf("\n");
3276 ret = 1;
3277 } else if (count == 0) {
3278 printf("Unknown command '%s'\n", argv[0]);
3279 ret = 1;
3280 } else {
3281 ret = match->handler(ctrl, argc - 1, &argv[1]);
3282 }
3283
3284 return ret;
3285}
3286
3287
3288static int str_match(const char *a, const char *b)
3289{
3290 return os_strncmp(a, b, os_strlen(b)) == 0;
3291}
3292
3293
3294static int wpa_cli_exec(const char *program, const char *arg1,
3295 const char *arg2)
3296{
3297 char *cmd;
3298 size_t len;
3299 int res;
308a4ec8 3300 int ret = 0;
6fc6879b
JM
3301
3302 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3303 cmd = os_malloc(len);
3304 if (cmd == NULL)
3305 return -1;
3306 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3307 if (res < 0 || (size_t) res >= len) {
3308 os_free(cmd);
3309 return -1;
3310 }
3311 cmd[len - 1] = '\0';
3312#ifndef _WIN32_WCE
308a4ec8
JM
3313 if (system(cmd) < 0)
3314 ret = -1;
6fc6879b
JM
3315#endif /* _WIN32_WCE */
3316 os_free(cmd);
3317
308a4ec8 3318 return ret;
6fc6879b
JM
3319}
3320
3321
3322static void wpa_cli_action_process(const char *msg)
3323{
3324 const char *pos;
3325 char *copy = NULL, *id, *pos2;
3326
3327 pos = msg;
3328 if (*pos == '<') {
3329 /* skip priority */
3330 pos = os_strchr(pos, '>');
3331 if (pos)
3332 pos++;
3333 else
3334 pos = msg;
3335 }
3336
3337 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3338 int new_id = -1;
3339 os_unsetenv("WPA_ID");
3340 os_unsetenv("WPA_ID_STR");
3341 os_unsetenv("WPA_CTRL_DIR");
3342
3343 pos = os_strstr(pos, "[id=");
3344 if (pos)
3345 copy = os_strdup(pos + 4);
3346
3347 if (copy) {
3348 pos2 = id = copy;
3349 while (*pos2 && *pos2 != ' ')
3350 pos2++;
3351 *pos2++ = '\0';
3352 new_id = atoi(id);
3353 os_setenv("WPA_ID", id, 1);
3354 while (*pos2 && *pos2 != '=')
3355 pos2++;
3356 if (*pos2 == '=')
3357 pos2++;
3358 id = pos2;
3359 while (*pos2 && *pos2 != ']')
3360 pos2++;
3361 *pos2 = '\0';
3362 os_setenv("WPA_ID_STR", id, 1);
3363 os_free(copy);
3364 }
3365
3366 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3367
3368 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3369 wpa_cli_connected = 1;
3370 wpa_cli_last_id = new_id;
3371 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3372 }
3373 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3374 if (wpa_cli_connected) {
3375 wpa_cli_connected = 0;
3376 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3377 }
42f0101b
JM
3378 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3379 wpa_cli_exec(action_file, ctrl_ifname, pos);
3380 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3381 wpa_cli_exec(action_file, ctrl_ifname, pos);
72044390
JM
3382 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3383 wpa_cli_exec(action_file, ctrl_ifname, pos);
3384 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3385 wpa_cli_exec(action_file, ctrl_ifname, pos);
e670738a
DS
3386 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3387 wpa_cli_exec(action_file, ctrl_ifname, pos);
876103dc
AC
3388 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3389 wpa_cli_exec(action_file, ctrl_ifname, pos);
3390 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3391 wpa_cli_exec(action_file, ctrl_ifname, pos);
653c4893
NKG
3392 } else if (str_match(pos, AP_STA_CONNECTED)) {
3393 wpa_cli_exec(action_file, ctrl_ifname, pos);
3394 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3395 wpa_cli_exec(action_file, ctrl_ifname, pos);
6fc6879b
JM
3396 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3397 printf("wpa_supplicant is terminating - stop monitoring\n");
3398 wpa_cli_quit = 1;
3399 }
3400}
3401
3402
3403#ifndef CONFIG_ANSI_C_EXTRA
3404static void wpa_cli_action_cb(char *msg, size_t len)
3405{
3406 wpa_cli_action_process(msg);
3407}
3408#endif /* CONFIG_ANSI_C_EXTRA */
3409
3410
3411static void wpa_cli_reconnect(void)
3412{
3413 wpa_cli_close_connection();
4a3ade4e 3414 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
3415}
3416
3417
a624f20b
JM
3418static void cli_event(const char *str)
3419{
3420 const char *start, *s;
3421
3422 start = os_strchr(str, '>');
3423 if (start == NULL)
3424 return;
3425
3426 start++;
3427
3428 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3429 s = os_strchr(start, ' ');
3430 if (s == NULL)
3431 return;
3432 s = os_strchr(s + 1, ' ');
3433 if (s == NULL)
3434 return;
3435 cli_txt_list_add(&bsses, s + 1);
3436 return;
3437 }
3438
3439 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3440 s = os_strchr(start, ' ');
3441 if (s == NULL)
3442 return;
3443 s = os_strchr(s + 1, ' ');
3444 if (s == NULL)
3445 return;
3446 cli_txt_list_del_addr(&bsses, s + 1);
3447 return;
3448 }
3449
3450#ifdef CONFIG_P2P
3451 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3452 s = os_strstr(start, " p2p_dev_addr=");
3453 if (s == NULL)
3454 return;
3455 cli_txt_list_add_addr(&p2p_peers, s + 14);
3456 return;
3457 }
3458
3459 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3460 s = os_strstr(start, " p2p_dev_addr=");
3461 if (s == NULL)
3462 return;
3463 cli_txt_list_del_addr(&p2p_peers, s + 14);
3464 return;
3465 }
76788542
JM
3466
3467 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3468 s = os_strchr(start, ' ');
3469 if (s == NULL)
3470 return;
3471 cli_txt_list_add_word(&p2p_groups, s + 1);
3472 return;
3473 }
3474
3475 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3476 s = os_strchr(start, ' ');
3477 if (s == NULL)
3478 return;
3479 cli_txt_list_del_word(&p2p_groups, s + 1);
3480 return;
3481 }
a624f20b
JM
3482#endif /* CONFIG_P2P */
3483}
3484
3485
cd101567 3486static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
6fc6879b 3487{
6fc6879b
JM
3488 if (ctrl_conn == NULL) {
3489 wpa_cli_reconnect();
3490 return;
3491 }
3492 while (wpa_ctrl_pending(ctrl) > 0) {
3493 char buf[256];
3494 size_t len = sizeof(buf) - 1;
3495 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3496 buf[len] = '\0';
3497 if (action_monitor)
3498 wpa_cli_action_process(buf);
3499 else {
a624f20b 3500 cli_event(buf);
f3f0f648 3501 if (wpa_cli_show_event(buf)) {
82a855bd 3502 edit_clear_line();
cd101567 3503 printf("\r%s\n", buf);
bdc45634 3504 edit_redraw();
f3f0f648 3505 }
6fc6879b
JM
3506 }
3507 } else {
3508 printf("Could not read pending message.\n");
3509 break;
3510 }
3511 }
3512
3513 if (wpa_ctrl_pending(ctrl) < 0) {
3514 printf("Connection to wpa_supplicant lost - trying to "
3515 "reconnect\n");
3516 wpa_cli_reconnect();
3517 }
3518}
3519
6f1c6549
JM
3520#define max_args 10
3521
3522static int tokenize_cmd(char *cmd, char *argv[])
3523{
3524 char *pos;
3525 int argc = 0;
3526
3527 pos = cmd;
3528 for (;;) {
3529 while (*pos == ' ')
3530 pos++;
3531 if (*pos == '\0')
3532 break;
3533 argv[argc] = pos;
3534 argc++;
3535 if (argc == max_args)
3536 break;
3537 if (*pos == '"') {
3538 char *pos2 = os_strrchr(pos, '"');
3539 if (pos2)
3540 pos = pos2 + 1;
3541 }
3542 while (*pos != '\0' && *pos != ' ')
3543 pos++;
3544 if (*pos == ' ')
3545 *pos++ = '\0';
3546 }
3547
3548 return argc;
3549}
3550
3551
cd101567
JM
3552static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3553{
3554 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3555 printf("Connection to wpa_supplicant lost - trying to "
3556 "reconnect\n");
3557 wpa_cli_close_connection();
3558 }
3559 if (!ctrl_conn)
3560 wpa_cli_reconnect();
3561 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3562}
3563
3564
3565static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3566{
3567 eloop_terminate();
3568}
3569
3570
3571static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3572{
3573 wpa_cli_recv_pending(mon_conn, 0);
3574}
3575
3576
82a855bd 3577static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
aee680e8
JM
3578{
3579 char *argv[max_args];
3580 int argc;
82a855bd 3581 argc = tokenize_cmd(cmd, argv);
aee680e8
JM
3582 if (argc)
3583 wpa_request(ctrl_conn, argc, argv);
aee680e8
JM
3584}
3585
3586
82a855bd 3587static void wpa_cli_edit_eof_cb(void *ctx)
6f1c6549 3588{
82a855bd 3589 eloop_terminate();
cd101567
JM
3590}
3591
3592
3593static void wpa_cli_interactive(void)
3594{
8953e968 3595 char *home, *hfile = NULL;
aee680e8 3596
cd101567 3597 printf("\nInteractive mode\n\n");
cd101567 3598
8953e968
JM
3599 home = getenv("HOME");
3600 if (home) {
3601 const char *fname = ".wpa_cli_history";
3602 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3603 hfile = os_malloc(hfile_len);
3604 if (hfile)
3605 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3606 }
3607
cd101567 3608 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
8953e968
JM
3609 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3610 wpa_cli_edit_completion_cb, NULL, hfile);
cd101567
JM
3611 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3612
cd101567
JM
3613 eloop_run();
3614
a624f20b 3615 cli_txt_list_flush(&p2p_peers);
76788542 3616 cli_txt_list_flush(&p2p_groups);
a624f20b 3617 cli_txt_list_flush(&bsses);
8953e968
JM
3618 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3619 os_free(hfile);
cd101567
JM
3620 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3621 wpa_cli_close_connection();
6f1c6549
JM
3622}
3623
6fc6879b
JM
3624
3625static void wpa_cli_action(struct wpa_ctrl *ctrl)
3626{
3627#ifdef CONFIG_ANSI_C_EXTRA
3628 /* TODO: ANSI C version(?) */
3629 printf("Action processing not supported in ANSI C build.\n");
3630#else /* CONFIG_ANSI_C_EXTRA */
3631 fd_set rfds;
3632 int fd, res;
3633 struct timeval tv;
3634 char buf[256]; /* note: large enough to fit in unsolicited messages */
3635 size_t len;
3636
3637 fd = wpa_ctrl_get_fd(ctrl);
3638
3639 while (!wpa_cli_quit) {
3640 FD_ZERO(&rfds);
3641 FD_SET(fd, &rfds);
1cc84c1c 3642 tv.tv_sec = ping_interval;
6fc6879b
JM
3643 tv.tv_usec = 0;
3644 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3645 if (res < 0 && errno != EINTR) {
3646 perror("select");
3647 break;
3648 }
3649
3650 if (FD_ISSET(fd, &rfds))
cd101567 3651 wpa_cli_recv_pending(ctrl, 1);
6fc6879b
JM
3652 else {
3653 /* verify that connection is still working */
3654 len = sizeof(buf) - 1;
3655 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3656 wpa_cli_action_cb) < 0 ||
3657 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3658 printf("wpa_supplicant did not reply to PING "
3659 "command - exiting\n");
3660 break;
3661 }
3662 }
3663 }
3664#endif /* CONFIG_ANSI_C_EXTRA */
3665}
3666
3667
3668static void wpa_cli_cleanup(void)
3669{
3670 wpa_cli_close_connection();
3671 if (pid_file)
3672 os_daemonize_terminate(pid_file);
3673
3674 os_program_deinit();
3675}
3676
3677static void wpa_cli_terminate(int sig)
3678{
3679 wpa_cli_cleanup();
3680 exit(0);
3681}
3682
3683
6fc6879b
JM
3684static char * wpa_cli_get_default_ifname(void)
3685{
3686 char *ifname = NULL;
3687
3688#ifdef CONFIG_CTRL_IFACE_UNIX
3689 struct dirent *dent;
3690 DIR *dir = opendir(ctrl_iface_dir);
b1001e4c
DS
3691 if (!dir) {
3692#ifdef ANDROID
3693 char ifprop[PROPERTY_VALUE_MAX];
3694 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3695 ifname = os_strdup(ifprop);
3696 printf("Using interface '%s'\n", ifname);
3697 return ifname;
3698 }
3699#endif /* ANDROID */
6fc6879b 3700 return NULL;
b1001e4c 3701 }
6fc6879b
JM
3702 while ((dent = readdir(dir))) {
3703#ifdef _DIRENT_HAVE_D_TYPE
3704 /*
3705 * Skip the file if it is not a socket. Also accept
3706 * DT_UNKNOWN (0) in case the C library or underlying
3707 * file system does not support d_type.
3708 */
3709 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3710 continue;
3711#endif /* _DIRENT_HAVE_D_TYPE */
3712 if (os_strcmp(dent->d_name, ".") == 0 ||
3713 os_strcmp(dent->d_name, "..") == 0)
3714 continue;
3715 printf("Selected interface '%s'\n", dent->d_name);
3716 ifname = os_strdup(dent->d_name);
3717 break;
3718 }
3719 closedir(dir);
3720#endif /* CONFIG_CTRL_IFACE_UNIX */
3721
3722#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3723 char buf[2048], *pos;
3724 size_t len;
3725 struct wpa_ctrl *ctrl;
3726 int ret;
3727
3728 ctrl = wpa_ctrl_open(NULL);
3729 if (ctrl == NULL)
3730 return NULL;
3731
3732 len = sizeof(buf) - 1;
3733 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3734 if (ret >= 0) {
3735 buf[len] = '\0';
3736 pos = os_strchr(buf, '\n');
3737 if (pos)
3738 *pos = '\0';
3739 ifname = os_strdup(buf);
3740 }
3741 wpa_ctrl_close(ctrl);
3742#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3743
3744 return ifname;
3745}
3746
3747
3748int main(int argc, char *argv[])
3749{
6fc6879b
JM
3750 int warning_displayed = 0;
3751 int c;
3752 int daemonize = 0;
3753 int ret = 0;
3754 const char *global = NULL;
3755
3756 if (os_program_init())
3757 return -1;
3758
3759 for (;;) {
1cc84c1c 3760 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
3761 if (c < 0)
3762 break;
3763 switch (c) {
3764 case 'a':
3765 action_file = optarg;
3766 break;
3767 case 'B':
3768 daemonize = 1;
3769 break;
3770 case 'g':
3771 global = optarg;
3772 break;
1cc84c1c
JM
3773 case 'G':
3774 ping_interval = atoi(optarg);
3775 break;
6fc6879b
JM
3776 case 'h':
3777 usage();
3778 return 0;
3779 case 'v':
3780 printf("%s\n", wpa_cli_version);
3781 return 0;
3782 case 'i':
3783 os_free(ctrl_ifname);
3784 ctrl_ifname = os_strdup(optarg);
3785 break;
3786 case 'p':
3787 ctrl_iface_dir = optarg;
3788 break;
3789 case 'P':
3790 pid_file = optarg;
3791 break;
3792 default:
3793 usage();
3794 return -1;
3795 }
3796 }
3797
3798 interactive = (argc == optind) && (action_file == NULL);
3799
3800 if (interactive)
3801 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3802
cd101567
JM
3803 if (eloop_init())
3804 return -1;
3805
6fc6879b
JM
3806 if (global) {
3807#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3808 ctrl_conn = wpa_ctrl_open(NULL);
3809#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3810 ctrl_conn = wpa_ctrl_open(global);
3811#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3812 if (ctrl_conn == NULL) {
5a49459e
BG
3813 fprintf(stderr, "Failed to connect to wpa_supplicant "
3814 "global interface: %s error: %s\n",
3815 global, strerror(errno));
6fc6879b
JM
3816 return -1;
3817 }
3818 }
3819
6fc6879b
JM
3820#ifndef _WIN32_WCE
3821 signal(SIGINT, wpa_cli_terminate);
3822 signal(SIGTERM, wpa_cli_terminate);
3823#endif /* _WIN32_WCE */
6fc6879b 3824
4a3ade4e
JM
3825 if (ctrl_ifname == NULL)
3826 ctrl_ifname = wpa_cli_get_default_ifname();
3827
3828 if (interactive) {
3829 for (; !global;) {
3830 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3831 if (warning_displayed)
3832 printf("Connection established.\n");
3833 break;
3834 }
3835
3836 if (!warning_displayed) {
5a49459e
BG
3837 printf("Could not connect to wpa_supplicant: "
3838 "%s - re-trying\n", ctrl_ifname);
4a3ade4e
JM
3839 warning_displayed = 1;
3840 }
3841 os_sleep(1, 0);
3842 continue;
3843 }
3844 } else {
3845 if (!global &&
3846 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
5a49459e
BG
3847 fprintf(stderr, "Failed to connect to non-global "
3848 "ctrl_ifname: %s error: %s\n",
3849 ctrl_ifname, strerror(errno));
4a3ade4e
JM
3850 return -1;
3851 }
3852
3853 if (action_file) {
3854 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3855 wpa_cli_attached = 1;
3856 } else {
3857 printf("Warning: Failed to attach to "
3858 "wpa_supplicant.\n");
6fc6879b 3859 return -1;
4a3ade4e 3860 }
6fc6879b
JM
3861 }
3862 }
3863
3864 if (daemonize && os_daemonize(pid_file))
3865 return -1;
3866
3867 if (interactive)
3868 wpa_cli_interactive();
3869 else if (action_file)
3870 wpa_cli_action(ctrl_conn);
3871 else
3872 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3873
3874 os_free(ctrl_ifname);
cd101567 3875 eloop_destroy();
6fc6879b
JM
3876 wpa_cli_cleanup();
3877
3878 return ret;
3879}
3880
3881#else /* CONFIG_CTRL_IFACE */
3882int main(int argc, char *argv[])
3883{
3884 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3885 return -1;
3886}
3887#endif /* CONFIG_CTRL_IFACE */