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