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