blob: 5a0af0dc9bba358198187eadb40cfa5316b40e0c [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
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"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080031"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800336 if (os_snprintf_error(flen, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 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 Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800451 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800457 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700535static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
536 char *argv[])
537{
538 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
539}
540
541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700542static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
543{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700544 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700545 return 0;
546}
547
548
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549static char ** wpa_cli_complete_help(const char *str, int pos)
550{
551 int arg = get_cmd_arg_num(str, pos);
552 char **res = NULL;
553
554 switch (arg) {
555 case 1:
556 res = wpa_list_cmd_list();
557 break;
558 }
559
560 return res;
561}
562
563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
567 return 0;
568}
569
570
571static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
572{
573 wpa_cli_quit = 1;
574 if (interactive)
575 eloop_terminate();
576 return 0;
577}
578
579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
581{
582 char cmd[256];
583 int res;
584
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700585 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800586 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800587 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700588 printf("Too long SET command.\n");
589 return -1;
590 }
591 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700592 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700593
594 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
595}
596
597
598static char ** wpa_cli_complete_set(const char *str, int pos)
599{
600 int arg = get_cmd_arg_num(str, pos);
601 const char *fields[] = {
602 /* runtime values */
603 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
604 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
605 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
606 "wps_fragment_size", "wps_version_number", "ampdu",
607 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
608 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
609 "no_keep_alive",
610 /* global configuration parameters */
611 "eapol_version", "ap_scan", "disable_scan_offload",
612 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800613 "pkcs11_module_path", "openssl_ciphers",
614 "pcsc_reader", "pcsc_pin",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700615 "driver_param", "dot11RSNAConfigPMKLifetime",
616 "dot11RSNAConfigPMKReauthThreshold",
617 "dot11RSNAConfigSATimeout",
618 "update_config", "load_dynamic_eap", "uuid", "device_name",
619 "manufacturer", "model_name", "model_number", "serial_number",
620 "device_type", "os_version", "config_methods",
621 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
622 "p2p_listen_reg_class", "p2p_listen_channel",
623 "p2p_oper_reg_class", "p2p_oper_channel",
624 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
625 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700626 "p2p_no_go_freq",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700627 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700628 "p2p_go_vht",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700629 "p2p_ignore_shared_freq", "country", "bss_max_count",
630 "bss_expiration_age", "bss_expiration_scan_count",
631 "filter_ssids", "filter_rssi", "max_num_sta",
632 "disassoc_low_ack", "hs20", "interworking", "hessid",
633 "access_network_type", "pbc_in_m1", "autoscan",
634 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
635 "wps_nfc_dev_pw", "ext_password_backend",
636 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
637 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt97672262014-02-03 13:02:54 -0800638 "ignore_old_scan_res", "freq_list", "external_sim",
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700639 "tdls_external_control", "p2p_search_delay"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700640 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700641 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700642
643 if (arg == 1) {
644 char **res = os_calloc(num_fields + 1, sizeof(char *));
645 if (res == NULL)
646 return NULL;
647 for (i = 0; i < num_fields; i++) {
648 res[i] = os_strdup(fields[i]);
649 if (res[i] == NULL)
650 return res;
651 }
652 return res;
653 }
654
655 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
656 return cli_txt_list_array(&bsses);
657
658 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659}
660
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800661static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
662{
663 return wpa_ctrl_command(ctrl, "DUMP");
664}
665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666
667static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
668{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700669 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670}
671
672
673static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "LOGOFF");
676}
677
678
679static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
680{
681 return wpa_ctrl_command(ctrl, "LOGON");
682}
683
684
685static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
686 char *argv[])
687{
688 return wpa_ctrl_command(ctrl, "REASSOCIATE");
689}
690
691
Dmitry Shmidt98660862014-03-11 17:26:21 -0700692static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
694 return wpa_ctrl_command(ctrl, "REATTACH");
695}
696
697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702}
703
704
705static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
706{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700707 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708}
709
710
711static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
712 char *argv[])
713{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700714 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700715}
716
717
718static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
719 char *argv[])
720{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700721 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722}
723
724
725static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
727{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729}
730
731
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700732static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
733{
734 char cmd[256];
735 int res;
736
737 if (argc < 1)
738 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
739 else
740 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800741 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700742 printf("Too long BSS_FLUSH command.\n");
743 return -1;
744 }
745 return wpa_ctrl_command(ctrl, cmd);
746}
747
748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
750 char *argv[])
751{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700752 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753}
754
755
756static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
757{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700758 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759}
760
761
762static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
763{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700764 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700765}
766
767
768static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
769{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 if (argc == 0) {
771 printf("Invalid WPS_PIN command: need one or two arguments:\n"
772 "- BSSID: use 'any' to select any\n"
773 "- PIN: optional, used only with devices that have no "
774 "display\n");
775 return -1;
776 }
777
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700778 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779}
780
781
782static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
783 char *argv[])
784{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700785 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786}
787
788
789static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
790 char *argv[])
791{
792 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
793}
794
795
Dmitry Shmidt04949592012-07-19 12:16:46 -0700796#ifdef CONFIG_WPS_NFC
797
798static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
799{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700800 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700801}
802
803
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800804static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
805 char *argv[])
806{
807 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
808}
809
810
Dmitry Shmidt04949592012-07-19 12:16:46 -0700811static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
812 char *argv[])
813{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700814 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700815}
816
817
818static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
819 char *argv[])
820{
821 int ret;
822 char *buf;
823 size_t buflen;
824
825 if (argc != 1) {
826 printf("Invalid 'wps_nfc_tag_read' command - one argument "
827 "is required.\n");
828 return -1;
829 }
830
831 buflen = 18 + os_strlen(argv[0]);
832 buf = os_malloc(buflen);
833 if (buf == NULL)
834 return -1;
835 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
836
837 ret = wpa_ctrl_command(ctrl, buf);
838 os_free(buf);
839
840 return ret;
841}
842
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800843
844static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
845 char *argv[])
846{
847 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
848}
849
850
851static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
852 char *argv[])
853{
854 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
855}
856
857
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800858static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
859 char *argv[])
860{
861 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
862}
863
Dmitry Shmidt04949592012-07-19 12:16:46 -0700864#endif /* CONFIG_WPS_NFC */
865
866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700867static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
868{
869 char cmd[256];
870 int res;
871
872 if (argc == 2)
873 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
874 argv[0], argv[1]);
875 else if (argc == 5 || argc == 6) {
876 char ssid_hex[2 * 32 + 1];
877 char key_hex[2 * 64 + 1];
878 int i;
879
880 ssid_hex[0] = '\0';
881 for (i = 0; i < 32; i++) {
882 if (argv[2][i] == '\0')
883 break;
884 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
885 }
886
887 key_hex[0] = '\0';
888 if (argc == 6) {
889 for (i = 0; i < 64; i++) {
890 if (argv[5][i] == '\0')
891 break;
892 os_snprintf(&key_hex[i * 2], 3, "%02x",
893 argv[5][i]);
894 }
895 }
896
897 res = os_snprintf(cmd, sizeof(cmd),
898 "WPS_REG %s %s %s %s %s %s",
899 argv[0], argv[1], ssid_hex, argv[3], argv[4],
900 key_hex);
901 } else {
902 printf("Invalid WPS_REG command: need two arguments:\n"
903 "- BSSID of the target AP\n"
904 "- AP PIN\n");
905 printf("Alternatively, six arguments can be used to "
906 "reconfigure the AP:\n"
907 "- BSSID of the target AP\n"
908 "- AP PIN\n"
909 "- new SSID\n"
910 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
911 "- new encr (NONE, WEP, TKIP, CCMP)\n"
912 "- new key\n");
913 return -1;
914 }
915
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800916 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917 printf("Too long WPS_REG command.\n");
918 return -1;
919 }
920 return wpa_ctrl_command(ctrl, cmd);
921}
922
923
924static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
925 char *argv[])
926{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700927 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928}
929
930
931static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
932 char *argv[])
933{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700934 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935}
936
937
938static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
941 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
942
943}
944
945
946static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
947 char *argv[])
948{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700949 if (argc < 2) {
950 printf("Invalid WPS_ER_PIN command: need at least two "
951 "arguments:\n"
952 "- UUID: use 'any' to select any\n"
953 "- PIN: Enrollee PIN\n"
954 "optional: - Enrollee MAC address\n");
955 return -1;
956 }
957
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700958 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959}
960
961
962static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
963 char *argv[])
964{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700965 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966}
967
968
969static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
970 char *argv[])
971{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972 if (argc != 2) {
973 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
974 "- UUID: specify which AP to use\n"
975 "- PIN: AP PIN\n");
976 return -1;
977 }
978
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700979 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980}
981
982
983static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
984 char *argv[])
985{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986 if (argc != 2) {
987 printf("Invalid WPS_ER_SET_CONFIG command: need two "
988 "arguments:\n"
989 "- UUID: specify which AP to use\n"
990 "- Network configuration id\n");
991 return -1;
992 }
993
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700994 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995}
996
997
998static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
999 char *argv[])
1000{
1001 char cmd[256];
1002 int res;
1003
1004 if (argc == 5 || argc == 6) {
1005 char ssid_hex[2 * 32 + 1];
1006 char key_hex[2 * 64 + 1];
1007 int i;
1008
1009 ssid_hex[0] = '\0';
1010 for (i = 0; i < 32; i++) {
1011 if (argv[2][i] == '\0')
1012 break;
1013 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1014 }
1015
1016 key_hex[0] = '\0';
1017 if (argc == 6) {
1018 for (i = 0; i < 64; i++) {
1019 if (argv[5][i] == '\0')
1020 break;
1021 os_snprintf(&key_hex[i * 2], 3, "%02x",
1022 argv[5][i]);
1023 }
1024 }
1025
1026 res = os_snprintf(cmd, sizeof(cmd),
1027 "WPS_ER_CONFIG %s %s %s %s %s %s",
1028 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1029 key_hex);
1030 } else {
1031 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1032 "- AP UUID\n"
1033 "- AP PIN\n"
1034 "- new SSID\n"
1035 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1036 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1037 "- new key\n");
1038 return -1;
1039 }
1040
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001041 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042 printf("Too long WPS_ER_CONFIG command.\n");
1043 return -1;
1044 }
1045 return wpa_ctrl_command(ctrl, cmd);
1046}
1047
1048
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049#ifdef CONFIG_WPS_NFC
1050static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1051 char *argv[])
1052{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001053 if (argc != 2) {
1054 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1055 "arguments:\n"
1056 "- WPS/NDEF: token format\n"
1057 "- UUID: specify which AP to use\n");
1058 return -1;
1059 }
1060
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001061 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001062}
1063#endif /* CONFIG_WPS_NFC */
1064
1065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1067{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001068 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069}
1070
1071
1072static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1073{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001074 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075}
1076
1077
1078static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1079{
1080 char cmd[256], *pos, *end;
1081 int i, ret;
1082
1083 if (argc < 2) {
1084 printf("Invalid IDENTITY command: needs two arguments "
1085 "(network id and identity)\n");
1086 return -1;
1087 }
1088
1089 end = cmd + sizeof(cmd);
1090 pos = cmd;
1091 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1092 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001093 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094 printf("Too long IDENTITY command.\n");
1095 return -1;
1096 }
1097 pos += ret;
1098 for (i = 2; i < argc; i++) {
1099 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001100 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 printf("Too long IDENTITY command.\n");
1102 return -1;
1103 }
1104 pos += ret;
1105 }
1106
1107 return wpa_ctrl_command(ctrl, cmd);
1108}
1109
1110
1111static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1112{
1113 char cmd[256], *pos, *end;
1114 int i, ret;
1115
1116 if (argc < 2) {
1117 printf("Invalid PASSWORD command: needs two arguments "
1118 "(network id and password)\n");
1119 return -1;
1120 }
1121
1122 end = cmd + sizeof(cmd);
1123 pos = cmd;
1124 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1125 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001126 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127 printf("Too long PASSWORD command.\n");
1128 return -1;
1129 }
1130 pos += ret;
1131 for (i = 2; i < argc; i++) {
1132 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001133 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 printf("Too long PASSWORD command.\n");
1135 return -1;
1136 }
1137 pos += ret;
1138 }
1139
1140 return wpa_ctrl_command(ctrl, cmd);
1141}
1142
1143
1144static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1145 char *argv[])
1146{
1147 char cmd[256], *pos, *end;
1148 int i, ret;
1149
1150 if (argc < 2) {
1151 printf("Invalid NEW_PASSWORD command: needs two arguments "
1152 "(network id and password)\n");
1153 return -1;
1154 }
1155
1156 end = cmd + sizeof(cmd);
1157 pos = cmd;
1158 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1159 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001160 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001161 printf("Too long NEW_PASSWORD command.\n");
1162 return -1;
1163 }
1164 pos += ret;
1165 for (i = 2; i < argc; i++) {
1166 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001167 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168 printf("Too long NEW_PASSWORD command.\n");
1169 return -1;
1170 }
1171 pos += ret;
1172 }
1173
1174 return wpa_ctrl_command(ctrl, cmd);
1175}
1176
1177
1178static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1179{
1180 char cmd[256], *pos, *end;
1181 int i, ret;
1182
1183 if (argc < 2) {
1184 printf("Invalid PIN command: needs two arguments "
1185 "(network id and pin)\n");
1186 return -1;
1187 }
1188
1189 end = cmd + sizeof(cmd);
1190 pos = cmd;
1191 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1192 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001193 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 printf("Too long PIN command.\n");
1195 return -1;
1196 }
1197 pos += ret;
1198 for (i = 2; i < argc; i++) {
1199 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001200 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001201 printf("Too long PIN command.\n");
1202 return -1;
1203 }
1204 pos += ret;
1205 }
1206 return wpa_ctrl_command(ctrl, cmd);
1207}
1208
1209
1210static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1211{
1212 char cmd[256], *pos, *end;
1213 int i, ret;
1214
1215 if (argc < 2) {
1216 printf("Invalid OTP command: needs two arguments (network "
1217 "id and password)\n");
1218 return -1;
1219 }
1220
1221 end = cmd + sizeof(cmd);
1222 pos = cmd;
1223 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1224 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001225 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226 printf("Too long OTP command.\n");
1227 return -1;
1228 }
1229 pos += ret;
1230 for (i = 2; i < argc; i++) {
1231 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001232 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001233 printf("Too long OTP command.\n");
1234 return -1;
1235 }
1236 pos += ret;
1237 }
1238
1239 return wpa_ctrl_command(ctrl, cmd);
1240}
1241
1242
Dmitry Shmidt051af732013-10-22 13:52:46 -07001243static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1244{
1245 char cmd[256], *pos, *end;
1246 int i, ret;
1247
1248 if (argc < 2) {
1249 printf("Invalid SIM command: needs two arguments "
1250 "(network id and SIM operation response)\n");
1251 return -1;
1252 }
1253
1254 end = cmd + sizeof(cmd);
1255 pos = cmd;
1256 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1257 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001258 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001259 printf("Too long SIM command.\n");
1260 return -1;
1261 }
1262 pos += ret;
1263 for (i = 2; i < argc; i++) {
1264 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001265 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001266 printf("Too long SIM command.\n");
1267 return -1;
1268 }
1269 pos += ret;
1270 }
1271 return wpa_ctrl_command(ctrl, cmd);
1272}
1273
1274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001275static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1276 char *argv[])
1277{
1278 char cmd[256], *pos, *end;
1279 int i, ret;
1280
1281 if (argc < 2) {
1282 printf("Invalid PASSPHRASE command: needs two arguments "
1283 "(network id and passphrase)\n");
1284 return -1;
1285 }
1286
1287 end = cmd + sizeof(cmd);
1288 pos = cmd;
1289 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1290 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001291 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001292 printf("Too long PASSPHRASE command.\n");
1293 return -1;
1294 }
1295 pos += ret;
1296 for (i = 2; i < argc; i++) {
1297 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001298 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299 printf("Too long PASSPHRASE command.\n");
1300 return -1;
1301 }
1302 pos += ret;
1303 }
1304
1305 return wpa_ctrl_command(ctrl, cmd);
1306}
1307
1308
1309static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1310{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311 if (argc < 2) {
1312 printf("Invalid BSSID command: needs two arguments (network "
1313 "id and BSSID)\n");
1314 return -1;
1315 }
1316
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001317 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318}
1319
1320
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001321static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001323 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001324}
1325
1326
1327static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1328{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001329 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001330}
1331
1332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1334 char *argv[])
1335{
1336 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1337}
1338
1339
1340static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1341 char *argv[])
1342{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001343 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344}
1345
1346
1347static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1348 char *argv[])
1349{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001350 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001351}
1352
1353
1354static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1355 char *argv[])
1356{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001357 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001358}
1359
1360
1361static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1362 char *argv[])
1363{
1364 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1365}
1366
1367
1368static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1369 char *argv[])
1370{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001371 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372}
1373
1374
1375static void wpa_cli_show_network_variables(void)
1376{
1377 printf("set_network variables:\n"
1378 " ssid (network name, SSID)\n"
1379 " psk (WPA passphrase or pre-shared key)\n"
1380 " key_mgmt (key management protocol)\n"
1381 " identity (EAP identity)\n"
1382 " password (EAP password)\n"
1383 " ...\n"
1384 "\n"
1385 "Note: Values are entered in the same format as the "
1386 "configuration file is using,\n"
1387 "i.e., strings values need to be inside double quotation "
1388 "marks.\n"
1389 "For example: set_network 1 ssid \"network name\"\n"
1390 "\n"
1391 "Please see wpa_supplicant.conf documentation for full list "
1392 "of\navailable variables.\n");
1393}
1394
1395
1396static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1397 char *argv[])
1398{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399 if (argc == 0) {
1400 wpa_cli_show_network_variables();
1401 return 0;
1402 }
1403
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001404 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 printf("Invalid SET_NETWORK command: needs three arguments\n"
1406 "(network id, variable name, and value)\n");
1407 return -1;
1408 }
1409
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001410 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001411}
1412
1413
1414static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1415 char *argv[])
1416{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 if (argc == 0) {
1418 wpa_cli_show_network_variables();
1419 return 0;
1420 }
1421
1422 if (argc != 2) {
1423 printf("Invalid GET_NETWORK command: needs two arguments\n"
1424 "(network id and variable name)\n");
1425 return -1;
1426 }
1427
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001428 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001429}
1430
1431
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001432static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1433 char *argv[])
1434{
1435 if (argc == 0) {
1436 wpa_cli_show_network_variables();
1437 return 0;
1438 }
1439
1440 if (argc < 3) {
1441 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1442 "(src netid, dest netid, and variable name)\n");
1443 return -1;
1444 }
1445
1446 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1447}
1448
1449
Dmitry Shmidt04949592012-07-19 12:16:46 -07001450static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1451 char *argv[])
1452{
1453 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1454}
1455
1456
1457static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458{
1459 return wpa_ctrl_command(ctrl, "ADD_CRED");
1460}
1461
1462
1463static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1464 char *argv[])
1465{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001466 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001467}
1468
1469
1470static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001472 if (argc != 3) {
1473 printf("Invalid SET_CRED command: needs three arguments\n"
1474 "(cred id, variable name, and value)\n");
1475 return -1;
1476 }
1477
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001478 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001479}
1480
1481
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001482static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1483{
1484 if (argc != 2) {
1485 printf("Invalid GET_CRED command: needs two arguments\n"
1486 "(cred id, variable name)\n");
1487 return -1;
1488 }
1489
1490 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1491}
1492
1493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1495 char *argv[])
1496{
1497 return wpa_ctrl_command(ctrl, "DISCONNECT");
1498}
1499
1500
1501static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1502 char *argv[])
1503{
1504 return wpa_ctrl_command(ctrl, "RECONNECT");
1505}
1506
1507
1508static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1509 char *argv[])
1510{
1511 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1512}
1513
1514
1515static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001517 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001518}
1519
1520
1521static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1522 char *argv[])
1523{
1524 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1525}
1526
1527
1528static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1529{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001530 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531}
1532
1533
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001534static char ** wpa_cli_complete_bss(const char *str, int pos)
1535{
1536 int arg = get_cmd_arg_num(str, pos);
1537 char **res = NULL;
1538
1539 switch (arg) {
1540 case 1:
1541 res = cli_txt_list_array(&bsses);
1542 break;
1543 }
1544
1545 return res;
1546}
1547
1548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001549static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1550 char *argv[])
1551{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 if (argc < 1 || argc > 2) {
1553 printf("Invalid GET_CAPABILITY command: need either one or "
1554 "two arguments\n");
1555 return -1;
1556 }
1557
1558 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1559 printf("Invalid GET_CAPABILITY command: second argument, "
1560 "if any, must be 'strict'\n");
1561 return -1;
1562 }
1563
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001564 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001565}
1566
1567
1568static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1569{
1570 printf("Available interfaces:\n");
1571 return wpa_ctrl_command(ctrl, "INTERFACES");
1572}
1573
1574
1575static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1576{
1577 if (argc < 1) {
1578 wpa_cli_list_interfaces(ctrl);
1579 return 0;
1580 }
1581
1582 wpa_cli_close_connection();
1583 os_free(ctrl_ifname);
1584 ctrl_ifname = os_strdup(argv[0]);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001585 if (!ctrl_ifname) {
1586 printf("Failed to allocate memory\n");
1587 return 0;
1588 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001590 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 printf("Connected to interface '%s.\n", ctrl_ifname);
1592 } else {
1593 printf("Could not connect to interface '%s' - re-trying\n",
1594 ctrl_ifname);
1595 }
1596 return 0;
1597}
1598
1599
1600static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1601 char *argv[])
1602{
1603 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1604}
1605
1606
1607static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1608 char *argv[])
1609{
1610 return wpa_ctrl_command(ctrl, "TERMINATE");
1611}
1612
1613
1614static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1615 char *argv[])
1616{
1617 char cmd[256];
1618 int res;
1619
1620 if (argc < 1) {
1621 printf("Invalid INTERFACE_ADD command: needs at least one "
1622 "argument (interface name)\n"
1623 "All arguments: ifname confname driver ctrl_interface "
1624 "driver_param bridge_name\n");
1625 return -1;
1626 }
1627
1628 /*
1629 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1630 * <driver_param>TAB<bridge_name>
1631 */
1632 res = os_snprintf(cmd, sizeof(cmd),
1633 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1634 argv[0],
1635 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1636 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1637 argc > 5 ? argv[5] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001638 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639 return -1;
1640 cmd[sizeof(cmd) - 1] = '\0';
1641 return wpa_ctrl_command(ctrl, cmd);
1642}
1643
1644
1645static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1646 char *argv[])
1647{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001648 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649}
1650
1651
1652static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1653 char *argv[])
1654{
1655 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1656}
1657
1658
1659#ifdef CONFIG_AP
1660static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1661{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001662 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001663}
1664
1665
1666static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1667 char *addr, size_t addr_len)
1668{
1669 char buf[4096], *pos;
1670 size_t len;
1671 int ret;
1672
1673 if (ctrl_conn == NULL) {
1674 printf("Not connected to hostapd - command dropped.\n");
1675 return -1;
1676 }
1677 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001678 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679 wpa_cli_msg_cb);
1680 if (ret == -2) {
1681 printf("'%s' command timed out.\n", cmd);
1682 return -2;
1683 } else if (ret < 0) {
1684 printf("'%s' command failed.\n", cmd);
1685 return -1;
1686 }
1687
1688 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001689 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 return -1;
1691 printf("%s", buf);
1692
1693 pos = buf;
1694 while (*pos != '\0' && *pos != '\n')
1695 pos++;
1696 *pos = '\0';
1697 os_strlcpy(addr, buf, addr_len);
1698 return 0;
1699}
1700
1701
1702static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1703{
1704 char addr[32], cmd[64];
1705
1706 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1707 return 0;
1708 do {
1709 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1710 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1711
1712 return -1;
1713}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001714
1715
1716static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1717 char *argv[])
1718{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001719 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001720}
1721
1722
1723static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1724 char *argv[])
1725{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001726 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001727}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001728
1729static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1730 char *argv[])
1731{
1732 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1733}
1734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001735#endif /* CONFIG_AP */
1736
1737
1738static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1739{
1740 return wpa_ctrl_command(ctrl, "SUSPEND");
1741}
1742
1743
1744static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1745{
1746 return wpa_ctrl_command(ctrl, "RESUME");
1747}
1748
1749
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001750#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1752{
1753 return wpa_ctrl_command(ctrl, "DROP_SA");
1754}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001755#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001756
1757
1758static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1759{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001760 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761}
1762
1763
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001764#ifdef CONFIG_MESH
1765
1766static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
1767 char *argv[])
1768{
1769 return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
1770}
1771
1772
1773static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
1774 char *argv[])
1775{
1776 return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
1777}
1778
1779
1780static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
1781 char *argv[])
1782{
1783 return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
1784}
1785
1786#endif /* CONFIG_MESH */
1787
1788
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001789#ifdef CONFIG_P2P
1790
1791static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1792{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001793 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1794}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001797static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1798{
1799 char **res = NULL;
1800 int arg = get_cmd_arg_num(str, pos);
1801
1802 res = os_calloc(6, sizeof(char *));
1803 if (res == NULL)
1804 return NULL;
1805 res[0] = os_strdup("type=social");
1806 if (res[0] == NULL) {
1807 os_free(res);
1808 return NULL;
1809 }
1810 res[1] = os_strdup("type=progressive");
1811 if (res[1] == NULL)
1812 return res;
1813 res[2] = os_strdup("delay=");
1814 if (res[2] == NULL)
1815 return res;
1816 res[3] = os_strdup("dev_id=");
1817 if (res[3] == NULL)
1818 return res;
1819 if (arg == 1)
1820 res[4] = os_strdup("[timeout]");
1821
1822 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823}
1824
1825
1826static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1827 char *argv[])
1828{
1829 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1830}
1831
1832
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001833static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
1834 char *argv[])
1835{
1836 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
1837}
1838
1839
1840static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
1841 char *argv[])
1842{
1843 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
1844}
1845
1846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1848 char *argv[])
1849{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001850 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851}
1852
1853
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001854static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1855{
1856 int arg = get_cmd_arg_num(str, pos);
1857 char **res = NULL;
1858
1859 switch (arg) {
1860 case 1:
1861 res = cli_txt_list_array(&p2p_peers);
1862 break;
1863 }
1864
1865 return res;
1866}
1867
1868
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1870 char *argv[])
1871{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001872 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001873}
1874
1875
1876static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1877 char *argv[])
1878{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001879 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880}
1881
1882
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001883static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1884{
1885 int arg = get_cmd_arg_num(str, pos);
1886 char **res = NULL;
1887
1888 switch (arg) {
1889 case 1:
1890 res = cli_txt_list_array(&p2p_groups);
1891 break;
1892 }
1893
1894 return res;
1895}
1896
1897
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1899 char *argv[])
1900{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001901 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902}
1903
1904
1905static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1906 char *argv[])
1907{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001908 if (argc != 2 && argc != 3) {
1909 printf("Invalid P2P_PROV_DISC command: needs at least "
1910 "two arguments, address and config method\n"
1911 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912 return -1;
1913 }
1914
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001915 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916}
1917
1918
1919static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1920 char *argv[])
1921{
1922 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1923}
1924
1925
1926static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1927 char *argv[])
1928{
1929 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001931 if (argc < 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001933 "or more arguments (address and TLVs)\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 return -1;
1935 }
1936
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001937 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 return wpa_ctrl_command(ctrl, cmd);
1940}
1941
1942
1943static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1944 int argc, char *argv[])
1945{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001946 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947}
1948
1949
1950static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1951 char *argv[])
1952{
1953 char cmd[4096];
1954 int res;
1955
1956 if (argc != 4) {
1957 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1958 "arguments (freq, address, dialog token, and TLVs)\n");
1959 return -1;
1960 }
1961
1962 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1963 argv[0], argv[1], argv[2], argv[3]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001964 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001965 return -1;
1966 cmd[sizeof(cmd) - 1] = '\0';
1967 return wpa_ctrl_command(ctrl, cmd);
1968}
1969
1970
1971static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1972 char *argv[])
1973{
1974 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1975}
1976
1977
1978static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1979 int argc, char *argv[])
1980{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001981 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982}
1983
1984
1985static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1986 char *argv[])
1987{
1988 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1989}
1990
1991
1992static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1993 char *argv[])
1994{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001995 if (argc < 3) {
1996 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
1997 return -1;
1998 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002000 return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2001}
2002
2003
2004static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2005 char *argv[])
2006{
2007 if (argc < 5 || argc > 6) {
2008 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 "arguments\n");
2010 return -1;
2011 }
2012
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002013 return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014}
2015
2016
2017static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2018 char *argv[])
2019{
2020 char cmd[4096];
2021 int res;
2022
2023 if (argc != 2 && argc != 3) {
2024 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2025 "arguments\n");
2026 return -1;
2027 }
2028
2029 if (argc == 3)
2030 res = os_snprintf(cmd, sizeof(cmd),
2031 "P2P_SERVICE_DEL %s %s %s",
2032 argv[0], argv[1], argv[2]);
2033 else
2034 res = os_snprintf(cmd, sizeof(cmd),
2035 "P2P_SERVICE_DEL %s %s",
2036 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002037 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038 return -1;
2039 cmd[sizeof(cmd) - 1] = '\0';
2040 return wpa_ctrl_command(ctrl, cmd);
2041}
2042
2043
2044static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2045 int argc, char *argv[])
2046{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002047 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048}
2049
2050
2051static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2052 int argc, char *argv[])
2053{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002054 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055}
2056
2057
2058static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2059{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002060 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061}
2062
2063
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002064static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2065{
2066 int arg = get_cmd_arg_num(str, pos);
2067 char **res = NULL;
2068
2069 switch (arg) {
2070 case 1:
2071 res = cli_txt_list_array(&p2p_peers);
2072 break;
2073 }
2074
2075 return res;
2076}
2077
2078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2080 char *addr, size_t addr_len,
2081 int discovered)
2082{
2083 char buf[4096], *pos;
2084 size_t len;
2085 int ret;
2086
2087 if (ctrl_conn == NULL)
2088 return -1;
2089 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002090 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091 wpa_cli_msg_cb);
2092 if (ret == -2) {
2093 printf("'%s' command timed out.\n", cmd);
2094 return -2;
2095 } else if (ret < 0) {
2096 printf("'%s' command failed.\n", cmd);
2097 return -1;
2098 }
2099
2100 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002101 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 return -1;
2103
2104 pos = buf;
2105 while (*pos != '\0' && *pos != '\n')
2106 pos++;
2107 *pos++ = '\0';
2108 os_strlcpy(addr, buf, addr_len);
2109 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2110 printf("%s\n", addr);
2111 return 0;
2112}
2113
2114
2115static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2116{
2117 char addr[32], cmd[64];
2118 int discovered;
2119
2120 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2121
2122 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2123 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002124 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125 do {
2126 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2127 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2128 discovered) == 0);
2129
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002130 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131}
2132
2133
2134static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2135{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002136 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137}
2138
2139
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002140static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2141{
2142 int arg = get_cmd_arg_num(str, pos);
2143 const char *fields[] = {
2144 "discoverability",
2145 "managed",
2146 "listen_channel",
2147 "ssid_postfix",
2148 "noa",
2149 "ps",
2150 "oppps",
2151 "ctwindow",
2152 "disabled",
2153 "conc_pref",
2154 "force_long_sd",
2155 "peer_filter",
2156 "cross_connect",
2157 "go_apsd",
2158 "client_apsd",
2159 "disallow_freq",
2160 "disc_int",
2161 "per_sta_psk",
2162 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002163 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002164
2165 if (arg == 1) {
2166 char **res = os_calloc(num_fields + 1, sizeof(char *));
2167 if (res == NULL)
2168 return NULL;
2169 for (i = 0; i < num_fields; i++) {
2170 res[i] = os_strdup(fields[i]);
2171 if (res[i] == NULL)
2172 return res;
2173 }
2174 return res;
2175 }
2176
2177 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2178 return cli_txt_list_array(&p2p_peers);
2179
2180 return NULL;
2181}
2182
2183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2185{
2186 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2187}
2188
2189
2190static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2191 char *argv[])
2192{
2193 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2194}
2195
2196
2197static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2198 char *argv[])
2199{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002200 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002201}
2202
2203
2204static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2205 char *argv[])
2206{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 if (argc != 0 && argc != 2 && argc != 4) {
2208 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2209 "(preferred duration, interval; in microsecods).\n"
2210 "Optional second pair can be used to provide "
2211 "acceptable values.\n");
2212 return -1;
2213 }
2214
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002215 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216}
2217
2218
2219static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2220 char *argv[])
2221{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002222 if (argc != 0 && argc != 2) {
2223 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2224 "(availability period, availability interval; in "
2225 "millisecods).\n"
2226 "Extended Listen Timing can be cancelled with this "
2227 "command when used without parameters.\n");
2228 return -1;
2229 }
2230
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2232}
2233
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002234
2235static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
2238 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2239}
2240
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002241#endif /* CONFIG_P2P */
2242
2243#ifdef CONFIG_WIFI_DISPLAY
2244
2245static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2246 char *argv[])
2247{
2248 char cmd[100];
2249 int res;
2250
2251 if (argc != 1 && argc != 2) {
2252 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2253 "arguments (subelem, hexdump)\n");
2254 return -1;
2255 }
2256
2257 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2258 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002259 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 return -1;
2261 cmd[sizeof(cmd) - 1] = '\0';
2262 return wpa_ctrl_command(ctrl, cmd);
2263}
2264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002265
2266static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2267 char *argv[])
2268{
2269 char cmd[100];
2270 int res;
2271
2272 if (argc != 1) {
2273 printf("Invalid WFD_SUBELEM_GET command: needs one "
2274 "argument (subelem)\n");
2275 return -1;
2276 }
2277
2278 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2279 argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002280 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002281 return -1;
2282 cmd[sizeof(cmd) - 1] = '\0';
2283 return wpa_ctrl_command(ctrl, cmd);
2284}
2285#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286
2287
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002288#ifdef CONFIG_INTERWORKING
2289static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2290 char *argv[])
2291{
2292 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2293}
2294
2295
2296static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2297 char *argv[])
2298{
2299 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2300}
2301
2302
2303static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2304 char *argv[])
2305{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002306 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002307}
2308
2309
2310static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2311 char *argv[])
2312{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002313 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002314}
2315
2316
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002317static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2318 char *argv[])
2319{
2320 return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2321}
2322
2323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002324static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2325{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002326 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2327}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002328
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002329
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002330static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2331 char *argv[])
2332{
2333 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2334}
2335
2336
2337static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2338 char *argv[])
2339{
2340 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002341}
2342#endif /* CONFIG_INTERWORKING */
2343
2344
Dmitry Shmidt04949592012-07-19 12:16:46 -07002345#ifdef CONFIG_HS20
2346
2347static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2348 char *argv[])
2349{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002351}
2352
2353
2354static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2355 char *argv[])
2356{
2357 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002358
2359 if (argc == 0) {
2360 printf("Command needs one or two arguments (dst mac addr and "
2361 "optional home realm)\n");
2362 return -1;
2363 }
2364
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002365 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2366 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002367 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002368
2369 return wpa_ctrl_command(ctrl, cmd);
2370}
2371
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002372
2373static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2374 char *argv[])
2375{
2376 char cmd[512];
2377
2378 if (argc < 2) {
2379 printf("Command needs two arguments (dst mac addr and "
2380 "icon name)\n");
2381 return -1;
2382 }
2383
2384 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2385 return -1;
2386
2387 return wpa_ctrl_command(ctrl, cmd);
2388}
2389
2390
2391static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2392{
2393 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2394}
2395
2396
2397static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2398 char *argv[])
2399{
2400 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2401}
2402
Dmitry Shmidt04949592012-07-19 12:16:46 -07002403#endif /* CONFIG_HS20 */
2404
2405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2407 char *argv[])
2408{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410}
2411
2412
2413static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2414 char *argv[])
2415{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002416 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417}
2418
2419
2420static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2421 char *argv[])
2422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424}
2425
2426
2427static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2428 char *argv[])
2429{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002430 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002431}
2432
2433
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002434static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2435 char *argv[])
2436{
2437 return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2438}
2439
2440
2441static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2442 char *argv[])
2443{
2444 return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2445}
2446
2447
2448static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2449 char *argv[])
2450{
2451 return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2452}
2453
2454
2455static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2456 char *argv[])
2457{
2458 return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2459}
2460
2461
2462static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2463 char *argv[])
2464{
2465 return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2466}
2467
2468
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2470 char *argv[])
2471{
2472 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2473}
2474
2475
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002476static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2477 char *argv[])
2478{
2479 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2480}
2481
2482
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002483static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2484 char *argv[])
2485{
2486 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2487}
2488
Dmitry Shmidt04949592012-07-19 12:16:46 -07002489
2490#ifdef CONFIG_AUTOSCAN
2491
2492static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2493{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002494 if (argc == 0)
2495 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2496
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002498}
2499
2500#endif /* CONFIG_AUTOSCAN */
2501
2502
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002503#ifdef CONFIG_WNM
2504
2505static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2506{
2507 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2508}
2509
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002510
2511static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2512{
2513 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2514}
2515
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002516#endif /* CONFIG_WNM */
2517
2518
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2520{
2521 if (argc == 0)
2522 return -1;
2523 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2524}
2525
2526
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002527#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002528static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2529{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002530 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002531}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002532#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002533
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002535static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2536{
2537 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2538}
2539
2540
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002541static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2542{
2543 return wpa_ctrl_command(ctrl, "FLUSH");
2544}
2545
2546
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002547static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2548{
2549 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2550}
2551
2552
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002553static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2554 char *argv[])
2555{
2556 return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2557}
2558
2559
2560static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2561{
2562 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2563}
2564
2565
2566static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2567 char *argv[])
2568{
2569 return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2570}
2571
2572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573enum wpa_cli_cmd_flags {
2574 cli_cmd_flag_none = 0x00,
2575 cli_cmd_flag_sensitive = 0x01
2576};
2577
2578struct wpa_cli_cmd {
2579 const char *cmd;
2580 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 enum wpa_cli_cmd_flags flags;
2583 const char *usage;
2584};
2585
2586static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 cli_cmd_flag_none,
2589 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "ifname", wpa_cli_cmd_ifname, NULL,
2591 cli_cmd_flag_none,
2592 "= get current interface name" },
2593 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594 cli_cmd_flag_none,
2595 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 cli_cmd_flag_none,
2598 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002599 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 cli_cmd_flag_none,
2601 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_none,
2604 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002607 "[command] = show usage help" },
2608 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_none,
2610 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 cli_cmd_flag_none,
2613 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 cli_cmd_flag_none,
2616 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 cli_cmd_flag_none,
2619 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002620 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 cli_cmd_flag_none,
2622 "= set variables (shows list of variables when run without "
2623 "arguments)" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002624 { "dump", wpa_cli_cmd_dump, NULL,
2625 cli_cmd_flag_none,
2626 "= dump config variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 cli_cmd_flag_none,
2632 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 cli_cmd_flag_none,
2635 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 cli_cmd_flag_none,
2638 "= show PMKSA cache" },
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002639 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2640 cli_cmd_flag_none,
2641 "= flush PMKSA cache entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 cli_cmd_flag_none,
2644 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002645 { "reattach", wpa_cli_cmd_reattach, NULL,
2646 cli_cmd_flag_none,
2647 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002648 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 cli_cmd_flag_none,
2650 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 cli_cmd_flag_none,
2653 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 cli_cmd_flag_sensitive,
2656 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_sensitive,
2659 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_sensitive,
2662 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 cli_cmd_flag_sensitive,
2665 "<network id> <password> = configure one-time-password for an SSID"
2666 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002667 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 cli_cmd_flag_sensitive,
2669 "<network id> <passphrase> = configure private key passphrase\n"
2670 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002671 { "sim", wpa_cli_cmd_sim, NULL,
2672 cli_cmd_flag_sensitive,
2673 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002678 cli_cmd_flag_none,
2679 "<BSSID> = add a BSSID to the blacklist\n"
2680 "blacklist clear = clear the blacklist\n"
2681 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002683 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002684 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002685 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 cli_cmd_flag_none,
2688 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_none,
2691 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 cli_cmd_flag_none,
2694 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 cli_cmd_flag_none,
2697 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002698 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 cli_cmd_flag_none,
2700 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 cli_cmd_flag_none,
2703 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 cli_cmd_flag_sensitive,
2706 "<network id> <variable> <value> = set network variables (shows\n"
2707 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 cli_cmd_flag_none,
2710 "<network id> <variable> = get network variables" },
Dmitry Shmidt684785c2014-05-12 13:34:29 -07002711 { "dup_network", wpa_cli_cmd_dup_network, NULL,
2712 cli_cmd_flag_none,
2713 "<src network id> <dst network id> <variable> = duplicate network variables"
2714 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002716 cli_cmd_flag_none,
2717 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002719 cli_cmd_flag_none,
2720 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002722 cli_cmd_flag_none,
2723 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002725 cli_cmd_flag_sensitive,
2726 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002727 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2728 cli_cmd_flag_none,
2729 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 cli_cmd_flag_none,
2732 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 cli_cmd_flag_none,
2735 "= disconnect and wait for reassociate/reconnect command before\n"
2736 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 cli_cmd_flag_none,
2739 "= like reassociate, but only takes effect if already disconnected"
2740 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 cli_cmd_flag_none,
2743 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 cli_cmd_flag_none,
2746 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 cli_cmd_flag_none,
2749 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002752 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 "= get capabilies" },
2754 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 cli_cmd_flag_none,
2756 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 cli_cmd_flag_none,
2759 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 cli_cmd_flag_none,
2762 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2763 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2764 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 cli_cmd_flag_none,
2767 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002768 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 cli_cmd_flag_none,
2770 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 cli_cmd_flag_none,
2773 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 cli_cmd_flag_none,
2776 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 cli_cmd_flag_none,
2779 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 cli_cmd_flag_none,
2782 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002784 cli_cmd_flag_none,
2785 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002786 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787 cli_cmd_flag_none,
2788 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002789 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002790 cli_cmd_flag_none,
2791 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 cli_cmd_flag_none,
2794 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 cli_cmd_flag_sensitive,
2797 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2798 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 cli_cmd_flag_sensitive,
2801 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002804#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002806 cli_cmd_flag_none,
2807 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002808 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2809 cli_cmd_flag_none,
2810 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002812 cli_cmd_flag_none,
2813 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002815 cli_cmd_flag_sensitive,
2816 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002817 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2818 cli_cmd_flag_none,
2819 "<NDEF> <WPS> = create NFC handover request" },
2820 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2821 cli_cmd_flag_none,
2822 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002823 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2824 cli_cmd_flag_none,
2825 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2826 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002827#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002828 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002829 cli_cmd_flag_sensitive,
2830 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 cli_cmd_flag_sensitive,
2833 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 cli_cmd_flag_none,
2836 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 cli_cmd_flag_none,
2839 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841 cli_cmd_flag_sensitive,
2842 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002844 cli_cmd_flag_none,
2845 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002846 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002847 cli_cmd_flag_sensitive,
2848 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002849 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002850 cli_cmd_flag_none,
2851 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002852 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002853 cli_cmd_flag_sensitive,
2854 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002855#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002857 cli_cmd_flag_none,
2858 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2859#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002860 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861 cli_cmd_flag_none,
2862 "<addr> = request RSN authentication with <addr> in IBSS" },
2863#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 cli_cmd_flag_none,
2866 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002867 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868 cli_cmd_flag_none,
2869 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002870 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002871 cli_cmd_flag_none,
2872 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002873 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002874 cli_cmd_flag_none,
2875 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002876 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2877 cli_cmd_flag_none,
2878 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2879 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2880 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002881#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002884 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002886#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002887 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002889#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002890 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002891 cli_cmd_flag_none,
2892 "<addr> = roam to the specified BSS" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002893#ifdef CONFIG_MESH
2894 { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
2895 cli_cmd_flag_none,
2896 "[ifname] = Create a new mesh interface" },
2897 { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
2898 cli_cmd_flag_none,
2899 "<network id> = join a mesh network (disable others)" },
2900 { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
2901 cli_cmd_flag_none,
2902 "<ifname> = Remove mesh group interface" },
2903#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002905 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2906 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002907 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002908 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909 "= stop P2P Devices search" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002910 { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
2911 cli_cmd_flag_none,
2912 "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
2913 { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
2914 cli_cmd_flag_none,
2915 "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002916 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2917 cli_cmd_flag_none,
2918 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2919 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002921 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2922 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002923 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002924 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2925 "[ht40] = add a new P2P group (local end as GO)" },
2926 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2927 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002929 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002930 cli_cmd_flag_none,
2931 "= get the passphrase for a group (GO only)" },
2932 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002933 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002934 "<addr> <TLVs> = schedule service discovery request" },
2935 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002936 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002937 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002938 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002939 cli_cmd_flag_none,
2940 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002941 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 cli_cmd_flag_none,
2943 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002944 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002945 cli_cmd_flag_none,
2946 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002947 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002948 cli_cmd_flag_none,
2949 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002950 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 cli_cmd_flag_none,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002952 "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002953 "service" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002954 { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
2955 cli_cmd_flag_none,
2956 "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
2957 "local ASP service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002958 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 cli_cmd_flag_none,
2960 "<bonjour|upnp> <query|version> [|service] = remove a local "
2961 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002962 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963 cli_cmd_flag_none,
2964 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002965 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 cli_cmd_flag_none,
2967 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002968 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002969 "[discovered] = list known (optionally, only fully discovered) P2P "
2970 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002971 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2972 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002974 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2975 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002976 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002977 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002978 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002979 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002981 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2982 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002984 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2985 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002986 "[<duration> <interval>] [<duration> <interval>] = request GO "
2987 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002988 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2989 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002990 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002991 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2992 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2993 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002995#ifdef CONFIG_WIFI_DISPLAY
2996 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2997 cli_cmd_flag_none,
2998 "<subelem> [contents] = set Wi-Fi Display subelement" },
2999 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3000 cli_cmd_flag_none,
3001 "<subelem> = get Wi-Fi Display subelement" },
3002#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003003#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003004 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003005 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003006 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3007 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003008 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003009 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003010 cli_cmd_flag_none,
3011 "[auto] = perform Interworking network selection" },
3012 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003013 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003014 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003015 { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3016 wpa_cli_complete_bss, cli_cmd_flag_none,
3017 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003018 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3019 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003020 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003021 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3022 cli_cmd_flag_none,
3023 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3024 { "gas_response_get", wpa_cli_cmd_gas_response_get,
3025 wpa_cli_complete_bss, cli_cmd_flag_none,
3026 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003027#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003028#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003029 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3030 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003031 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3032 },
3033 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003034 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003035 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003036 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3037 wpa_cli_complete_bss, cli_cmd_flag_none,
3038 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3039 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3040 "= fetch OSU provider information from all APs" },
3041 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3042 cli_cmd_flag_none,
3043 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003044#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003045 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3046 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003047 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003048 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 cli_cmd_flag_none,
3050 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003051 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 cli_cmd_flag_none,
3053 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003054 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055 cli_cmd_flag_none,
3056 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003057 { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3058 cli_cmd_flag_none,
3059 "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3060 "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3061 "= add WMM-AC traffic stream" },
3062 { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3063 cli_cmd_flag_none,
3064 "<tsid> = delete WMM-AC traffic stream" },
3065 { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3066 cli_cmd_flag_none,
3067 "= show status for Wireless Multi-Media Admission-Control" },
3068 { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3069 cli_cmd_flag_none,
3070 "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3071 "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3072 "with TDLS peer" },
3073 { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3074 cli_cmd_flag_none,
3075 "<addr> = disable channel switching with TDLS peer <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003076 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003077 cli_cmd_flag_none,
3078 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003079 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07003080 cli_cmd_flag_none,
3081 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003082 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3083 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003084 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003085#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003086 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003087 "[params] = Set or unset (if none) autoscan parameters" },
3088#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003089#ifdef CONFIG_WNM
3090 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3091 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07003092 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3093 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003094#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003095 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3096 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003097 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3098 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003099#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003100 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003101 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003102#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003103 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3104 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003105 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3106 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3107 },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003108 { "neighbor_rep_request",
3109 wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3110 "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3111 "(with optional given SSID, default: current SSID)"
3112 },
3113 { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3114 "= flush ERP keys" },
3115 { "mac_rand_scan",
3116 wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3117 "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3118 "mask=mac-address-mask] = scan MAC randomization"
3119 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003120 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003121};
3122
3123
3124/*
3125 * Prints command usage, lines are padded with the specified string.
3126 */
3127static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3128{
3129 char c;
3130 size_t n;
3131
3132 printf("%s%s ", pad, cmd->cmd);
3133 for (n = 0; (c = cmd->usage[n]); n++) {
3134 printf("%c", c);
3135 if (c == '\n')
3136 printf("%s", pad);
3137 }
3138 printf("\n");
3139}
3140
3141
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003142static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003143{
3144 int n;
3145 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003146 for (n = 0; wpa_cli_commands[n].cmd; n++) {
3147 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3148 print_cmd_help(&wpa_cli_commands[n], " ");
3149 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003150}
3151
3152
3153static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3154{
3155 const char *c, *delim;
3156 int n;
3157 size_t len;
3158
3159 delim = os_strchr(cmd, ' ');
3160 if (delim)
3161 len = delim - cmd;
3162 else
3163 len = os_strlen(cmd);
3164
3165 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3166 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3167 return (wpa_cli_commands[n].flags &
3168 cli_cmd_flag_sensitive);
3169 }
3170 return 0;
3171}
3172
3173
3174static char ** wpa_list_cmd_list(void)
3175{
3176 char **res;
3177 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003178 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003179
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003180 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003181 count += dl_list_len(&p2p_groups);
3182 count += dl_list_len(&ifnames);
3183 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 if (res == NULL)
3185 return NULL;
3186
3187 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3188 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3189 if (res[i] == NULL)
3190 break;
3191 }
3192
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003193 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3194 size_t len = 8 + os_strlen(e->txt);
3195 res[i] = os_malloc(len);
3196 if (res[i] == NULL)
3197 break;
3198 os_snprintf(res[i], len, "ifname=%s", e->txt);
3199 i++;
3200 }
3201
3202 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3203 res[i] = os_strdup(e->txt);
3204 if (res[i] == NULL)
3205 break;
3206 i++;
3207 }
3208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003209 return res;
3210}
3211
3212
3213static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3214 int pos)
3215{
3216 int i;
3217
3218 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3219 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003220 if (wpa_cli_commands[i].completion)
3221 return wpa_cli_commands[i].completion(str,
3222 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223 edit_clear_line();
3224 printf("\r%s\n", wpa_cli_commands[i].usage);
3225 edit_redraw();
3226 break;
3227 }
3228 }
3229
3230 return NULL;
3231}
3232
3233
3234static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3235{
3236 char **res;
3237 const char *end;
3238 char *cmd;
3239
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003240 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3241 end = os_strchr(str, ' ');
3242 if (end && pos > end - str) {
3243 pos -= end - str + 1;
3244 str = end + 1;
3245 }
3246 }
3247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003248 end = os_strchr(str, ' ');
3249 if (end == NULL || str + pos < end)
3250 return wpa_list_cmd_list();
3251
3252 cmd = os_malloc(pos + 1);
3253 if (cmd == NULL)
3254 return NULL;
3255 os_memcpy(cmd, str, pos);
3256 cmd[end - str] = '\0';
3257 res = wpa_cli_cmd_completion(cmd, str, pos);
3258 os_free(cmd);
3259 return res;
3260}
3261
3262
3263static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3264{
3265 struct wpa_cli_cmd *cmd, *match = NULL;
3266 int count;
3267 int ret = 0;
3268
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003269 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3270 ifname_prefix = argv[0] + 7;
3271 argv = &argv[1];
3272 argc--;
3273 } else
3274 ifname_prefix = NULL;
3275
3276 if (argc == 0)
3277 return -1;
3278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003279 count = 0;
3280 cmd = wpa_cli_commands;
3281 while (cmd->cmd) {
3282 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3283 {
3284 match = cmd;
3285 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3286 /* we have an exact match */
3287 count = 1;
3288 break;
3289 }
3290 count++;
3291 }
3292 cmd++;
3293 }
3294
3295 if (count > 1) {
3296 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3297 cmd = wpa_cli_commands;
3298 while (cmd->cmd) {
3299 if (os_strncasecmp(cmd->cmd, argv[0],
3300 os_strlen(argv[0])) == 0) {
3301 printf(" %s", cmd->cmd);
3302 }
3303 cmd++;
3304 }
3305 printf("\n");
3306 ret = 1;
3307 } else if (count == 0) {
3308 printf("Unknown command '%s'\n", argv[0]);
3309 ret = 1;
3310 } else {
3311 ret = match->handler(ctrl, argc - 1, &argv[1]);
3312 }
3313
3314 return ret;
3315}
3316
3317
3318static int str_match(const char *a, const char *b)
3319{
3320 return os_strncmp(a, b, os_strlen(b)) == 0;
3321}
3322
3323
3324static int wpa_cli_exec(const char *program, const char *arg1,
3325 const char *arg2)
3326{
Jouni Malinen772e12c2014-10-07 10:29:35 -07003327 char *arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003328 size_t len;
3329 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003330
Jouni Malinen772e12c2014-10-07 10:29:35 -07003331 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3332 arg = os_malloc(len);
3333 if (arg == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003334 return -1;
Jouni Malinen772e12c2014-10-07 10:29:35 -07003335 os_snprintf(arg, len, "%s %s", arg1, arg2);
3336 res = os_exec(program, arg, 1);
3337 os_free(arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003338
Jouni Malinen772e12c2014-10-07 10:29:35 -07003339 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003340}
3341
3342
3343static void wpa_cli_action_process(const char *msg)
3344{
3345 const char *pos;
3346 char *copy = NULL, *id, *pos2;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003347 const char *ifname = ctrl_ifname;
3348 char ifname_buf[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003349
3350 pos = msg;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003351 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3352 const char *end;
3353 end = os_strchr(pos + 7, ' ');
3354 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3355 pos += 7;
3356 os_memcpy(ifname_buf, pos, end - pos);
3357 ifname_buf[end - pos] = '\0';
3358 ifname = ifname_buf;
3359 pos = end + 1;
3360 }
3361 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362 if (*pos == '<') {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003363 const char *prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003364 /* skip priority */
3365 pos = os_strchr(pos, '>');
3366 if (pos)
3367 pos++;
3368 else
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003369 pos = prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370 }
3371
3372 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3373 int new_id = -1;
3374 os_unsetenv("WPA_ID");
3375 os_unsetenv("WPA_ID_STR");
3376 os_unsetenv("WPA_CTRL_DIR");
3377
3378 pos = os_strstr(pos, "[id=");
3379 if (pos)
3380 copy = os_strdup(pos + 4);
3381
3382 if (copy) {
3383 pos2 = id = copy;
3384 while (*pos2 && *pos2 != ' ')
3385 pos2++;
3386 *pos2++ = '\0';
3387 new_id = atoi(id);
3388 os_setenv("WPA_ID", id, 1);
3389 while (*pos2 && *pos2 != '=')
3390 pos2++;
3391 if (*pos2 == '=')
3392 pos2++;
3393 id = pos2;
3394 while (*pos2 && *pos2 != ']')
3395 pos2++;
3396 *pos2 = '\0';
3397 os_setenv("WPA_ID_STR", id, 1);
3398 os_free(copy);
3399 }
3400
3401 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3402
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003403 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404 wpa_cli_connected = 1;
3405 wpa_cli_last_id = new_id;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003406 wpa_cli_exec(action_file, ifname, "CONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407 }
3408 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3409 if (wpa_cli_connected) {
3410 wpa_cli_connected = 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003411 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003413 } else if (str_match(pos, MESH_GROUP_STARTED)) {
3414 wpa_cli_exec(action_file, ctrl_ifname, pos);
3415 } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3416 wpa_cli_exec(action_file, ctrl_ifname, pos);
3417 } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3418 wpa_cli_exec(action_file, ctrl_ifname, pos);
3419 } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3420 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003422 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003424 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003426 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003427 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003428 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003429 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003430 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003432 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003433 } else if (str_match(pos, WPS_EVENT_FAIL)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003434 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003435 } else if (str_match(pos, AP_STA_CONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003436 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003437 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003438 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003439 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003440 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003441 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003442 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003443 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003444 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003445 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3446 printf("wpa_supplicant is terminating - stop monitoring\n");
3447 wpa_cli_quit = 1;
3448 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003449}
3450
3451
3452#ifndef CONFIG_ANSI_C_EXTRA
3453static void wpa_cli_action_cb(char *msg, size_t len)
3454{
3455 wpa_cli_action_process(msg);
3456}
3457#endif /* CONFIG_ANSI_C_EXTRA */
3458
3459
3460static void wpa_cli_reconnect(void)
3461{
3462 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003463 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3464 return;
3465
3466 if (interactive) {
3467 edit_clear_line();
3468 printf("\rConnection to wpa_supplicant re-established\n");
3469 edit_redraw();
3470 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003471}
3472
3473
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003474static void cli_event(const char *str)
3475{
3476 const char *start, *s;
3477
3478 start = os_strchr(str, '>');
3479 if (start == NULL)
3480 return;
3481
3482 start++;
3483
3484 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3485 s = os_strchr(start, ' ');
3486 if (s == NULL)
3487 return;
3488 s = os_strchr(s + 1, ' ');
3489 if (s == NULL)
3490 return;
3491 cli_txt_list_add(&bsses, s + 1);
3492 return;
3493 }
3494
3495 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3496 s = os_strchr(start, ' ');
3497 if (s == NULL)
3498 return;
3499 s = os_strchr(s + 1, ' ');
3500 if (s == NULL)
3501 return;
3502 cli_txt_list_del_addr(&bsses, s + 1);
3503 return;
3504 }
3505
3506#ifdef CONFIG_P2P
3507 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3508 s = os_strstr(start, " p2p_dev_addr=");
3509 if (s == NULL)
3510 return;
3511 cli_txt_list_add_addr(&p2p_peers, s + 14);
3512 return;
3513 }
3514
3515 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3516 s = os_strstr(start, " p2p_dev_addr=");
3517 if (s == NULL)
3518 return;
3519 cli_txt_list_del_addr(&p2p_peers, s + 14);
3520 return;
3521 }
3522
3523 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3524 s = os_strchr(start, ' ');
3525 if (s == NULL)
3526 return;
3527 cli_txt_list_add_word(&p2p_groups, s + 1);
3528 return;
3529 }
3530
3531 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3532 s = os_strchr(start, ' ');
3533 if (s == NULL)
3534 return;
3535 cli_txt_list_del_word(&p2p_groups, s + 1);
3536 return;
3537 }
3538#endif /* CONFIG_P2P */
3539}
3540
3541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003542static int check_terminating(const char *msg)
3543{
3544 const char *pos = msg;
3545
3546 if (*pos == '<') {
3547 /* skip priority */
3548 pos = os_strchr(pos, '>');
3549 if (pos)
3550 pos++;
3551 else
3552 pos = msg;
3553 }
3554
3555 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3556 edit_clear_line();
3557 printf("\rConnection to wpa_supplicant lost - trying to "
3558 "reconnect\n");
3559 edit_redraw();
3560 wpa_cli_attached = 0;
3561 wpa_cli_close_connection();
3562 return 1;
3563 }
3564
3565 return 0;
3566}
3567
3568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003569static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3570{
3571 if (ctrl_conn == NULL) {
3572 wpa_cli_reconnect();
3573 return;
3574 }
3575 while (wpa_ctrl_pending(ctrl) > 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003576 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003577 size_t len = sizeof(buf) - 1;
3578 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3579 buf[len] = '\0';
3580 if (action_monitor)
3581 wpa_cli_action_process(buf);
3582 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003583 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 if (wpa_cli_show_event(buf)) {
3585 edit_clear_line();
3586 printf("\r%s\n", buf);
3587 edit_redraw();
3588 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003589
3590 if (interactive && check_terminating(buf) > 0)
3591 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 }
3593 } else {
3594 printf("Could not read pending message.\n");
3595 break;
3596 }
3597 }
3598
3599 if (wpa_ctrl_pending(ctrl) < 0) {
3600 printf("Connection to wpa_supplicant lost - trying to "
3601 "reconnect\n");
3602 wpa_cli_reconnect();
3603 }
3604}
3605
3606#define max_args 10
3607
3608static int tokenize_cmd(char *cmd, char *argv[])
3609{
3610 char *pos;
3611 int argc = 0;
3612
3613 pos = cmd;
3614 for (;;) {
3615 while (*pos == ' ')
3616 pos++;
3617 if (*pos == '\0')
3618 break;
3619 argv[argc] = pos;
3620 argc++;
3621 if (argc == max_args)
3622 break;
3623 if (*pos == '"') {
3624 char *pos2 = os_strrchr(pos, '"');
3625 if (pos2)
3626 pos = pos2 + 1;
3627 }
3628 while (*pos != '\0' && *pos != ' ')
3629 pos++;
3630 if (*pos == ' ')
3631 *pos++ = '\0';
3632 }
3633
3634 return argc;
3635}
3636
3637
3638static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3639{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003640 if (ctrl_conn) {
3641 int res;
3642 char *prefix = ifname_prefix;
3643
3644 ifname_prefix = NULL;
3645 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3646 ifname_prefix = prefix;
3647 if (res) {
3648 printf("Connection to wpa_supplicant lost - trying to "
3649 "reconnect\n");
3650 wpa_cli_close_connection();
3651 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 }
3653 if (!ctrl_conn)
3654 wpa_cli_reconnect();
3655 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3656}
3657
3658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003659static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3660{
3661 wpa_cli_recv_pending(mon_conn, 0);
3662}
3663
3664
3665static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3666{
3667 char *argv[max_args];
3668 int argc;
3669 argc = tokenize_cmd(cmd, argv);
3670 if (argc)
3671 wpa_request(ctrl_conn, argc, argv);
3672}
3673
3674
3675static void wpa_cli_edit_eof_cb(void *ctx)
3676{
3677 eloop_terminate();
3678}
3679
3680
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003681static int warning_displayed = 0;
3682static char *hfile = NULL;
3683static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003684
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003685static void start_edit(void)
3686{
3687 char *home;
3688 char *ps = NULL;
3689
3690#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3691 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3692#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003693
3694 home = getenv("HOME");
3695 if (home) {
3696 const char *fname = ".wpa_cli_history";
3697 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3698 hfile = os_malloc(hfile_len);
3699 if (hfile)
3700 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3701 }
3702
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003703 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3704 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3705 eloop_terminate();
3706 return;
3707 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003709 edit_started = 1;
3710 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3711}
3712
3713
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003714static void update_bssid_list(struct wpa_ctrl *ctrl)
3715{
3716 char buf[4096];
3717 size_t len = sizeof(buf);
3718 int ret;
3719 char *cmd = "BSS RANGE=ALL MASK=0x2";
3720 char *pos, *end;
3721
3722 if (ctrl == NULL)
3723 return;
3724 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3725 if (ret < 0)
3726 return;
3727 buf[len] = '\0';
3728
3729 pos = buf;
3730 while (pos) {
3731 pos = os_strstr(pos, "bssid=");
3732 if (pos == NULL)
3733 break;
3734 pos += 6;
3735 end = os_strchr(pos, '\n');
3736 if (end == NULL)
3737 break;
3738 *end = '\0';
3739 cli_txt_list_add(&bsses, pos);
3740 pos = end + 1;
3741 }
3742}
3743
3744
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003745static void update_ifnames(struct wpa_ctrl *ctrl)
3746{
3747 char buf[4096];
3748 size_t len = sizeof(buf);
3749 int ret;
3750 char *cmd = "INTERFACES";
3751 char *pos, *end;
3752 char txt[200];
3753
3754 cli_txt_list_flush(&ifnames);
3755
3756 if (ctrl == NULL)
3757 return;
3758 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3759 if (ret < 0)
3760 return;
3761 buf[len] = '\0';
3762
3763 pos = buf;
3764 while (pos) {
3765 end = os_strchr(pos, '\n');
3766 if (end == NULL)
3767 break;
3768 *end = '\0';
3769 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003770 if (!os_snprintf_error(sizeof(txt), ret))
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003771 cli_txt_list_add(&ifnames, txt);
3772 pos = end + 1;
3773 }
3774}
3775
3776
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003777static void try_connection(void *eloop_ctx, void *timeout_ctx)
3778{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003779 if (ctrl_conn)
3780 goto done;
3781
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003782 if (ctrl_ifname == NULL)
3783 ctrl_ifname = wpa_cli_get_default_ifname();
3784
3785 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3786 if (!warning_displayed) {
3787 printf("Could not connect to wpa_supplicant: "
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003788 "%s - re-trying\n",
3789 ctrl_ifname ? ctrl_ifname : "(nil)");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003790 warning_displayed = 1;
3791 }
3792 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3793 return;
3794 }
3795
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003796 update_bssid_list(ctrl_conn);
3797
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003798 if (warning_displayed)
3799 printf("Connection established.\n");
3800
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003801done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003802 start_edit();
3803}
3804
3805
3806static void wpa_cli_interactive(void)
3807{
3808 printf("\nInteractive mode\n\n");
3809
3810 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003811 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003812 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003814 cli_txt_list_flush(&p2p_peers);
3815 cli_txt_list_flush(&p2p_groups);
3816 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003817 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003818 if (edit_started)
3819 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003820 os_free(hfile);
3821 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3822 wpa_cli_close_connection();
3823}
3824
3825
3826static void wpa_cli_action(struct wpa_ctrl *ctrl)
3827{
3828#ifdef CONFIG_ANSI_C_EXTRA
3829 /* TODO: ANSI C version(?) */
3830 printf("Action processing not supported in ANSI C build.\n");
3831#else /* CONFIG_ANSI_C_EXTRA */
3832 fd_set rfds;
3833 int fd, res;
3834 struct timeval tv;
3835 char buf[256]; /* note: large enough to fit in unsolicited messages */
3836 size_t len;
3837
3838 fd = wpa_ctrl_get_fd(ctrl);
3839
3840 while (!wpa_cli_quit) {
3841 FD_ZERO(&rfds);
3842 FD_SET(fd, &rfds);
3843 tv.tv_sec = ping_interval;
3844 tv.tv_usec = 0;
3845 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3846 if (res < 0 && errno != EINTR) {
3847 perror("select");
3848 break;
3849 }
3850
3851 if (FD_ISSET(fd, &rfds))
3852 wpa_cli_recv_pending(ctrl, 1);
3853 else {
3854 /* verify that connection is still working */
3855 len = sizeof(buf) - 1;
3856 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3857 wpa_cli_action_cb) < 0 ||
3858 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3859 printf("wpa_supplicant did not reply to PING "
3860 "command - exiting\n");
3861 break;
3862 }
3863 }
3864 }
3865#endif /* CONFIG_ANSI_C_EXTRA */
3866}
3867
3868
3869static void wpa_cli_cleanup(void)
3870{
3871 wpa_cli_close_connection();
3872 if (pid_file)
3873 os_daemonize_terminate(pid_file);
3874
3875 os_program_deinit();
3876}
3877
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003878
3879static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003880{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003881 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003882}
3883
3884
3885static char * wpa_cli_get_default_ifname(void)
3886{
3887 char *ifname = NULL;
3888
3889#ifdef CONFIG_CTRL_IFACE_UNIX
3890 struct dirent *dent;
3891 DIR *dir = opendir(ctrl_iface_dir);
3892 if (!dir) {
3893#ifdef ANDROID
3894 char ifprop[PROPERTY_VALUE_MAX];
3895 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3896 ifname = os_strdup(ifprop);
3897 printf("Using interface '%s'\n", ifname);
3898 return ifname;
3899 }
3900#endif /* ANDROID */
3901 return NULL;
3902 }
3903 while ((dent = readdir(dir))) {
3904#ifdef _DIRENT_HAVE_D_TYPE
3905 /*
3906 * Skip the file if it is not a socket. Also accept
3907 * DT_UNKNOWN (0) in case the C library or underlying
3908 * file system does not support d_type.
3909 */
3910 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3911 continue;
3912#endif /* _DIRENT_HAVE_D_TYPE */
3913 if (os_strcmp(dent->d_name, ".") == 0 ||
3914 os_strcmp(dent->d_name, "..") == 0)
3915 continue;
3916 printf("Selected interface '%s'\n", dent->d_name);
3917 ifname = os_strdup(dent->d_name);
3918 break;
3919 }
3920 closedir(dir);
3921#endif /* CONFIG_CTRL_IFACE_UNIX */
3922
3923#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003924 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003925 size_t len;
3926 struct wpa_ctrl *ctrl;
3927 int ret;
3928
3929 ctrl = wpa_ctrl_open(NULL);
3930 if (ctrl == NULL)
3931 return NULL;
3932
3933 len = sizeof(buf) - 1;
3934 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3935 if (ret >= 0) {
3936 buf[len] = '\0';
3937 pos = os_strchr(buf, '\n');
3938 if (pos)
3939 *pos = '\0';
3940 ifname = os_strdup(buf);
3941 }
3942 wpa_ctrl_close(ctrl);
3943#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3944
3945 return ifname;
3946}
3947
3948
3949int main(int argc, char *argv[])
3950{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951 int c;
3952 int daemonize = 0;
3953 int ret = 0;
3954 const char *global = NULL;
3955
3956 if (os_program_init())
3957 return -1;
3958
3959 for (;;) {
3960 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3961 if (c < 0)
3962 break;
3963 switch (c) {
3964 case 'a':
3965 action_file = optarg;
3966 break;
3967 case 'B':
3968 daemonize = 1;
3969 break;
3970 case 'g':
3971 global = optarg;
3972 break;
3973 case 'G':
3974 ping_interval = atoi(optarg);
3975 break;
3976 case 'h':
3977 usage();
3978 return 0;
3979 case 'v':
3980 printf("%s\n", wpa_cli_version);
3981 return 0;
3982 case 'i':
3983 os_free(ctrl_ifname);
3984 ctrl_ifname = os_strdup(optarg);
3985 break;
3986 case 'p':
3987 ctrl_iface_dir = optarg;
3988 break;
3989 case 'P':
3990 pid_file = optarg;
3991 break;
3992 default:
3993 usage();
3994 return -1;
3995 }
3996 }
3997
3998 interactive = (argc == optind) && (action_file == NULL);
3999
4000 if (interactive)
4001 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4002
4003 if (eloop_init())
4004 return -1;
4005
4006 if (global) {
4007#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4008 ctrl_conn = wpa_ctrl_open(NULL);
4009#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4010 ctrl_conn = wpa_ctrl_open(global);
4011#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4012 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004013 fprintf(stderr, "Failed to connect to wpa_supplicant "
4014 "global interface: %s error: %s\n",
4015 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004016 return -1;
4017 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004018
4019 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004020 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004021 mon_conn = wpa_ctrl_open(global);
4022 if (mon_conn) {
4023 if (wpa_ctrl_attach(mon_conn) == 0) {
4024 wpa_cli_attached = 1;
4025 eloop_register_read_sock(
4026 wpa_ctrl_get_fd(mon_conn),
4027 wpa_cli_mon_receive,
4028 NULL, NULL);
4029 } else {
4030 printf("Failed to open monitor "
4031 "connection through global "
4032 "control interface\n");
4033 }
4034 }
4035 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004036 }
4037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004038 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004039
4040 if (ctrl_ifname == NULL)
4041 ctrl_ifname = wpa_cli_get_default_ifname();
4042
4043 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004044 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045 } else {
4046 if (!global &&
4047 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004048 fprintf(stderr, "Failed to connect to non-global "
4049 "ctrl_ifname: %s error: %s\n",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004050 ctrl_ifname ? ctrl_ifname : "(nil)",
4051 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004052 return -1;
4053 }
4054
4055 if (action_file) {
4056 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4057 wpa_cli_attached = 1;
4058 } else {
4059 printf("Warning: Failed to attach to "
4060 "wpa_supplicant.\n");
4061 return -1;
4062 }
4063 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004064
4065 if (daemonize && os_daemonize(pid_file))
4066 return -1;
4067
4068 if (action_file)
4069 wpa_cli_action(ctrl_conn);
4070 else
4071 ret = wpa_request(ctrl_conn, argc - optind,
4072 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 }
4074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 os_free(ctrl_ifname);
4076 eloop_destroy();
4077 wpa_cli_cleanup();
4078
4079 return ret;
4080}
4081
4082#else /* CONFIG_CTRL_IFACE */
4083int main(int argc, char *argv[])
4084{
4085 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4086 return -1;
4087}
4088#endif /* CONFIG_CTRL_IFACE */