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