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