blob: bed13dd9cf3d6df2eb0dd2f2879615fce95984f1 [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
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700717static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
718{
719 char cmd[256];
720 int res;
721
722 if (argc < 1)
723 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
724 else
725 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
726 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
727 printf("Too long BSS_FLUSH command.\n");
728 return -1;
729 }
730 return wpa_ctrl_command(ctrl, cmd);
731}
732
733
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
735 char *argv[])
736{
737 char cmd[256];
738 int res;
739
740 if (argc != 1) {
741 printf("Invalid STKSTART command: needs one argument "
742 "(Peer STA MAC address)\n");
743 return -1;
744 }
745
746 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
747 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
748 printf("Too long STKSTART command.\n");
749 return -1;
750 }
751 return wpa_ctrl_command(ctrl, cmd);
752}
753
754
755static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
757 char cmd[256];
758 int res;
759
760 if (argc != 1) {
761 printf("Invalid FT_DS command: needs one argument "
762 "(Target AP MAC address)\n");
763 return -1;
764 }
765
766 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
767 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
768 printf("Too long FT_DS command.\n");
769 return -1;
770 }
771 return wpa_ctrl_command(ctrl, cmd);
772}
773
774
775static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
776{
777 char cmd[256];
778 int res;
779
780 if (argc == 0) {
781 /* Any BSSID */
782 return wpa_ctrl_command(ctrl, "WPS_PBC");
783 }
784
785 /* Specific BSSID */
786 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
787 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
788 printf("Too long WPS_PBC command.\n");
789 return -1;
790 }
791 return wpa_ctrl_command(ctrl, cmd);
792}
793
794
795static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
796{
797 char cmd[256];
798 int res;
799
800 if (argc == 0) {
801 printf("Invalid WPS_PIN command: need one or two arguments:\n"
802 "- BSSID: use 'any' to select any\n"
803 "- PIN: optional, used only with devices that have no "
804 "display\n");
805 return -1;
806 }
807
808 if (argc == 1) {
809 /* Use dynamically generated PIN (returned as reply) */
810 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
811 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
812 printf("Too long WPS_PIN command.\n");
813 return -1;
814 }
815 return wpa_ctrl_command(ctrl, cmd);
816 }
817
818 /* Use hardcoded PIN from a label */
819 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
820 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
821 printf("Too long WPS_PIN command.\n");
822 return -1;
823 }
824 return wpa_ctrl_command(ctrl, cmd);
825}
826
827
828static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
829 char *argv[])
830{
831 char cmd[256];
832 int res;
833
834 if (argc != 1 && argc != 2) {
835 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
836 "- PIN to be verified\n");
837 return -1;
838 }
839
840 if (argc == 2)
841 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
842 argv[0], argv[1]);
843 else
844 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
845 argv[0]);
846 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
847 printf("Too long WPS_CHECK_PIN command.\n");
848 return -1;
849 }
850 return wpa_ctrl_command(ctrl, cmd);
851}
852
853
854static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
855 char *argv[])
856{
857 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
858}
859
860
861#ifdef CONFIG_WPS_OOB
862static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
863{
864 char cmd[256];
865 int res;
866
867 if (argc != 3 && argc != 4) {
868 printf("Invalid WPS_OOB command: need three or four "
869 "arguments:\n"
870 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
871 "- PATH: path of OOB device like '/mnt'\n"
872 "- METHOD: OOB method 'pin-e' or 'pin-r', "
873 "'cred'\n"
874 "- DEV_NAME: (only for NFC) device name like "
875 "'pn531'\n");
876 return -1;
877 }
878
879 if (argc == 3)
880 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
881 argv[0], argv[1], argv[2]);
882 else
883 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
884 argv[0], argv[1], argv[2], argv[3]);
885 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
886 printf("Too long WPS_OOB command.\n");
887 return -1;
888 }
889 return wpa_ctrl_command(ctrl, cmd);
890}
891#endif /* CONFIG_WPS_OOB */
892
893
Dmitry Shmidt04949592012-07-19 12:16:46 -0700894#ifdef CONFIG_WPS_NFC
895
896static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
897{
898 char cmd[256];
899 int res;
900
901 if (argc >= 1)
902 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC %s",
903 argv[0]);
904 else
905 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC");
906 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
907 printf("Too long WPS_NFC command.\n");
908 return -1;
909 }
910 return wpa_ctrl_command(ctrl, cmd);
911}
912
913
914static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
915 char *argv[])
916{
917 char cmd[256];
918 int res;
919
920 if (argc != 1) {
921 printf("Invalid WPS_NFC_TOKEN command: need one argument:\n"
922 "format: WPS or NDEF\n");
923 return -1;
924 }
925 if (argc >= 1)
926 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s",
927 argv[0]);
928 else
929 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN");
930 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
931 printf("Too long WPS_NFC_TOKEN command.\n");
932 return -1;
933 }
934 return wpa_ctrl_command(ctrl, cmd);
935}
936
937
938static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
941 int ret;
942 char *buf;
943 size_t buflen;
944
945 if (argc != 1) {
946 printf("Invalid 'wps_nfc_tag_read' command - one argument "
947 "is required.\n");
948 return -1;
949 }
950
951 buflen = 18 + os_strlen(argv[0]);
952 buf = os_malloc(buflen);
953 if (buf == NULL)
954 return -1;
955 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
956
957 ret = wpa_ctrl_command(ctrl, buf);
958 os_free(buf);
959
960 return ret;
961}
962
963#endif /* CONFIG_WPS_NFC */
964
965
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
967{
968 char cmd[256];
969 int res;
970
971 if (argc == 2)
972 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
973 argv[0], argv[1]);
974 else if (argc == 5 || argc == 6) {
975 char ssid_hex[2 * 32 + 1];
976 char key_hex[2 * 64 + 1];
977 int i;
978
979 ssid_hex[0] = '\0';
980 for (i = 0; i < 32; i++) {
981 if (argv[2][i] == '\0')
982 break;
983 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
984 }
985
986 key_hex[0] = '\0';
987 if (argc == 6) {
988 for (i = 0; i < 64; i++) {
989 if (argv[5][i] == '\0')
990 break;
991 os_snprintf(&key_hex[i * 2], 3, "%02x",
992 argv[5][i]);
993 }
994 }
995
996 res = os_snprintf(cmd, sizeof(cmd),
997 "WPS_REG %s %s %s %s %s %s",
998 argv[0], argv[1], ssid_hex, argv[3], argv[4],
999 key_hex);
1000 } else {
1001 printf("Invalid WPS_REG command: need two arguments:\n"
1002 "- BSSID of the target AP\n"
1003 "- AP PIN\n");
1004 printf("Alternatively, six arguments can be used to "
1005 "reconfigure the AP:\n"
1006 "- BSSID of the target AP\n"
1007 "- AP PIN\n"
1008 "- new SSID\n"
1009 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1010 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1011 "- new key\n");
1012 return -1;
1013 }
1014
1015 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1016 printf("Too long WPS_REG command.\n");
1017 return -1;
1018 }
1019 return wpa_ctrl_command(ctrl, cmd);
1020}
1021
1022
1023static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
1024 char *argv[])
1025{
1026 char cmd[256];
1027 int res;
1028
1029 if (argc < 1) {
1030 printf("Invalid WPS_AP_PIN command: needs at least one "
1031 "argument\n");
1032 return -1;
1033 }
1034
1035 if (argc > 2)
1036 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s %s",
1037 argv[0], argv[1], argv[2]);
1038 else if (argc > 1)
1039 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s",
1040 argv[0], argv[1]);
1041 else
1042 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s",
1043 argv[0]);
1044 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1045 printf("Too long WPS_AP_PIN command.\n");
1046 return -1;
1047 }
1048 return wpa_ctrl_command(ctrl, cmd);
1049}
1050
1051
1052static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
1053 char *argv[])
1054{
1055 char cmd[100];
1056 if (argc > 0) {
1057 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
1058 return wpa_ctrl_command(ctrl, cmd);
1059 }
1060 return wpa_ctrl_command(ctrl, "WPS_ER_START");
1061}
1062
1063
1064static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
1065 char *argv[])
1066{
1067 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
1068
1069}
1070
1071
1072static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
1073 char *argv[])
1074{
1075 char cmd[256];
1076 int res;
1077
1078 if (argc < 2) {
1079 printf("Invalid WPS_ER_PIN command: need at least two "
1080 "arguments:\n"
1081 "- UUID: use 'any' to select any\n"
1082 "- PIN: Enrollee PIN\n"
1083 "optional: - Enrollee MAC address\n");
1084 return -1;
1085 }
1086
1087 if (argc > 2)
1088 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
1089 argv[0], argv[1], argv[2]);
1090 else
1091 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
1092 argv[0], argv[1]);
1093 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1094 printf("Too long WPS_ER_PIN command.\n");
1095 return -1;
1096 }
1097 return wpa_ctrl_command(ctrl, cmd);
1098}
1099
1100
1101static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1102 char *argv[])
1103{
1104 char cmd[256];
1105 int res;
1106
1107 if (argc != 1) {
1108 printf("Invalid WPS_ER_PBC command: need one argument:\n"
1109 "- UUID: Specify the Enrollee\n");
1110 return -1;
1111 }
1112
1113 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
1114 argv[0]);
1115 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1116 printf("Too long WPS_ER_PBC command.\n");
1117 return -1;
1118 }
1119 return wpa_ctrl_command(ctrl, cmd);
1120}
1121
1122
1123static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1124 char *argv[])
1125{
1126 char cmd[256];
1127 int res;
1128
1129 if (argc != 2) {
1130 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1131 "- UUID: specify which AP to use\n"
1132 "- PIN: AP PIN\n");
1133 return -1;
1134 }
1135
1136 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
1137 argv[0], argv[1]);
1138 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1139 printf("Too long WPS_ER_LEARN command.\n");
1140 return -1;
1141 }
1142 return wpa_ctrl_command(ctrl, cmd);
1143}
1144
1145
1146static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1147 char *argv[])
1148{
1149 char cmd[256];
1150 int res;
1151
1152 if (argc != 2) {
1153 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1154 "arguments:\n"
1155 "- UUID: specify which AP to use\n"
1156 "- Network configuration id\n");
1157 return -1;
1158 }
1159
1160 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s",
1161 argv[0], argv[1]);
1162 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1163 printf("Too long WPS_ER_SET_CONFIG command.\n");
1164 return -1;
1165 }
1166 return wpa_ctrl_command(ctrl, cmd);
1167}
1168
1169
1170static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1171 char *argv[])
1172{
1173 char cmd[256];
1174 int res;
1175
1176 if (argc == 5 || argc == 6) {
1177 char ssid_hex[2 * 32 + 1];
1178 char key_hex[2 * 64 + 1];
1179 int i;
1180
1181 ssid_hex[0] = '\0';
1182 for (i = 0; i < 32; i++) {
1183 if (argv[2][i] == '\0')
1184 break;
1185 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1186 }
1187
1188 key_hex[0] = '\0';
1189 if (argc == 6) {
1190 for (i = 0; i < 64; i++) {
1191 if (argv[5][i] == '\0')
1192 break;
1193 os_snprintf(&key_hex[i * 2], 3, "%02x",
1194 argv[5][i]);
1195 }
1196 }
1197
1198 res = os_snprintf(cmd, sizeof(cmd),
1199 "WPS_ER_CONFIG %s %s %s %s %s %s",
1200 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1201 key_hex);
1202 } else {
1203 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1204 "- AP UUID\n"
1205 "- AP PIN\n"
1206 "- new SSID\n"
1207 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1208 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1209 "- new key\n");
1210 return -1;
1211 }
1212
1213 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1214 printf("Too long WPS_ER_CONFIG command.\n");
1215 return -1;
1216 }
1217 return wpa_ctrl_command(ctrl, cmd);
1218}
1219
1220
Dmitry Shmidt04949592012-07-19 12:16:46 -07001221#ifdef CONFIG_WPS_NFC
1222static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1223 char *argv[])
1224{
1225 char cmd[256];
1226 int res;
1227
1228 if (argc != 2) {
1229 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1230 "arguments:\n"
1231 "- WPS/NDEF: token format\n"
1232 "- UUID: specify which AP to use\n");
1233 return -1;
1234 }
1235
1236 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_NFC_CONFIG_TOKEN %s %s",
1237 argv[0], argv[1]);
1238 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1239 printf("Too long WPS_ER_NFC_CONFIG_TOKEN command.\n");
1240 return -1;
1241 }
1242 return wpa_ctrl_command(ctrl, cmd);
1243}
1244#endif /* CONFIG_WPS_NFC */
1245
1246
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1248{
1249 char cmd[256];
1250 int res;
1251
1252 if (argc != 1) {
1253 printf("Invalid IBSS_RSN command: needs one argument "
1254 "(Peer STA MAC address)\n");
1255 return -1;
1256 }
1257
1258 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
1259 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1260 printf("Too long IBSS_RSN command.\n");
1261 return -1;
1262 }
1263 return wpa_ctrl_command(ctrl, cmd);
1264}
1265
1266
1267static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1268{
1269 char cmd[256];
1270 int res;
1271
1272 if (argc != 1) {
1273 printf("Invalid LEVEL command: needs one argument (debug "
1274 "level)\n");
1275 return -1;
1276 }
1277 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
1278 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1279 printf("Too long LEVEL command.\n");
1280 return -1;
1281 }
1282 return wpa_ctrl_command(ctrl, cmd);
1283}
1284
1285
1286static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1287{
1288 char cmd[256], *pos, *end;
1289 int i, ret;
1290
1291 if (argc < 2) {
1292 printf("Invalid IDENTITY command: needs two arguments "
1293 "(network id and identity)\n");
1294 return -1;
1295 }
1296
1297 end = cmd + sizeof(cmd);
1298 pos = cmd;
1299 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1300 argv[0], argv[1]);
1301 if (ret < 0 || ret >= end - pos) {
1302 printf("Too long IDENTITY command.\n");
1303 return -1;
1304 }
1305 pos += ret;
1306 for (i = 2; i < argc; i++) {
1307 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1308 if (ret < 0 || ret >= end - pos) {
1309 printf("Too long IDENTITY command.\n");
1310 return -1;
1311 }
1312 pos += ret;
1313 }
1314
1315 return wpa_ctrl_command(ctrl, cmd);
1316}
1317
1318
1319static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1320{
1321 char cmd[256], *pos, *end;
1322 int i, ret;
1323
1324 if (argc < 2) {
1325 printf("Invalid PASSWORD command: needs two arguments "
1326 "(network id and password)\n");
1327 return -1;
1328 }
1329
1330 end = cmd + sizeof(cmd);
1331 pos = cmd;
1332 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1333 argv[0], argv[1]);
1334 if (ret < 0 || ret >= end - pos) {
1335 printf("Too long PASSWORD command.\n");
1336 return -1;
1337 }
1338 pos += ret;
1339 for (i = 2; i < argc; i++) {
1340 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1341 if (ret < 0 || ret >= end - pos) {
1342 printf("Too long PASSWORD command.\n");
1343 return -1;
1344 }
1345 pos += ret;
1346 }
1347
1348 return wpa_ctrl_command(ctrl, cmd);
1349}
1350
1351
1352static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1353 char *argv[])
1354{
1355 char cmd[256], *pos, *end;
1356 int i, ret;
1357
1358 if (argc < 2) {
1359 printf("Invalid NEW_PASSWORD command: needs two arguments "
1360 "(network id and password)\n");
1361 return -1;
1362 }
1363
1364 end = cmd + sizeof(cmd);
1365 pos = cmd;
1366 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1367 argv[0], argv[1]);
1368 if (ret < 0 || ret >= end - pos) {
1369 printf("Too long NEW_PASSWORD command.\n");
1370 return -1;
1371 }
1372 pos += ret;
1373 for (i = 2; i < argc; i++) {
1374 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1375 if (ret < 0 || ret >= end - pos) {
1376 printf("Too long NEW_PASSWORD command.\n");
1377 return -1;
1378 }
1379 pos += ret;
1380 }
1381
1382 return wpa_ctrl_command(ctrl, cmd);
1383}
1384
1385
1386static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1387{
1388 char cmd[256], *pos, *end;
1389 int i, ret;
1390
1391 if (argc < 2) {
1392 printf("Invalid PIN command: needs two arguments "
1393 "(network id and pin)\n");
1394 return -1;
1395 }
1396
1397 end = cmd + sizeof(cmd);
1398 pos = cmd;
1399 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1400 argv[0], argv[1]);
1401 if (ret < 0 || ret >= end - pos) {
1402 printf("Too long PIN command.\n");
1403 return -1;
1404 }
1405 pos += ret;
1406 for (i = 2; i < argc; i++) {
1407 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1408 if (ret < 0 || ret >= end - pos) {
1409 printf("Too long PIN command.\n");
1410 return -1;
1411 }
1412 pos += ret;
1413 }
1414 return wpa_ctrl_command(ctrl, cmd);
1415}
1416
1417
1418static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1419{
1420 char cmd[256], *pos, *end;
1421 int i, ret;
1422
1423 if (argc < 2) {
1424 printf("Invalid OTP command: needs two arguments (network "
1425 "id and password)\n");
1426 return -1;
1427 }
1428
1429 end = cmd + sizeof(cmd);
1430 pos = cmd;
1431 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1432 argv[0], argv[1]);
1433 if (ret < 0 || ret >= end - pos) {
1434 printf("Too long OTP command.\n");
1435 return -1;
1436 }
1437 pos += ret;
1438 for (i = 2; i < argc; i++) {
1439 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1440 if (ret < 0 || ret >= end - pos) {
1441 printf("Too long OTP command.\n");
1442 return -1;
1443 }
1444 pos += ret;
1445 }
1446
1447 return wpa_ctrl_command(ctrl, cmd);
1448}
1449
1450
1451static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1452 char *argv[])
1453{
1454 char cmd[256], *pos, *end;
1455 int i, ret;
1456
1457 if (argc < 2) {
1458 printf("Invalid PASSPHRASE command: needs two arguments "
1459 "(network id and passphrase)\n");
1460 return -1;
1461 }
1462
1463 end = cmd + sizeof(cmd);
1464 pos = cmd;
1465 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1466 argv[0], argv[1]);
1467 if (ret < 0 || ret >= end - pos) {
1468 printf("Too long PASSPHRASE command.\n");
1469 return -1;
1470 }
1471 pos += ret;
1472 for (i = 2; i < argc; i++) {
1473 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1474 if (ret < 0 || ret >= end - pos) {
1475 printf("Too long PASSPHRASE command.\n");
1476 return -1;
1477 }
1478 pos += ret;
1479 }
1480
1481 return wpa_ctrl_command(ctrl, cmd);
1482}
1483
1484
1485static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1486{
1487 char cmd[256], *pos, *end;
1488 int i, ret;
1489
1490 if (argc < 2) {
1491 printf("Invalid BSSID command: needs two arguments (network "
1492 "id and BSSID)\n");
1493 return -1;
1494 }
1495
1496 end = cmd + sizeof(cmd);
1497 pos = cmd;
1498 ret = os_snprintf(pos, end - pos, "BSSID");
1499 if (ret < 0 || ret >= end - pos) {
1500 printf("Too long BSSID command.\n");
1501 return -1;
1502 }
1503 pos += ret;
1504 for (i = 0; i < argc; i++) {
1505 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1506 if (ret < 0 || ret >= end - pos) {
1507 printf("Too long BSSID command.\n");
1508 return -1;
1509 }
1510 pos += ret;
1511 }
1512
1513 return wpa_ctrl_command(ctrl, cmd);
1514}
1515
1516
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001517static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1518{
1519 char cmd[256], *pos, *end;
1520 int i, ret;
1521
1522 end = cmd + sizeof(cmd);
1523 pos = cmd;
1524 ret = os_snprintf(pos, end - pos, "BLACKLIST");
1525 if (ret < 0 || ret >= end - pos) {
1526 printf("Too long BLACKLIST command.\n");
1527 return -1;
1528 }
1529 pos += ret;
1530 for (i = 0; i < argc; i++) {
1531 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1532 if (ret < 0 || ret >= end - pos) {
1533 printf("Too long BLACKLIST command.\n");
1534 return -1;
1535 }
1536 pos += ret;
1537 }
1538
1539 return wpa_ctrl_command(ctrl, cmd);
1540}
1541
1542
1543static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1544{
1545 char cmd[256], *pos, *end;
1546 int i, ret;
1547
1548 end = cmd + sizeof(cmd);
1549 pos = cmd;
1550 ret = os_snprintf(pos, end - pos, "LOG_LEVEL");
1551 if (ret < 0 || ret >= end - pos) {
1552 printf("Too long LOG_LEVEL command.\n");
1553 return -1;
1554 }
1555 pos += ret;
1556 for (i = 0; i < argc; i++) {
1557 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1558 if (ret < 0 || ret >= end - pos) {
1559 printf("Too long LOG_LEVEL command.\n");
1560 return -1;
1561 }
1562 pos += ret;
1563 }
1564
1565 return wpa_ctrl_command(ctrl, cmd);
1566}
1567
1568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001569static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1570 char *argv[])
1571{
1572 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1573}
1574
1575
1576static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1577 char *argv[])
1578{
1579 char cmd[32];
1580 int res;
1581
1582 if (argc < 1) {
1583 printf("Invalid SELECT_NETWORK command: needs one argument "
1584 "(network id)\n");
1585 return -1;
1586 }
1587
1588 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1589 if (res < 0 || (size_t) res >= sizeof(cmd))
1590 return -1;
1591 cmd[sizeof(cmd) - 1] = '\0';
1592
1593 return wpa_ctrl_command(ctrl, cmd);
1594}
1595
1596
1597static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1598 char *argv[])
1599{
1600 char cmd[32];
1601 int res;
1602
1603 if (argc < 1) {
1604 printf("Invalid ENABLE_NETWORK command: needs one argument "
1605 "(network id)\n");
1606 return -1;
1607 }
1608
Dmitry Shmidt04949592012-07-19 12:16:46 -07001609 if (argc > 1)
1610 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s %s",
1611 argv[0], argv[1]);
1612 else
1613 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s",
1614 argv[0]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001615 if (res < 0 || (size_t) res >= sizeof(cmd))
1616 return -1;
1617 cmd[sizeof(cmd) - 1] = '\0';
1618
1619 return wpa_ctrl_command(ctrl, cmd);
1620}
1621
1622
1623static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1624 char *argv[])
1625{
1626 char cmd[32];
1627 int res;
1628
1629 if (argc < 1) {
1630 printf("Invalid DISABLE_NETWORK command: needs one argument "
1631 "(network id)\n");
1632 return -1;
1633 }
1634
1635 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1636 if (res < 0 || (size_t) res >= sizeof(cmd))
1637 return -1;
1638 cmd[sizeof(cmd) - 1] = '\0';
1639
1640 return wpa_ctrl_command(ctrl, cmd);
1641}
1642
1643
1644static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1645 char *argv[])
1646{
1647 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1648}
1649
1650
1651static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1652 char *argv[])
1653{
1654 char cmd[32];
1655 int res;
1656
1657 if (argc < 1) {
1658 printf("Invalid REMOVE_NETWORK command: needs one argument "
1659 "(network id)\n");
1660 return -1;
1661 }
1662
1663 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1664 if (res < 0 || (size_t) res >= sizeof(cmd))
1665 return -1;
1666 cmd[sizeof(cmd) - 1] = '\0';
1667
1668 return wpa_ctrl_command(ctrl, cmd);
1669}
1670
1671
1672static void wpa_cli_show_network_variables(void)
1673{
1674 printf("set_network variables:\n"
1675 " ssid (network name, SSID)\n"
1676 " psk (WPA passphrase or pre-shared key)\n"
1677 " key_mgmt (key management protocol)\n"
1678 " identity (EAP identity)\n"
1679 " password (EAP password)\n"
1680 " ...\n"
1681 "\n"
1682 "Note: Values are entered in the same format as the "
1683 "configuration file is using,\n"
1684 "i.e., strings values need to be inside double quotation "
1685 "marks.\n"
1686 "For example: set_network 1 ssid \"network name\"\n"
1687 "\n"
1688 "Please see wpa_supplicant.conf documentation for full list "
1689 "of\navailable variables.\n");
1690}
1691
1692
1693static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1694 char *argv[])
1695{
1696 char cmd[256];
1697 int res;
1698
1699 if (argc == 0) {
1700 wpa_cli_show_network_variables();
1701 return 0;
1702 }
1703
1704 if (argc != 3) {
1705 printf("Invalid SET_NETWORK command: needs three arguments\n"
1706 "(network id, variable name, and value)\n");
1707 return -1;
1708 }
1709
1710 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1711 argv[0], argv[1], argv[2]);
1712 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1713 printf("Too long SET_NETWORK command.\n");
1714 return -1;
1715 }
1716 return wpa_ctrl_command(ctrl, cmd);
1717}
1718
1719
1720static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1721 char *argv[])
1722{
1723 char cmd[256];
1724 int res;
1725
1726 if (argc == 0) {
1727 wpa_cli_show_network_variables();
1728 return 0;
1729 }
1730
1731 if (argc != 2) {
1732 printf("Invalid GET_NETWORK command: needs two arguments\n"
1733 "(network id and variable name)\n");
1734 return -1;
1735 }
1736
1737 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1738 argv[0], argv[1]);
1739 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1740 printf("Too long GET_NETWORK command.\n");
1741 return -1;
1742 }
1743 return wpa_ctrl_command(ctrl, cmd);
1744}
1745
1746
Dmitry Shmidt04949592012-07-19 12:16:46 -07001747static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1748 char *argv[])
1749{
1750 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1751}
1752
1753
1754static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1755{
1756 return wpa_ctrl_command(ctrl, "ADD_CRED");
1757}
1758
1759
1760static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1761 char *argv[])
1762{
1763 char cmd[32];
1764 int res;
1765
1766 if (argc < 1) {
1767 printf("Invalid REMOVE_CRED command: needs one argument "
1768 "(cred id)\n");
1769 return -1;
1770 }
1771
1772 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_CRED %s", argv[0]);
1773 if (res < 0 || (size_t) res >= sizeof(cmd))
1774 return -1;
1775 cmd[sizeof(cmd) - 1] = '\0';
1776
1777 return wpa_ctrl_command(ctrl, cmd);
1778}
1779
1780
1781static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1782{
1783 char cmd[256];
1784 int res;
1785
1786 if (argc != 3) {
1787 printf("Invalid SET_CRED command: needs three arguments\n"
1788 "(cred id, variable name, and value)\n");
1789 return -1;
1790 }
1791
1792 res = os_snprintf(cmd, sizeof(cmd), "SET_CRED %s %s %s",
1793 argv[0], argv[1], argv[2]);
1794 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1795 printf("Too long SET_CRED command.\n");
1796 return -1;
1797 }
1798 return wpa_ctrl_command(ctrl, cmd);
1799}
1800
1801
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1803 char *argv[])
1804{
1805 return wpa_ctrl_command(ctrl, "DISCONNECT");
1806}
1807
1808
1809static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1810 char *argv[])
1811{
1812 return wpa_ctrl_command(ctrl, "RECONNECT");
1813}
1814
1815
1816static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1817 char *argv[])
1818{
1819 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1820}
1821
1822
1823static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1824{
1825 return wpa_ctrl_command(ctrl, "SCAN");
1826}
1827
1828
1829static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1830 char *argv[])
1831{
1832 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1833}
1834
1835
1836static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1837{
1838 char cmd[64];
1839 int res;
1840
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07001841 if (argc < 1) {
1842 printf("Invalid BSS command: need at least one argument"
1843 "(index or BSSID)\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844 return -1;
1845 }
1846
Dmitry Shmidt04949592012-07-19 12:16:46 -07001847 res = os_snprintf(cmd, sizeof(cmd), "BSS %s%s%s%s%s", argv[0],
1848 argc > 1 ? " " : "", argc > 1 ? argv[1] : "",
1849 argc > 2 ? " " : "", argc > 2 ? argv[2] : "");
Dmitry Shmidtf2df2f22012-03-26 12:43:26 -07001850
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 if (res < 0 || (size_t) res >= sizeof(cmd))
1852 return -1;
1853 cmd[sizeof(cmd) - 1] = '\0';
1854
1855 return wpa_ctrl_command(ctrl, cmd);
1856}
1857
1858
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001859static char ** wpa_cli_complete_bss(const char *str, int pos)
1860{
1861 int arg = get_cmd_arg_num(str, pos);
1862 char **res = NULL;
1863
1864 switch (arg) {
1865 case 1:
1866 res = cli_txt_list_array(&bsses);
1867 break;
1868 }
1869
1870 return res;
1871}
1872
1873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001874static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1875 char *argv[])
1876{
1877 char cmd[64];
1878 int res;
1879
1880 if (argc < 1 || argc > 2) {
1881 printf("Invalid GET_CAPABILITY command: need either one or "
1882 "two arguments\n");
1883 return -1;
1884 }
1885
1886 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1887 printf("Invalid GET_CAPABILITY command: second argument, "
1888 "if any, must be 'strict'\n");
1889 return -1;
1890 }
1891
1892 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1893 (argc == 2) ? " strict" : "");
1894 if (res < 0 || (size_t) res >= sizeof(cmd))
1895 return -1;
1896 cmd[sizeof(cmd) - 1] = '\0';
1897
1898 return wpa_ctrl_command(ctrl, cmd);
1899}
1900
1901
1902static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1903{
1904 printf("Available interfaces:\n");
1905 return wpa_ctrl_command(ctrl, "INTERFACES");
1906}
1907
1908
1909static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1910{
1911 if (argc < 1) {
1912 wpa_cli_list_interfaces(ctrl);
1913 return 0;
1914 }
1915
1916 wpa_cli_close_connection();
1917 os_free(ctrl_ifname);
1918 ctrl_ifname = os_strdup(argv[0]);
1919
1920 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1921 printf("Connected to interface '%s.\n", ctrl_ifname);
1922 } else {
1923 printf("Could not connect to interface '%s' - re-trying\n",
1924 ctrl_ifname);
1925 }
1926 return 0;
1927}
1928
1929
1930static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1931 char *argv[])
1932{
1933 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1934}
1935
1936
1937static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1938 char *argv[])
1939{
1940 return wpa_ctrl_command(ctrl, "TERMINATE");
1941}
1942
1943
1944static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1945 char *argv[])
1946{
1947 char cmd[256];
1948 int res;
1949
1950 if (argc < 1) {
1951 printf("Invalid INTERFACE_ADD command: needs at least one "
1952 "argument (interface name)\n"
1953 "All arguments: ifname confname driver ctrl_interface "
1954 "driver_param bridge_name\n");
1955 return -1;
1956 }
1957
1958 /*
1959 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1960 * <driver_param>TAB<bridge_name>
1961 */
1962 res = os_snprintf(cmd, sizeof(cmd),
1963 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1964 argv[0],
1965 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1966 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1967 argc > 5 ? argv[5] : "");
1968 if (res < 0 || (size_t) res >= sizeof(cmd))
1969 return -1;
1970 cmd[sizeof(cmd) - 1] = '\0';
1971 return wpa_ctrl_command(ctrl, cmd);
1972}
1973
1974
1975static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1976 char *argv[])
1977{
1978 char cmd[128];
1979 int res;
1980
1981 if (argc != 1) {
1982 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1983 "(interface name)\n");
1984 return -1;
1985 }
1986
1987 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1988 if (res < 0 || (size_t) res >= sizeof(cmd))
1989 return -1;
1990 cmd[sizeof(cmd) - 1] = '\0';
1991 return wpa_ctrl_command(ctrl, cmd);
1992}
1993
1994
1995static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1996 char *argv[])
1997{
1998 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1999}
2000
2001
2002#ifdef CONFIG_AP
2003static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
2004{
2005 char buf[64];
2006 if (argc != 1) {
2007 printf("Invalid 'sta' command - exactly one argument, STA "
2008 "address, is required.\n");
2009 return -1;
2010 }
2011 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
2012 return wpa_ctrl_command(ctrl, buf);
2013}
2014
2015
2016static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
2017 char *addr, size_t addr_len)
2018{
2019 char buf[4096], *pos;
2020 size_t len;
2021 int ret;
2022
2023 if (ctrl_conn == NULL) {
2024 printf("Not connected to hostapd - command dropped.\n");
2025 return -1;
2026 }
2027 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002028 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029 wpa_cli_msg_cb);
2030 if (ret == -2) {
2031 printf("'%s' command timed out.\n", cmd);
2032 return -2;
2033 } else if (ret < 0) {
2034 printf("'%s' command failed.\n", cmd);
2035 return -1;
2036 }
2037
2038 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002039 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002040 return -1;
2041 printf("%s", buf);
2042
2043 pos = buf;
2044 while (*pos != '\0' && *pos != '\n')
2045 pos++;
2046 *pos = '\0';
2047 os_strlcpy(addr, buf, addr_len);
2048 return 0;
2049}
2050
2051
2052static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
2053{
2054 char addr[32], cmd[64];
2055
2056 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
2057 return 0;
2058 do {
2059 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
2060 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
2061
2062 return -1;
2063}
Dmitry Shmidt04949592012-07-19 12:16:46 -07002064
2065
2066static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
2067 char *argv[])
2068{
2069 char buf[64];
2070 if (argc < 1) {
2071 printf("Invalid 'deauthenticate' command - exactly one "
2072 "argument, STA address, is required.\n");
2073 return -1;
2074 }
2075 if (argc > 1)
2076 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
2077 argv[0], argv[1]);
2078 else
2079 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
2080 return wpa_ctrl_command(ctrl, buf);
2081}
2082
2083
2084static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
2085 char *argv[])
2086{
2087 char buf[64];
2088 if (argc < 1) {
2089 printf("Invalid 'disassociate' command - exactly one "
2090 "argument, STA address, is required.\n");
2091 return -1;
2092 }
2093 if (argc > 1)
2094 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
2095 argv[0], argv[1]);
2096 else
2097 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
2098 return wpa_ctrl_command(ctrl, buf);
2099}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002100#endif /* CONFIG_AP */
2101
2102
2103static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
2104{
2105 return wpa_ctrl_command(ctrl, "SUSPEND");
2106}
2107
2108
2109static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
2110{
2111 return wpa_ctrl_command(ctrl, "RESUME");
2112}
2113
2114
2115static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
2116{
2117 return wpa_ctrl_command(ctrl, "DROP_SA");
2118}
2119
2120
2121static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
2122{
2123 char cmd[128];
2124 int res;
2125
2126 if (argc != 1) {
2127 printf("Invalid ROAM command: needs one argument "
2128 "(target AP's BSSID)\n");
2129 return -1;
2130 }
2131
2132 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
2133 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2134 printf("Too long ROAM command.\n");
2135 return -1;
2136 }
2137 return wpa_ctrl_command(ctrl, cmd);
2138}
2139
2140
2141#ifdef CONFIG_P2P
2142
2143static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2144{
2145 char cmd[128];
2146 int res;
2147
2148 if (argc == 0)
2149 return wpa_ctrl_command(ctrl, "P2P_FIND");
2150
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002151 if (argc > 2)
2152 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s %s",
2153 argv[0], argv[1], argv[2]);
2154 else if (argc > 1)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
2156 argv[0], argv[1]);
2157 else
2158 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
2159 if (res < 0 || (size_t) res >= sizeof(cmd))
2160 return -1;
2161 cmd[sizeof(cmd) - 1] = '\0';
2162 return wpa_ctrl_command(ctrl, cmd);
2163}
2164
2165
2166static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2167 char *argv[])
2168{
2169 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2170}
2171
2172
2173static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2174 char *argv[])
2175{
2176 char cmd[128];
2177 int res;
2178
2179 if (argc < 2) {
2180 printf("Invalid P2P_CONNECT command: needs at least two "
2181 "arguments (address and pbc/PIN)\n");
2182 return -1;
2183 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002184#ifdef ANDROID_P2P
2185 if (argc > 5)
2186 res = os_snprintf(cmd, sizeof(cmd),
2187 "P2P_CONNECT %s %s %s %s %s %s",
2188 argv[0], argv[1], argv[2], argv[3],
2189 argv[4], argv[5]);
2190 else
2191#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192 if (argc > 4)
2193 res = os_snprintf(cmd, sizeof(cmd),
2194 "P2P_CONNECT %s %s %s %s %s",
2195 argv[0], argv[1], argv[2], argv[3],
2196 argv[4]);
2197 else if (argc > 3)
2198 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
2199 argv[0], argv[1], argv[2], argv[3]);
2200 else if (argc > 2)
2201 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
2202 argv[0], argv[1], argv[2]);
2203 else
2204 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
2205 argv[0], argv[1]);
2206 if (res < 0 || (size_t) res >= sizeof(cmd))
2207 return -1;
2208 cmd[sizeof(cmd) - 1] = '\0';
2209 return wpa_ctrl_command(ctrl, cmd);
2210}
2211
2212
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002213static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2214{
2215 int arg = get_cmd_arg_num(str, pos);
2216 char **res = NULL;
2217
2218 switch (arg) {
2219 case 1:
2220 res = cli_txt_list_array(&p2p_peers);
2221 break;
2222 }
2223
2224 return res;
2225}
2226
2227
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
2231 char cmd[128];
2232 int res;
2233
2234 if (argc == 0)
2235 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
2236
2237 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
2238 if (res < 0 || (size_t) res >= sizeof(cmd))
2239 return -1;
2240 cmd[sizeof(cmd) - 1] = '\0';
2241 return wpa_ctrl_command(ctrl, cmd);
2242}
2243
2244
2245static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2246 char *argv[])
2247{
2248 char cmd[128];
2249 int res;
2250
2251 if (argc != 1) {
2252 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
2253 "(interface name)\n");
2254 return -1;
2255 }
2256
2257 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
2258 if (res < 0 || (size_t) res >= sizeof(cmd))
2259 return -1;
2260 cmd[sizeof(cmd) - 1] = '\0';
2261 return wpa_ctrl_command(ctrl, cmd);
2262}
2263
2264
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002265static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2266{
2267 int arg = get_cmd_arg_num(str, pos);
2268 char **res = NULL;
2269
2270 switch (arg) {
2271 case 1:
2272 res = cli_txt_list_array(&p2p_groups);
2273 break;
2274 }
2275
2276 return res;
2277}
2278
2279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002280static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2281 char *argv[])
2282{
2283 char cmd[128];
2284 int res;
2285
2286 if (argc == 0)
2287 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
2288
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002289 if (argc > 1)
2290 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s %s",
2291 argv[0], argv[1]);
2292 else
2293 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s",
2294 argv[0]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002295 if (res < 0 || (size_t) res >= sizeof(cmd))
2296 return -1;
2297 cmd[sizeof(cmd) - 1] = '\0';
2298 return wpa_ctrl_command(ctrl, cmd);
2299}
2300
2301
2302static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2303 char *argv[])
2304{
2305 char cmd[128];
2306 int res;
2307
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002308 if (argc != 2 && argc != 3) {
2309 printf("Invalid P2P_PROV_DISC command: needs at least "
2310 "two arguments, address and config method\n"
2311 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 return -1;
2313 }
2314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002315 if (argc == 3)
2316 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s %s",
2317 argv[0], argv[1], argv[2]);
2318 else
2319 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
2320 argv[0], argv[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002321 if (res < 0 || (size_t) res >= sizeof(cmd))
2322 return -1;
2323 cmd[sizeof(cmd) - 1] = '\0';
2324 return wpa_ctrl_command(ctrl, cmd);
2325}
2326
2327
2328static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2329 char *argv[])
2330{
2331 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2332}
2333
2334
2335static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2336 char *argv[])
2337{
2338 char cmd[4096];
2339 int res;
2340
2341 if (argc != 2 && argc != 4) {
2342 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2343 "arguments (address and TLVs) or four arguments "
2344 "(address, \"upnp\", version, search target "
2345 "(SSDP ST:)\n");
2346 return -1;
2347 }
2348
2349 if (argc == 4)
2350 res = os_snprintf(cmd, sizeof(cmd),
2351 "P2P_SERV_DISC_REQ %s %s %s %s",
2352 argv[0], argv[1], argv[2], argv[3]);
2353 else
2354 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
2355 argv[0], argv[1]);
2356 if (res < 0 || (size_t) res >= sizeof(cmd))
2357 return -1;
2358 cmd[sizeof(cmd) - 1] = '\0';
2359 return wpa_ctrl_command(ctrl, cmd);
2360}
2361
2362
2363static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2364 int argc, char *argv[])
2365{
2366 char cmd[128];
2367 int res;
2368
2369 if (argc != 1) {
2370 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
2371 "argument (pending request identifier)\n");
2372 return -1;
2373 }
2374
2375 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
2376 argv[0]);
2377 if (res < 0 || (size_t) res >= sizeof(cmd))
2378 return -1;
2379 cmd[sizeof(cmd) - 1] = '\0';
2380 return wpa_ctrl_command(ctrl, cmd);
2381}
2382
2383
2384static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2385 char *argv[])
2386{
2387 char cmd[4096];
2388 int res;
2389
2390 if (argc != 4) {
2391 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2392 "arguments (freq, address, dialog token, and TLVs)\n");
2393 return -1;
2394 }
2395
2396 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2397 argv[0], argv[1], argv[2], argv[3]);
2398 if (res < 0 || (size_t) res >= sizeof(cmd))
2399 return -1;
2400 cmd[sizeof(cmd) - 1] = '\0';
2401 return wpa_ctrl_command(ctrl, cmd);
2402}
2403
2404
2405static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2406 char *argv[])
2407{
2408 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2409}
2410
2411
2412static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2413 int argc, char *argv[])
2414{
2415 char cmd[128];
2416 int res;
2417
2418 if (argc != 1) {
2419 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
2420 "argument (external processing: 0/1)\n");
2421 return -1;
2422 }
2423
2424 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
2425 argv[0]);
2426 if (res < 0 || (size_t) res >= sizeof(cmd))
2427 return -1;
2428 cmd[sizeof(cmd) - 1] = '\0';
2429 return wpa_ctrl_command(ctrl, cmd);
2430}
2431
2432
2433static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2434 char *argv[])
2435{
2436 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2437}
2438
2439
2440static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2441 char *argv[])
2442{
2443 char cmd[4096];
2444 int res;
2445
2446 if (argc != 3 && argc != 4) {
2447 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
2448 "arguments\n");
2449 return -1;
2450 }
2451
2452 if (argc == 4)
2453 res = os_snprintf(cmd, sizeof(cmd),
2454 "P2P_SERVICE_ADD %s %s %s %s",
2455 argv[0], argv[1], argv[2], argv[3]);
2456 else
2457 res = os_snprintf(cmd, sizeof(cmd),
2458 "P2P_SERVICE_ADD %s %s %s",
2459 argv[0], argv[1], argv[2]);
2460 if (res < 0 || (size_t) res >= sizeof(cmd))
2461 return -1;
2462 cmd[sizeof(cmd) - 1] = '\0';
2463 return wpa_ctrl_command(ctrl, cmd);
2464}
2465
2466
2467static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2468 char *argv[])
2469{
2470 char cmd[4096];
2471 int res;
2472
2473 if (argc != 2 && argc != 3) {
2474 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2475 "arguments\n");
2476 return -1;
2477 }
2478
2479 if (argc == 3)
2480 res = os_snprintf(cmd, sizeof(cmd),
2481 "P2P_SERVICE_DEL %s %s %s",
2482 argv[0], argv[1], argv[2]);
2483 else
2484 res = os_snprintf(cmd, sizeof(cmd),
2485 "P2P_SERVICE_DEL %s %s",
2486 argv[0], argv[1]);
2487 if (res < 0 || (size_t) res >= sizeof(cmd))
2488 return -1;
2489 cmd[sizeof(cmd) - 1] = '\0';
2490 return wpa_ctrl_command(ctrl, cmd);
2491}
2492
2493
2494static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2495 int argc, char *argv[])
2496{
2497 char cmd[128];
2498 int res;
2499
2500 if (argc != 1) {
2501 printf("Invalid P2P_REJECT command: needs one argument "
2502 "(peer address)\n");
2503 return -1;
2504 }
2505
2506 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
2507 if (res < 0 || (size_t) res >= sizeof(cmd))
2508 return -1;
2509 cmd[sizeof(cmd) - 1] = '\0';
2510 return wpa_ctrl_command(ctrl, cmd);
2511}
2512
2513
2514static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2515 int argc, char *argv[])
2516{
2517 char cmd[128];
2518 int res;
2519
2520 if (argc < 1) {
2521 printf("Invalid P2P_INVITE command: needs at least one "
2522 "argument\n");
2523 return -1;
2524 }
2525
2526 if (argc > 2)
2527 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
2528 argv[0], argv[1], argv[2]);
2529 else if (argc > 1)
2530 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
2531 argv[0], argv[1]);
2532 else
2533 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
2534 if (res < 0 || (size_t) res >= sizeof(cmd))
2535 return -1;
2536 cmd[sizeof(cmd) - 1] = '\0';
2537 return wpa_ctrl_command(ctrl, cmd);
2538}
2539
2540
2541static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2542{
2543 char buf[64];
2544 if (argc != 1) {
2545 printf("Invalid 'p2p_peer' command - exactly one argument, "
2546 "P2P peer device address, is required.\n");
2547 return -1;
2548 }
2549 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
2550 return wpa_ctrl_command(ctrl, buf);
2551}
2552
2553
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002554static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2555{
2556 int arg = get_cmd_arg_num(str, pos);
2557 char **res = NULL;
2558
2559 switch (arg) {
2560 case 1:
2561 res = cli_txt_list_array(&p2p_peers);
2562 break;
2563 }
2564
2565 return res;
2566}
2567
2568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2570 char *addr, size_t addr_len,
2571 int discovered)
2572{
2573 char buf[4096], *pos;
2574 size_t len;
2575 int ret;
2576
2577 if (ctrl_conn == NULL)
2578 return -1;
2579 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 wpa_cli_msg_cb);
2582 if (ret == -2) {
2583 printf("'%s' command timed out.\n", cmd);
2584 return -2;
2585 } else if (ret < 0) {
2586 printf("'%s' command failed.\n", cmd);
2587 return -1;
2588 }
2589
2590 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002591 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 return -1;
2593
2594 pos = buf;
2595 while (*pos != '\0' && *pos != '\n')
2596 pos++;
2597 *pos++ = '\0';
2598 os_strlcpy(addr, buf, addr_len);
2599 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2600 printf("%s\n", addr);
2601 return 0;
2602}
2603
2604
2605static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2606{
2607 char addr[32], cmd[64];
2608 int discovered;
2609
2610 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2611
2612 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2613 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002614 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 do {
2616 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2617 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2618 discovered) == 0);
2619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002620 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621}
2622
2623
2624static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2625{
2626 char cmd[100];
2627 int res;
2628
2629 if (argc != 2) {
2630 printf("Invalid P2P_SET command: needs two arguments (field, "
2631 "value)\n");
2632 return -1;
2633 }
2634
2635 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2636 if (res < 0 || (size_t) res >= sizeof(cmd))
2637 return -1;
2638 cmd[sizeof(cmd) - 1] = '\0';
2639 return wpa_ctrl_command(ctrl, cmd);
2640}
2641
2642
2643static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2644{
2645 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2646}
2647
2648
2649static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2650 char *argv[])
2651{
2652 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2653}
2654
2655
2656static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2657 char *argv[])
2658{
2659 char cmd[100];
2660 int res;
2661
2662 if (argc != 1) {
2663 printf("Invalid P2P_UNAUTHORIZE command: needs one argument "
2664 "(peer address)\n");
2665 return -1;
2666 }
2667
2668 res = os_snprintf(cmd, sizeof(cmd), "P2P_UNAUTHORIZE %s", argv[0]);
2669
2670 if (res < 0 || (size_t) res >= sizeof(cmd))
2671 return -1;
2672
2673 cmd[sizeof(cmd) - 1] = '\0';
2674 return wpa_ctrl_command(ctrl, cmd);
2675}
2676
2677
2678static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2679 char *argv[])
2680{
2681 char cmd[100];
2682 int res;
2683
2684 if (argc != 0 && argc != 2 && argc != 4) {
2685 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2686 "(preferred duration, interval; in microsecods).\n"
2687 "Optional second pair can be used to provide "
2688 "acceptable values.\n");
2689 return -1;
2690 }
2691
2692 if (argc == 4)
2693 res = os_snprintf(cmd, sizeof(cmd),
2694 "P2P_PRESENCE_REQ %s %s %s %s",
2695 argv[0], argv[1], argv[2], argv[3]);
2696 else if (argc == 2)
2697 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2698 argv[0], argv[1]);
2699 else
2700 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2701 if (res < 0 || (size_t) res >= sizeof(cmd))
2702 return -1;
2703 cmd[sizeof(cmd) - 1] = '\0';
2704 return wpa_ctrl_command(ctrl, cmd);
2705}
2706
2707
2708static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2709 char *argv[])
2710{
2711 char cmd[100];
2712 int res;
2713
2714 if (argc != 0 && argc != 2) {
2715 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2716 "(availability period, availability interval; in "
2717 "millisecods).\n"
2718 "Extended Listen Timing can be cancelled with this "
2719 "command when used without parameters.\n");
2720 return -1;
2721 }
2722
2723 if (argc == 2)
2724 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2725 argv[0], argv[1]);
2726 else
2727 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2728 if (res < 0 || (size_t) res >= sizeof(cmd))
2729 return -1;
2730 cmd[sizeof(cmd) - 1] = '\0';
2731 return wpa_ctrl_command(ctrl, cmd);
2732}
2733
2734#endif /* CONFIG_P2P */
2735
2736
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002737#ifdef CONFIG_INTERWORKING
2738static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2739 char *argv[])
2740{
2741 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2742}
2743
2744
2745static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2746 char *argv[])
2747{
2748 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2749}
2750
2751
2752static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2753 char *argv[])
2754{
2755 char cmd[100];
2756 int res;
2757
2758 if (argc == 0)
2759 return wpa_ctrl_command(ctrl, "INTERWORKING_SELECT");
2760
2761 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_SELECT %s", argv[0]);
2762 if (res < 0 || (size_t) res >= sizeof(cmd))
2763 return -1;
2764 cmd[sizeof(cmd) - 1] = '\0';
2765 return wpa_ctrl_command(ctrl, cmd);
2766}
2767
2768
2769static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2770 char *argv[])
2771{
2772 char cmd[100];
2773 int res;
2774
2775 if (argc != 1) {
2776 printf("Invalid INTERWORKING_CONNECT commands: needs one "
2777 "argument (BSSID)\n");
2778 return -1;
2779 }
2780
2781 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_CONNECT %s",
2782 argv[0]);
2783 if (res < 0 || (size_t) res >= sizeof(cmd))
2784 return -1;
2785 cmd[sizeof(cmd) - 1] = '\0';
2786 return wpa_ctrl_command(ctrl, cmd);
2787}
2788
2789
2790static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2791{
2792 char cmd[100];
2793 int res;
2794
2795 if (argc != 2) {
2796 printf("Invalid ANQP_GET command: needs two arguments "
2797 "(addr and info id list)\n");
2798 return -1;
2799 }
2800
2801 res = os_snprintf(cmd, sizeof(cmd), "ANQP_GET %s %s",
2802 argv[0], argv[1]);
2803 if (res < 0 || (size_t) res >= sizeof(cmd))
2804 return -1;
2805 cmd[sizeof(cmd) - 1] = '\0';
2806 return wpa_ctrl_command(ctrl, cmd);
2807}
2808#endif /* CONFIG_INTERWORKING */
2809
2810
Dmitry Shmidt04949592012-07-19 12:16:46 -07002811#ifdef CONFIG_HS20
2812
2813static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2814 char *argv[])
2815{
2816 char cmd[100];
2817 int res;
2818
2819 if (argc != 2) {
2820 printf("Invalid HS20_ANQP_GET command: needs two arguments "
2821 "(addr and subtype list)\n");
2822 return -1;
2823 }
2824
2825 res = os_snprintf(cmd, sizeof(cmd), "HS20_ANQP_GET %s %s",
2826 argv[0], argv[1]);
2827 if (res < 0 || (size_t) res >= sizeof(cmd))
2828 return -1;
2829 cmd[sizeof(cmd) - 1] = '\0';
2830 return wpa_ctrl_command(ctrl, cmd);
2831}
2832
2833
2834static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2835 char *argv[])
2836{
2837 char cmd[512];
2838 int res;
2839
2840 if (argc == 0) {
2841 printf("Command needs one or two arguments (dst mac addr and "
2842 "optional home realm)\n");
2843 return -1;
2844 }
2845
2846 if (argc == 1)
2847 res = os_snprintf(cmd, sizeof(cmd),
2848 "HS20_GET_NAI_HOME_REALM_LIST %s",
2849 argv[0]);
2850 else
2851 res = os_snprintf(cmd, sizeof(cmd),
2852 "HS20_GET_NAI_HOME_REALM_LIST %s %s",
2853 argv[0], argv[1]);
2854 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2855 printf("Too long command.\n");
2856 return -1;
2857 }
2858
2859 return wpa_ctrl_command(ctrl, cmd);
2860}
2861
2862#endif /* CONFIG_HS20 */
2863
2864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2866 char *argv[])
2867{
2868 char cmd[256];
2869 int res;
2870
2871 if (argc != 1) {
2872 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2873 "(0/1 = disable/enable automatic reconnection)\n");
2874 return -1;
2875 }
2876 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2877 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2878 printf("Too long STA_AUTOCONNECT command.\n");
2879 return -1;
2880 }
2881 return wpa_ctrl_command(ctrl, cmd);
2882}
2883
2884
2885static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2886 char *argv[])
2887{
2888 char cmd[256];
2889 int res;
2890
2891 if (argc != 1) {
2892 printf("Invalid TDLS_DISCOVER command: needs one argument "
2893 "(Peer STA MAC address)\n");
2894 return -1;
2895 }
2896
2897 res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
2898 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2899 printf("Too long TDLS_DISCOVER command.\n");
2900 return -1;
2901 }
2902 return wpa_ctrl_command(ctrl, cmd);
2903}
2904
2905
2906static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2907 char *argv[])
2908{
2909 char cmd[256];
2910 int res;
2911
2912 if (argc != 1) {
2913 printf("Invalid TDLS_SETUP command: needs one argument "
2914 "(Peer STA MAC address)\n");
2915 return -1;
2916 }
2917
2918 res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
2919 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2920 printf("Too long TDLS_SETUP command.\n");
2921 return -1;
2922 }
2923 return wpa_ctrl_command(ctrl, cmd);
2924}
2925
2926
2927static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2928 char *argv[])
2929{
2930 char cmd[256];
2931 int res;
2932
2933 if (argc != 1) {
2934 printf("Invalid TDLS_TEARDOWN command: needs one argument "
2935 "(Peer STA MAC address)\n");
2936 return -1;
2937 }
2938
2939 res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
2940 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2941 printf("Too long TDLS_TEARDOWN command.\n");
2942 return -1;
2943 }
2944 return wpa_ctrl_command(ctrl, cmd);
2945}
2946
2947
2948static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2949 char *argv[])
2950{
2951 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2952}
2953
2954
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002955static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2956 char *argv[])
2957{
2958 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2959}
2960
2961
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002962static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2963 char *argv[])
2964{
2965 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2966}
2967
Dmitry Shmidt04949592012-07-19 12:16:46 -07002968
2969#ifdef CONFIG_AUTOSCAN
2970
2971static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2972{
2973 char cmd[256];
2974 int res;
2975
2976 if (argc == 0)
2977 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2978
2979 res = os_snprintf(cmd, sizeof(cmd), "AUTOSCAN %s", argv[0]);
2980 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2981 printf("Too long AUTOSCAN command.\n");
2982 return -1;
2983 }
2984
2985 return wpa_ctrl_command(ctrl, cmd);
2986}
2987
2988#endif /* CONFIG_AUTOSCAN */
2989
2990
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002991#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002992static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2993{
2994 char cmd[256];
2995 int i;
2996 int len;
2997
2998 if (argc < 1) {
2999 printf("Invalid DRIVER command: needs one argument (cmd)\n");
3000 return -1;
3001 }
3002
3003 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
3004 for (i=1; i < argc; i++)
3005 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
3006 cmd[sizeof(cmd) - 1] = '\0';
3007 printf("%s: %s\n", __func__, cmd);
3008 return wpa_ctrl_command(ctrl, cmd);
3009}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003010#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003011
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003012enum wpa_cli_cmd_flags {
3013 cli_cmd_flag_none = 0x00,
3014 cli_cmd_flag_sensitive = 0x01
3015};
3016
3017struct wpa_cli_cmd {
3018 const char *cmd;
3019 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
3020 enum wpa_cli_cmd_flags flags;
3021 const char *usage;
3022};
3023
3024static struct wpa_cli_cmd wpa_cli_commands[] = {
3025 { "status", wpa_cli_cmd_status,
3026 cli_cmd_flag_none,
3027 "[verbose] = get current WPA/EAPOL/EAP status" },
3028 { "ping", wpa_cli_cmd_ping,
3029 cli_cmd_flag_none,
3030 "= pings wpa_supplicant" },
3031 { "relog", wpa_cli_cmd_relog,
3032 cli_cmd_flag_none,
3033 "= re-open log-file (allow rolling logs)" },
3034 { "note", wpa_cli_cmd_note,
3035 cli_cmd_flag_none,
3036 "<text> = add a note to wpa_supplicant debug log" },
3037 { "mib", wpa_cli_cmd_mib,
3038 cli_cmd_flag_none,
3039 "= get MIB variables (dot1x, dot11)" },
3040 { "help", wpa_cli_cmd_help,
3041 cli_cmd_flag_none,
3042 "= show this usage help" },
3043 { "interface", wpa_cli_cmd_interface,
3044 cli_cmd_flag_none,
3045 "[ifname] = show interfaces/select interface" },
3046 { "level", wpa_cli_cmd_level,
3047 cli_cmd_flag_none,
3048 "<debug level> = change debug level" },
3049 { "license", wpa_cli_cmd_license,
3050 cli_cmd_flag_none,
3051 "= show full wpa_cli license" },
3052 { "quit", wpa_cli_cmd_quit,
3053 cli_cmd_flag_none,
3054 "= exit wpa_cli" },
3055 { "set", wpa_cli_cmd_set,
3056 cli_cmd_flag_none,
3057 "= set variables (shows list of variables when run without "
3058 "arguments)" },
3059 { "get", wpa_cli_cmd_get,
3060 cli_cmd_flag_none,
3061 "<name> = get information" },
3062 { "logon", wpa_cli_cmd_logon,
3063 cli_cmd_flag_none,
3064 "= IEEE 802.1X EAPOL state machine logon" },
3065 { "logoff", wpa_cli_cmd_logoff,
3066 cli_cmd_flag_none,
3067 "= IEEE 802.1X EAPOL state machine logoff" },
3068 { "pmksa", wpa_cli_cmd_pmksa,
3069 cli_cmd_flag_none,
3070 "= show PMKSA cache" },
3071 { "reassociate", wpa_cli_cmd_reassociate,
3072 cli_cmd_flag_none,
3073 "= force reassociation" },
3074 { "preauthenticate", wpa_cli_cmd_preauthenticate,
3075 cli_cmd_flag_none,
3076 "<BSSID> = force preauthentication" },
3077 { "identity", wpa_cli_cmd_identity,
3078 cli_cmd_flag_none,
3079 "<network id> <identity> = configure identity for an SSID" },
3080 { "password", wpa_cli_cmd_password,
3081 cli_cmd_flag_sensitive,
3082 "<network id> <password> = configure password for an SSID" },
3083 { "new_password", wpa_cli_cmd_new_password,
3084 cli_cmd_flag_sensitive,
3085 "<network id> <password> = change password for an SSID" },
3086 { "pin", wpa_cli_cmd_pin,
3087 cli_cmd_flag_sensitive,
3088 "<network id> <pin> = configure pin for an SSID" },
3089 { "otp", wpa_cli_cmd_otp,
3090 cli_cmd_flag_sensitive,
3091 "<network id> <password> = configure one-time-password for an SSID"
3092 },
3093 { "passphrase", wpa_cli_cmd_passphrase,
3094 cli_cmd_flag_sensitive,
3095 "<network id> <passphrase> = configure private key passphrase\n"
3096 " for an SSID" },
3097 { "bssid", wpa_cli_cmd_bssid,
3098 cli_cmd_flag_none,
3099 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt696359e2011-03-16 15:04:31 -07003100 { "blacklist", wpa_cli_cmd_blacklist,
3101 cli_cmd_flag_none,
3102 "<BSSID> = add a BSSID to the blacklist\n"
3103 "blacklist clear = clear the blacklist\n"
3104 "blacklist = display the blacklist" },
3105 { "log_level", wpa_cli_cmd_log_level,
3106 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003107 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07003108 "log_level = display the current log level and log options" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003109 { "list_networks", wpa_cli_cmd_list_networks,
3110 cli_cmd_flag_none,
3111 "= list configured networks" },
3112 { "select_network", wpa_cli_cmd_select_network,
3113 cli_cmd_flag_none,
3114 "<network id> = select a network (disable others)" },
3115 { "enable_network", wpa_cli_cmd_enable_network,
3116 cli_cmd_flag_none,
3117 "<network id> = enable a network" },
3118 { "disable_network", wpa_cli_cmd_disable_network,
3119 cli_cmd_flag_none,
3120 "<network id> = disable a network" },
3121 { "add_network", wpa_cli_cmd_add_network,
3122 cli_cmd_flag_none,
3123 "= add a network" },
3124 { "remove_network", wpa_cli_cmd_remove_network,
3125 cli_cmd_flag_none,
3126 "<network id> = remove a network" },
3127 { "set_network", wpa_cli_cmd_set_network,
3128 cli_cmd_flag_sensitive,
3129 "<network id> <variable> <value> = set network variables (shows\n"
3130 " list of variables when run without arguments)" },
3131 { "get_network", wpa_cli_cmd_get_network,
3132 cli_cmd_flag_none,
3133 "<network id> <variable> = get network variables" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003134 { "list_creds", wpa_cli_cmd_list_creds,
3135 cli_cmd_flag_none,
3136 "= list configured credentials" },
3137 { "add_cred", wpa_cli_cmd_add_cred,
3138 cli_cmd_flag_none,
3139 "= add a credential" },
3140 { "remove_cred", wpa_cli_cmd_remove_cred,
3141 cli_cmd_flag_none,
3142 "<cred id> = remove a credential" },
3143 { "set_cred", wpa_cli_cmd_set_cred,
3144 cli_cmd_flag_sensitive,
3145 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003146 { "save_config", wpa_cli_cmd_save_config,
3147 cli_cmd_flag_none,
3148 "= save the current configuration" },
3149 { "disconnect", wpa_cli_cmd_disconnect,
3150 cli_cmd_flag_none,
3151 "= disconnect and wait for reassociate/reconnect command before\n"
3152 " connecting" },
3153 { "reconnect", wpa_cli_cmd_reconnect,
3154 cli_cmd_flag_none,
3155 "= like reassociate, but only takes effect if already disconnected"
3156 },
3157 { "scan", wpa_cli_cmd_scan,
3158 cli_cmd_flag_none,
3159 "= request new BSS scan" },
3160 { "scan_results", wpa_cli_cmd_scan_results,
3161 cli_cmd_flag_none,
3162 "= get latest scan results" },
3163 { "bss", wpa_cli_cmd_bss,
3164 cli_cmd_flag_none,
3165 "<<idx> | <bssid>> = get detailed scan result info" },
3166 { "get_capability", wpa_cli_cmd_get_capability,
3167 cli_cmd_flag_none,
Dmitry Shmidt0e6d08e2012-07-10 12:49:30 -07003168 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels>\n"
3169 " = get capabilities" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170 { "reconfigure", wpa_cli_cmd_reconfigure,
3171 cli_cmd_flag_none,
3172 "= force wpa_supplicant to re-read its configuration file" },
3173 { "terminate", wpa_cli_cmd_terminate,
3174 cli_cmd_flag_none,
3175 "= terminate wpa_supplicant" },
3176 { "interface_add", wpa_cli_cmd_interface_add,
3177 cli_cmd_flag_none,
3178 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
3179 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
3180 " are optional" },
3181 { "interface_remove", wpa_cli_cmd_interface_remove,
3182 cli_cmd_flag_none,
3183 "<ifname> = removes the interface" },
3184 { "interface_list", wpa_cli_cmd_interface_list,
3185 cli_cmd_flag_none,
3186 "= list available interfaces" },
3187 { "ap_scan", wpa_cli_cmd_ap_scan,
3188 cli_cmd_flag_none,
3189 "<value> = set ap_scan parameter" },
3190 { "scan_interval", wpa_cli_cmd_scan_interval,
3191 cli_cmd_flag_none,
3192 "<value> = set scan_interval parameter (in seconds)" },
3193 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
3194 cli_cmd_flag_none,
3195 "<value> = set BSS expiration age parameter" },
3196 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
3197 cli_cmd_flag_none,
3198 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07003199 { "bss_flush", wpa_cli_cmd_bss_flush,
3200 cli_cmd_flag_none,
3201 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 { "stkstart", wpa_cli_cmd_stkstart,
3203 cli_cmd_flag_none,
3204 "<addr> = request STK negotiation with <addr>" },
3205 { "ft_ds", wpa_cli_cmd_ft_ds,
3206 cli_cmd_flag_none,
3207 "<addr> = request over-the-DS FT with <addr>" },
3208 { "wps_pbc", wpa_cli_cmd_wps_pbc,
3209 cli_cmd_flag_none,
3210 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3211 { "wps_pin", wpa_cli_cmd_wps_pin,
3212 cli_cmd_flag_sensitive,
3213 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3214 "hardcoded)" },
3215 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
3216 cli_cmd_flag_sensitive,
3217 "<PIN> = verify PIN checksum" },
3218 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
3219 "Cancels the pending WPS operation" },
3220#ifdef CONFIG_WPS_OOB
3221 { "wps_oob", wpa_cli_cmd_wps_oob,
3222 cli_cmd_flag_sensitive,
3223 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
3224#endif /* CONFIG_WPS_OOB */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003225#ifdef CONFIG_WPS_NFC
3226 { "wps_nfc", wpa_cli_cmd_wps_nfc,
3227 cli_cmd_flag_none,
3228 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3229 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token,
3230 cli_cmd_flag_none,
3231 "<WPS|NDEF> = create password token" },
3232 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read,
3233 cli_cmd_flag_sensitive,
3234 "<hexdump of payload> = report read NFC tag with WPS data" },
3235#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236 { "wps_reg", wpa_cli_cmd_wps_reg,
3237 cli_cmd_flag_sensitive,
3238 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3239 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
3240 cli_cmd_flag_sensitive,
3241 "[params..] = enable/disable AP PIN" },
3242 { "wps_er_start", wpa_cli_cmd_wps_er_start,
3243 cli_cmd_flag_none,
3244 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3245 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
3246 cli_cmd_flag_none,
3247 "= stop Wi-Fi Protected Setup External Registrar" },
3248 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
3249 cli_cmd_flag_sensitive,
3250 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3251 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
3252 cli_cmd_flag_none,
3253 "<UUID> = accept an Enrollee PBC using External Registrar" },
3254 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
3255 cli_cmd_flag_sensitive,
3256 "<UUID> <PIN> = learn AP configuration" },
3257 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
3258 cli_cmd_flag_none,
3259 "<UUID> <network id> = set AP configuration for enrolling" },
3260 { "wps_er_config", wpa_cli_cmd_wps_er_config,
3261 cli_cmd_flag_sensitive,
3262 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003263#ifdef CONFIG_WPS_NFC
3264 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token,
3265 cli_cmd_flag_none,
3266 "<WPS/NDEF> <UUID> = build NFC configuration token" },
3267#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
3269 cli_cmd_flag_none,
3270 "<addr> = request RSN authentication with <addr> in IBSS" },
3271#ifdef CONFIG_AP
3272 { "sta", wpa_cli_cmd_sta,
3273 cli_cmd_flag_none,
3274 "<addr> = get information about an associated station (AP)" },
3275 { "all_sta", wpa_cli_cmd_all_sta,
3276 cli_cmd_flag_none,
3277 "= get information about all associated stations (AP)" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003278 { "deauthenticate", wpa_cli_cmd_deauthenticate,
3279 cli_cmd_flag_none,
3280 "<addr> = deauthenticate a station" },
3281 { "disassociate", wpa_cli_cmd_disassociate,
3282 cli_cmd_flag_none,
3283 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284#endif /* CONFIG_AP */
3285 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
3286 "= notification of suspend/hibernate" },
3287 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
3288 "= notification of resume/thaw" },
3289 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
3290 "= drop SA without deauth/disassoc (test command)" },
3291 { "roam", wpa_cli_cmd_roam,
3292 cli_cmd_flag_none,
3293 "<addr> = roam to the specified BSS" },
3294#ifdef CONFIG_P2P
3295 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
3296 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3297 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
3298 "= stop P2P Devices search" },
3299 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
3300 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
3301 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
3302 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3303 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
3304 "<ifname> = remove P2P group interface (terminate group if GO)" },
3305 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
3306 "= add a new P2P group (local end as GO)" },
3307 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
3308 "<addr> <method> = request provisioning discovery" },
3309 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
3310 cli_cmd_flag_none,
3311 "= get the passphrase for a group (GO only)" },
3312 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3313 cli_cmd_flag_none,
3314 "<addr> <TLVs> = schedule service discovery request" },
3315 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3316 cli_cmd_flag_none,
3317 "<id> = cancel pending service discovery request" },
3318 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
3319 cli_cmd_flag_none,
3320 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3321 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
3322 cli_cmd_flag_none,
3323 "= indicate change in local services" },
3324 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
3325 cli_cmd_flag_none,
3326 "<external> = set external processing of service discovery" },
3327 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
3328 cli_cmd_flag_none,
3329 "= remove all stored service entries" },
3330 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
3331 cli_cmd_flag_none,
3332 "<bonjour|upnp> <query|version> <response|service> = add a local "
3333 "service" },
3334 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
3335 cli_cmd_flag_none,
3336 "<bonjour|upnp> <query|version> [|service] = remove a local "
3337 "service" },
3338 { "p2p_reject", wpa_cli_cmd_p2p_reject,
3339 cli_cmd_flag_none,
3340 "<addr> = reject connection attempts from a specific peer" },
3341 { "p2p_invite", wpa_cli_cmd_p2p_invite,
3342 cli_cmd_flag_none,
3343 "<cmd> [peer=addr] = invite peer" },
3344 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
3345 "[discovered] = list known (optionally, only fully discovered) P2P "
3346 "peers" },
3347 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
3348 "<address> = show information about known P2P peer" },
3349 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
3350 "<field> <value> = set a P2P parameter" },
3351 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
3352 "= flush P2P state" },
3353 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
3354 "= cancel P2P group formation" },
3355 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
3356 "<address> = unauthorize a peer" },
3357 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
3358 "[<duration> <interval>] [<duration> <interval>] = request GO "
3359 "presence" },
3360 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
3361 "[<period> <interval>] = set extended listen timing" },
3362#endif /* CONFIG_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003363
3364#ifdef CONFIG_INTERWORKING
3365 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
3366 "= fetch ANQP information for all APs" },
3367 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
3368 "= stop fetch_anqp operation" },
3369 { "interworking_select", wpa_cli_cmd_interworking_select,
3370 cli_cmd_flag_none,
3371 "[auto] = perform Interworking network selection" },
3372 { "interworking_connect", wpa_cli_cmd_interworking_connect,
3373 cli_cmd_flag_none,
3374 "<BSSID> = connect using Interworking credentials" },
3375 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
3376 "<addr> <info id>[,<info id>]... = request ANQP information" },
3377#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003378#ifdef CONFIG_HS20
3379 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, cli_cmd_flag_none,
3380 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3381 },
3382 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3383 cli_cmd_flag_none,
3384 "<addr> <home realm> = get HS20 nai home realm list" },
3385#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003386 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
3387 "<0/1> = disable/enable automatic reconnection" },
3388 { "tdls_discover", wpa_cli_cmd_tdls_discover,
3389 cli_cmd_flag_none,
3390 "<addr> = request TDLS discovery with <addr>" },
3391 { "tdls_setup", wpa_cli_cmd_tdls_setup,
3392 cli_cmd_flag_none,
3393 "<addr> = request TDLS setup with <addr>" },
3394 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
3395 cli_cmd_flag_none,
3396 "<addr> = tear down TDLS with <addr>" },
3397 { "signal_poll", wpa_cli_cmd_signal_poll,
3398 cli_cmd_flag_none,
3399 "= get signal parameters" },
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07003400 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll,
3401 cli_cmd_flag_none,
3402 "= get TX/RX packet counters" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003403 { "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none,
3404 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003405#ifdef CONFIG_AUTOSCAN
3406 { "autoscan", wpa_cli_cmd_autoscan, cli_cmd_flag_none,
3407 "[params] = Set or unset (if none) autoscan parameters" },
3408#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003409#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003410 { "driver", wpa_cli_cmd_driver,
3411 cli_cmd_flag_none,
3412 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003413#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 { NULL, NULL, cli_cmd_flag_none, NULL }
3415};
3416
3417
3418/*
3419 * Prints command usage, lines are padded with the specified string.
3420 */
3421static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3422{
3423 char c;
3424 size_t n;
3425
3426 printf("%s%s ", pad, cmd->cmd);
3427 for (n = 0; (c = cmd->usage[n]); n++) {
3428 printf("%c", c);
3429 if (c == '\n')
3430 printf("%s", pad);
3431 }
3432 printf("\n");
3433}
3434
3435
3436static void print_help(void)
3437{
3438 int n;
3439 printf("commands:\n");
3440 for (n = 0; wpa_cli_commands[n].cmd; n++)
3441 print_cmd_help(&wpa_cli_commands[n], " ");
3442}
3443
3444
3445static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3446{
3447 const char *c, *delim;
3448 int n;
3449 size_t len;
3450
3451 delim = os_strchr(cmd, ' ');
3452 if (delim)
3453 len = delim - cmd;
3454 else
3455 len = os_strlen(cmd);
3456
3457 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3458 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3459 return (wpa_cli_commands[n].flags &
3460 cli_cmd_flag_sensitive);
3461 }
3462 return 0;
3463}
3464
3465
3466static char ** wpa_list_cmd_list(void)
3467{
3468 char **res;
3469 int i, count;
3470
3471 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3472 res = os_zalloc(count * sizeof(char *));
3473 if (res == NULL)
3474 return NULL;
3475
3476 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3477 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3478 if (res[i] == NULL)
3479 break;
3480 }
3481
3482 return res;
3483}
3484
3485
3486static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3487 int pos)
3488{
3489 int i;
3490
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003491 if (os_strcasecmp(cmd, "bss") == 0)
3492 return wpa_cli_complete_bss(str, pos);
3493#ifdef CONFIG_P2P
3494 if (os_strcasecmp(cmd, "p2p_connect") == 0)
3495 return wpa_cli_complete_p2p_connect(str, pos);
3496 if (os_strcasecmp(cmd, "p2p_peer") == 0)
3497 return wpa_cli_complete_p2p_peer(str, pos);
3498 if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3499 return wpa_cli_complete_p2p_group_remove(str, pos);
3500#endif /* CONFIG_P2P */
3501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3503 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3504 edit_clear_line();
3505 printf("\r%s\n", wpa_cli_commands[i].usage);
3506 edit_redraw();
3507 break;
3508 }
3509 }
3510
3511 return NULL;
3512}
3513
3514
3515static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3516{
3517 char **res;
3518 const char *end;
3519 char *cmd;
3520
3521 end = os_strchr(str, ' ');
3522 if (end == NULL || str + pos < end)
3523 return wpa_list_cmd_list();
3524
3525 cmd = os_malloc(pos + 1);
3526 if (cmd == NULL)
3527 return NULL;
3528 os_memcpy(cmd, str, pos);
3529 cmd[end - str] = '\0';
3530 res = wpa_cli_cmd_completion(cmd, str, pos);
3531 os_free(cmd);
3532 return res;
3533}
3534
3535
3536static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3537{
3538 struct wpa_cli_cmd *cmd, *match = NULL;
3539 int count;
3540 int ret = 0;
3541
3542 count = 0;
3543 cmd = wpa_cli_commands;
3544 while (cmd->cmd) {
3545 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3546 {
3547 match = cmd;
3548 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3549 /* we have an exact match */
3550 count = 1;
3551 break;
3552 }
3553 count++;
3554 }
3555 cmd++;
3556 }
3557
3558 if (count > 1) {
3559 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3560 cmd = wpa_cli_commands;
3561 while (cmd->cmd) {
3562 if (os_strncasecmp(cmd->cmd, argv[0],
3563 os_strlen(argv[0])) == 0) {
3564 printf(" %s", cmd->cmd);
3565 }
3566 cmd++;
3567 }
3568 printf("\n");
3569 ret = 1;
3570 } else if (count == 0) {
3571 printf("Unknown command '%s'\n", argv[0]);
3572 ret = 1;
3573 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003574#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
3575 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
3576 redirect_interface = os_strdup(argv[1]);
3577 ret = match->handler(ctrl, argc - 2, &argv[2]);
3578 }
3579 else
3580#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003581 ret = match->handler(ctrl, argc - 1, &argv[1]);
3582 }
3583
3584 return ret;
3585}
3586
3587
3588static int str_match(const char *a, const char *b)
3589{
3590 return os_strncmp(a, b, os_strlen(b)) == 0;
3591}
3592
3593
3594static int wpa_cli_exec(const char *program, const char *arg1,
3595 const char *arg2)
3596{
3597 char *cmd;
3598 size_t len;
3599 int res;
3600 int ret = 0;
3601
3602 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3603 cmd = os_malloc(len);
3604 if (cmd == NULL)
3605 return -1;
3606 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3607 if (res < 0 || (size_t) res >= len) {
3608 os_free(cmd);
3609 return -1;
3610 }
3611 cmd[len - 1] = '\0';
3612#ifndef _WIN32_WCE
3613 if (system(cmd) < 0)
3614 ret = -1;
3615#endif /* _WIN32_WCE */
3616 os_free(cmd);
3617
3618 return ret;
3619}
3620
3621
3622static void wpa_cli_action_process(const char *msg)
3623{
3624 const char *pos;
3625 char *copy = NULL, *id, *pos2;
3626
3627 pos = msg;
3628 if (*pos == '<') {
3629 /* skip priority */
3630 pos = os_strchr(pos, '>');
3631 if (pos)
3632 pos++;
3633 else
3634 pos = msg;
3635 }
3636
3637 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3638 int new_id = -1;
3639 os_unsetenv("WPA_ID");
3640 os_unsetenv("WPA_ID_STR");
3641 os_unsetenv("WPA_CTRL_DIR");
3642
3643 pos = os_strstr(pos, "[id=");
3644 if (pos)
3645 copy = os_strdup(pos + 4);
3646
3647 if (copy) {
3648 pos2 = id = copy;
3649 while (*pos2 && *pos2 != ' ')
3650 pos2++;
3651 *pos2++ = '\0';
3652 new_id = atoi(id);
3653 os_setenv("WPA_ID", id, 1);
3654 while (*pos2 && *pos2 != '=')
3655 pos2++;
3656 if (*pos2 == '=')
3657 pos2++;
3658 id = pos2;
3659 while (*pos2 && *pos2 != ']')
3660 pos2++;
3661 *pos2 = '\0';
3662 os_setenv("WPA_ID_STR", id, 1);
3663 os_free(copy);
3664 }
3665
3666 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3667
3668 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3669 wpa_cli_connected = 1;
3670 wpa_cli_last_id = new_id;
3671 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3672 }
3673 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3674 if (wpa_cli_connected) {
3675 wpa_cli_connected = 0;
3676 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3677 }
3678 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3679 wpa_cli_exec(action_file, ctrl_ifname, pos);
3680 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3681 wpa_cli_exec(action_file, ctrl_ifname, pos);
3682 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3683 wpa_cli_exec(action_file, ctrl_ifname, pos);
3684 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3685 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003686 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3687 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003688 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3689 wpa_cli_exec(action_file, ctrl_ifname, pos);
3690 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3691 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003692 } else if (str_match(pos, AP_STA_CONNECTED)) {
3693 wpa_cli_exec(action_file, ctrl_ifname, pos);
3694 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3695 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3697 printf("wpa_supplicant is terminating - stop monitoring\n");
3698 wpa_cli_quit = 1;
3699 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003700}
3701
3702
3703#ifndef CONFIG_ANSI_C_EXTRA
3704static void wpa_cli_action_cb(char *msg, size_t len)
3705{
3706 wpa_cli_action_process(msg);
3707}
3708#endif /* CONFIG_ANSI_C_EXTRA */
3709
3710
3711static void wpa_cli_reconnect(void)
3712{
3713 wpa_cli_close_connection();
3714 wpa_cli_open_connection(ctrl_ifname, 1);
3715}
3716
3717
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003718static void cli_event(const char *str)
3719{
3720 const char *start, *s;
3721
3722 start = os_strchr(str, '>');
3723 if (start == NULL)
3724 return;
3725
3726 start++;
3727
3728 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3729 s = os_strchr(start, ' ');
3730 if (s == NULL)
3731 return;
3732 s = os_strchr(s + 1, ' ');
3733 if (s == NULL)
3734 return;
3735 cli_txt_list_add(&bsses, s + 1);
3736 return;
3737 }
3738
3739 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3740 s = os_strchr(start, ' ');
3741 if (s == NULL)
3742 return;
3743 s = os_strchr(s + 1, ' ');
3744 if (s == NULL)
3745 return;
3746 cli_txt_list_del_addr(&bsses, s + 1);
3747 return;
3748 }
3749
3750#ifdef CONFIG_P2P
3751 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3752 s = os_strstr(start, " p2p_dev_addr=");
3753 if (s == NULL)
3754 return;
3755 cli_txt_list_add_addr(&p2p_peers, s + 14);
3756 return;
3757 }
3758
3759 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3760 s = os_strstr(start, " p2p_dev_addr=");
3761 if (s == NULL)
3762 return;
3763 cli_txt_list_del_addr(&p2p_peers, s + 14);
3764 return;
3765 }
3766
3767 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3768 s = os_strchr(start, ' ');
3769 if (s == NULL)
3770 return;
3771 cli_txt_list_add_word(&p2p_groups, s + 1);
3772 return;
3773 }
3774
3775 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3776 s = os_strchr(start, ' ');
3777 if (s == NULL)
3778 return;
3779 cli_txt_list_del_word(&p2p_groups, s + 1);
3780 return;
3781 }
3782#endif /* CONFIG_P2P */
3783}
3784
3785
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3787{
3788 if (ctrl_conn == NULL) {
3789 wpa_cli_reconnect();
3790 return;
3791 }
3792 while (wpa_ctrl_pending(ctrl) > 0) {
3793 char buf[256];
3794 size_t len = sizeof(buf) - 1;
3795 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3796 buf[len] = '\0';
3797 if (action_monitor)
3798 wpa_cli_action_process(buf);
3799 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003800 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 if (wpa_cli_show_event(buf)) {
3802 edit_clear_line();
3803 printf("\r%s\n", buf);
3804 edit_redraw();
3805 }
3806 }
3807 } else {
3808 printf("Could not read pending message.\n");
3809 break;
3810 }
3811 }
3812
3813 if (wpa_ctrl_pending(ctrl) < 0) {
3814 printf("Connection to wpa_supplicant lost - trying to "
3815 "reconnect\n");
3816 wpa_cli_reconnect();
3817 }
3818}
3819
3820#define max_args 10
3821
3822static int tokenize_cmd(char *cmd, char *argv[])
3823{
3824 char *pos;
3825 int argc = 0;
3826
3827 pos = cmd;
3828 for (;;) {
3829 while (*pos == ' ')
3830 pos++;
3831 if (*pos == '\0')
3832 break;
3833 argv[argc] = pos;
3834 argc++;
3835 if (argc == max_args)
3836 break;
3837 if (*pos == '"') {
3838 char *pos2 = os_strrchr(pos, '"');
3839 if (pos2)
3840 pos = pos2 + 1;
3841 }
3842 while (*pos != '\0' && *pos != ' ')
3843 pos++;
3844 if (*pos == ' ')
3845 *pos++ = '\0';
3846 }
3847
3848 return argc;
3849}
3850
3851
3852static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3853{
3854 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3855 printf("Connection to wpa_supplicant lost - trying to "
3856 "reconnect\n");
3857 wpa_cli_close_connection();
3858 }
3859 if (!ctrl_conn)
3860 wpa_cli_reconnect();
3861 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3862}
3863
3864
3865static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3866{
3867 eloop_terminate();
3868}
3869
3870
3871static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3872{
3873 wpa_cli_recv_pending(mon_conn, 0);
3874}
3875
3876
3877static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3878{
3879 char *argv[max_args];
3880 int argc;
3881 argc = tokenize_cmd(cmd, argv);
3882 if (argc)
3883 wpa_request(ctrl_conn, argc, argv);
3884}
3885
3886
3887static void wpa_cli_edit_eof_cb(void *ctx)
3888{
3889 eloop_terminate();
3890}
3891
3892
3893static void wpa_cli_interactive(void)
3894{
3895 char *home, *hfile = NULL;
3896
3897 printf("\nInteractive mode\n\n");
3898
3899 home = getenv("HOME");
3900 if (home) {
3901 const char *fname = ".wpa_cli_history";
3902 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3903 hfile = os_malloc(hfile_len);
3904 if (hfile)
3905 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3906 }
3907
3908 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3909 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3910 wpa_cli_edit_completion_cb, NULL, hfile);
3911 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3912
3913 eloop_run();
3914
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003915 cli_txt_list_flush(&p2p_peers);
3916 cli_txt_list_flush(&p2p_groups);
3917 cli_txt_list_flush(&bsses);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003918 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3919 os_free(hfile);
3920 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3921 wpa_cli_close_connection();
3922}
3923
3924
3925static void wpa_cli_action(struct wpa_ctrl *ctrl)
3926{
3927#ifdef CONFIG_ANSI_C_EXTRA
3928 /* TODO: ANSI C version(?) */
3929 printf("Action processing not supported in ANSI C build.\n");
3930#else /* CONFIG_ANSI_C_EXTRA */
3931 fd_set rfds;
3932 int fd, res;
3933 struct timeval tv;
3934 char buf[256]; /* note: large enough to fit in unsolicited messages */
3935 size_t len;
3936
3937 fd = wpa_ctrl_get_fd(ctrl);
3938
3939 while (!wpa_cli_quit) {
3940 FD_ZERO(&rfds);
3941 FD_SET(fd, &rfds);
3942 tv.tv_sec = ping_interval;
3943 tv.tv_usec = 0;
3944 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3945 if (res < 0 && errno != EINTR) {
3946 perror("select");
3947 break;
3948 }
3949
3950 if (FD_ISSET(fd, &rfds))
3951 wpa_cli_recv_pending(ctrl, 1);
3952 else {
3953 /* verify that connection is still working */
3954 len = sizeof(buf) - 1;
3955 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3956 wpa_cli_action_cb) < 0 ||
3957 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3958 printf("wpa_supplicant did not reply to PING "
3959 "command - exiting\n");
3960 break;
3961 }
3962 }
3963 }
3964#endif /* CONFIG_ANSI_C_EXTRA */
3965}
3966
3967
3968static void wpa_cli_cleanup(void)
3969{
3970 wpa_cli_close_connection();
3971 if (pid_file)
3972 os_daemonize_terminate(pid_file);
3973
3974 os_program_deinit();
3975}
3976
3977static void wpa_cli_terminate(int sig)
3978{
3979 wpa_cli_cleanup();
3980 exit(0);
3981}
3982
3983
3984static char * wpa_cli_get_default_ifname(void)
3985{
3986 char *ifname = NULL;
3987
3988#ifdef CONFIG_CTRL_IFACE_UNIX
3989 struct dirent *dent;
3990 DIR *dir = opendir(ctrl_iface_dir);
3991 if (!dir) {
3992#ifdef ANDROID
3993 char ifprop[PROPERTY_VALUE_MAX];
3994 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3995 ifname = os_strdup(ifprop);
3996 printf("Using interface '%s'\n", ifname);
3997 return ifname;
3998 }
3999#endif /* ANDROID */
4000 return NULL;
4001 }
4002 while ((dent = readdir(dir))) {
4003#ifdef _DIRENT_HAVE_D_TYPE
4004 /*
4005 * Skip the file if it is not a socket. Also accept
4006 * DT_UNKNOWN (0) in case the C library or underlying
4007 * file system does not support d_type.
4008 */
4009 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4010 continue;
4011#endif /* _DIRENT_HAVE_D_TYPE */
4012 if (os_strcmp(dent->d_name, ".") == 0 ||
4013 os_strcmp(dent->d_name, "..") == 0)
4014 continue;
4015 printf("Selected interface '%s'\n", dent->d_name);
4016 ifname = os_strdup(dent->d_name);
4017 break;
4018 }
4019 closedir(dir);
4020#endif /* CONFIG_CTRL_IFACE_UNIX */
4021
4022#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004023#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07004024 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004025#else
4026 char buf[2048], *pos;
4027#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004028 size_t len;
4029 struct wpa_ctrl *ctrl;
4030 int ret;
4031
4032 ctrl = wpa_ctrl_open(NULL);
4033 if (ctrl == NULL)
4034 return NULL;
4035
4036 len = sizeof(buf) - 1;
4037 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4038 if (ret >= 0) {
4039 buf[len] = '\0';
4040 pos = os_strchr(buf, '\n');
4041 if (pos)
4042 *pos = '\0';
4043 ifname = os_strdup(buf);
4044 }
4045 wpa_ctrl_close(ctrl);
4046#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4047
4048 return ifname;
4049}
4050
4051
4052int main(int argc, char *argv[])
4053{
4054 int warning_displayed = 0;
4055 int c;
4056 int daemonize = 0;
4057 int ret = 0;
4058 const char *global = NULL;
4059
4060 if (os_program_init())
4061 return -1;
4062
4063 for (;;) {
4064 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
4065 if (c < 0)
4066 break;
4067 switch (c) {
4068 case 'a':
4069 action_file = optarg;
4070 break;
4071 case 'B':
4072 daemonize = 1;
4073 break;
4074 case 'g':
4075 global = optarg;
4076 break;
4077 case 'G':
4078 ping_interval = atoi(optarg);
4079 break;
4080 case 'h':
4081 usage();
4082 return 0;
4083 case 'v':
4084 printf("%s\n", wpa_cli_version);
4085 return 0;
4086 case 'i':
4087 os_free(ctrl_ifname);
4088 ctrl_ifname = os_strdup(optarg);
4089 break;
4090 case 'p':
4091 ctrl_iface_dir = optarg;
4092 break;
4093 case 'P':
4094 pid_file = optarg;
4095 break;
4096 default:
4097 usage();
4098 return -1;
4099 }
4100 }
4101
4102 interactive = (argc == optind) && (action_file == NULL);
4103
4104 if (interactive)
4105 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4106
4107 if (eloop_init())
4108 return -1;
4109
4110 if (global) {
4111#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4112 ctrl_conn = wpa_ctrl_open(NULL);
4113#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4114 ctrl_conn = wpa_ctrl_open(global);
4115#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4116 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004117 fprintf(stderr, "Failed to connect to wpa_supplicant "
4118 "global interface: %s error: %s\n",
4119 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120 return -1;
4121 }
4122 }
4123
4124#ifndef _WIN32_WCE
4125 signal(SIGINT, wpa_cli_terminate);
4126 signal(SIGTERM, wpa_cli_terminate);
4127#endif /* _WIN32_WCE */
4128
4129 if (ctrl_ifname == NULL)
4130 ctrl_ifname = wpa_cli_get_default_ifname();
4131
4132 if (interactive) {
4133 for (; !global;) {
4134 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
4135 if (warning_displayed)
4136 printf("Connection established.\n");
4137 break;
4138 }
4139
4140 if (!warning_displayed) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004141 printf("Could not connect to wpa_supplicant: "
4142 "%s - re-trying\n", ctrl_ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143 warning_displayed = 1;
4144 }
4145 os_sleep(1, 0);
4146 continue;
4147 }
4148 } else {
4149 if (!global &&
4150 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004151 fprintf(stderr, "Failed to connect to non-global "
4152 "ctrl_ifname: %s error: %s\n",
4153 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004154 return -1;
4155 }
4156
4157 if (action_file) {
4158 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4159 wpa_cli_attached = 1;
4160 } else {
4161 printf("Warning: Failed to attach to "
4162 "wpa_supplicant.\n");
4163 return -1;
4164 }
4165 }
4166 }
4167
4168 if (daemonize && os_daemonize(pid_file))
4169 return -1;
4170
4171 if (interactive)
4172 wpa_cli_interactive();
4173 else if (action_file)
4174 wpa_cli_action(ctrl_conn);
4175 else
4176 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
4177
4178 os_free(ctrl_ifname);
4179 eloop_destroy();
4180 wpa_cli_cleanup();
4181
4182 return ret;
4183}
4184
4185#else /* CONFIG_CTRL_IFACE */
4186int main(int argc, char *argv[])
4187{
4188 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4189 return -1;
4190}
4191#endif /* CONFIG_CTRL_IFACE */