blob: 4685970961a16ab556607857faae45f29ae48b04 [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,
2852 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2853 { "reconfigure", wpa_cli_cmd_reconfigure,
2854 cli_cmd_flag_none,
2855 "= force wpa_supplicant to re-read its configuration file" },
2856 { "terminate", wpa_cli_cmd_terminate,
2857 cli_cmd_flag_none,
2858 "= terminate wpa_supplicant" },
2859 { "interface_add", wpa_cli_cmd_interface_add,
2860 cli_cmd_flag_none,
2861 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2862 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2863 " are optional" },
2864 { "interface_remove", wpa_cli_cmd_interface_remove,
2865 cli_cmd_flag_none,
2866 "<ifname> = removes the interface" },
2867 { "interface_list", wpa_cli_cmd_interface_list,
2868 cli_cmd_flag_none,
2869 "= list available interfaces" },
2870 { "ap_scan", wpa_cli_cmd_ap_scan,
2871 cli_cmd_flag_none,
2872 "<value> = set ap_scan parameter" },
2873 { "scan_interval", wpa_cli_cmd_scan_interval,
2874 cli_cmd_flag_none,
2875 "<value> = set scan_interval parameter (in seconds)" },
2876 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2877 cli_cmd_flag_none,
2878 "<value> = set BSS expiration age parameter" },
2879 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2880 cli_cmd_flag_none,
2881 "<value> = set BSS expiration scan count parameter" },
2882 { "stkstart", wpa_cli_cmd_stkstart,
2883 cli_cmd_flag_none,
2884 "<addr> = request STK negotiation with <addr>" },
2885 { "ft_ds", wpa_cli_cmd_ft_ds,
2886 cli_cmd_flag_none,
2887 "<addr> = request over-the-DS FT with <addr>" },
2888 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2889 cli_cmd_flag_none,
2890 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2891 { "wps_pin", wpa_cli_cmd_wps_pin,
2892 cli_cmd_flag_sensitive,
2893 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2894 "hardcoded)" },
2895 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2896 cli_cmd_flag_sensitive,
2897 "<PIN> = verify PIN checksum" },
2898 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2899 "Cancels the pending WPS operation" },
2900#ifdef CONFIG_WPS_OOB
2901 { "wps_oob", wpa_cli_cmd_wps_oob,
2902 cli_cmd_flag_sensitive,
2903 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2904#endif /* CONFIG_WPS_OOB */
2905 { "wps_reg", wpa_cli_cmd_wps_reg,
2906 cli_cmd_flag_sensitive,
2907 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2908 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
2909 cli_cmd_flag_sensitive,
2910 "[params..] = enable/disable AP PIN" },
2911 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2912 cli_cmd_flag_none,
2913 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2914 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2915 cli_cmd_flag_none,
2916 "= stop Wi-Fi Protected Setup External Registrar" },
2917 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2918 cli_cmd_flag_sensitive,
2919 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2920 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2921 cli_cmd_flag_none,
2922 "<UUID> = accept an Enrollee PBC using External Registrar" },
2923 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2924 cli_cmd_flag_sensitive,
2925 "<UUID> <PIN> = learn AP configuration" },
2926 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2927 cli_cmd_flag_none,
2928 "<UUID> <network id> = set AP configuration for enrolling" },
2929 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2930 cli_cmd_flag_sensitive,
2931 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2932 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2933 cli_cmd_flag_none,
2934 "<addr> = request RSN authentication with <addr> in IBSS" },
2935#ifdef CONFIG_AP
2936 { "sta", wpa_cli_cmd_sta,
2937 cli_cmd_flag_none,
2938 "<addr> = get information about an associated station (AP)" },
2939 { "all_sta", wpa_cli_cmd_all_sta,
2940 cli_cmd_flag_none,
2941 "= get information about all associated stations (AP)" },
2942#endif /* CONFIG_AP */
2943 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2944 "= notification of suspend/hibernate" },
2945 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2946 "= notification of resume/thaw" },
2947 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2948 "= drop SA without deauth/disassoc (test command)" },
2949 { "roam", wpa_cli_cmd_roam,
2950 cli_cmd_flag_none,
2951 "<addr> = roam to the specified BSS" },
2952#ifdef CONFIG_P2P
2953 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2954 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2955 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2956 "= stop P2P Devices search" },
2957 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2958 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2959 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2960 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2961 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2962 "<ifname> = remove P2P group interface (terminate group if GO)" },
2963 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2964 "= add a new P2P group (local end as GO)" },
2965 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2966 "<addr> <method> = request provisioning discovery" },
2967 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2968 cli_cmd_flag_none,
2969 "= get the passphrase for a group (GO only)" },
2970 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2971 cli_cmd_flag_none,
2972 "<addr> <TLVs> = schedule service discovery request" },
2973 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2974 cli_cmd_flag_none,
2975 "<id> = cancel pending service discovery request" },
2976 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2977 cli_cmd_flag_none,
2978 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2979 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2980 cli_cmd_flag_none,
2981 "= indicate change in local services" },
2982 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2983 cli_cmd_flag_none,
2984 "<external> = set external processing of service discovery" },
2985 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2986 cli_cmd_flag_none,
2987 "= remove all stored service entries" },
2988 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2989 cli_cmd_flag_none,
2990 "<bonjour|upnp> <query|version> <response|service> = add a local "
2991 "service" },
2992 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2993 cli_cmd_flag_none,
2994 "<bonjour|upnp> <query|version> [|service] = remove a local "
2995 "service" },
2996 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2997 cli_cmd_flag_none,
2998 "<addr> = reject connection attempts from a specific peer" },
2999 { "p2p_invite", wpa_cli_cmd_p2p_invite,
3000 cli_cmd_flag_none,
3001 "<cmd> [peer=addr] = invite peer" },
3002 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
3003 "[discovered] = list known (optionally, only fully discovered) P2P "
3004 "peers" },
3005 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
3006 "<address> = show information about known P2P peer" },
3007 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
3008 "<field> <value> = set a P2P parameter" },
3009 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
3010 "= flush P2P state" },
3011 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
3012 "= cancel P2P group formation" },
3013 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
3014 "<address> = unauthorize a peer" },
3015 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
3016 "[<duration> <interval>] [<duration> <interval>] = request GO "
3017 "presence" },
3018 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
3019 "[<period> <interval>] = set extended listen timing" },
3020#endif /* CONFIG_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003021
3022#ifdef CONFIG_INTERWORKING
3023 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
3024 "= fetch ANQP information for all APs" },
3025 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
3026 "= stop fetch_anqp operation" },
3027 { "interworking_select", wpa_cli_cmd_interworking_select,
3028 cli_cmd_flag_none,
3029 "[auto] = perform Interworking network selection" },
3030 { "interworking_connect", wpa_cli_cmd_interworking_connect,
3031 cli_cmd_flag_none,
3032 "<BSSID> = connect using Interworking credentials" },
3033 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
3034 "<addr> <info id>[,<info id>]... = request ANQP information" },
3035#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003036 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
3037 "<0/1> = disable/enable automatic reconnection" },
3038 { "tdls_discover", wpa_cli_cmd_tdls_discover,
3039 cli_cmd_flag_none,
3040 "<addr> = request TDLS discovery with <addr>" },
3041 { "tdls_setup", wpa_cli_cmd_tdls_setup,
3042 cli_cmd_flag_none,
3043 "<addr> = request TDLS setup with <addr>" },
3044 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
3045 cli_cmd_flag_none,
3046 "<addr> = tear down TDLS with <addr>" },
3047 { "signal_poll", wpa_cli_cmd_signal_poll,
3048 cli_cmd_flag_none,
3049 "= get signal parameters" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003050 { "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none,
3051 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003052#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003053 { "driver", wpa_cli_cmd_driver,
3054 cli_cmd_flag_none,
3055 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003056#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003057 { NULL, NULL, cli_cmd_flag_none, NULL }
3058};
3059
3060
3061/*
3062 * Prints command usage, lines are padded with the specified string.
3063 */
3064static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3065{
3066 char c;
3067 size_t n;
3068
3069 printf("%s%s ", pad, cmd->cmd);
3070 for (n = 0; (c = cmd->usage[n]); n++) {
3071 printf("%c", c);
3072 if (c == '\n')
3073 printf("%s", pad);
3074 }
3075 printf("\n");
3076}
3077
3078
3079static void print_help(void)
3080{
3081 int n;
3082 printf("commands:\n");
3083 for (n = 0; wpa_cli_commands[n].cmd; n++)
3084 print_cmd_help(&wpa_cli_commands[n], " ");
3085}
3086
3087
3088static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3089{
3090 const char *c, *delim;
3091 int n;
3092 size_t len;
3093
3094 delim = os_strchr(cmd, ' ');
3095 if (delim)
3096 len = delim - cmd;
3097 else
3098 len = os_strlen(cmd);
3099
3100 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3101 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3102 return (wpa_cli_commands[n].flags &
3103 cli_cmd_flag_sensitive);
3104 }
3105 return 0;
3106}
3107
3108
3109static char ** wpa_list_cmd_list(void)
3110{
3111 char **res;
3112 int i, count;
3113
3114 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3115 res = os_zalloc(count * sizeof(char *));
3116 if (res == NULL)
3117 return NULL;
3118
3119 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3120 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3121 if (res[i] == NULL)
3122 break;
3123 }
3124
3125 return res;
3126}
3127
3128
3129static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3130 int pos)
3131{
3132 int i;
3133
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003134 if (os_strcasecmp(cmd, "bss") == 0)
3135 return wpa_cli_complete_bss(str, pos);
3136#ifdef CONFIG_P2P
3137 if (os_strcasecmp(cmd, "p2p_connect") == 0)
3138 return wpa_cli_complete_p2p_connect(str, pos);
3139 if (os_strcasecmp(cmd, "p2p_peer") == 0)
3140 return wpa_cli_complete_p2p_peer(str, pos);
3141 if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3142 return wpa_cli_complete_p2p_group_remove(str, pos);
3143#endif /* CONFIG_P2P */
3144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3146 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3147 edit_clear_line();
3148 printf("\r%s\n", wpa_cli_commands[i].usage);
3149 edit_redraw();
3150 break;
3151 }
3152 }
3153
3154 return NULL;
3155}
3156
3157
3158static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3159{
3160 char **res;
3161 const char *end;
3162 char *cmd;
3163
3164 end = os_strchr(str, ' ');
3165 if (end == NULL || str + pos < end)
3166 return wpa_list_cmd_list();
3167
3168 cmd = os_malloc(pos + 1);
3169 if (cmd == NULL)
3170 return NULL;
3171 os_memcpy(cmd, str, pos);
3172 cmd[end - str] = '\0';
3173 res = wpa_cli_cmd_completion(cmd, str, pos);
3174 os_free(cmd);
3175 return res;
3176}
3177
3178
3179static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3180{
3181 struct wpa_cli_cmd *cmd, *match = NULL;
3182 int count;
3183 int ret = 0;
3184
3185 count = 0;
3186 cmd = wpa_cli_commands;
3187 while (cmd->cmd) {
3188 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3189 {
3190 match = cmd;
3191 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3192 /* we have an exact match */
3193 count = 1;
3194 break;
3195 }
3196 count++;
3197 }
3198 cmd++;
3199 }
3200
3201 if (count > 1) {
3202 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3203 cmd = wpa_cli_commands;
3204 while (cmd->cmd) {
3205 if (os_strncasecmp(cmd->cmd, argv[0],
3206 os_strlen(argv[0])) == 0) {
3207 printf(" %s", cmd->cmd);
3208 }
3209 cmd++;
3210 }
3211 printf("\n");
3212 ret = 1;
3213 } else if (count == 0) {
3214 printf("Unknown command '%s'\n", argv[0]);
3215 ret = 1;
3216 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003217#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
3218 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
3219 redirect_interface = os_strdup(argv[1]);
3220 ret = match->handler(ctrl, argc - 2, &argv[2]);
3221 }
3222 else
3223#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224 ret = match->handler(ctrl, argc - 1, &argv[1]);
3225 }
3226
3227 return ret;
3228}
3229
3230
3231static int str_match(const char *a, const char *b)
3232{
3233 return os_strncmp(a, b, os_strlen(b)) == 0;
3234}
3235
3236
3237static int wpa_cli_exec(const char *program, const char *arg1,
3238 const char *arg2)
3239{
3240 char *cmd;
3241 size_t len;
3242 int res;
3243 int ret = 0;
3244
3245 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3246 cmd = os_malloc(len);
3247 if (cmd == NULL)
3248 return -1;
3249 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3250 if (res < 0 || (size_t) res >= len) {
3251 os_free(cmd);
3252 return -1;
3253 }
3254 cmd[len - 1] = '\0';
3255#ifndef _WIN32_WCE
3256 if (system(cmd) < 0)
3257 ret = -1;
3258#endif /* _WIN32_WCE */
3259 os_free(cmd);
3260
3261 return ret;
3262}
3263
3264
3265static void wpa_cli_action_process(const char *msg)
3266{
3267 const char *pos;
3268 char *copy = NULL, *id, *pos2;
3269
3270 pos = msg;
3271 if (*pos == '<') {
3272 /* skip priority */
3273 pos = os_strchr(pos, '>');
3274 if (pos)
3275 pos++;
3276 else
3277 pos = msg;
3278 }
3279
3280 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3281 int new_id = -1;
3282 os_unsetenv("WPA_ID");
3283 os_unsetenv("WPA_ID_STR");
3284 os_unsetenv("WPA_CTRL_DIR");
3285
3286 pos = os_strstr(pos, "[id=");
3287 if (pos)
3288 copy = os_strdup(pos + 4);
3289
3290 if (copy) {
3291 pos2 = id = copy;
3292 while (*pos2 && *pos2 != ' ')
3293 pos2++;
3294 *pos2++ = '\0';
3295 new_id = atoi(id);
3296 os_setenv("WPA_ID", id, 1);
3297 while (*pos2 && *pos2 != '=')
3298 pos2++;
3299 if (*pos2 == '=')
3300 pos2++;
3301 id = pos2;
3302 while (*pos2 && *pos2 != ']')
3303 pos2++;
3304 *pos2 = '\0';
3305 os_setenv("WPA_ID_STR", id, 1);
3306 os_free(copy);
3307 }
3308
3309 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3310
3311 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3312 wpa_cli_connected = 1;
3313 wpa_cli_last_id = new_id;
3314 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3315 }
3316 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3317 if (wpa_cli_connected) {
3318 wpa_cli_connected = 0;
3319 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3320 }
3321 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3322 wpa_cli_exec(action_file, ctrl_ifname, pos);
3323 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3324 wpa_cli_exec(action_file, ctrl_ifname, pos);
3325 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3326 wpa_cli_exec(action_file, ctrl_ifname, pos);
3327 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3328 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003329 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3330 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003331 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3332 wpa_cli_exec(action_file, ctrl_ifname, pos);
3333 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3334 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003335 } else if (str_match(pos, AP_STA_CONNECTED)) {
3336 wpa_cli_exec(action_file, ctrl_ifname, pos);
3337 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3338 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3340 printf("wpa_supplicant is terminating - stop monitoring\n");
3341 wpa_cli_quit = 1;
3342 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343}
3344
3345
3346#ifndef CONFIG_ANSI_C_EXTRA
3347static void wpa_cli_action_cb(char *msg, size_t len)
3348{
3349 wpa_cli_action_process(msg);
3350}
3351#endif /* CONFIG_ANSI_C_EXTRA */
3352
3353
3354static void wpa_cli_reconnect(void)
3355{
3356 wpa_cli_close_connection();
3357 wpa_cli_open_connection(ctrl_ifname, 1);
3358}
3359
3360
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003361static void cli_event(const char *str)
3362{
3363 const char *start, *s;
3364
3365 start = os_strchr(str, '>');
3366 if (start == NULL)
3367 return;
3368
3369 start++;
3370
3371 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3372 s = os_strchr(start, ' ');
3373 if (s == NULL)
3374 return;
3375 s = os_strchr(s + 1, ' ');
3376 if (s == NULL)
3377 return;
3378 cli_txt_list_add(&bsses, s + 1);
3379 return;
3380 }
3381
3382 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3383 s = os_strchr(start, ' ');
3384 if (s == NULL)
3385 return;
3386 s = os_strchr(s + 1, ' ');
3387 if (s == NULL)
3388 return;
3389 cli_txt_list_del_addr(&bsses, s + 1);
3390 return;
3391 }
3392
3393#ifdef CONFIG_P2P
3394 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3395 s = os_strstr(start, " p2p_dev_addr=");
3396 if (s == NULL)
3397 return;
3398 cli_txt_list_add_addr(&p2p_peers, s + 14);
3399 return;
3400 }
3401
3402 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3403 s = os_strstr(start, " p2p_dev_addr=");
3404 if (s == NULL)
3405 return;
3406 cli_txt_list_del_addr(&p2p_peers, s + 14);
3407 return;
3408 }
3409
3410 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3411 s = os_strchr(start, ' ');
3412 if (s == NULL)
3413 return;
3414 cli_txt_list_add_word(&p2p_groups, s + 1);
3415 return;
3416 }
3417
3418 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3419 s = os_strchr(start, ' ');
3420 if (s == NULL)
3421 return;
3422 cli_txt_list_del_word(&p2p_groups, s + 1);
3423 return;
3424 }
3425#endif /* CONFIG_P2P */
3426}
3427
3428
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003429static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3430{
3431 if (ctrl_conn == NULL) {
3432 wpa_cli_reconnect();
3433 return;
3434 }
3435 while (wpa_ctrl_pending(ctrl) > 0) {
3436 char buf[256];
3437 size_t len = sizeof(buf) - 1;
3438 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3439 buf[len] = '\0';
3440 if (action_monitor)
3441 wpa_cli_action_process(buf);
3442 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003443 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444 if (wpa_cli_show_event(buf)) {
3445 edit_clear_line();
3446 printf("\r%s\n", buf);
3447 edit_redraw();
3448 }
3449 }
3450 } else {
3451 printf("Could not read pending message.\n");
3452 break;
3453 }
3454 }
3455
3456 if (wpa_ctrl_pending(ctrl) < 0) {
3457 printf("Connection to wpa_supplicant lost - trying to "
3458 "reconnect\n");
3459 wpa_cli_reconnect();
3460 }
3461}
3462
3463#define max_args 10
3464
3465static int tokenize_cmd(char *cmd, char *argv[])
3466{
3467 char *pos;
3468 int argc = 0;
3469
3470 pos = cmd;
3471 for (;;) {
3472 while (*pos == ' ')
3473 pos++;
3474 if (*pos == '\0')
3475 break;
3476 argv[argc] = pos;
3477 argc++;
3478 if (argc == max_args)
3479 break;
3480 if (*pos == '"') {
3481 char *pos2 = os_strrchr(pos, '"');
3482 if (pos2)
3483 pos = pos2 + 1;
3484 }
3485 while (*pos != '\0' && *pos != ' ')
3486 pos++;
3487 if (*pos == ' ')
3488 *pos++ = '\0';
3489 }
3490
3491 return argc;
3492}
3493
3494
3495static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3496{
3497 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3498 printf("Connection to wpa_supplicant lost - trying to "
3499 "reconnect\n");
3500 wpa_cli_close_connection();
3501 }
3502 if (!ctrl_conn)
3503 wpa_cli_reconnect();
3504 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3505}
3506
3507
3508static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3509{
3510 eloop_terminate();
3511}
3512
3513
3514static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3515{
3516 wpa_cli_recv_pending(mon_conn, 0);
3517}
3518
3519
3520static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3521{
3522 char *argv[max_args];
3523 int argc;
3524 argc = tokenize_cmd(cmd, argv);
3525 if (argc)
3526 wpa_request(ctrl_conn, argc, argv);
3527}
3528
3529
3530static void wpa_cli_edit_eof_cb(void *ctx)
3531{
3532 eloop_terminate();
3533}
3534
3535
3536static void wpa_cli_interactive(void)
3537{
3538 char *home, *hfile = NULL;
3539
3540 printf("\nInteractive mode\n\n");
3541
3542 home = getenv("HOME");
3543 if (home) {
3544 const char *fname = ".wpa_cli_history";
3545 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3546 hfile = os_malloc(hfile_len);
3547 if (hfile)
3548 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3549 }
3550
3551 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3552 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3553 wpa_cli_edit_completion_cb, NULL, hfile);
3554 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3555
3556 eloop_run();
3557
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003558 cli_txt_list_flush(&p2p_peers);
3559 cli_txt_list_flush(&p2p_groups);
3560 cli_txt_list_flush(&bsses);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3562 os_free(hfile);
3563 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3564 wpa_cli_close_connection();
3565}
3566
3567
3568static void wpa_cli_action(struct wpa_ctrl *ctrl)
3569{
3570#ifdef CONFIG_ANSI_C_EXTRA
3571 /* TODO: ANSI C version(?) */
3572 printf("Action processing not supported in ANSI C build.\n");
3573#else /* CONFIG_ANSI_C_EXTRA */
3574 fd_set rfds;
3575 int fd, res;
3576 struct timeval tv;
3577 char buf[256]; /* note: large enough to fit in unsolicited messages */
3578 size_t len;
3579
3580 fd = wpa_ctrl_get_fd(ctrl);
3581
3582 while (!wpa_cli_quit) {
3583 FD_ZERO(&rfds);
3584 FD_SET(fd, &rfds);
3585 tv.tv_sec = ping_interval;
3586 tv.tv_usec = 0;
3587 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3588 if (res < 0 && errno != EINTR) {
3589 perror("select");
3590 break;
3591 }
3592
3593 if (FD_ISSET(fd, &rfds))
3594 wpa_cli_recv_pending(ctrl, 1);
3595 else {
3596 /* verify that connection is still working */
3597 len = sizeof(buf) - 1;
3598 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3599 wpa_cli_action_cb) < 0 ||
3600 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3601 printf("wpa_supplicant did not reply to PING "
3602 "command - exiting\n");
3603 break;
3604 }
3605 }
3606 }
3607#endif /* CONFIG_ANSI_C_EXTRA */
3608}
3609
3610
3611static void wpa_cli_cleanup(void)
3612{
3613 wpa_cli_close_connection();
3614 if (pid_file)
3615 os_daemonize_terminate(pid_file);
3616
3617 os_program_deinit();
3618}
3619
3620static void wpa_cli_terminate(int sig)
3621{
3622 wpa_cli_cleanup();
3623 exit(0);
3624}
3625
3626
3627static char * wpa_cli_get_default_ifname(void)
3628{
3629 char *ifname = NULL;
3630
3631#ifdef CONFIG_CTRL_IFACE_UNIX
3632 struct dirent *dent;
3633 DIR *dir = opendir(ctrl_iface_dir);
3634 if (!dir) {
3635#ifdef ANDROID
3636 char ifprop[PROPERTY_VALUE_MAX];
3637 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3638 ifname = os_strdup(ifprop);
3639 printf("Using interface '%s'\n", ifname);
3640 return ifname;
3641 }
3642#endif /* ANDROID */
3643 return NULL;
3644 }
3645 while ((dent = readdir(dir))) {
3646#ifdef _DIRENT_HAVE_D_TYPE
3647 /*
3648 * Skip the file if it is not a socket. Also accept
3649 * DT_UNKNOWN (0) in case the C library or underlying
3650 * file system does not support d_type.
3651 */
3652 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3653 continue;
3654#endif /* _DIRENT_HAVE_D_TYPE */
3655 if (os_strcmp(dent->d_name, ".") == 0 ||
3656 os_strcmp(dent->d_name, "..") == 0)
3657 continue;
3658 printf("Selected interface '%s'\n", dent->d_name);
3659 ifname = os_strdup(dent->d_name);
3660 break;
3661 }
3662 closedir(dir);
3663#endif /* CONFIG_CTRL_IFACE_UNIX */
3664
3665#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003666#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003667 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003668#else
3669 char buf[2048], *pos;
3670#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003671 size_t len;
3672 struct wpa_ctrl *ctrl;
3673 int ret;
3674
3675 ctrl = wpa_ctrl_open(NULL);
3676 if (ctrl == NULL)
3677 return NULL;
3678
3679 len = sizeof(buf) - 1;
3680 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3681 if (ret >= 0) {
3682 buf[len] = '\0';
3683 pos = os_strchr(buf, '\n');
3684 if (pos)
3685 *pos = '\0';
3686 ifname = os_strdup(buf);
3687 }
3688 wpa_ctrl_close(ctrl);
3689#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3690
3691 return ifname;
3692}
3693
3694
3695int main(int argc, char *argv[])
3696{
3697 int warning_displayed = 0;
3698 int c;
3699 int daemonize = 0;
3700 int ret = 0;
3701 const char *global = NULL;
3702
3703 if (os_program_init())
3704 return -1;
3705
3706 for (;;) {
3707 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3708 if (c < 0)
3709 break;
3710 switch (c) {
3711 case 'a':
3712 action_file = optarg;
3713 break;
3714 case 'B':
3715 daemonize = 1;
3716 break;
3717 case 'g':
3718 global = optarg;
3719 break;
3720 case 'G':
3721 ping_interval = atoi(optarg);
3722 break;
3723 case 'h':
3724 usage();
3725 return 0;
3726 case 'v':
3727 printf("%s\n", wpa_cli_version);
3728 return 0;
3729 case 'i':
3730 os_free(ctrl_ifname);
3731 ctrl_ifname = os_strdup(optarg);
3732 break;
3733 case 'p':
3734 ctrl_iface_dir = optarg;
3735 break;
3736 case 'P':
3737 pid_file = optarg;
3738 break;
3739 default:
3740 usage();
3741 return -1;
3742 }
3743 }
3744
3745 interactive = (argc == optind) && (action_file == NULL);
3746
3747 if (interactive)
3748 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3749
3750 if (eloop_init())
3751 return -1;
3752
3753 if (global) {
3754#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3755 ctrl_conn = wpa_ctrl_open(NULL);
3756#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3757 ctrl_conn = wpa_ctrl_open(global);
3758#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3759 if (ctrl_conn == NULL) {
3760 perror("Failed to connect to wpa_supplicant - "
3761 "wpa_ctrl_open");
3762 return -1;
3763 }
3764 }
3765
3766#ifndef _WIN32_WCE
3767 signal(SIGINT, wpa_cli_terminate);
3768 signal(SIGTERM, wpa_cli_terminate);
3769#endif /* _WIN32_WCE */
3770
3771 if (ctrl_ifname == NULL)
3772 ctrl_ifname = wpa_cli_get_default_ifname();
3773
3774 if (interactive) {
3775 for (; !global;) {
3776 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3777 if (warning_displayed)
3778 printf("Connection established.\n");
3779 break;
3780 }
3781
3782 if (!warning_displayed) {
3783 printf("Could not connect to wpa_supplicant - "
3784 "re-trying\n");
3785 warning_displayed = 1;
3786 }
3787 os_sleep(1, 0);
3788 continue;
3789 }
3790 } else {
3791 if (!global &&
3792 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3793 perror("Failed to connect to wpa_supplicant - "
3794 "wpa_ctrl_open");
3795 return -1;
3796 }
3797
3798 if (action_file) {
3799 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3800 wpa_cli_attached = 1;
3801 } else {
3802 printf("Warning: Failed to attach to "
3803 "wpa_supplicant.\n");
3804 return -1;
3805 }
3806 }
3807 }
3808
3809 if (daemonize && os_daemonize(pid_file))
3810 return -1;
3811
3812 if (interactive)
3813 wpa_cli_interactive();
3814 else if (action_file)
3815 wpa_cli_action(ctrl_conn);
3816 else
3817 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3818
3819 os_free(ctrl_ifname);
3820 eloop_destroy();
3821 wpa_cli_cleanup();
3822
3823 return ret;
3824}
3825
3826#else /* CONFIG_CTRL_IFACE */
3827int main(int argc, char *argv[])
3828{
3829 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3830 return -1;
3831}
3832#endif /* CONFIG_CTRL_IFACE */