blob: 2b40bbf847641daf5db80f5e5a37a7b7fc7ccf2d [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 */
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700611#ifdef CONFIG_CTRL_IFACE
612 "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
613#endif /* CONFIG_CTRL_IFACE */
614 "eapol_version", "ap_scan", "bgscan",
615#ifdef CONFIG_MESH
616 "user_mpm", "max_peer_links", "mesh_max_inactivity",
617#endif /* CONFIG_MESH */
618 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
619 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
620 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
621 "dot11RSNAConfigPMKLifetime",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700622 "dot11RSNAConfigPMKReauthThreshold",
623 "dot11RSNAConfigSATimeout",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700624#ifndef CONFIG_NO_CONFIG_WRITE
625 "update_config",
626#endif /* CONFIG_NO_CONFIG_WRITE */
627 "load_dynamic_eap",
628#ifdef CONFIG_WPS
629 "uuid", "device_name", "manufacturer", "model_name",
630 "model_number", "serial_number", "device_type", "os_version",
631 "config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
632#endif /* CONFIG_WPS */
633#ifdef CONFIG_P2P
634 "sec_device_type",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700635 "p2p_listen_reg_class", "p2p_listen_channel",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700636 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
637 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
638 "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
639 "p2p_no_go_freq", "p2p_add_cli_chan",
640 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
641 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
642 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
643 "ip_addr_start", "ip_addr_end",
644#endif /* CONFIG_P2P */
645 "country", "bss_max_count", "bss_expiration_age",
646 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
647 "max_num_sta", "disassoc_low_ack",
648#ifdef CONFIG_HS20
649 "hs20",
650#endif /* CONFIG_HS20 */
651 "interworking", "hessid", "access_network_type", "pbc_in_m1",
652 "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
653 "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700654 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700655 "sae_groups", "dtim_period", "beacon_int",
656 "ap_vendor_elements", "ignore_old_scan_res", "freq_list",
657 "scan_cur_freq", "sched_scan_interval",
658 "tdls_external_control", "osu_dir", "wowlan_triggers",
659 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
660 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
661 "reassoc_same_bss_optim"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700662 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700663 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700664
665 if (arg == 1) {
666 char **res = os_calloc(num_fields + 1, sizeof(char *));
667 if (res == NULL)
668 return NULL;
669 for (i = 0; i < num_fields; i++) {
670 res[i] = os_strdup(fields[i]);
671 if (res[i] == NULL)
672 return res;
673 }
674 return res;
675 }
676
677 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
678 return cli_txt_list_array(&bsses);
679
680 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681}
682
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800683static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
684{
685 return wpa_ctrl_command(ctrl, "DUMP");
686}
687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688
689static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
690{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700691 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692}
693
694
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700695static char ** wpa_cli_complete_get(const char *str, int pos)
696{
697 int arg = get_cmd_arg_num(str, pos);
698 const char *fields[] = {
699#ifdef CONFIG_CTRL_IFACE
700 "ctrl_interface", "ctrl_interface_group",
701#endif /* CONFIG_CTRL_IFACE */
702 "eapol_version", "ap_scan",
703#ifdef CONFIG_MESH
704 "user_mpm", "max_peer_links", "mesh_max_inactivity",
705#endif /* CONFIG_MESH */
706 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
707 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
708 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
709 "dot11RSNAConfigPMKLifetime",
710 "dot11RSNAConfigPMKReauthThreshold",
711 "dot11RSNAConfigSATimeout",
712#ifndef CONFIG_NO_CONFIG_WRITE
713 "update_config",
714#endif /* CONFIG_NO_CONFIG_WRITE */
715#ifdef CONFIG_WPS
716 "device_name", "manufacturer", "model_name", "model_number",
717 "serial_number", "config_methods", "wps_cred_processing",
718#endif /* CONFIG_WPS */
719#ifdef CONFIG_P2P
720 "p2p_listen_reg_class", "p2p_listen_channel",
721 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
722 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
723 "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
724 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
725 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
726 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
727 "ip_addr_start", "ip_addr_end",
728#endif /* CONFIG_P2P */
729 "bss_max_count", "bss_expiration_age",
730 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
731 "max_num_sta", "disassoc_low_ack",
732#ifdef CONFIG_HS20
733 "hs20",
734#endif /* CONFIG_HS20 */
735 "interworking", "access_network_type", "pbc_in_m1", "autoscan",
736 "wps_nfc_dev_pw_id", "ext_password_backend",
737 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
738 "dtim_period", "beacon_int", "ignore_old_scan_res",
739 "scan_cur_freq", "sched_scan_interval",
740 "tdls_external_control", "osu_dir", "wowlan_triggers",
741 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
742 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
743 "reassoc_same_bss_optim"
744 };
745 int i, num_fields = ARRAY_SIZE(fields);
746
747 if (arg == 1) {
748 char **res = os_calloc(num_fields + 1, sizeof(char *));
749 if (res == NULL)
750 return NULL;
751 for (i = 0; i < num_fields; i++) {
752 res[i] = os_strdup(fields[i]);
753 if (res[i] == NULL)
754 return res;
755 }
756 return res;
757 }
758
759 return NULL;
760}
761
762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
764{
765 return wpa_ctrl_command(ctrl, "LOGOFF");
766}
767
768
769static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
770{
771 return wpa_ctrl_command(ctrl, "LOGON");
772}
773
774
775static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
776 char *argv[])
777{
778 return wpa_ctrl_command(ctrl, "REASSOCIATE");
779}
780
781
Dmitry Shmidt98660862014-03-11 17:26:21 -0700782static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
783{
784 return wpa_ctrl_command(ctrl, "REATTACH");
785}
786
787
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
789 char *argv[])
790{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700791 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792}
793
794
795static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
796{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700797 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798}
799
800
801static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
802 char *argv[])
803{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700804 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805}
806
807
808static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
809 char *argv[])
810{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700811 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812}
813
814
815static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
816 char *argv[])
817{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700818 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819}
820
821
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700822static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
823{
824 char cmd[256];
825 int res;
826
827 if (argc < 1)
828 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
829 else
830 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800831 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700832 printf("Too long BSS_FLUSH command.\n");
833 return -1;
834 }
835 return wpa_ctrl_command(ctrl, cmd);
836}
837
838
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
840 char *argv[])
841{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700842 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843}
844
845
846static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
847{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700848 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849}
850
851
852static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
853{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700854 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855}
856
857
858static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
859{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700860 if (argc == 0) {
861 printf("Invalid WPS_PIN command: need one or two arguments:\n"
862 "- BSSID: use 'any' to select any\n"
863 "- PIN: optional, used only with devices that have no "
864 "display\n");
865 return -1;
866 }
867
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700868 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869}
870
871
872static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
873 char *argv[])
874{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700875 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876}
877
878
879static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
880 char *argv[])
881{
882 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
883}
884
885
Dmitry Shmidt04949592012-07-19 12:16:46 -0700886#ifdef CONFIG_WPS_NFC
887
888static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
889{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700890 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700891}
892
893
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800894static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
895 char *argv[])
896{
897 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
898}
899
900
Dmitry Shmidt04949592012-07-19 12:16:46 -0700901static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
902 char *argv[])
903{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700904 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700905}
906
907
908static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
909 char *argv[])
910{
911 int ret;
912 char *buf;
913 size_t buflen;
914
915 if (argc != 1) {
916 printf("Invalid 'wps_nfc_tag_read' command - one argument "
917 "is required.\n");
918 return -1;
919 }
920
921 buflen = 18 + os_strlen(argv[0]);
922 buf = os_malloc(buflen);
923 if (buf == NULL)
924 return -1;
925 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
926
927 ret = wpa_ctrl_command(ctrl, buf);
928 os_free(buf);
929
930 return ret;
931}
932
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800933
934static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
935 char *argv[])
936{
937 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
938}
939
940
941static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
942 char *argv[])
943{
944 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
945}
946
947
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800948static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
949 char *argv[])
950{
951 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
952}
953
Dmitry Shmidt04949592012-07-19 12:16:46 -0700954#endif /* CONFIG_WPS_NFC */
955
956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
958{
959 char cmd[256];
960 int res;
961
962 if (argc == 2)
963 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
964 argv[0], argv[1]);
965 else if (argc == 5 || argc == 6) {
966 char ssid_hex[2 * 32 + 1];
967 char key_hex[2 * 64 + 1];
968 int i;
969
970 ssid_hex[0] = '\0';
971 for (i = 0; i < 32; i++) {
972 if (argv[2][i] == '\0')
973 break;
974 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
975 }
976
977 key_hex[0] = '\0';
978 if (argc == 6) {
979 for (i = 0; i < 64; i++) {
980 if (argv[5][i] == '\0')
981 break;
982 os_snprintf(&key_hex[i * 2], 3, "%02x",
983 argv[5][i]);
984 }
985 }
986
987 res = os_snprintf(cmd, sizeof(cmd),
988 "WPS_REG %s %s %s %s %s %s",
989 argv[0], argv[1], ssid_hex, argv[3], argv[4],
990 key_hex);
991 } else {
992 printf("Invalid WPS_REG command: need two arguments:\n"
993 "- BSSID of the target AP\n"
994 "- AP PIN\n");
995 printf("Alternatively, six arguments can be used to "
996 "reconfigure the AP:\n"
997 "- BSSID of the target AP\n"
998 "- AP PIN\n"
999 "- new SSID\n"
1000 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1001 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1002 "- new key\n");
1003 return -1;
1004 }
1005
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001006 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 printf("Too long WPS_REG command.\n");
1008 return -1;
1009 }
1010 return wpa_ctrl_command(ctrl, cmd);
1011}
1012
1013
1014static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
1015 char *argv[])
1016{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001017 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018}
1019
1020
1021static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
1022 char *argv[])
1023{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001024 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025}
1026
1027
1028static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
1029 char *argv[])
1030{
1031 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
1032
1033}
1034
1035
1036static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
1037 char *argv[])
1038{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 if (argc < 2) {
1040 printf("Invalid WPS_ER_PIN command: need at least two "
1041 "arguments:\n"
1042 "- UUID: use 'any' to select any\n"
1043 "- PIN: Enrollee PIN\n"
1044 "optional: - Enrollee MAC address\n");
1045 return -1;
1046 }
1047
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001048 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049}
1050
1051
1052static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1053 char *argv[])
1054{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001055 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056}
1057
1058
1059static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1060 char *argv[])
1061{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 if (argc != 2) {
1063 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1064 "- UUID: specify which AP to use\n"
1065 "- PIN: AP PIN\n");
1066 return -1;
1067 }
1068
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001069 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070}
1071
1072
1073static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1074 char *argv[])
1075{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076 if (argc != 2) {
1077 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1078 "arguments:\n"
1079 "- UUID: specify which AP to use\n"
1080 "- Network configuration id\n");
1081 return -1;
1082 }
1083
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001084 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085}
1086
1087
1088static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1089 char *argv[])
1090{
1091 char cmd[256];
1092 int res;
1093
1094 if (argc == 5 || argc == 6) {
1095 char ssid_hex[2 * 32 + 1];
1096 char key_hex[2 * 64 + 1];
1097 int i;
1098
1099 ssid_hex[0] = '\0';
1100 for (i = 0; i < 32; i++) {
1101 if (argv[2][i] == '\0')
1102 break;
1103 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1104 }
1105
1106 key_hex[0] = '\0';
1107 if (argc == 6) {
1108 for (i = 0; i < 64; i++) {
1109 if (argv[5][i] == '\0')
1110 break;
1111 os_snprintf(&key_hex[i * 2], 3, "%02x",
1112 argv[5][i]);
1113 }
1114 }
1115
1116 res = os_snprintf(cmd, sizeof(cmd),
1117 "WPS_ER_CONFIG %s %s %s %s %s %s",
1118 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1119 key_hex);
1120 } else {
1121 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1122 "- AP UUID\n"
1123 "- AP PIN\n"
1124 "- new SSID\n"
1125 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1126 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1127 "- new key\n");
1128 return -1;
1129 }
1130
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001131 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 printf("Too long WPS_ER_CONFIG command.\n");
1133 return -1;
1134 }
1135 return wpa_ctrl_command(ctrl, cmd);
1136}
1137
1138
Dmitry Shmidt04949592012-07-19 12:16:46 -07001139#ifdef CONFIG_WPS_NFC
1140static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1141 char *argv[])
1142{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001143 if (argc != 2) {
1144 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1145 "arguments:\n"
1146 "- WPS/NDEF: token format\n"
1147 "- UUID: specify which AP to use\n");
1148 return -1;
1149 }
1150
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001151 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001152}
1153#endif /* CONFIG_WPS_NFC */
1154
1155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1157{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001158 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159}
1160
1161
1162static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1163{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001164 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165}
1166
1167
1168static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1169{
1170 char cmd[256], *pos, *end;
1171 int i, ret;
1172
1173 if (argc < 2) {
1174 printf("Invalid IDENTITY command: needs two arguments "
1175 "(network id and identity)\n");
1176 return -1;
1177 }
1178
1179 end = cmd + sizeof(cmd);
1180 pos = cmd;
1181 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1182 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001183 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 printf("Too long IDENTITY command.\n");
1185 return -1;
1186 }
1187 pos += ret;
1188 for (i = 2; i < argc; i++) {
1189 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001190 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191 printf("Too long IDENTITY command.\n");
1192 return -1;
1193 }
1194 pos += ret;
1195 }
1196
1197 return wpa_ctrl_command(ctrl, cmd);
1198}
1199
1200
1201static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1202{
1203 char cmd[256], *pos, *end;
1204 int i, ret;
1205
1206 if (argc < 2) {
1207 printf("Invalid PASSWORD command: needs two arguments "
1208 "(network id and password)\n");
1209 return -1;
1210 }
1211
1212 end = cmd + sizeof(cmd);
1213 pos = cmd;
1214 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1215 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001216 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217 printf("Too long PASSWORD command.\n");
1218 return -1;
1219 }
1220 pos += ret;
1221 for (i = 2; i < argc; i++) {
1222 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001223 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224 printf("Too long PASSWORD command.\n");
1225 return -1;
1226 }
1227 pos += ret;
1228 }
1229
1230 return wpa_ctrl_command(ctrl, cmd);
1231}
1232
1233
1234static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1235 char *argv[])
1236{
1237 char cmd[256], *pos, *end;
1238 int i, ret;
1239
1240 if (argc < 2) {
1241 printf("Invalid NEW_PASSWORD command: needs two arguments "
1242 "(network id and password)\n");
1243 return -1;
1244 }
1245
1246 end = cmd + sizeof(cmd);
1247 pos = cmd;
1248 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1249 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001250 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001251 printf("Too long NEW_PASSWORD command.\n");
1252 return -1;
1253 }
1254 pos += ret;
1255 for (i = 2; i < argc; i++) {
1256 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001257 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258 printf("Too long NEW_PASSWORD command.\n");
1259 return -1;
1260 }
1261 pos += ret;
1262 }
1263
1264 return wpa_ctrl_command(ctrl, cmd);
1265}
1266
1267
1268static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1269{
1270 char cmd[256], *pos, *end;
1271 int i, ret;
1272
1273 if (argc < 2) {
1274 printf("Invalid PIN command: needs two arguments "
1275 "(network id and pin)\n");
1276 return -1;
1277 }
1278
1279 end = cmd + sizeof(cmd);
1280 pos = cmd;
1281 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1282 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001283 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001284 printf("Too long PIN command.\n");
1285 return -1;
1286 }
1287 pos += ret;
1288 for (i = 2; i < argc; i++) {
1289 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001290 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291 printf("Too long PIN command.\n");
1292 return -1;
1293 }
1294 pos += ret;
1295 }
1296 return wpa_ctrl_command(ctrl, cmd);
1297}
1298
1299
1300static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1301{
1302 char cmd[256], *pos, *end;
1303 int i, ret;
1304
1305 if (argc < 2) {
1306 printf("Invalid OTP command: needs two arguments (network "
1307 "id and password)\n");
1308 return -1;
1309 }
1310
1311 end = cmd + sizeof(cmd);
1312 pos = cmd;
1313 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1314 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001315 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316 printf("Too long OTP command.\n");
1317 return -1;
1318 }
1319 pos += ret;
1320 for (i = 2; i < argc; i++) {
1321 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001322 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323 printf("Too long OTP command.\n");
1324 return -1;
1325 }
1326 pos += ret;
1327 }
1328
1329 return wpa_ctrl_command(ctrl, cmd);
1330}
1331
1332
Dmitry Shmidt051af732013-10-22 13:52:46 -07001333static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1334{
1335 char cmd[256], *pos, *end;
1336 int i, ret;
1337
1338 if (argc < 2) {
1339 printf("Invalid SIM command: needs two arguments "
1340 "(network id and SIM operation response)\n");
1341 return -1;
1342 }
1343
1344 end = cmd + sizeof(cmd);
1345 pos = cmd;
1346 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1347 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001348 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001349 printf("Too long SIM command.\n");
1350 return -1;
1351 }
1352 pos += ret;
1353 for (i = 2; i < argc; i++) {
1354 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001355 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001356 printf("Too long SIM command.\n");
1357 return -1;
1358 }
1359 pos += ret;
1360 }
1361 return wpa_ctrl_command(ctrl, cmd);
1362}
1363
1364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1366 char *argv[])
1367{
1368 char cmd[256], *pos, *end;
1369 int i, ret;
1370
1371 if (argc < 2) {
1372 printf("Invalid PASSPHRASE command: needs two arguments "
1373 "(network id and passphrase)\n");
1374 return -1;
1375 }
1376
1377 end = cmd + sizeof(cmd);
1378 pos = cmd;
1379 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1380 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001381 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001382 printf("Too long PASSPHRASE command.\n");
1383 return -1;
1384 }
1385 pos += ret;
1386 for (i = 2; i < argc; i++) {
1387 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001388 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 printf("Too long PASSPHRASE command.\n");
1390 return -1;
1391 }
1392 pos += ret;
1393 }
1394
1395 return wpa_ctrl_command(ctrl, cmd);
1396}
1397
1398
1399static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1400{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401 if (argc < 2) {
1402 printf("Invalid BSSID command: needs two arguments (network "
1403 "id and BSSID)\n");
1404 return -1;
1405 }
1406
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001407 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001408}
1409
1410
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001411static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1412{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001413 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001414}
1415
1416
1417static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1418{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001419 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001420}
1421
1422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001423static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1424 char *argv[])
1425{
1426 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1427}
1428
1429
1430static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1431 char *argv[])
1432{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001433 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001434}
1435
1436
1437static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1438 char *argv[])
1439{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001440 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441}
1442
1443
1444static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1445 char *argv[])
1446{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001447 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448}
1449
1450
1451static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1452 char *argv[])
1453{
1454 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1455}
1456
1457
1458static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1459 char *argv[])
1460{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001461 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462}
1463
1464
1465static void wpa_cli_show_network_variables(void)
1466{
1467 printf("set_network variables:\n"
1468 " ssid (network name, SSID)\n"
1469 " psk (WPA passphrase or pre-shared key)\n"
1470 " key_mgmt (key management protocol)\n"
1471 " identity (EAP identity)\n"
1472 " password (EAP password)\n"
1473 " ...\n"
1474 "\n"
1475 "Note: Values are entered in the same format as the "
1476 "configuration file is using,\n"
1477 "i.e., strings values need to be inside double quotation "
1478 "marks.\n"
1479 "For example: set_network 1 ssid \"network name\"\n"
1480 "\n"
1481 "Please see wpa_supplicant.conf documentation for full list "
1482 "of\navailable variables.\n");
1483}
1484
1485
1486static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1487 char *argv[])
1488{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489 if (argc == 0) {
1490 wpa_cli_show_network_variables();
1491 return 0;
1492 }
1493
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001494 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001495 printf("Invalid SET_NETWORK command: needs three arguments\n"
1496 "(network id, variable name, and value)\n");
1497 return -1;
1498 }
1499
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001500 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001501}
1502
1503
1504static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1505 char *argv[])
1506{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001507 if (argc == 0) {
1508 wpa_cli_show_network_variables();
1509 return 0;
1510 }
1511
1512 if (argc != 2) {
1513 printf("Invalid GET_NETWORK command: needs two arguments\n"
1514 "(network id and variable name)\n");
1515 return -1;
1516 }
1517
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001518 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519}
1520
1521
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001522static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1523 char *argv[])
1524{
1525 if (argc == 0) {
1526 wpa_cli_show_network_variables();
1527 return 0;
1528 }
1529
1530 if (argc < 3) {
1531 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1532 "(src netid, dest netid, and variable name)\n");
1533 return -1;
1534 }
1535
1536 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1537}
1538
1539
Dmitry Shmidt04949592012-07-19 12:16:46 -07001540static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1541 char *argv[])
1542{
1543 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1544}
1545
1546
1547static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1548{
1549 return wpa_ctrl_command(ctrl, "ADD_CRED");
1550}
1551
1552
1553static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1554 char *argv[])
1555{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001556 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001557}
1558
1559
1560static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1561{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001562 if (argc != 3) {
1563 printf("Invalid SET_CRED command: needs three arguments\n"
1564 "(cred id, variable name, and value)\n");
1565 return -1;
1566 }
1567
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001568 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001569}
1570
1571
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001572static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1573{
1574 if (argc != 2) {
1575 printf("Invalid GET_CRED command: needs two arguments\n"
1576 "(cred id, variable name)\n");
1577 return -1;
1578 }
1579
1580 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1581}
1582
1583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1585 char *argv[])
1586{
1587 return wpa_ctrl_command(ctrl, "DISCONNECT");
1588}
1589
1590
1591static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1592 char *argv[])
1593{
1594 return wpa_ctrl_command(ctrl, "RECONNECT");
1595}
1596
1597
1598static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1599 char *argv[])
1600{
1601 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1602}
1603
1604
1605static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1606{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001607 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001608}
1609
1610
1611static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1612 char *argv[])
1613{
1614 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1615}
1616
1617
1618static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1619{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001620 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001621}
1622
1623
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001624static char ** wpa_cli_complete_bss(const char *str, int pos)
1625{
1626 int arg = get_cmd_arg_num(str, pos);
1627 char **res = NULL;
1628
1629 switch (arg) {
1630 case 1:
1631 res = cli_txt_list_array(&bsses);
1632 break;
1633 }
1634
1635 return res;
1636}
1637
1638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1640 char *argv[])
1641{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 if (argc < 1 || argc > 2) {
1643 printf("Invalid GET_CAPABILITY command: need either one or "
1644 "two arguments\n");
1645 return -1;
1646 }
1647
1648 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1649 printf("Invalid GET_CAPABILITY command: second argument, "
1650 "if any, must be 'strict'\n");
1651 return -1;
1652 }
1653
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001654 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655}
1656
1657
1658static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1659{
1660 printf("Available interfaces:\n");
1661 return wpa_ctrl_command(ctrl, "INTERFACES");
1662}
1663
1664
1665static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1666{
1667 if (argc < 1) {
1668 wpa_cli_list_interfaces(ctrl);
1669 return 0;
1670 }
1671
1672 wpa_cli_close_connection();
1673 os_free(ctrl_ifname);
1674 ctrl_ifname = os_strdup(argv[0]);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001675 if (!ctrl_ifname) {
1676 printf("Failed to allocate memory\n");
1677 return 0;
1678 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001680 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 printf("Connected to interface '%s.\n", ctrl_ifname);
1682 } else {
1683 printf("Could not connect to interface '%s' - re-trying\n",
1684 ctrl_ifname);
1685 }
1686 return 0;
1687}
1688
1689
1690static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1691 char *argv[])
1692{
1693 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1694}
1695
1696
1697static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1698 char *argv[])
1699{
1700 return wpa_ctrl_command(ctrl, "TERMINATE");
1701}
1702
1703
1704static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1705 char *argv[])
1706{
1707 char cmd[256];
1708 int res;
1709
1710 if (argc < 1) {
1711 printf("Invalid INTERFACE_ADD command: needs at least one "
1712 "argument (interface name)\n"
1713 "All arguments: ifname confname driver ctrl_interface "
1714 "driver_param bridge_name\n");
1715 return -1;
1716 }
1717
1718 /*
1719 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1720 * <driver_param>TAB<bridge_name>
1721 */
1722 res = os_snprintf(cmd, sizeof(cmd),
1723 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1724 argv[0],
1725 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1726 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1727 argc > 5 ? argv[5] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001728 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001729 return -1;
1730 cmd[sizeof(cmd) - 1] = '\0';
1731 return wpa_ctrl_command(ctrl, cmd);
1732}
1733
1734
1735static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1736 char *argv[])
1737{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001738 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739}
1740
1741
1742static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1743 char *argv[])
1744{
1745 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1746}
1747
1748
1749#ifdef CONFIG_AP
1750static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1751{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001752 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753}
1754
1755
1756static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1757 char *addr, size_t addr_len)
1758{
1759 char buf[4096], *pos;
1760 size_t len;
1761 int ret;
1762
1763 if (ctrl_conn == NULL) {
1764 printf("Not connected to hostapd - command dropped.\n");
1765 return -1;
1766 }
1767 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001768 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769 wpa_cli_msg_cb);
1770 if (ret == -2) {
1771 printf("'%s' command timed out.\n", cmd);
1772 return -2;
1773 } else if (ret < 0) {
1774 printf("'%s' command failed.\n", cmd);
1775 return -1;
1776 }
1777
1778 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001779 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 return -1;
1781 printf("%s", buf);
1782
1783 pos = buf;
1784 while (*pos != '\0' && *pos != '\n')
1785 pos++;
1786 *pos = '\0';
1787 os_strlcpy(addr, buf, addr_len);
1788 return 0;
1789}
1790
1791
1792static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1793{
1794 char addr[32], cmd[64];
1795
1796 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1797 return 0;
1798 do {
1799 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1800 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1801
1802 return -1;
1803}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001804
1805
1806static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1807 char *argv[])
1808{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001809 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001810}
1811
1812
1813static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1814 char *argv[])
1815{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001816 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001817}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001818
1819static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
1822 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1823}
1824
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001825#endif /* CONFIG_AP */
1826
1827
1828static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1829{
1830 return wpa_ctrl_command(ctrl, "SUSPEND");
1831}
1832
1833
1834static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1835{
1836 return wpa_ctrl_command(ctrl, "RESUME");
1837}
1838
1839
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001840#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1842{
1843 return wpa_ctrl_command(ctrl, "DROP_SA");
1844}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001845#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846
1847
1848static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1849{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001850 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851}
1852
1853
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001854#ifdef CONFIG_MESH
1855
1856static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
1857 char *argv[])
1858{
1859 return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
1860}
1861
1862
1863static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
1864 char *argv[])
1865{
1866 return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
1867}
1868
1869
1870static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
1871 char *argv[])
1872{
1873 return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
1874}
1875
1876#endif /* CONFIG_MESH */
1877
1878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879#ifdef CONFIG_P2P
1880
1881static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1882{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001883 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1884}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001886
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001887static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1888{
1889 char **res = NULL;
1890 int arg = get_cmd_arg_num(str, pos);
1891
1892 res = os_calloc(6, sizeof(char *));
1893 if (res == NULL)
1894 return NULL;
1895 res[0] = os_strdup("type=social");
1896 if (res[0] == NULL) {
1897 os_free(res);
1898 return NULL;
1899 }
1900 res[1] = os_strdup("type=progressive");
1901 if (res[1] == NULL)
1902 return res;
1903 res[2] = os_strdup("delay=");
1904 if (res[2] == NULL)
1905 return res;
1906 res[3] = os_strdup("dev_id=");
1907 if (res[3] == NULL)
1908 return res;
1909 if (arg == 1)
1910 res[4] = os_strdup("[timeout]");
1911
1912 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913}
1914
1915
1916static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1917 char *argv[])
1918{
1919 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1920}
1921
1922
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001923static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
1924 char *argv[])
1925{
1926 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
1927}
1928
1929
1930static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
1931 char *argv[])
1932{
1933 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
1934}
1935
1936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001937static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1938 char *argv[])
1939{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001940 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941}
1942
1943
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001944static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1945{
1946 int arg = get_cmd_arg_num(str, pos);
1947 char **res = NULL;
1948
1949 switch (arg) {
1950 case 1:
1951 res = cli_txt_list_array(&p2p_peers);
1952 break;
1953 }
1954
1955 return res;
1956}
1957
1958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001959static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1960 char *argv[])
1961{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001962 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963}
1964
1965
1966static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1967 char *argv[])
1968{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001969 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001970}
1971
1972
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001973static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1974{
1975 int arg = get_cmd_arg_num(str, pos);
1976 char **res = NULL;
1977
1978 switch (arg) {
1979 case 1:
1980 res = cli_txt_list_array(&p2p_groups);
1981 break;
1982 }
1983
1984 return res;
1985}
1986
1987
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1989 char *argv[])
1990{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001991 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992}
1993
1994
1995static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1996 char *argv[])
1997{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001998 if (argc != 2 && argc != 3) {
1999 printf("Invalid P2P_PROV_DISC command: needs at least "
2000 "two arguments, address and config method\n"
2001 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002 return -1;
2003 }
2004
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002005 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002006}
2007
2008
2009static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2010 char *argv[])
2011{
2012 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2013}
2014
2015
2016static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2017 char *argv[])
2018{
2019 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002021 if (argc < 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002023 "or more arguments (address and TLVs)\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 return -1;
2025 }
2026
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002027 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029 return wpa_ctrl_command(ctrl, cmd);
2030}
2031
2032
2033static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2034 int argc, char *argv[])
2035{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002036 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037}
2038
2039
2040static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2041 char *argv[])
2042{
2043 char cmd[4096];
2044 int res;
2045
2046 if (argc != 4) {
2047 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2048 "arguments (freq, address, dialog token, and TLVs)\n");
2049 return -1;
2050 }
2051
2052 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2053 argv[0], argv[1], argv[2], argv[3]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002054 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055 return -1;
2056 cmd[sizeof(cmd) - 1] = '\0';
2057 return wpa_ctrl_command(ctrl, cmd);
2058}
2059
2060
2061static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2062 char *argv[])
2063{
2064 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2065}
2066
2067
2068static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2069 int argc, char *argv[])
2070{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002071 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002072}
2073
2074
2075static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2076 char *argv[])
2077{
2078 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2079}
2080
2081
2082static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2083 char *argv[])
2084{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002085 if (argc < 3) {
2086 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2087 return -1;
2088 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002090 return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2091}
2092
2093
2094static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2095 char *argv[])
2096{
2097 if (argc < 5 || argc > 6) {
2098 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099 "arguments\n");
2100 return -1;
2101 }
2102
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002103 return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104}
2105
2106
2107static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2108 char *argv[])
2109{
2110 char cmd[4096];
2111 int res;
2112
2113 if (argc != 2 && argc != 3) {
2114 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2115 "arguments\n");
2116 return -1;
2117 }
2118
2119 if (argc == 3)
2120 res = os_snprintf(cmd, sizeof(cmd),
2121 "P2P_SERVICE_DEL %s %s %s",
2122 argv[0], argv[1], argv[2]);
2123 else
2124 res = os_snprintf(cmd, sizeof(cmd),
2125 "P2P_SERVICE_DEL %s %s",
2126 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002127 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002128 return -1;
2129 cmd[sizeof(cmd) - 1] = '\0';
2130 return wpa_ctrl_command(ctrl, cmd);
2131}
2132
2133
2134static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2135 int argc, char *argv[])
2136{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002137 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138}
2139
2140
2141static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2142 int argc, char *argv[])
2143{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002144 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002145}
2146
2147
2148static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2149{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002150 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002151}
2152
2153
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002154static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2155{
2156 int arg = get_cmd_arg_num(str, pos);
2157 char **res = NULL;
2158
2159 switch (arg) {
2160 case 1:
2161 res = cli_txt_list_array(&p2p_peers);
2162 break;
2163 }
2164
2165 return res;
2166}
2167
2168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2170 char *addr, size_t addr_len,
2171 int discovered)
2172{
2173 char buf[4096], *pos;
2174 size_t len;
2175 int ret;
2176
2177 if (ctrl_conn == NULL)
2178 return -1;
2179 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002180 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002181 wpa_cli_msg_cb);
2182 if (ret == -2) {
2183 printf("'%s' command timed out.\n", cmd);
2184 return -2;
2185 } else if (ret < 0) {
2186 printf("'%s' command failed.\n", cmd);
2187 return -1;
2188 }
2189
2190 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002191 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192 return -1;
2193
2194 pos = buf;
2195 while (*pos != '\0' && *pos != '\n')
2196 pos++;
2197 *pos++ = '\0';
2198 os_strlcpy(addr, buf, addr_len);
2199 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2200 printf("%s\n", addr);
2201 return 0;
2202}
2203
2204
2205static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2206{
2207 char addr[32], cmd[64];
2208 int discovered;
2209
2210 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2211
2212 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2213 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002214 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002215 do {
2216 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2217 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2218 discovered) == 0);
2219
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002220 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221}
2222
2223
2224static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2225{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002226 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002227}
2228
2229
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002230static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2231{
2232 int arg = get_cmd_arg_num(str, pos);
2233 const char *fields[] = {
2234 "discoverability",
2235 "managed",
2236 "listen_channel",
2237 "ssid_postfix",
2238 "noa",
2239 "ps",
2240 "oppps",
2241 "ctwindow",
2242 "disabled",
2243 "conc_pref",
2244 "force_long_sd",
2245 "peer_filter",
2246 "cross_connect",
2247 "go_apsd",
2248 "client_apsd",
2249 "disallow_freq",
2250 "disc_int",
2251 "per_sta_psk",
2252 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002253 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002254
2255 if (arg == 1) {
2256 char **res = os_calloc(num_fields + 1, sizeof(char *));
2257 if (res == NULL)
2258 return NULL;
2259 for (i = 0; i < num_fields; i++) {
2260 res[i] = os_strdup(fields[i]);
2261 if (res[i] == NULL)
2262 return res;
2263 }
2264 return res;
2265 }
2266
2267 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2268 return cli_txt_list_array(&p2p_peers);
2269
2270 return NULL;
2271}
2272
2273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002274static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2275{
2276 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2277}
2278
2279
2280static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2281 char *argv[])
2282{
2283 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2284}
2285
2286
2287static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2288 char *argv[])
2289{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002290 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291}
2292
2293
2294static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2295 char *argv[])
2296{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002297 if (argc != 0 && argc != 2 && argc != 4) {
2298 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2299 "(preferred duration, interval; in microsecods).\n"
2300 "Optional second pair can be used to provide "
2301 "acceptable values.\n");
2302 return -1;
2303 }
2304
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306}
2307
2308
2309static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2310 char *argv[])
2311{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 if (argc != 0 && argc != 2) {
2313 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2314 "(availability period, availability interval; in "
2315 "millisecods).\n"
2316 "Extended Listen Timing can be cancelled with this "
2317 "command when used without parameters.\n");
2318 return -1;
2319 }
2320
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002321 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2322}
2323
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002324
2325static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2326 char *argv[])
2327{
2328 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2329}
2330
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002331#endif /* CONFIG_P2P */
2332
2333#ifdef CONFIG_WIFI_DISPLAY
2334
2335static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2336 char *argv[])
2337{
2338 char cmd[100];
2339 int res;
2340
2341 if (argc != 1 && argc != 2) {
2342 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2343 "arguments (subelem, hexdump)\n");
2344 return -1;
2345 }
2346
2347 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2348 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002349 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002350 return -1;
2351 cmd[sizeof(cmd) - 1] = '\0';
2352 return wpa_ctrl_command(ctrl, cmd);
2353}
2354
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002355
2356static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2357 char *argv[])
2358{
2359 char cmd[100];
2360 int res;
2361
2362 if (argc != 1) {
2363 printf("Invalid WFD_SUBELEM_GET command: needs one "
2364 "argument (subelem)\n");
2365 return -1;
2366 }
2367
2368 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2369 argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002370 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 return -1;
2372 cmd[sizeof(cmd) - 1] = '\0';
2373 return wpa_ctrl_command(ctrl, cmd);
2374}
2375#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376
2377
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002378#ifdef CONFIG_INTERWORKING
2379static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2380 char *argv[])
2381{
2382 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2383}
2384
2385
2386static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2387 char *argv[])
2388{
2389 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2390}
2391
2392
2393static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2394 char *argv[])
2395{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002396 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002397}
2398
2399
2400static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2401 char *argv[])
2402{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002404}
2405
2406
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002407static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2408 char *argv[])
2409{
2410 return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2411}
2412
2413
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002414static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2415{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002416 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2417}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002418
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002419
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2421 char *argv[])
2422{
2423 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2424}
2425
2426
2427static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2428 char *argv[])
2429{
2430 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002431}
2432#endif /* CONFIG_INTERWORKING */
2433
2434
Dmitry Shmidt04949592012-07-19 12:16:46 -07002435#ifdef CONFIG_HS20
2436
2437static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2438 char *argv[])
2439{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002440 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002441}
2442
2443
2444static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2445 char *argv[])
2446{
2447 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002448
2449 if (argc == 0) {
2450 printf("Command needs one or two arguments (dst mac addr and "
2451 "optional home realm)\n");
2452 return -1;
2453 }
2454
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2456 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002457 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002458
2459 return wpa_ctrl_command(ctrl, cmd);
2460}
2461
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002462
2463static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2464 char *argv[])
2465{
2466 char cmd[512];
2467
2468 if (argc < 2) {
2469 printf("Command needs two arguments (dst mac addr and "
2470 "icon name)\n");
2471 return -1;
2472 }
2473
2474 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2475 return -1;
2476
2477 return wpa_ctrl_command(ctrl, cmd);
2478}
2479
2480
2481static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2482{
2483 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2484}
2485
2486
2487static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2488 char *argv[])
2489{
2490 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2491}
2492
Dmitry Shmidt04949592012-07-19 12:16:46 -07002493#endif /* CONFIG_HS20 */
2494
2495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2497 char *argv[])
2498{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002499 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500}
2501
2502
2503static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2504 char *argv[])
2505{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507}
2508
2509
2510static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2511 char *argv[])
2512{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514}
2515
2516
2517static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2518 char *argv[])
2519{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521}
2522
2523
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002524static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2525 char *argv[])
2526{
2527 return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2528}
2529
2530
2531static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2532 char *argv[])
2533{
2534 return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2535}
2536
2537
2538static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2539 char *argv[])
2540{
2541 return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2542}
2543
2544
2545static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2546 char *argv[])
2547{
2548 return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2549}
2550
2551
2552static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2553 char *argv[])
2554{
2555 return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2556}
2557
2558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2560 char *argv[])
2561{
2562 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2563}
2564
2565
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002566static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2567 char *argv[])
2568{
2569 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2570}
2571
2572
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002573static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2574 char *argv[])
2575{
2576 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2577}
2578
Dmitry Shmidt04949592012-07-19 12:16:46 -07002579
2580#ifdef CONFIG_AUTOSCAN
2581
2582static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2583{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002584 if (argc == 0)
2585 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2586
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002588}
2589
2590#endif /* CONFIG_AUTOSCAN */
2591
2592
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002593#ifdef CONFIG_WNM
2594
2595static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2596{
2597 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2598}
2599
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002600
2601static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2602{
2603 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2604}
2605
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002606#endif /* CONFIG_WNM */
2607
2608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002609static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2610{
2611 if (argc == 0)
2612 return -1;
2613 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2614}
2615
2616
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002617#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002618static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2619{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002620 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002621}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002622#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002623
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002624
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002625static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2626{
2627 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2628}
2629
2630
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002631static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2632{
2633 return wpa_ctrl_command(ctrl, "FLUSH");
2634}
2635
2636
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002637static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2638{
2639 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2640}
2641
2642
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002643static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2644 char *argv[])
2645{
2646 return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2647}
2648
2649
2650static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2651{
2652 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2653}
2654
2655
2656static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2657 char *argv[])
2658{
2659 return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2660}
2661
2662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663enum wpa_cli_cmd_flags {
2664 cli_cmd_flag_none = 0x00,
2665 cli_cmd_flag_sensitive = 0x01
2666};
2667
2668struct wpa_cli_cmd {
2669 const char *cmd;
2670 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 enum wpa_cli_cmd_flags flags;
2673 const char *usage;
2674};
2675
2676static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 cli_cmd_flag_none,
2679 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "ifname", wpa_cli_cmd_ifname, NULL,
2681 cli_cmd_flag_none,
2682 "= get current interface name" },
2683 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 cli_cmd_flag_none,
2685 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 cli_cmd_flag_none,
2688 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_none,
2691 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 cli_cmd_flag_none,
2694 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 "[command] = show usage help" },
2698 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 cli_cmd_flag_none,
2700 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 cli_cmd_flag_none,
2703 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 cli_cmd_flag_none,
2706 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 cli_cmd_flag_none,
2709 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002710 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 cli_cmd_flag_none,
2712 "= set variables (shows list of variables when run without "
2713 "arguments)" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002714 { "dump", wpa_cli_cmd_dump, NULL,
2715 cli_cmd_flag_none,
2716 "= dump config variables" },
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07002717 { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 cli_cmd_flag_none,
2719 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 cli_cmd_flag_none,
2722 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 cli_cmd_flag_none,
2725 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727 cli_cmd_flag_none,
2728 "= show PMKSA cache" },
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002729 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2730 cli_cmd_flag_none,
2731 "= flush PMKSA cache entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 cli_cmd_flag_none,
2734 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002735 { "reattach", wpa_cli_cmd_reattach, NULL,
2736 cli_cmd_flag_none,
2737 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002738 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739 cli_cmd_flag_none,
2740 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 cli_cmd_flag_none,
2743 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 cli_cmd_flag_sensitive,
2746 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 cli_cmd_flag_sensitive,
2749 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 cli_cmd_flag_sensitive,
2752 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754 cli_cmd_flag_sensitive,
2755 "<network id> <password> = configure one-time-password for an SSID"
2756 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 cli_cmd_flag_sensitive,
2759 "<network id> <passphrase> = configure private key passphrase\n"
2760 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002761 { "sim", wpa_cli_cmd_sim, NULL,
2762 cli_cmd_flag_sensitive,
2763 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002764 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 cli_cmd_flag_none,
2766 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002768 cli_cmd_flag_none,
2769 "<BSSID> = add a BSSID to the blacklist\n"
2770 "blacklist clear = clear the blacklist\n"
2771 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002772 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002773 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002774 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002775 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002776 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 cli_cmd_flag_none,
2778 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 cli_cmd_flag_none,
2781 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 cli_cmd_flag_none,
2784 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 cli_cmd_flag_none,
2787 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 cli_cmd_flag_none,
2790 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002791 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792 cli_cmd_flag_none,
2793 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002794 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 cli_cmd_flag_sensitive,
2796 "<network id> <variable> <value> = set network variables (shows\n"
2797 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002798 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002799 cli_cmd_flag_none,
2800 "<network id> <variable> = get network variables" },
Dmitry Shmidt684785c2014-05-12 13:34:29 -07002801 { "dup_network", wpa_cli_cmd_dup_network, NULL,
2802 cli_cmd_flag_none,
2803 "<src network id> <dst network id> <variable> = duplicate network variables"
2804 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002806 cli_cmd_flag_none,
2807 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002808 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002809 cli_cmd_flag_none,
2810 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002812 cli_cmd_flag_none,
2813 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002815 cli_cmd_flag_sensitive,
2816 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002817 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2818 cli_cmd_flag_none,
2819 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002820 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821 cli_cmd_flag_none,
2822 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002823 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 cli_cmd_flag_none,
2825 "= disconnect and wait for reassociate/reconnect command before\n"
2826 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 cli_cmd_flag_none,
2829 "= like reassociate, but only takes effect if already disconnected"
2830 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 cli_cmd_flag_none,
2833 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 cli_cmd_flag_none,
2836 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 cli_cmd_flag_none,
2839 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002842 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 "= get capabilies" },
2844 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845 cli_cmd_flag_none,
2846 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002847 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848 cli_cmd_flag_none,
2849 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002850 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002851 cli_cmd_flag_none,
2852 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2853 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2854 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002855 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856 cli_cmd_flag_none,
2857 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002858 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859 cli_cmd_flag_none,
2860 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002861 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862 cli_cmd_flag_none,
2863 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 cli_cmd_flag_none,
2866 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002867 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868 cli_cmd_flag_none,
2869 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002870 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002871 cli_cmd_flag_none,
2872 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002873 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002874 cli_cmd_flag_none,
2875 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002876 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 cli_cmd_flag_none,
2878 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 cli_cmd_flag_none,
2881 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 cli_cmd_flag_none,
2884 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002885 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 cli_cmd_flag_sensitive,
2887 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2888 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002889 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890 cli_cmd_flag_sensitive,
2891 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002892 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002894#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002895 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002896 cli_cmd_flag_none,
2897 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002898 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2899 cli_cmd_flag_none,
2900 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002901 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002902 cli_cmd_flag_none,
2903 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002904 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002905 cli_cmd_flag_sensitive,
2906 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002907 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2908 cli_cmd_flag_none,
2909 "<NDEF> <WPS> = create NFC handover request" },
2910 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2911 cli_cmd_flag_none,
2912 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002913 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2914 cli_cmd_flag_none,
2915 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2916 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002917#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002918 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 cli_cmd_flag_sensitive,
2920 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002921 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002922 cli_cmd_flag_sensitive,
2923 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002924 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 cli_cmd_flag_none,
2926 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002927 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 cli_cmd_flag_none,
2929 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002930 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931 cli_cmd_flag_sensitive,
2932 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002933 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002934 cli_cmd_flag_none,
2935 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002936 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002937 cli_cmd_flag_sensitive,
2938 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002939 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 cli_cmd_flag_none,
2941 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002942 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943 cli_cmd_flag_sensitive,
2944 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002945#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002946 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002947 cli_cmd_flag_none,
2948 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2949#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002950 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 cli_cmd_flag_none,
2952 "<addr> = request RSN authentication with <addr> in IBSS" },
2953#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002954 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 cli_cmd_flag_none,
2956 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002957 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958 cli_cmd_flag_none,
2959 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002960 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002961 cli_cmd_flag_none,
2962 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002963 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002964 cli_cmd_flag_none,
2965 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002966 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2967 cli_cmd_flag_none,
2968 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2969 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2970 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002972 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002974 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002975 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002976#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002977 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002978 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002979#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002980 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002981 cli_cmd_flag_none,
2982 "<addr> = roam to the specified BSS" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002983#ifdef CONFIG_MESH
2984 { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
2985 cli_cmd_flag_none,
2986 "[ifname] = Create a new mesh interface" },
2987 { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
2988 cli_cmd_flag_none,
2989 "<network id> = join a mesh network (disable others)" },
2990 { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
2991 cli_cmd_flag_none,
2992 "<ifname> = Remove mesh group interface" },
2993#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002995 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2996 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002997 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002998 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999 "= stop P2P Devices search" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003000 { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3001 cli_cmd_flag_none,
3002 "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3003 { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3004 cli_cmd_flag_none,
3005 "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003006 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3007 cli_cmd_flag_none,
3008 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3009 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003010 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003011 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3012 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003013 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003014 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3015 "[ht40] = add a new P2P group (local end as GO)" },
3016 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3017 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003018 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003019 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003020 cli_cmd_flag_none,
3021 "= get the passphrase for a group (GO only)" },
3022 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003023 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003024 "<addr> <TLVs> = schedule service discovery request" },
3025 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003026 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003028 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029 cli_cmd_flag_none,
3030 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003031 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003032 cli_cmd_flag_none,
3033 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003034 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003035 cli_cmd_flag_none,
3036 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003037 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003038 cli_cmd_flag_none,
3039 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003040 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 cli_cmd_flag_none,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003042 "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043 "service" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003044 { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3045 cli_cmd_flag_none,
3046 "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3047 "local ASP service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003048 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 cli_cmd_flag_none,
3050 "<bonjour|upnp> <query|version> [|service] = remove a local "
3051 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003052 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003053 cli_cmd_flag_none,
3054 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003055 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003056 cli_cmd_flag_none,
3057 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003058 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003059 "[discovered] = list known (optionally, only fully discovered) P2P "
3060 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003061 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3062 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003064 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3065 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003066 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003067 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003068 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003069 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003070 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003071 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3072 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003074 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3075 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 "[<duration> <interval>] [<duration> <interval>] = request GO "
3077 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003078 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3079 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003080 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003081 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3082 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3083 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003085#ifdef CONFIG_WIFI_DISPLAY
3086 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3087 cli_cmd_flag_none,
3088 "<subelem> [contents] = set Wi-Fi Display subelement" },
3089 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3090 cli_cmd_flag_none,
3091 "<subelem> = get Wi-Fi Display subelement" },
3092#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003093#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003094 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003095 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003096 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3097 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003098 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003099 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003100 cli_cmd_flag_none,
3101 "[auto] = perform Interworking network selection" },
3102 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003103 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003104 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003105 { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3106 wpa_cli_complete_bss, cli_cmd_flag_none,
3107 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003108 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3109 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003110 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003111 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3112 cli_cmd_flag_none,
3113 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3114 { "gas_response_get", wpa_cli_cmd_gas_response_get,
3115 wpa_cli_complete_bss, cli_cmd_flag_none,
3116 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003117#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003118#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003119 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3120 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003121 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3122 },
3123 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003124 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003125 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003126 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3127 wpa_cli_complete_bss, cli_cmd_flag_none,
3128 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3129 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3130 "= fetch OSU provider information from all APs" },
3131 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3132 cli_cmd_flag_none,
3133 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003134#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003135 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3136 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003137 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003138 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139 cli_cmd_flag_none,
3140 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003141 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003142 cli_cmd_flag_none,
3143 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003144 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145 cli_cmd_flag_none,
3146 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003147 { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3148 cli_cmd_flag_none,
3149 "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3150 "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3151 "= add WMM-AC traffic stream" },
3152 { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3153 cli_cmd_flag_none,
3154 "<tsid> = delete WMM-AC traffic stream" },
3155 { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3156 cli_cmd_flag_none,
3157 "= show status for Wireless Multi-Media Admission-Control" },
3158 { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3159 cli_cmd_flag_none,
3160 "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3161 "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3162 "with TDLS peer" },
3163 { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3164 cli_cmd_flag_none,
3165 "<addr> = disable channel switching with TDLS peer <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003166 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003167 cli_cmd_flag_none,
3168 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003169 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07003170 cli_cmd_flag_none,
3171 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003172 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3173 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003174 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003175#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003176 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003177 "[params] = Set or unset (if none) autoscan parameters" },
3178#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003179#ifdef CONFIG_WNM
3180 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3181 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07003182 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3183 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003184#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003185 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3186 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003187 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3188 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003189#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003190 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003191 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003192#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003193 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3194 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003195 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3196 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3197 },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003198 { "neighbor_rep_request",
3199 wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3200 "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3201 "(with optional given SSID, default: current SSID)"
3202 },
3203 { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3204 "= flush ERP keys" },
3205 { "mac_rand_scan",
3206 wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3207 "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3208 "mask=mac-address-mask] = scan MAC randomization"
3209 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003210 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211};
3212
3213
3214/*
3215 * Prints command usage, lines are padded with the specified string.
3216 */
3217static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3218{
3219 char c;
3220 size_t n;
3221
3222 printf("%s%s ", pad, cmd->cmd);
3223 for (n = 0; (c = cmd->usage[n]); n++) {
3224 printf("%c", c);
3225 if (c == '\n')
3226 printf("%s", pad);
3227 }
3228 printf("\n");
3229}
3230
3231
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003232static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003233{
3234 int n;
3235 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003236 for (n = 0; wpa_cli_commands[n].cmd; n++) {
3237 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3238 print_cmd_help(&wpa_cli_commands[n], " ");
3239 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003240}
3241
3242
3243static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3244{
3245 const char *c, *delim;
3246 int n;
3247 size_t len;
3248
3249 delim = os_strchr(cmd, ' ');
3250 if (delim)
3251 len = delim - cmd;
3252 else
3253 len = os_strlen(cmd);
3254
3255 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3256 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3257 return (wpa_cli_commands[n].flags &
3258 cli_cmd_flag_sensitive);
3259 }
3260 return 0;
3261}
3262
3263
3264static char ** wpa_list_cmd_list(void)
3265{
3266 char **res;
3267 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003268 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003269
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003270 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003271 count += dl_list_len(&p2p_groups);
3272 count += dl_list_len(&ifnames);
3273 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003274 if (res == NULL)
3275 return NULL;
3276
3277 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3278 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3279 if (res[i] == NULL)
3280 break;
3281 }
3282
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003283 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3284 size_t len = 8 + os_strlen(e->txt);
3285 res[i] = os_malloc(len);
3286 if (res[i] == NULL)
3287 break;
3288 os_snprintf(res[i], len, "ifname=%s", e->txt);
3289 i++;
3290 }
3291
3292 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3293 res[i] = os_strdup(e->txt);
3294 if (res[i] == NULL)
3295 break;
3296 i++;
3297 }
3298
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003299 return res;
3300}
3301
3302
3303static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3304 int pos)
3305{
3306 int i;
3307
3308 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3309 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003310 if (wpa_cli_commands[i].completion)
3311 return wpa_cli_commands[i].completion(str,
3312 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003313 edit_clear_line();
3314 printf("\r%s\n", wpa_cli_commands[i].usage);
3315 edit_redraw();
3316 break;
3317 }
3318 }
3319
3320 return NULL;
3321}
3322
3323
3324static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3325{
3326 char **res;
3327 const char *end;
3328 char *cmd;
3329
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003330 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3331 end = os_strchr(str, ' ');
3332 if (end && pos > end - str) {
3333 pos -= end - str + 1;
3334 str = end + 1;
3335 }
3336 }
3337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003338 end = os_strchr(str, ' ');
3339 if (end == NULL || str + pos < end)
3340 return wpa_list_cmd_list();
3341
3342 cmd = os_malloc(pos + 1);
3343 if (cmd == NULL)
3344 return NULL;
3345 os_memcpy(cmd, str, pos);
3346 cmd[end - str] = '\0';
3347 res = wpa_cli_cmd_completion(cmd, str, pos);
3348 os_free(cmd);
3349 return res;
3350}
3351
3352
3353static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3354{
3355 struct wpa_cli_cmd *cmd, *match = NULL;
3356 int count;
3357 int ret = 0;
3358
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003359 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3360 ifname_prefix = argv[0] + 7;
3361 argv = &argv[1];
3362 argc--;
3363 } else
3364 ifname_prefix = NULL;
3365
3366 if (argc == 0)
3367 return -1;
3368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369 count = 0;
3370 cmd = wpa_cli_commands;
3371 while (cmd->cmd) {
3372 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3373 {
3374 match = cmd;
3375 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3376 /* we have an exact match */
3377 count = 1;
3378 break;
3379 }
3380 count++;
3381 }
3382 cmd++;
3383 }
3384
3385 if (count > 1) {
3386 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3387 cmd = wpa_cli_commands;
3388 while (cmd->cmd) {
3389 if (os_strncasecmp(cmd->cmd, argv[0],
3390 os_strlen(argv[0])) == 0) {
3391 printf(" %s", cmd->cmd);
3392 }
3393 cmd++;
3394 }
3395 printf("\n");
3396 ret = 1;
3397 } else if (count == 0) {
3398 printf("Unknown command '%s'\n", argv[0]);
3399 ret = 1;
3400 } else {
3401 ret = match->handler(ctrl, argc - 1, &argv[1]);
3402 }
3403
3404 return ret;
3405}
3406
3407
3408static int str_match(const char *a, const char *b)
3409{
3410 return os_strncmp(a, b, os_strlen(b)) == 0;
3411}
3412
3413
3414static int wpa_cli_exec(const char *program, const char *arg1,
3415 const char *arg2)
3416{
Jouni Malinen772e12c2014-10-07 10:29:35 -07003417 char *arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 size_t len;
3419 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420
Jouni Malinen772e12c2014-10-07 10:29:35 -07003421 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3422 arg = os_malloc(len);
3423 if (arg == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003424 return -1;
Jouni Malinen772e12c2014-10-07 10:29:35 -07003425 os_snprintf(arg, len, "%s %s", arg1, arg2);
3426 res = os_exec(program, arg, 1);
3427 os_free(arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428
Jouni Malinen772e12c2014-10-07 10:29:35 -07003429 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003430}
3431
3432
3433static void wpa_cli_action_process(const char *msg)
3434{
3435 const char *pos;
3436 char *copy = NULL, *id, *pos2;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003437 const char *ifname = ctrl_ifname;
3438 char ifname_buf[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439
3440 pos = msg;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003441 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3442 const char *end;
3443 end = os_strchr(pos + 7, ' ');
3444 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3445 pos += 7;
3446 os_memcpy(ifname_buf, pos, end - pos);
3447 ifname_buf[end - pos] = '\0';
3448 ifname = ifname_buf;
3449 pos = end + 1;
3450 }
3451 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003452 if (*pos == '<') {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003453 const char *prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 /* skip priority */
3455 pos = os_strchr(pos, '>');
3456 if (pos)
3457 pos++;
3458 else
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003459 pos = prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460 }
3461
3462 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3463 int new_id = -1;
3464 os_unsetenv("WPA_ID");
3465 os_unsetenv("WPA_ID_STR");
3466 os_unsetenv("WPA_CTRL_DIR");
3467
3468 pos = os_strstr(pos, "[id=");
3469 if (pos)
3470 copy = os_strdup(pos + 4);
3471
3472 if (copy) {
3473 pos2 = id = copy;
3474 while (*pos2 && *pos2 != ' ')
3475 pos2++;
3476 *pos2++ = '\0';
3477 new_id = atoi(id);
3478 os_setenv("WPA_ID", id, 1);
3479 while (*pos2 && *pos2 != '=')
3480 pos2++;
3481 if (*pos2 == '=')
3482 pos2++;
3483 id = pos2;
3484 while (*pos2 && *pos2 != ']')
3485 pos2++;
3486 *pos2 = '\0';
3487 os_setenv("WPA_ID_STR", id, 1);
3488 os_free(copy);
3489 }
3490
3491 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3492
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003493 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003494 wpa_cli_connected = 1;
3495 wpa_cli_last_id = new_id;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003496 wpa_cli_exec(action_file, ifname, "CONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497 }
3498 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3499 if (wpa_cli_connected) {
3500 wpa_cli_connected = 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003501 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003503 } else if (str_match(pos, MESH_GROUP_STARTED)) {
3504 wpa_cli_exec(action_file, ctrl_ifname, pos);
3505 } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3506 wpa_cli_exec(action_file, ctrl_ifname, pos);
3507 } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3508 wpa_cli_exec(action_file, ctrl_ifname, pos);
3509 } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3510 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003512 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003514 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003516 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003518 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003519 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003520 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003522 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523 } else if (str_match(pos, WPS_EVENT_FAIL)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003524 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003525 } else if (str_match(pos, AP_STA_CONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003526 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003527 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003528 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003529 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003530 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003531 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003532 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003533 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003534 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3536 printf("wpa_supplicant is terminating - stop monitoring\n");
3537 wpa_cli_quit = 1;
3538 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539}
3540
3541
3542#ifndef CONFIG_ANSI_C_EXTRA
3543static void wpa_cli_action_cb(char *msg, size_t len)
3544{
3545 wpa_cli_action_process(msg);
3546}
3547#endif /* CONFIG_ANSI_C_EXTRA */
3548
3549
3550static void wpa_cli_reconnect(void)
3551{
3552 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003553 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3554 return;
3555
3556 if (interactive) {
3557 edit_clear_line();
3558 printf("\rConnection to wpa_supplicant re-established\n");
3559 edit_redraw();
3560 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561}
3562
3563
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003564static void cli_event(const char *str)
3565{
3566 const char *start, *s;
3567
3568 start = os_strchr(str, '>');
3569 if (start == NULL)
3570 return;
3571
3572 start++;
3573
3574 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3575 s = os_strchr(start, ' ');
3576 if (s == NULL)
3577 return;
3578 s = os_strchr(s + 1, ' ');
3579 if (s == NULL)
3580 return;
3581 cli_txt_list_add(&bsses, s + 1);
3582 return;
3583 }
3584
3585 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3586 s = os_strchr(start, ' ');
3587 if (s == NULL)
3588 return;
3589 s = os_strchr(s + 1, ' ');
3590 if (s == NULL)
3591 return;
3592 cli_txt_list_del_addr(&bsses, s + 1);
3593 return;
3594 }
3595
3596#ifdef CONFIG_P2P
3597 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3598 s = os_strstr(start, " p2p_dev_addr=");
3599 if (s == NULL)
3600 return;
3601 cli_txt_list_add_addr(&p2p_peers, s + 14);
3602 return;
3603 }
3604
3605 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3606 s = os_strstr(start, " p2p_dev_addr=");
3607 if (s == NULL)
3608 return;
3609 cli_txt_list_del_addr(&p2p_peers, s + 14);
3610 return;
3611 }
3612
3613 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3614 s = os_strchr(start, ' ');
3615 if (s == NULL)
3616 return;
3617 cli_txt_list_add_word(&p2p_groups, s + 1);
3618 return;
3619 }
3620
3621 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3622 s = os_strchr(start, ' ');
3623 if (s == NULL)
3624 return;
3625 cli_txt_list_del_word(&p2p_groups, s + 1);
3626 return;
3627 }
3628#endif /* CONFIG_P2P */
3629}
3630
3631
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003632static int check_terminating(const char *msg)
3633{
3634 const char *pos = msg;
3635
3636 if (*pos == '<') {
3637 /* skip priority */
3638 pos = os_strchr(pos, '>');
3639 if (pos)
3640 pos++;
3641 else
3642 pos = msg;
3643 }
3644
3645 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3646 edit_clear_line();
3647 printf("\rConnection to wpa_supplicant lost - trying to "
3648 "reconnect\n");
3649 edit_redraw();
3650 wpa_cli_attached = 0;
3651 wpa_cli_close_connection();
3652 return 1;
3653 }
3654
3655 return 0;
3656}
3657
3658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003659static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3660{
3661 if (ctrl_conn == NULL) {
3662 wpa_cli_reconnect();
3663 return;
3664 }
3665 while (wpa_ctrl_pending(ctrl) > 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003666 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 size_t len = sizeof(buf) - 1;
3668 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3669 buf[len] = '\0';
3670 if (action_monitor)
3671 wpa_cli_action_process(buf);
3672 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003673 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 if (wpa_cli_show_event(buf)) {
3675 edit_clear_line();
3676 printf("\r%s\n", buf);
3677 edit_redraw();
3678 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003679
3680 if (interactive && check_terminating(buf) > 0)
3681 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003682 }
3683 } else {
3684 printf("Could not read pending message.\n");
3685 break;
3686 }
3687 }
3688
3689 if (wpa_ctrl_pending(ctrl) < 0) {
3690 printf("Connection to wpa_supplicant lost - trying to "
3691 "reconnect\n");
3692 wpa_cli_reconnect();
3693 }
3694}
3695
3696#define max_args 10
3697
3698static int tokenize_cmd(char *cmd, char *argv[])
3699{
3700 char *pos;
3701 int argc = 0;
3702
3703 pos = cmd;
3704 for (;;) {
3705 while (*pos == ' ')
3706 pos++;
3707 if (*pos == '\0')
3708 break;
3709 argv[argc] = pos;
3710 argc++;
3711 if (argc == max_args)
3712 break;
3713 if (*pos == '"') {
3714 char *pos2 = os_strrchr(pos, '"');
3715 if (pos2)
3716 pos = pos2 + 1;
3717 }
3718 while (*pos != '\0' && *pos != ' ')
3719 pos++;
3720 if (*pos == ' ')
3721 *pos++ = '\0';
3722 }
3723
3724 return argc;
3725}
3726
3727
3728static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3729{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003730 if (ctrl_conn) {
3731 int res;
3732 char *prefix = ifname_prefix;
3733
3734 ifname_prefix = NULL;
3735 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3736 ifname_prefix = prefix;
3737 if (res) {
3738 printf("Connection to wpa_supplicant lost - trying to "
3739 "reconnect\n");
3740 wpa_cli_close_connection();
3741 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003742 }
3743 if (!ctrl_conn)
3744 wpa_cli_reconnect();
3745 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3746}
3747
3748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3750{
3751 wpa_cli_recv_pending(mon_conn, 0);
3752}
3753
3754
3755static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3756{
3757 char *argv[max_args];
3758 int argc;
3759 argc = tokenize_cmd(cmd, argv);
3760 if (argc)
3761 wpa_request(ctrl_conn, argc, argv);
3762}
3763
3764
3765static void wpa_cli_edit_eof_cb(void *ctx)
3766{
3767 eloop_terminate();
3768}
3769
3770
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003771static int warning_displayed = 0;
3772static char *hfile = NULL;
3773static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003774
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003775static void start_edit(void)
3776{
3777 char *home;
3778 char *ps = NULL;
3779
3780#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3781 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3782#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003783
3784 home = getenv("HOME");
3785 if (home) {
3786 const char *fname = ".wpa_cli_history";
3787 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3788 hfile = os_malloc(hfile_len);
3789 if (hfile)
3790 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3791 }
3792
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003793 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3794 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3795 eloop_terminate();
3796 return;
3797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003799 edit_started = 1;
3800 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3801}
3802
3803
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003804static void update_bssid_list(struct wpa_ctrl *ctrl)
3805{
3806 char buf[4096];
3807 size_t len = sizeof(buf);
3808 int ret;
3809 char *cmd = "BSS RANGE=ALL MASK=0x2";
3810 char *pos, *end;
3811
3812 if (ctrl == NULL)
3813 return;
3814 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3815 if (ret < 0)
3816 return;
3817 buf[len] = '\0';
3818
3819 pos = buf;
3820 while (pos) {
3821 pos = os_strstr(pos, "bssid=");
3822 if (pos == NULL)
3823 break;
3824 pos += 6;
3825 end = os_strchr(pos, '\n');
3826 if (end == NULL)
3827 break;
3828 *end = '\0';
3829 cli_txt_list_add(&bsses, pos);
3830 pos = end + 1;
3831 }
3832}
3833
3834
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003835static void update_ifnames(struct wpa_ctrl *ctrl)
3836{
3837 char buf[4096];
3838 size_t len = sizeof(buf);
3839 int ret;
3840 char *cmd = "INTERFACES";
3841 char *pos, *end;
3842 char txt[200];
3843
3844 cli_txt_list_flush(&ifnames);
3845
3846 if (ctrl == NULL)
3847 return;
3848 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3849 if (ret < 0)
3850 return;
3851 buf[len] = '\0';
3852
3853 pos = buf;
3854 while (pos) {
3855 end = os_strchr(pos, '\n');
3856 if (end == NULL)
3857 break;
3858 *end = '\0';
3859 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003860 if (!os_snprintf_error(sizeof(txt), ret))
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003861 cli_txt_list_add(&ifnames, txt);
3862 pos = end + 1;
3863 }
3864}
3865
3866
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003867static void try_connection(void *eloop_ctx, void *timeout_ctx)
3868{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003869 if (ctrl_conn)
3870 goto done;
3871
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003872 if (ctrl_ifname == NULL)
3873 ctrl_ifname = wpa_cli_get_default_ifname();
3874
3875 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3876 if (!warning_displayed) {
3877 printf("Could not connect to wpa_supplicant: "
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003878 "%s - re-trying\n",
3879 ctrl_ifname ? ctrl_ifname : "(nil)");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003880 warning_displayed = 1;
3881 }
3882 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3883 return;
3884 }
3885
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003886 update_bssid_list(ctrl_conn);
3887
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003888 if (warning_displayed)
3889 printf("Connection established.\n");
3890
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003891done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003892 start_edit();
3893}
3894
3895
3896static void wpa_cli_interactive(void)
3897{
3898 printf("\nInteractive mode\n\n");
3899
3900 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003901 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003902 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003904 cli_txt_list_flush(&p2p_peers);
3905 cli_txt_list_flush(&p2p_groups);
3906 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003907 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003908 if (edit_started)
3909 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003910 os_free(hfile);
3911 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3912 wpa_cli_close_connection();
3913}
3914
3915
3916static void wpa_cli_action(struct wpa_ctrl *ctrl)
3917{
3918#ifdef CONFIG_ANSI_C_EXTRA
3919 /* TODO: ANSI C version(?) */
3920 printf("Action processing not supported in ANSI C build.\n");
3921#else /* CONFIG_ANSI_C_EXTRA */
3922 fd_set rfds;
3923 int fd, res;
3924 struct timeval tv;
3925 char buf[256]; /* note: large enough to fit in unsolicited messages */
3926 size_t len;
3927
3928 fd = wpa_ctrl_get_fd(ctrl);
3929
3930 while (!wpa_cli_quit) {
3931 FD_ZERO(&rfds);
3932 FD_SET(fd, &rfds);
3933 tv.tv_sec = ping_interval;
3934 tv.tv_usec = 0;
3935 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3936 if (res < 0 && errno != EINTR) {
3937 perror("select");
3938 break;
3939 }
3940
3941 if (FD_ISSET(fd, &rfds))
3942 wpa_cli_recv_pending(ctrl, 1);
3943 else {
3944 /* verify that connection is still working */
3945 len = sizeof(buf) - 1;
3946 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3947 wpa_cli_action_cb) < 0 ||
3948 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3949 printf("wpa_supplicant did not reply to PING "
3950 "command - exiting\n");
3951 break;
3952 }
3953 }
3954 }
3955#endif /* CONFIG_ANSI_C_EXTRA */
3956}
3957
3958
3959static void wpa_cli_cleanup(void)
3960{
3961 wpa_cli_close_connection();
3962 if (pid_file)
3963 os_daemonize_terminate(pid_file);
3964
3965 os_program_deinit();
3966}
3967
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003968
3969static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003970{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003971 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972}
3973
3974
3975static char * wpa_cli_get_default_ifname(void)
3976{
3977 char *ifname = NULL;
3978
3979#ifdef CONFIG_CTRL_IFACE_UNIX
3980 struct dirent *dent;
3981 DIR *dir = opendir(ctrl_iface_dir);
3982 if (!dir) {
3983#ifdef ANDROID
3984 char ifprop[PROPERTY_VALUE_MAX];
3985 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3986 ifname = os_strdup(ifprop);
3987 printf("Using interface '%s'\n", ifname);
3988 return ifname;
3989 }
3990#endif /* ANDROID */
3991 return NULL;
3992 }
3993 while ((dent = readdir(dir))) {
3994#ifdef _DIRENT_HAVE_D_TYPE
3995 /*
3996 * Skip the file if it is not a socket. Also accept
3997 * DT_UNKNOWN (0) in case the C library or underlying
3998 * file system does not support d_type.
3999 */
4000 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4001 continue;
4002#endif /* _DIRENT_HAVE_D_TYPE */
4003 if (os_strcmp(dent->d_name, ".") == 0 ||
4004 os_strcmp(dent->d_name, "..") == 0)
4005 continue;
4006 printf("Selected interface '%s'\n", dent->d_name);
4007 ifname = os_strdup(dent->d_name);
4008 break;
4009 }
4010 closedir(dir);
4011#endif /* CONFIG_CTRL_IFACE_UNIX */
4012
4013#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004014 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 size_t len;
4016 struct wpa_ctrl *ctrl;
4017 int ret;
4018
4019 ctrl = wpa_ctrl_open(NULL);
4020 if (ctrl == NULL)
4021 return NULL;
4022
4023 len = sizeof(buf) - 1;
4024 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4025 if (ret >= 0) {
4026 buf[len] = '\0';
4027 pos = os_strchr(buf, '\n');
4028 if (pos)
4029 *pos = '\0';
4030 ifname = os_strdup(buf);
4031 }
4032 wpa_ctrl_close(ctrl);
4033#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4034
4035 return ifname;
4036}
4037
4038
4039int main(int argc, char *argv[])
4040{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004041 int c;
4042 int daemonize = 0;
4043 int ret = 0;
4044 const char *global = NULL;
4045
4046 if (os_program_init())
4047 return -1;
4048
4049 for (;;) {
4050 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
4051 if (c < 0)
4052 break;
4053 switch (c) {
4054 case 'a':
4055 action_file = optarg;
4056 break;
4057 case 'B':
4058 daemonize = 1;
4059 break;
4060 case 'g':
4061 global = optarg;
4062 break;
4063 case 'G':
4064 ping_interval = atoi(optarg);
4065 break;
4066 case 'h':
4067 usage();
4068 return 0;
4069 case 'v':
4070 printf("%s\n", wpa_cli_version);
4071 return 0;
4072 case 'i':
4073 os_free(ctrl_ifname);
4074 ctrl_ifname = os_strdup(optarg);
4075 break;
4076 case 'p':
4077 ctrl_iface_dir = optarg;
4078 break;
4079 case 'P':
4080 pid_file = optarg;
4081 break;
4082 default:
4083 usage();
4084 return -1;
4085 }
4086 }
4087
4088 interactive = (argc == optind) && (action_file == NULL);
4089
4090 if (interactive)
4091 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4092
4093 if (eloop_init())
4094 return -1;
4095
4096 if (global) {
4097#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4098 ctrl_conn = wpa_ctrl_open(NULL);
4099#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4100 ctrl_conn = wpa_ctrl_open(global);
4101#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4102 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004103 fprintf(stderr, "Failed to connect to wpa_supplicant "
4104 "global interface: %s error: %s\n",
4105 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004106 return -1;
4107 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004108
4109 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004110 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004111 mon_conn = wpa_ctrl_open(global);
4112 if (mon_conn) {
4113 if (wpa_ctrl_attach(mon_conn) == 0) {
4114 wpa_cli_attached = 1;
4115 eloop_register_read_sock(
4116 wpa_ctrl_get_fd(mon_conn),
4117 wpa_cli_mon_receive,
4118 NULL, NULL);
4119 } else {
4120 printf("Failed to open monitor "
4121 "connection through global "
4122 "control interface\n");
4123 }
4124 }
4125 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 }
4127
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004128 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129
4130 if (ctrl_ifname == NULL)
4131 ctrl_ifname = wpa_cli_get_default_ifname();
4132
4133 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004134 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004135 } else {
4136 if (!global &&
4137 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004138 fprintf(stderr, "Failed to connect to non-global "
4139 "ctrl_ifname: %s error: %s\n",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004140 ctrl_ifname ? ctrl_ifname : "(nil)",
4141 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004142 return -1;
4143 }
4144
4145 if (action_file) {
4146 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4147 wpa_cli_attached = 1;
4148 } else {
4149 printf("Warning: Failed to attach to "
4150 "wpa_supplicant.\n");
4151 return -1;
4152 }
4153 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004154
4155 if (daemonize && os_daemonize(pid_file))
4156 return -1;
4157
4158 if (action_file)
4159 wpa_cli_action(ctrl_conn);
4160 else
4161 ret = wpa_request(ctrl_conn, argc - optind,
4162 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163 }
4164
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004165 os_free(ctrl_ifname);
4166 eloop_destroy();
4167 wpa_cli_cleanup();
4168
4169 return ret;
4170}
4171
4172#else /* CONFIG_CTRL_IFACE */
4173int main(int argc, char *argv[])
4174{
4175 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4176 return -1;
4177}
4178#endif /* CONFIG_CTRL_IFACE */