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