blob: 7012dfbe5fbed4c3ef295f53453c8b179e1b2a21 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003 * Copyright (c) 2004-2016, 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
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070029static const char *const wpa_cli_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidtde47be72016-01-07 12:52:55 -080031"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070034static const char *const 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
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070038static const char *const 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
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080069#define VENDOR_ELEM_FRAME_ID \
70 " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
71 "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
72 "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
73 "11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
74
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075static struct wpa_ctrl *ctrl_conn;
76static struct wpa_ctrl *mon_conn;
77static int wpa_cli_quit = 0;
78static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070079static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080static int wpa_cli_last_id = 0;
81#ifndef CONFIG_CTRL_IFACE_DIR
82#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
83#endif /* CONFIG_CTRL_IFACE_DIR */
84static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080085static const char *client_socket_dir = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070086static char *ctrl_ifname = NULL;
87static const char *pid_file = NULL;
88static const char *action_file = NULL;
89static int ping_interval = 5;
90static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070091static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070092
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080093struct cli_txt_entry {
94 struct dl_list list;
95 char *txt;
96};
97
98static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
99static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
100static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700101static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700102static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700105static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700107static void wpa_cli_close_connection(void);
108static char * wpa_cli_get_default_ifname(void);
109static char ** wpa_list_cmd_list(void);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700110static void update_networks(struct wpa_ctrl *ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111
112
113static void usage(void)
114{
115 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
116 "[-a<action file>] \\\n"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800117 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
118 "\\\n"
119 " [-s<wpa_client_socket_file_path>] "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700120 "[command..]\n"
121 " -h = help (show this usage text)\n"
122 " -v = shown version information\n"
123 " -a = run in daemon mode executing the action file based on "
124 "events from\n"
125 " wpa_supplicant\n"
126 " -B = run a daemon in the background\n"
127 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
128 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700129 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700130}
131
132
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800133static void cli_txt_list_free(struct cli_txt_entry *e)
134{
135 dl_list_del(&e->list);
136 os_free(e->txt);
137 os_free(e);
138}
139
140
141static void cli_txt_list_flush(struct dl_list *list)
142{
143 struct cli_txt_entry *e;
144 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
145 cli_txt_list_free(e);
146}
147
148
149static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
150 const char *txt)
151{
152 struct cli_txt_entry *e;
153 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
154 if (os_strcmp(e->txt, txt) == 0)
155 return e;
156 }
157 return NULL;
158}
159
160
161static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
162{
163 struct cli_txt_entry *e;
164 e = cli_txt_list_get(txt_list, txt);
165 if (e)
166 cli_txt_list_free(e);
167}
168
169
170static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
171{
172 u8 addr[ETH_ALEN];
173 char buf[18];
174 if (hwaddr_aton(txt, addr) < 0)
175 return;
176 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
177 cli_txt_list_del(txt_list, buf);
178}
179
180
181#ifdef CONFIG_P2P
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700182static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
183 int separator)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800184{
185 const char *end;
186 char *buf;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700187 end = os_strchr(txt, separator);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800188 if (end == NULL)
189 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700190 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800191 if (buf == NULL)
192 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800193 cli_txt_list_del(txt_list, buf);
194 os_free(buf);
195}
196#endif /* CONFIG_P2P */
197
198
199static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
200{
201 struct cli_txt_entry *e;
202 e = cli_txt_list_get(txt_list, txt);
203 if (e)
204 return 0;
205 e = os_zalloc(sizeof(*e));
206 if (e == NULL)
207 return -1;
208 e->txt = os_strdup(txt);
209 if (e->txt == NULL) {
210 os_free(e);
211 return -1;
212 }
213 dl_list_add(txt_list, &e->list);
214 return 0;
215}
216
217
218#ifdef CONFIG_P2P
219static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
220{
221 u8 addr[ETH_ALEN];
222 char buf[18];
223 if (hwaddr_aton(txt, addr) < 0)
224 return -1;
225 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
226 return cli_txt_list_add(txt_list, buf);
227}
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700228#endif /* CONFIG_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229
230
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700231static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
232 int separator)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800233{
234 const char *end;
235 char *buf;
236 int ret;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700237 end = os_strchr(txt, separator);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800238 if (end == NULL)
239 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700240 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800241 if (buf == NULL)
242 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 ret = cli_txt_list_add(txt_list, buf);
244 os_free(buf);
245 return ret;
246}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800247
248
249static char ** cli_txt_list_array(struct dl_list *txt_list)
250{
251 unsigned int i, count = dl_list_len(txt_list);
252 char **res;
253 struct cli_txt_entry *e;
254
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700255 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800256 if (res == NULL)
257 return NULL;
258
259 i = 0;
260 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
261 res[i] = os_strdup(e->txt);
262 if (res[i] == NULL)
263 break;
264 i++;
265 }
266
267 return res;
268}
269
270
271static int get_cmd_arg_num(const char *str, int pos)
272{
273 int arg = 0, i;
274
275 for (i = 0; i <= pos; i++) {
276 if (str[i] != ' ') {
277 arg++;
278 while (i <= pos && str[i] != ' ')
279 i++;
280 }
281 }
282
283 if (arg > 0)
284 arg--;
285 return arg;
286}
287
288
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700289static int str_starts(const char *src, const char *match)
290{
291 return os_strncmp(src, match, os_strlen(match)) == 0;
292}
293
294
295static int wpa_cli_show_event(const char *event)
296{
297 const char *start;
298
299 start = os_strchr(event, '>');
300 if (start == NULL)
301 return 1;
302
303 start++;
304 /*
305 * Skip BSS added/removed events since they can be relatively frequent
306 * and are likely of not much use for an interactive user.
307 */
308 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
309 str_starts(start, WPA_EVENT_BSS_REMOVED))
310 return 0;
311
312 return 1;
313}
314
315
316static int wpa_cli_open_connection(const char *ifname, int attach)
317{
318#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
319 ctrl_conn = wpa_ctrl_open(ifname);
320 if (ctrl_conn == NULL)
321 return -1;
322
323 if (attach && interactive)
324 mon_conn = wpa_ctrl_open(ifname);
325 else
326 mon_conn = NULL;
327#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
328 char *cfile = NULL;
329 int flen, res;
330
331 if (ifname == NULL)
332 return -1;
333
334#ifdef ANDROID
335 if (access(ctrl_iface_dir, F_OK) < 0) {
336 cfile = os_strdup(ifname);
337 if (cfile == NULL)
338 return -1;
339 }
340#endif /* ANDROID */
341
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800342 if (client_socket_dir && client_socket_dir[0] &&
343 access(client_socket_dir, F_OK) < 0) {
344 perror(client_socket_dir);
345 os_free(cfile);
346 return -1;
347 }
348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700349 if (cfile == NULL) {
350 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
351 cfile = os_malloc(flen);
352 if (cfile == NULL)
353 return -1;
354 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
355 ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800356 if (os_snprintf_error(flen, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700357 os_free(cfile);
358 return -1;
359 }
360 }
361
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800362 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700363 if (ctrl_conn == NULL) {
364 os_free(cfile);
365 return -1;
366 }
367
368 if (attach && interactive)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800369 mon_conn = wpa_ctrl_open2(cfile, client_socket_dir);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700370 else
371 mon_conn = NULL;
372 os_free(cfile);
373#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
374
375 if (mon_conn) {
376 if (wpa_ctrl_attach(mon_conn) == 0) {
377 wpa_cli_attached = 1;
378 if (interactive)
379 eloop_register_read_sock(
380 wpa_ctrl_get_fd(mon_conn),
381 wpa_cli_mon_receive, NULL, NULL);
382 } else {
383 printf("Warning: Failed to attach to "
384 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700385 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700386 return -1;
387 }
388 }
389
390 return 0;
391}
392
393
394static void wpa_cli_close_connection(void)
395{
396 if (ctrl_conn == NULL)
397 return;
398
399 if (wpa_cli_attached) {
400 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
401 wpa_cli_attached = 0;
402 }
403 wpa_ctrl_close(ctrl_conn);
404 ctrl_conn = NULL;
405 if (mon_conn) {
406 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
407 wpa_ctrl_close(mon_conn);
408 mon_conn = NULL;
409 }
410}
411
412
413static void wpa_cli_msg_cb(char *msg, size_t len)
414{
415 printf("%s\n", msg);
416}
417
418
419static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
420{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700421 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 size_t len;
423 int ret;
424
425 if (ctrl_conn == NULL) {
426 printf("Not connected to wpa_supplicant - command dropped.\n");
427 return -1;
428 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700429 if (ifname_prefix) {
430 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
431 ifname_prefix, cmd);
432 buf[sizeof(buf) - 1] = '\0';
433 cmd = buf;
434 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700435 len = sizeof(buf) - 1;
436 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
437 wpa_cli_msg_cb);
438 if (ret == -2) {
439 printf("'%s' command timed out.\n", cmd);
440 return -2;
441 } else if (ret < 0) {
442 printf("'%s' command failed.\n", cmd);
443 return -1;
444 }
445 if (print) {
446 buf[len] = '\0';
447 printf("%s", buf);
448 if (interactive && len > 0 && buf[len - 1] != '\n')
449 printf("\n");
450 }
451 return 0;
452}
453
454
455static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
456{
457 return _wpa_ctrl_command(ctrl, cmd, 1);
458}
459
460
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700461static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
462 char *argv[])
463{
464 int i, res;
465 char *pos, *end;
466
467 pos = buf;
468 end = buf + buflen;
469
470 res = os_snprintf(pos, end - pos, "%s", cmd);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800471 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700472 goto fail;
473 pos += res;
474
475 for (i = 0; i < argc; i++) {
476 res = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800477 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700478 goto fail;
479 pos += res;
480 }
481
482 buf[buflen - 1] = '\0';
483 return 0;
484
485fail:
486 printf("Too long command\n");
487 return -1;
488}
489
490
491static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
492 int argc, char *argv[])
493{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700494 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700495 if (argc < min_args) {
496 printf("Invalid %s command - at least %d argument%s "
497 "required.\n", cmd, min_args,
498 min_args > 1 ? "s are" : " is");
499 return -1;
500 }
501 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
502 return -1;
503 return wpa_ctrl_command(ctrl, buf);
504}
505
506
507static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
508{
509 return wpa_ctrl_command(ctrl, "IFNAME");
510}
511
512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700513static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
514{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800515 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
516 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
517 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
518 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700519 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
520 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800521#ifdef ANDROID
522 if (argc > 0 && os_strcmp(argv[0], "no_events") == 0)
523 return wpa_ctrl_command(ctrl, "STATUS-NO_EVENTS");
524#endif /* ANDROID */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800525 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526}
527
528
529static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PING");
532}
533
534
535static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
537 return wpa_ctrl_command(ctrl, "RELOG");
538}
539
540
541static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
542{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700543 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544}
545
546
547static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
548{
549 return wpa_ctrl_command(ctrl, "MIB");
550}
551
552
553static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
554{
555 return wpa_ctrl_command(ctrl, "PMKSA");
556}
557
558
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700559static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
560 char *argv[])
561{
562 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
563}
564
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
567{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700568 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569 return 0;
570}
571
572
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700573static char ** wpa_cli_complete_help(const char *str, int pos)
574{
575 int arg = get_cmd_arg_num(str, pos);
576 char **res = NULL;
577
578 switch (arg) {
579 case 1:
580 res = wpa_list_cmd_list();
581 break;
582 }
583
584 return res;
585}
586
587
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
589{
590 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
591 return 0;
592}
593
594
595static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
596{
597 wpa_cli_quit = 1;
598 if (interactive)
599 eloop_terminate();
600 return 0;
601}
602
603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
605{
606 char cmd[256];
607 int res;
608
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700609 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800610 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800611 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700612 printf("Too long SET command.\n");
613 return -1;
614 }
615 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700617
618 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
619}
620
621
622static char ** wpa_cli_complete_set(const char *str, int pos)
623{
624 int arg = get_cmd_arg_num(str, pos);
625 const char *fields[] = {
626 /* runtime values */
627 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
628 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
629 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
630 "wps_fragment_size", "wps_version_number", "ampdu",
631 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
632 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
633 "no_keep_alive",
634 /* global configuration parameters */
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700635#ifdef CONFIG_CTRL_IFACE
636 "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
637#endif /* CONFIG_CTRL_IFACE */
638 "eapol_version", "ap_scan", "bgscan",
639#ifdef CONFIG_MESH
640 "user_mpm", "max_peer_links", "mesh_max_inactivity",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800641 "dot11RSNASAERetransPeriod",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700642#endif /* CONFIG_MESH */
643 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
644 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
645 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
646 "dot11RSNAConfigPMKLifetime",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700647 "dot11RSNAConfigPMKReauthThreshold",
648 "dot11RSNAConfigSATimeout",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700649#ifndef CONFIG_NO_CONFIG_WRITE
650 "update_config",
651#endif /* CONFIG_NO_CONFIG_WRITE */
652 "load_dynamic_eap",
653#ifdef CONFIG_WPS
654 "uuid", "device_name", "manufacturer", "model_name",
655 "model_number", "serial_number", "device_type", "os_version",
656 "config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
657#endif /* CONFIG_WPS */
658#ifdef CONFIG_P2P
659 "sec_device_type",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700660 "p2p_listen_reg_class", "p2p_listen_channel",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700661 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
662 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
663 "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
664 "p2p_no_go_freq", "p2p_add_cli_chan",
665 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
666 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
667 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
668 "ip_addr_start", "ip_addr_end",
669#endif /* CONFIG_P2P */
670 "country", "bss_max_count", "bss_expiration_age",
671 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
672 "max_num_sta", "disassoc_low_ack",
673#ifdef CONFIG_HS20
674 "hs20",
675#endif /* CONFIG_HS20 */
676 "interworking", "hessid", "access_network_type", "pbc_in_m1",
677 "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
678 "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700679 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700680 "sae_groups", "dtim_period", "beacon_int",
681 "ap_vendor_elements", "ignore_old_scan_res", "freq_list",
682 "scan_cur_freq", "sched_scan_interval",
683 "tdls_external_control", "osu_dir", "wowlan_triggers",
684 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
685 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700686 "reassoc_same_bss_optim", "wps_priority"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700687 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700688 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700689
690 if (arg == 1) {
691 char **res = os_calloc(num_fields + 1, sizeof(char *));
692 if (res == NULL)
693 return NULL;
694 for (i = 0; i < num_fields; i++) {
695 res[i] = os_strdup(fields[i]);
696 if (res[i] == NULL)
697 return res;
698 }
699 return res;
700 }
701
702 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
703 return cli_txt_list_array(&bsses);
704
705 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706}
707
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800708static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
709{
710 return wpa_ctrl_command(ctrl, "DUMP");
711}
712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700713
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -0700714static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
715 char *argv[])
716{
717 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
718}
719
720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
722{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700723 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724}
725
726
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700727static char ** wpa_cli_complete_get(const char *str, int pos)
728{
729 int arg = get_cmd_arg_num(str, pos);
730 const char *fields[] = {
731#ifdef CONFIG_CTRL_IFACE
732 "ctrl_interface", "ctrl_interface_group",
733#endif /* CONFIG_CTRL_IFACE */
734 "eapol_version", "ap_scan",
735#ifdef CONFIG_MESH
736 "user_mpm", "max_peer_links", "mesh_max_inactivity",
737#endif /* CONFIG_MESH */
738 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
739 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
740 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
741 "dot11RSNAConfigPMKLifetime",
742 "dot11RSNAConfigPMKReauthThreshold",
743 "dot11RSNAConfigSATimeout",
744#ifndef CONFIG_NO_CONFIG_WRITE
745 "update_config",
746#endif /* CONFIG_NO_CONFIG_WRITE */
747#ifdef CONFIG_WPS
748 "device_name", "manufacturer", "model_name", "model_number",
749 "serial_number", "config_methods", "wps_cred_processing",
750#endif /* CONFIG_WPS */
751#ifdef CONFIG_P2P
752 "p2p_listen_reg_class", "p2p_listen_channel",
753 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
754 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
755 "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
756 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
757 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
758 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
759 "ip_addr_start", "ip_addr_end",
760#endif /* CONFIG_P2P */
761 "bss_max_count", "bss_expiration_age",
762 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
763 "max_num_sta", "disassoc_low_ack",
764#ifdef CONFIG_HS20
765 "hs20",
766#endif /* CONFIG_HS20 */
767 "interworking", "access_network_type", "pbc_in_m1", "autoscan",
768 "wps_nfc_dev_pw_id", "ext_password_backend",
769 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
770 "dtim_period", "beacon_int", "ignore_old_scan_res",
771 "scan_cur_freq", "sched_scan_interval",
772 "tdls_external_control", "osu_dir", "wowlan_triggers",
773 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
774 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
775 "reassoc_same_bss_optim"
776 };
777 int i, num_fields = ARRAY_SIZE(fields);
778
779 if (arg == 1) {
780 char **res = os_calloc(num_fields + 1, sizeof(char *));
781 if (res == NULL)
782 return NULL;
783 for (i = 0; i < num_fields; i++) {
784 res[i] = os_strdup(fields[i]);
785 if (res[i] == NULL)
786 return res;
787 }
788 return res;
789 }
790
791 return NULL;
792}
793
794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
796{
797 return wpa_ctrl_command(ctrl, "LOGOFF");
798}
799
800
801static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
802{
803 return wpa_ctrl_command(ctrl, "LOGON");
804}
805
806
807static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
808 char *argv[])
809{
810 return wpa_ctrl_command(ctrl, "REASSOCIATE");
811}
812
813
Dmitry Shmidt98660862014-03-11 17:26:21 -0700814static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
815{
816 return wpa_ctrl_command(ctrl, "REATTACH");
817}
818
819
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700820static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
821 char *argv[])
822{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700823 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700824}
825
826
827static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
828{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700829 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700830}
831
832
833static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
834 char *argv[])
835{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700836 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837}
838
839
840static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
841 char *argv[])
842{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700843 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844}
845
846
847static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
848 char *argv[])
849{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700850 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851}
852
853
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700854static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
855{
856 char cmd[256];
857 int res;
858
859 if (argc < 1)
860 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
861 else
862 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800863 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700864 printf("Too long BSS_FLUSH command.\n");
865 return -1;
866 }
867 return wpa_ctrl_command(ctrl, cmd);
868}
869
870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700871static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
872 char *argv[])
873{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700874 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875}
876
877
878static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
879{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700880 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881}
882
883
884static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
885{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700886 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700887}
888
889
890static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
891{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 if (argc == 0) {
893 printf("Invalid WPS_PIN command: need one or two arguments:\n"
894 "- BSSID: use 'any' to select any\n"
895 "- PIN: optional, used only with devices that have no "
896 "display\n");
897 return -1;
898 }
899
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700900 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700901}
902
903
904static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
905 char *argv[])
906{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700907 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700908}
909
910
911static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913{
914 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
915}
916
917
Dmitry Shmidt04949592012-07-19 12:16:46 -0700918#ifdef CONFIG_WPS_NFC
919
920static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
921{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700922 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700923}
924
925
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800926static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
927 char *argv[])
928{
929 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
930}
931
932
Dmitry Shmidt04949592012-07-19 12:16:46 -0700933static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
934 char *argv[])
935{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700936 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700937}
938
939
940static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
941 char *argv[])
942{
943 int ret;
944 char *buf;
945 size_t buflen;
946
947 if (argc != 1) {
948 printf("Invalid 'wps_nfc_tag_read' command - one argument "
949 "is required.\n");
950 return -1;
951 }
952
953 buflen = 18 + os_strlen(argv[0]);
954 buf = os_malloc(buflen);
955 if (buf == NULL)
956 return -1;
957 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
958
959 ret = wpa_ctrl_command(ctrl, buf);
960 os_free(buf);
961
962 return ret;
963}
964
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800965
966static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
967 char *argv[])
968{
969 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
970}
971
972
973static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
974 char *argv[])
975{
976 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
977}
978
979
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800980static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
981 char *argv[])
982{
983 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
984}
985
Dmitry Shmidt04949592012-07-19 12:16:46 -0700986#endif /* CONFIG_WPS_NFC */
987
988
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
990{
991 char cmd[256];
992 int res;
993
994 if (argc == 2)
995 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
996 argv[0], argv[1]);
997 else if (argc == 5 || argc == 6) {
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700998 char ssid_hex[2 * SSID_MAX_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 char key_hex[2 * 64 + 1];
1000 int i;
1001
1002 ssid_hex[0] = '\0';
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001003 for (i = 0; i < SSID_MAX_LEN; i++) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 if (argv[2][i] == '\0')
1005 break;
1006 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1007 }
1008
1009 key_hex[0] = '\0';
1010 if (argc == 6) {
1011 for (i = 0; i < 64; i++) {
1012 if (argv[5][i] == '\0')
1013 break;
1014 os_snprintf(&key_hex[i * 2], 3, "%02x",
1015 argv[5][i]);
1016 }
1017 }
1018
1019 res = os_snprintf(cmd, sizeof(cmd),
1020 "WPS_REG %s %s %s %s %s %s",
1021 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1022 key_hex);
1023 } else {
1024 printf("Invalid WPS_REG command: need two arguments:\n"
1025 "- BSSID of the target AP\n"
1026 "- AP PIN\n");
1027 printf("Alternatively, six arguments can be used to "
1028 "reconfigure the AP:\n"
1029 "- BSSID of the target AP\n"
1030 "- AP PIN\n"
1031 "- new SSID\n"
1032 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1033 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1034 "- new key\n");
1035 return -1;
1036 }
1037
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001038 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 printf("Too long WPS_REG command.\n");
1040 return -1;
1041 }
1042 return wpa_ctrl_command(ctrl, cmd);
1043}
1044
1045
1046static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
1047 char *argv[])
1048{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001049 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050}
1051
1052
1053static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
1054 char *argv[])
1055{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001056 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057}
1058
1059
1060static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
1061 char *argv[])
1062{
1063 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
1064
1065}
1066
1067
1068static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
1069 char *argv[])
1070{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001071 if (argc < 2) {
1072 printf("Invalid WPS_ER_PIN command: need at least two "
1073 "arguments:\n"
1074 "- UUID: use 'any' to select any\n"
1075 "- PIN: Enrollee PIN\n"
1076 "optional: - Enrollee MAC address\n");
1077 return -1;
1078 }
1079
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001080 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081}
1082
1083
1084static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1085 char *argv[])
1086{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001087 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088}
1089
1090
1091static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1092 char *argv[])
1093{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094 if (argc != 2) {
1095 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1096 "- UUID: specify which AP to use\n"
1097 "- PIN: AP PIN\n");
1098 return -1;
1099 }
1100
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001101 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102}
1103
1104
1105static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1106 char *argv[])
1107{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 if (argc != 2) {
1109 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1110 "arguments:\n"
1111 "- UUID: specify which AP to use\n"
1112 "- Network configuration id\n");
1113 return -1;
1114 }
1115
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001116 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117}
1118
1119
1120static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1121 char *argv[])
1122{
1123 char cmd[256];
1124 int res;
1125
1126 if (argc == 5 || argc == 6) {
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001127 char ssid_hex[2 * SSID_MAX_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128 char key_hex[2 * 64 + 1];
1129 int i;
1130
1131 ssid_hex[0] = '\0';
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001132 for (i = 0; i < SSID_MAX_LEN; i++) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 if (argv[2][i] == '\0')
1134 break;
1135 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1136 }
1137
1138 key_hex[0] = '\0';
1139 if (argc == 6) {
1140 for (i = 0; i < 64; i++) {
1141 if (argv[5][i] == '\0')
1142 break;
1143 os_snprintf(&key_hex[i * 2], 3, "%02x",
1144 argv[5][i]);
1145 }
1146 }
1147
1148 res = os_snprintf(cmd, sizeof(cmd),
1149 "WPS_ER_CONFIG %s %s %s %s %s %s",
1150 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1151 key_hex);
1152 } else {
1153 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1154 "- AP UUID\n"
1155 "- AP PIN\n"
1156 "- new SSID\n"
1157 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1158 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1159 "- new key\n");
1160 return -1;
1161 }
1162
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001163 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001164 printf("Too long WPS_ER_CONFIG command.\n");
1165 return -1;
1166 }
1167 return wpa_ctrl_command(ctrl, cmd);
1168}
1169
1170
Dmitry Shmidt04949592012-07-19 12:16:46 -07001171#ifdef CONFIG_WPS_NFC
1172static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1173 char *argv[])
1174{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001175 if (argc != 2) {
1176 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1177 "arguments:\n"
1178 "- WPS/NDEF: token format\n"
1179 "- UUID: specify which AP to use\n");
1180 return -1;
1181 }
1182
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001183 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001184}
1185#endif /* CONFIG_WPS_NFC */
1186
1187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1189{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001190 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191}
1192
1193
1194static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1195{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001196 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197}
1198
1199
1200static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1201{
1202 char cmd[256], *pos, *end;
1203 int i, ret;
1204
1205 if (argc < 2) {
1206 printf("Invalid IDENTITY command: needs two arguments "
1207 "(network id and identity)\n");
1208 return -1;
1209 }
1210
1211 end = cmd + sizeof(cmd);
1212 pos = cmd;
1213 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1214 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001215 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 printf("Too long IDENTITY command.\n");
1217 return -1;
1218 }
1219 pos += ret;
1220 for (i = 2; i < argc; i++) {
1221 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001222 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 printf("Too long IDENTITY command.\n");
1224 return -1;
1225 }
1226 pos += ret;
1227 }
1228
1229 return wpa_ctrl_command(ctrl, cmd);
1230}
1231
1232
1233static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1234{
1235 char cmd[256], *pos, *end;
1236 int i, ret;
1237
1238 if (argc < 2) {
1239 printf("Invalid PASSWORD command: needs two arguments "
1240 "(network id and password)\n");
1241 return -1;
1242 }
1243
1244 end = cmd + sizeof(cmd);
1245 pos = cmd;
1246 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1247 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001248 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001249 printf("Too long PASSWORD command.\n");
1250 return -1;
1251 }
1252 pos += ret;
1253 for (i = 2; i < argc; i++) {
1254 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001255 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256 printf("Too long PASSWORD command.\n");
1257 return -1;
1258 }
1259 pos += ret;
1260 }
1261
1262 return wpa_ctrl_command(ctrl, cmd);
1263}
1264
1265
1266static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1267 char *argv[])
1268{
1269 char cmd[256], *pos, *end;
1270 int i, ret;
1271
1272 if (argc < 2) {
1273 printf("Invalid NEW_PASSWORD command: needs two arguments "
1274 "(network id and password)\n");
1275 return -1;
1276 }
1277
1278 end = cmd + sizeof(cmd);
1279 pos = cmd;
1280 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1281 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001282 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283 printf("Too long NEW_PASSWORD command.\n");
1284 return -1;
1285 }
1286 pos += ret;
1287 for (i = 2; i < argc; i++) {
1288 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001289 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 printf("Too long NEW_PASSWORD command.\n");
1291 return -1;
1292 }
1293 pos += ret;
1294 }
1295
1296 return wpa_ctrl_command(ctrl, cmd);
1297}
1298
1299
1300static int wpa_cli_cmd_pin(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 PIN command: needs two arguments "
1307 "(network id and pin)\n");
1308 return -1;
1309 }
1310
1311 end = cmd + sizeof(cmd);
1312 pos = cmd;
1313 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%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 PIN 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 PIN command.\n");
1324 return -1;
1325 }
1326 pos += ret;
1327 }
1328 return wpa_ctrl_command(ctrl, cmd);
1329}
1330
1331
1332static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1333{
1334 char cmd[256], *pos, *end;
1335 int i, ret;
1336
1337 if (argc < 2) {
1338 printf("Invalid OTP command: needs two arguments (network "
1339 "id and password)\n");
1340 return -1;
1341 }
1342
1343 end = cmd + sizeof(cmd);
1344 pos = cmd;
1345 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1346 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001347 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348 printf("Too long OTP command.\n");
1349 return -1;
1350 }
1351 pos += ret;
1352 for (i = 2; i < argc; i++) {
1353 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001354 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001355 printf("Too long OTP command.\n");
1356 return -1;
1357 }
1358 pos += ret;
1359 }
1360
1361 return wpa_ctrl_command(ctrl, cmd);
1362}
1363
1364
Dmitry Shmidt051af732013-10-22 13:52:46 -07001365static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1366{
1367 char cmd[256], *pos, *end;
1368 int i, ret;
1369
1370 if (argc < 2) {
1371 printf("Invalid SIM command: needs two arguments "
1372 "(network id and SIM operation response)\n");
1373 return -1;
1374 }
1375
1376 end = cmd + sizeof(cmd);
1377 pos = cmd;
1378 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1379 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001380 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001381 printf("Too long SIM command.\n");
1382 return -1;
1383 }
1384 pos += ret;
1385 for (i = 2; i < argc; i++) {
1386 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001387 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001388 printf("Too long SIM command.\n");
1389 return -1;
1390 }
1391 pos += ret;
1392 }
1393 return wpa_ctrl_command(ctrl, cmd);
1394}
1395
1396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1398 char *argv[])
1399{
1400 char cmd[256], *pos, *end;
1401 int i, ret;
1402
1403 if (argc < 2) {
1404 printf("Invalid PASSPHRASE command: needs two arguments "
1405 "(network id and passphrase)\n");
1406 return -1;
1407 }
1408
1409 end = cmd + sizeof(cmd);
1410 pos = cmd;
1411 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1412 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001413 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414 printf("Too long PASSPHRASE command.\n");
1415 return -1;
1416 }
1417 pos += ret;
1418 for (i = 2; i < argc; i++) {
1419 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001420 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421 printf("Too long PASSPHRASE command.\n");
1422 return -1;
1423 }
1424 pos += ret;
1425 }
1426
1427 return wpa_ctrl_command(ctrl, cmd);
1428}
1429
1430
1431static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1432{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 if (argc < 2) {
1434 printf("Invalid BSSID command: needs two arguments (network "
1435 "id and BSSID)\n");
1436 return -1;
1437 }
1438
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001439 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001440}
1441
1442
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001443static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1444{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001445 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001446}
1447
1448
1449static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1450{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001451 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001452}
1453
1454
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1456 char *argv[])
1457{
1458 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1459}
1460
1461
1462static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1463 char *argv[])
1464{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001465 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466}
1467
1468
1469static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1470 char *argv[])
1471{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001472 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473}
1474
1475
1476static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1477 char *argv[])
1478{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001479 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480}
1481
1482
1483static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1484 char *argv[])
1485{
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001486 int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07001487 if (interactive)
1488 update_networks(ctrl);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001489 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490}
1491
1492
1493static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1494 char *argv[])
1495{
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001496 int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07001497 if (interactive)
1498 update_networks(ctrl);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001499 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500}
1501
1502
1503static void wpa_cli_show_network_variables(void)
1504{
1505 printf("set_network variables:\n"
1506 " ssid (network name, SSID)\n"
1507 " psk (WPA passphrase or pre-shared key)\n"
1508 " key_mgmt (key management protocol)\n"
1509 " identity (EAP identity)\n"
1510 " password (EAP password)\n"
1511 " ...\n"
1512 "\n"
1513 "Note: Values are entered in the same format as the "
1514 "configuration file is using,\n"
1515 "i.e., strings values need to be inside double quotation "
1516 "marks.\n"
1517 "For example: set_network 1 ssid \"network name\"\n"
1518 "\n"
1519 "Please see wpa_supplicant.conf documentation for full list "
1520 "of\navailable variables.\n");
1521}
1522
1523
1524static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1525 char *argv[])
1526{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001527 if (argc == 0) {
1528 wpa_cli_show_network_variables();
1529 return 0;
1530 }
1531
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001532 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533 printf("Invalid SET_NETWORK command: needs three arguments\n"
1534 "(network id, variable name, and value)\n");
1535 return -1;
1536 }
1537
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001538 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539}
1540
1541
1542static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1543 char *argv[])
1544{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545 if (argc == 0) {
1546 wpa_cli_show_network_variables();
1547 return 0;
1548 }
1549
1550 if (argc != 2) {
1551 printf("Invalid GET_NETWORK command: needs two arguments\n"
1552 "(network id and variable name)\n");
1553 return -1;
1554 }
1555
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001556 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557}
1558
1559
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001560static const char *network_fields[] = {
1561 "ssid", "scan_ssid", "bssid", "bssid_blacklist",
1562 "bssid_whitelist", "psk", "proto", "key_mgmt",
1563 "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001564 "freq_list", "max_oper_chwidth",
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001565#ifdef IEEE8021X_EAPOL
1566 "eap", "identity", "anonymous_identity", "password", "ca_cert",
1567 "ca_path", "client_cert", "private_key", "private_key_passwd",
1568 "dh_file", "subject_match", "altsubject_match",
1569 "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
1570 "client_cert2", "private_key2", "private_key2_passwd",
1571 "dh_file2", "subject_match2", "altsubject_match2",
1572 "domain_suffix_match2", "domain_match2", "phase1", "phase2",
1573 "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
1574 "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
1575 "engine", "engine2", "eapol_flags", "sim_num",
1576 "openssl_ciphers", "erp",
1577#endif /* IEEE8021X_EAPOL */
1578 "wep_key0", "wep_key1", "wep_key2", "wep_key3",
1579 "wep_tx_keyidx", "priority",
1580#ifdef IEEE8021X_EAPOL
1581 "eap_workaround", "pac_file", "fragment_size", "ocsp",
1582#endif /* IEEE8021X_EAPOL */
1583#ifdef CONFIG_MESH
1584 "mode", "no_auto_peer",
1585#else /* CONFIG_MESH */
1586 "mode",
1587#endif /* CONFIG_MESH */
1588 "proactive_key_caching", "disabled", "id_str",
1589#ifdef CONFIG_IEEE80211W
1590 "ieee80211w",
1591#endif /* CONFIG_IEEE80211W */
1592 "peerkey", "mixed_cell", "frequency", "fixed_freq",
1593#ifdef CONFIG_MESH
1594 "mesh_basic_rates", "dot11MeshMaxRetries",
1595 "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
1596 "dot11MeshHoldingTimeout",
1597#endif /* CONFIG_MESH */
1598 "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
1599#ifdef CONFIG_P2P
1600 "go_p2p_dev_addr", "p2p_client_list", "psk_list",
1601#endif /* CONFIG_P2P */
1602#ifdef CONFIG_HT_OVERRIDES
1603 "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
1604 "ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
1605 "ampdu_density", "ht_mcs",
1606#endif /* CONFIG_HT_OVERRIDES */
1607#ifdef CONFIG_VHT_OVERRIDES
1608 "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
1609 "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
1610 "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
1611 "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
1612 "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
1613 "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
1614#endif /* CONFIG_VHT_OVERRIDES */
1615 "ap_max_inactivity", "dtim_period", "beacon_int",
1616#ifdef CONFIG_MACSEC
1617 "macsec_policy",
1618#endif /* CONFIG_MACSEC */
1619#ifdef CONFIG_HS20
1620 "update_identifier",
1621#endif /* CONFIG_HS20 */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001622 "mac_addr", "pbss", "wps_disabled"
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001623};
1624
1625
1626static char ** wpa_cli_complete_network(const char *str, int pos)
1627{
1628 int arg = get_cmd_arg_num(str, pos);
1629 int i, num_fields = ARRAY_SIZE(network_fields);
1630 char **res = NULL;
1631
1632 switch (arg) {
1633 case 1:
1634 res = cli_txt_list_array(&networks);
1635 break;
1636 case 2:
1637 res = os_calloc(num_fields + 1, sizeof(char *));
1638 if (res == NULL)
1639 return NULL;
1640 for (i = 0; i < num_fields; i++) {
1641 res[i] = os_strdup(network_fields[i]);
1642 if (res[i] == NULL)
1643 break;
1644 }
1645 }
1646 return res;
1647}
1648
1649
1650static char ** wpa_cli_complete_network_id(const char *str, int pos)
1651{
1652 int arg = get_cmd_arg_num(str, pos);
1653 if (arg == 1)
1654 return cli_txt_list_array(&networks);
1655 return NULL;
1656}
1657
1658
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001659static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1660 char *argv[])
1661{
1662 if (argc == 0) {
1663 wpa_cli_show_network_variables();
1664 return 0;
1665 }
1666
1667 if (argc < 3) {
1668 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1669 "(src netid, dest netid, and variable name)\n");
1670 return -1;
1671 }
1672
1673 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1674}
1675
1676
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001677static char ** wpa_cli_complete_dup_network(const char *str, int pos)
1678{
1679 int arg = get_cmd_arg_num(str, pos);
1680 int i, num_fields = ARRAY_SIZE(network_fields);
1681 char **res = NULL;
1682
1683 switch (arg) {
1684 case 1:
1685 case 2:
1686 res = cli_txt_list_array(&networks);
1687 break;
1688 case 3:
1689 res = os_calloc(num_fields + 1, sizeof(char *));
1690 if (res == NULL)
1691 return NULL;
1692 for (i = 0; i < num_fields; i++) {
1693 res[i] = os_strdup(network_fields[i]);
1694 if (res[i] == NULL)
1695 break;
1696 }
1697 }
1698 return res;
1699}
1700
1701
Dmitry Shmidt04949592012-07-19 12:16:46 -07001702static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1703 char *argv[])
1704{
1705 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1706}
1707
1708
1709static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1710{
1711 return wpa_ctrl_command(ctrl, "ADD_CRED");
1712}
1713
1714
1715static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1716 char *argv[])
1717{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001718 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001719}
1720
1721
1722static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1723{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001724 if (argc != 3) {
1725 printf("Invalid SET_CRED command: needs three arguments\n"
1726 "(cred id, variable name, and value)\n");
1727 return -1;
1728 }
1729
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001730 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001731}
1732
1733
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001734static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1735{
1736 if (argc != 2) {
1737 printf("Invalid GET_CRED command: needs two arguments\n"
1738 "(cred id, variable name)\n");
1739 return -1;
1740 }
1741
1742 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1743}
1744
1745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1747 char *argv[])
1748{
1749 return wpa_ctrl_command(ctrl, "DISCONNECT");
1750}
1751
1752
1753static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1754 char *argv[])
1755{
1756 return wpa_ctrl_command(ctrl, "RECONNECT");
1757}
1758
1759
1760static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1761 char *argv[])
1762{
1763 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1764}
1765
1766
1767static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1768{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001769 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770}
1771
1772
1773static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1774 char *argv[])
1775{
1776 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1777}
1778
1779
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001780static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc,
1781 char *argv[])
1782{
1783 return wpa_ctrl_command(ctrl, "ABORT_SCAN");
1784}
1785
1786
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1788{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001789 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001790}
1791
1792
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001793static char ** wpa_cli_complete_bss(const char *str, int pos)
1794{
1795 int arg = get_cmd_arg_num(str, pos);
1796 char **res = NULL;
1797
1798 switch (arg) {
1799 case 1:
1800 res = cli_txt_list_array(&bsses);
1801 break;
1802 }
1803
1804 return res;
1805}
1806
1807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1809 char *argv[])
1810{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 if (argc < 1 || argc > 2) {
1812 printf("Invalid GET_CAPABILITY command: need either one or "
1813 "two arguments\n");
1814 return -1;
1815 }
1816
1817 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1818 printf("Invalid GET_CAPABILITY command: second argument, "
1819 "if any, must be 'strict'\n");
1820 return -1;
1821 }
1822
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001823 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824}
1825
1826
1827static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1828{
1829 printf("Available interfaces:\n");
1830 return wpa_ctrl_command(ctrl, "INTERFACES");
1831}
1832
1833
1834static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1835{
1836 if (argc < 1) {
1837 wpa_cli_list_interfaces(ctrl);
1838 return 0;
1839 }
1840
1841 wpa_cli_close_connection();
1842 os_free(ctrl_ifname);
1843 ctrl_ifname = os_strdup(argv[0]);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001844 if (!ctrl_ifname) {
1845 printf("Failed to allocate memory\n");
1846 return 0;
1847 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001849 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850 printf("Connected to interface '%s.\n", ctrl_ifname);
1851 } else {
1852 printf("Could not connect to interface '%s' - re-trying\n",
1853 ctrl_ifname);
1854 }
1855 return 0;
1856}
1857
1858
1859static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1860 char *argv[])
1861{
1862 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1863}
1864
1865
1866static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1867 char *argv[])
1868{
1869 return wpa_ctrl_command(ctrl, "TERMINATE");
1870}
1871
1872
1873static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1874 char *argv[])
1875{
1876 char cmd[256];
1877 int res;
1878
1879 if (argc < 1) {
1880 printf("Invalid INTERFACE_ADD command: needs at least one "
1881 "argument (interface name)\n"
1882 "All arguments: ifname confname driver ctrl_interface "
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001883 "driver_param bridge_name [create]\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 return -1;
1885 }
1886
1887 /*
1888 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001889 * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890 */
1891 res = os_snprintf(cmd, sizeof(cmd),
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001892 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 argv[0],
1894 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1895 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001896 argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
1897 argc > 7 ? argv[7] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001898 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899 return -1;
1900 cmd[sizeof(cmd) - 1] = '\0';
1901 return wpa_ctrl_command(ctrl, cmd);
1902}
1903
1904
1905static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1906 char *argv[])
1907{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001908 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001909}
1910
1911
1912static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1913 char *argv[])
1914{
1915 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1916}
1917
1918
1919#ifdef CONFIG_AP
1920static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1921{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001922 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923}
1924
1925
1926static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1927 char *addr, size_t addr_len)
1928{
1929 char buf[4096], *pos;
1930 size_t len;
1931 int ret;
1932
1933 if (ctrl_conn == NULL) {
1934 printf("Not connected to hostapd - command dropped.\n");
1935 return -1;
1936 }
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001937 if (ifname_prefix) {
1938 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
1939 ifname_prefix, cmd);
1940 buf[sizeof(buf) - 1] = '\0';
1941 cmd = buf;
1942 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001943 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001944 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945 wpa_cli_msg_cb);
1946 if (ret == -2) {
1947 printf("'%s' command timed out.\n", cmd);
1948 return -2;
1949 } else if (ret < 0) {
1950 printf("'%s' command failed.\n", cmd);
1951 return -1;
1952 }
1953
1954 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001955 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001956 return -1;
1957 printf("%s", buf);
1958
1959 pos = buf;
1960 while (*pos != '\0' && *pos != '\n')
1961 pos++;
1962 *pos = '\0';
1963 os_strlcpy(addr, buf, addr_len);
1964 return 0;
1965}
1966
1967
1968static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1969{
1970 char addr[32], cmd[64];
1971
1972 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1973 return 0;
1974 do {
1975 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1976 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1977
1978 return -1;
1979}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001980
1981
1982static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1983 char *argv[])
1984{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001985 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001986}
1987
1988
1989static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1990 char *argv[])
1991{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001992 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001993}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001994
1995static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1996 char *argv[])
1997{
1998 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1999}
2000
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001#endif /* CONFIG_AP */
2002
2003
2004static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
2005{
2006 return wpa_ctrl_command(ctrl, "SUSPEND");
2007}
2008
2009
2010static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
2011{
2012 return wpa_ctrl_command(ctrl, "RESUME");
2013}
2014
2015
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002016#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
2018{
2019 return wpa_ctrl_command(ctrl, "DROP_SA");
2020}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002021#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022
2023
2024static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
2025{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002026 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027}
2028
2029
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002030#ifdef CONFIG_MESH
2031
2032static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
2033 char *argv[])
2034{
2035 return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
2036}
2037
2038
2039static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
2040 char *argv[])
2041{
2042 return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
2043}
2044
2045
2046static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
2047 char *argv[])
2048{
2049 return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
2050}
2051
Dmitry Shmidte4663042016-04-04 10:07:49 -07002052
2053static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
2054 char *argv[])
2055{
2056 return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
2057}
2058
2059
2060static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
2061 char *argv[])
2062{
2063 return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
2064}
2065
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002066#endif /* CONFIG_MESH */
2067
2068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069#ifdef CONFIG_P2P
2070
2071static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2072{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002073 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2074}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002077static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2078{
2079 char **res = NULL;
2080 int arg = get_cmd_arg_num(str, pos);
2081
2082 res = os_calloc(6, sizeof(char *));
2083 if (res == NULL)
2084 return NULL;
2085 res[0] = os_strdup("type=social");
2086 if (res[0] == NULL) {
2087 os_free(res);
2088 return NULL;
2089 }
2090 res[1] = os_strdup("type=progressive");
2091 if (res[1] == NULL)
2092 return res;
2093 res[2] = os_strdup("delay=");
2094 if (res[2] == NULL)
2095 return res;
2096 res[3] = os_strdup("dev_id=");
2097 if (res[3] == NULL)
2098 return res;
2099 if (arg == 1)
2100 res[4] = os_strdup("[timeout]");
2101
2102 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002103}
2104
2105
2106static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2107 char *argv[])
2108{
2109 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2110}
2111
2112
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002113static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
2114 char *argv[])
2115{
2116 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
2117}
2118
2119
2120static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
2121 char *argv[])
2122{
2123 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
2124}
2125
2126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2128 char *argv[])
2129{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002130 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131}
2132
2133
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002134static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2135{
2136 int arg = get_cmd_arg_num(str, pos);
2137 char **res = NULL;
2138
2139 switch (arg) {
2140 case 1:
2141 res = cli_txt_list_array(&p2p_peers);
2142 break;
2143 }
2144
2145 return res;
2146}
2147
2148
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002152 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153}
2154
2155
2156static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002159 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160}
2161
2162
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002163static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2164{
2165 int arg = get_cmd_arg_num(str, pos);
2166 char **res = NULL;
2167
2168 switch (arg) {
2169 case 1:
2170 res = cli_txt_list_array(&p2p_groups);
2171 break;
2172 }
2173
2174 return res;
2175}
2176
2177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2179 char *argv[])
2180{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002181 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182}
2183
2184
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002185static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc,
2186 char *argv[])
2187{
2188 return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv);
2189}
2190
2191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2193 char *argv[])
2194{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002195 if (argc != 2 && argc != 3) {
2196 printf("Invalid P2P_PROV_DISC command: needs at least "
2197 "two arguments, address and config method\n"
2198 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002199 return -1;
2200 }
2201
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002202 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203}
2204
2205
2206static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2207 char *argv[])
2208{
2209 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2210}
2211
2212
2213static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2214 char *argv[])
2215{
2216 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002218 if (argc < 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002220 "or more arguments (address and TLVs)\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 return -1;
2222 }
2223
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002226 return wpa_ctrl_command(ctrl, cmd);
2227}
2228
2229
2230static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2231 int argc, char *argv[])
2232{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002233 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234}
2235
2236
2237static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2238 char *argv[])
2239{
2240 char cmd[4096];
2241 int res;
2242
2243 if (argc != 4) {
2244 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2245 "arguments (freq, address, dialog token, and TLVs)\n");
2246 return -1;
2247 }
2248
2249 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2250 argv[0], argv[1], argv[2], argv[3]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002251 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002252 return -1;
2253 cmd[sizeof(cmd) - 1] = '\0';
2254 return wpa_ctrl_command(ctrl, cmd);
2255}
2256
2257
2258static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
2261 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2262}
2263
2264
2265static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2266 int argc, char *argv[])
2267{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002268 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002269}
2270
2271
2272static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2273 char *argv[])
2274{
2275 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2276}
2277
2278
2279static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2280 char *argv[])
2281{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002282 if (argc < 3) {
2283 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2284 return -1;
2285 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002287 return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2288}
2289
2290
2291static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2292 char *argv[])
2293{
2294 if (argc < 5 || argc > 6) {
2295 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 "arguments\n");
2297 return -1;
2298 }
2299
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002300 return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301}
2302
2303
2304static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2305 char *argv[])
2306{
2307 char cmd[4096];
2308 int res;
2309
2310 if (argc != 2 && argc != 3) {
2311 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2312 "arguments\n");
2313 return -1;
2314 }
2315
2316 if (argc == 3)
2317 res = os_snprintf(cmd, sizeof(cmd),
2318 "P2P_SERVICE_DEL %s %s %s",
2319 argv[0], argv[1], argv[2]);
2320 else
2321 res = os_snprintf(cmd, sizeof(cmd),
2322 "P2P_SERVICE_DEL %s %s",
2323 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002324 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325 return -1;
2326 cmd[sizeof(cmd) - 1] = '\0';
2327 return wpa_ctrl_command(ctrl, cmd);
2328}
2329
2330
2331static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2332 int argc, char *argv[])
2333{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002334 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002335}
2336
2337
2338static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2339 int argc, char *argv[])
2340{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002341 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342}
2343
2344
2345static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2346{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002347 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348}
2349
2350
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002351static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2352{
2353 int arg = get_cmd_arg_num(str, pos);
2354 char **res = NULL;
2355
2356 switch (arg) {
2357 case 1:
2358 res = cli_txt_list_array(&p2p_peers);
2359 break;
2360 }
2361
2362 return res;
2363}
2364
2365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2367 char *addr, size_t addr_len,
2368 int discovered)
2369{
2370 char buf[4096], *pos;
2371 size_t len;
2372 int ret;
2373
2374 if (ctrl_conn == NULL)
2375 return -1;
2376 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002377 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 wpa_cli_msg_cb);
2379 if (ret == -2) {
2380 printf("'%s' command timed out.\n", cmd);
2381 return -2;
2382 } else if (ret < 0) {
2383 printf("'%s' command failed.\n", cmd);
2384 return -1;
2385 }
2386
2387 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002388 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 return -1;
2390
2391 pos = buf;
2392 while (*pos != '\0' && *pos != '\n')
2393 pos++;
2394 *pos++ = '\0';
2395 os_strlcpy(addr, buf, addr_len);
2396 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2397 printf("%s\n", addr);
2398 return 0;
2399}
2400
2401
2402static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2403{
2404 char addr[32], cmd[64];
2405 int discovered;
2406
2407 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2408
2409 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2410 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002411 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 do {
2413 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2414 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2415 discovered) == 0);
2416
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002417 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418}
2419
2420
2421static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424}
2425
2426
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002427static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2428{
2429 int arg = get_cmd_arg_num(str, pos);
2430 const char *fields[] = {
2431 "discoverability",
2432 "managed",
2433 "listen_channel",
2434 "ssid_postfix",
2435 "noa",
2436 "ps",
2437 "oppps",
2438 "ctwindow",
2439 "disabled",
2440 "conc_pref",
2441 "force_long_sd",
2442 "peer_filter",
2443 "cross_connect",
2444 "go_apsd",
2445 "client_apsd",
2446 "disallow_freq",
2447 "disc_int",
2448 "per_sta_psk",
2449 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002450 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002451
2452 if (arg == 1) {
2453 char **res = os_calloc(num_fields + 1, sizeof(char *));
2454 if (res == NULL)
2455 return NULL;
2456 for (i = 0; i < num_fields; i++) {
2457 res[i] = os_strdup(fields[i]);
2458 if (res[i] == NULL)
2459 return res;
2460 }
2461 return res;
2462 }
2463
2464 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2465 return cli_txt_list_array(&p2p_peers);
2466
2467 return NULL;
2468}
2469
2470
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2472{
2473 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2474}
2475
2476
2477static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2478 char *argv[])
2479{
2480 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2481}
2482
2483
2484static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2485 char *argv[])
2486{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488}
2489
2490
2491static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2492 char *argv[])
2493{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494 if (argc != 0 && argc != 2 && argc != 4) {
2495 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2496 "(preferred duration, interval; in microsecods).\n"
2497 "Optional second pair can be used to provide "
2498 "acceptable values.\n");
2499 return -1;
2500 }
2501
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002502 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503}
2504
2505
2506static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2507 char *argv[])
2508{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 if (argc != 0 && argc != 2) {
2510 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2511 "(availability period, availability interval; in "
2512 "millisecods).\n"
2513 "Extended Listen Timing can be cancelled with this "
2514 "command when used without parameters.\n");
2515 return -1;
2516 }
2517
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2519}
2520
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002521
2522static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2523 char *argv[])
2524{
2525 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2526}
2527
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002528
2529static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
2530 char *argv[])
2531{
2532 return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
2533}
2534
2535
2536static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
2537 char *argv[])
2538{
2539 return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
2540}
2541
2542
2543static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
2544 char *argv[])
2545{
2546 return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
2547}
2548
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549#endif /* CONFIG_P2P */
2550
2551#ifdef CONFIG_WIFI_DISPLAY
2552
2553static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2554 char *argv[])
2555{
2556 char cmd[100];
2557 int res;
2558
2559 if (argc != 1 && argc != 2) {
2560 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2561 "arguments (subelem, hexdump)\n");
2562 return -1;
2563 }
2564
2565 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2566 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002567 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002568 return -1;
2569 cmd[sizeof(cmd) - 1] = '\0';
2570 return wpa_ctrl_command(ctrl, cmd);
2571}
2572
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573
2574static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2575 char *argv[])
2576{
2577 char cmd[100];
2578 int res;
2579
2580 if (argc != 1) {
2581 printf("Invalid WFD_SUBELEM_GET command: needs one "
2582 "argument (subelem)\n");
2583 return -1;
2584 }
2585
2586 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2587 argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002588 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589 return -1;
2590 cmd[sizeof(cmd) - 1] = '\0';
2591 return wpa_ctrl_command(ctrl, cmd);
2592}
2593#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594
2595
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002596#ifdef CONFIG_INTERWORKING
2597static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2598 char *argv[])
2599{
2600 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2601}
2602
2603
2604static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2605 char *argv[])
2606{
2607 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2608}
2609
2610
2611static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2612 char *argv[])
2613{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002615}
2616
2617
2618static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2619 char *argv[])
2620{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002622}
2623
2624
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002625static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2626 char *argv[])
2627{
2628 return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2629}
2630
2631
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002632static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2633{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2635}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002636
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002637
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002638static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2639 char *argv[])
2640{
2641 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2642}
2643
2644
2645static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2646 char *argv[])
2647{
2648 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002649}
2650#endif /* CONFIG_INTERWORKING */
2651
2652
Dmitry Shmidt04949592012-07-19 12:16:46 -07002653#ifdef CONFIG_HS20
2654
2655static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2656 char *argv[])
2657{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002659}
2660
2661
2662static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2663 char *argv[])
2664{
2665 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002666
2667 if (argc == 0) {
2668 printf("Command needs one or two arguments (dst mac addr and "
2669 "optional home realm)\n");
2670 return -1;
2671 }
2672
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002673 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2674 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002675 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002676
2677 return wpa_ctrl_command(ctrl, cmd);
2678}
2679
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002680
2681static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2682 char *argv[])
2683{
2684 char cmd[512];
2685
2686 if (argc < 2) {
2687 printf("Command needs two arguments (dst mac addr and "
2688 "icon name)\n");
2689 return -1;
2690 }
2691
2692 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2693 return -1;
2694
2695 return wpa_ctrl_command(ctrl, cmd);
2696}
2697
2698
2699static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2700{
2701 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2702}
2703
2704
2705static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2706 char *argv[])
2707{
2708 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2709}
2710
Dmitry Shmidt04949592012-07-19 12:16:46 -07002711#endif /* CONFIG_HS20 */
2712
2713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2715 char *argv[])
2716{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718}
2719
2720
2721static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2722 char *argv[])
2723{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725}
2726
2727
2728static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2729 char *argv[])
2730{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732}
2733
2734
2735static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2736 char *argv[])
2737{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002738 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739}
2740
2741
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07002742static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
2743 char *argv[])
2744{
2745 return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
2746}
2747
2748
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002749static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2750 char *argv[])
2751{
2752 return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2753}
2754
2755
2756static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2757 char *argv[])
2758{
2759 return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2760}
2761
2762
2763static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2764 char *argv[])
2765{
2766 return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2767}
2768
2769
2770static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2771 char *argv[])
2772{
2773 return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2774}
2775
2776
2777static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2778 char *argv[])
2779{
2780 return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2781}
2782
2783
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002784static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2785 char *argv[])
2786{
2787 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2788}
2789
2790
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002791static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
2792 char *argv[])
2793{
2794 return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
2795}
2796
2797
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002798static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2799 char *argv[])
2800{
2801 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2802}
2803
2804
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002805static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2806 char *argv[])
2807{
2808 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2809}
2810
Dmitry Shmidt04949592012-07-19 12:16:46 -07002811
2812#ifdef CONFIG_AUTOSCAN
2813
2814static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2815{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002816 if (argc == 0)
2817 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2818
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002819 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002820}
2821
2822#endif /* CONFIG_AUTOSCAN */
2823
2824
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002825#ifdef CONFIG_WNM
2826
2827static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2828{
2829 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2830}
2831
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002832
2833static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2834{
2835 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2836}
2837
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002838#endif /* CONFIG_WNM */
2839
2840
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002841static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2842{
2843 if (argc == 0)
2844 return -1;
2845 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2846}
2847
2848
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002849#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002850static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2851{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002852 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002853}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002854#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002855
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002857static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2858{
2859 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2860}
2861
2862
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002863static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2864{
2865 return wpa_ctrl_command(ctrl, "FLUSH");
2866}
2867
2868
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002869static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2870{
2871 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2872}
2873
2874
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002875static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2876 char *argv[])
2877{
2878 return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2879}
2880
2881
2882static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2883{
2884 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2885}
2886
2887
2888static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2889 char *argv[])
2890{
2891 return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2892}
2893
2894
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002895static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
2896 char *argv[])
2897{
2898 return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
2899}
2900
2901
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002902static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
2903 char *argv[])
2904{
2905 return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
2906}
2907
2908
2909static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
2910 char *argv[])
2911{
2912 return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
2913}
2914
2915
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916enum wpa_cli_cmd_flags {
2917 cli_cmd_flag_none = 0x00,
2918 cli_cmd_flag_sensitive = 0x01
2919};
2920
2921struct wpa_cli_cmd {
2922 const char *cmd;
2923 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002924 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 enum wpa_cli_cmd_flags flags;
2926 const char *usage;
2927};
2928
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002929static const struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002930 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931 cli_cmd_flag_none,
2932 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002933 { "ifname", wpa_cli_cmd_ifname, NULL,
2934 cli_cmd_flag_none,
2935 "= get current interface name" },
2936 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002937 cli_cmd_flag_none,
2938 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002939 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 cli_cmd_flag_none,
2941 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002942 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943 cli_cmd_flag_none,
2944 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002945 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002946 cli_cmd_flag_none,
2947 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002948 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002950 "[command] = show usage help" },
2951 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002952 cli_cmd_flag_none,
2953 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002954 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 cli_cmd_flag_none,
2956 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002957 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958 cli_cmd_flag_none,
2959 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002960 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 cli_cmd_flag_none,
2962 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002963 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 cli_cmd_flag_none,
2965 "= set variables (shows list of variables when run without "
2966 "arguments)" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002967 { "dump", wpa_cli_cmd_dump, NULL,
2968 cli_cmd_flag_none,
2969 "= dump config variables" },
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07002970 { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971 cli_cmd_flag_none,
2972 "<name> = get information" },
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002973 { "driver_flags", wpa_cli_cmd_driver_flags, NULL,
2974 cli_cmd_flag_none,
2975 "= list driver flags" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002976 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 cli_cmd_flag_none,
2978 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002979 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 cli_cmd_flag_none,
2981 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002982 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 cli_cmd_flag_none,
2984 "= show PMKSA cache" },
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002985 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2986 cli_cmd_flag_none,
2987 "= flush PMKSA cache entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002988 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002989 cli_cmd_flag_none,
2990 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002991 { "reattach", wpa_cli_cmd_reattach, NULL,
2992 cli_cmd_flag_none,
2993 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002994 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 cli_cmd_flag_none,
2996 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002997 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002998 cli_cmd_flag_none,
2999 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003000 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003001 cli_cmd_flag_sensitive,
3002 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003003 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003004 cli_cmd_flag_sensitive,
3005 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003006 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 cli_cmd_flag_sensitive,
3008 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003009 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003010 cli_cmd_flag_sensitive,
3011 "<network id> <password> = configure one-time-password for an SSID"
3012 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003013 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 cli_cmd_flag_sensitive,
3015 "<network id> <passphrase> = configure private key passphrase\n"
3016 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07003017 { "sim", wpa_cli_cmd_sim, NULL,
3018 cli_cmd_flag_sensitive,
3019 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003020 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021 cli_cmd_flag_none,
3022 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003023 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07003024 cli_cmd_flag_none,
3025 "<BSSID> = add a BSSID to the blacklist\n"
3026 "blacklist clear = clear the blacklist\n"
3027 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003028 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07003029 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003030 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07003031 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003032 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033 cli_cmd_flag_none,
3034 "= list configured networks" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003035 { "select_network", wpa_cli_cmd_select_network,
3036 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037 cli_cmd_flag_none,
3038 "<network id> = select a network (disable others)" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003039 { "enable_network", wpa_cli_cmd_enable_network,
3040 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 cli_cmd_flag_none,
3042 "<network id> = enable a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003043 { "disable_network", wpa_cli_cmd_disable_network,
3044 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045 cli_cmd_flag_none,
3046 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003047 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 cli_cmd_flag_none,
3049 "= add a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003050 { "remove_network", wpa_cli_cmd_remove_network,
3051 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 cli_cmd_flag_none,
3053 "<network id> = remove a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003054 { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055 cli_cmd_flag_sensitive,
3056 "<network id> <variable> <value> = set network variables (shows\n"
3057 " list of variables when run without arguments)" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003058 { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003059 cli_cmd_flag_none,
3060 "<network id> <variable> = get network variables" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003061 { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
Dmitry Shmidt684785c2014-05-12 13:34:29 -07003062 cli_cmd_flag_none,
3063 "<src network id> <dst network id> <variable> = duplicate network variables"
3064 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003065 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003066 cli_cmd_flag_none,
3067 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003068 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003069 cli_cmd_flag_none,
3070 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003071 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003072 cli_cmd_flag_none,
3073 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003074 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003075 cli_cmd_flag_sensitive,
3076 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07003077 { "get_cred", wpa_cli_cmd_get_cred, NULL,
3078 cli_cmd_flag_none,
3079 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003080 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003081 cli_cmd_flag_none,
3082 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003083 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084 cli_cmd_flag_none,
3085 "= disconnect and wait for reassociate/reconnect command before\n"
3086 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003087 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 cli_cmd_flag_none,
3089 "= like reassociate, but only takes effect if already disconnected"
3090 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003091 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003092 cli_cmd_flag_none,
3093 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003094 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003095 cli_cmd_flag_none,
3096 "= get latest scan results" },
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003097 { "abort_scan", wpa_cli_cmd_abort_scan, NULL,
3098 cli_cmd_flag_none,
3099 "= request ongoing scan to be aborted" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003100 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003101 cli_cmd_flag_none,
3102 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003103 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003104 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003105 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07003106 "= get capabilities" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003107 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108 cli_cmd_flag_none,
3109 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003110 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003111 cli_cmd_flag_none,
3112 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003113 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003114 cli_cmd_flag_none,
3115 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003116 " <bridge_name> <create> <type> = adds new interface, all "
3117 "parameters but\n"
3118 " <ifname> are optional. Supported types are station ('sta') and "
3119 "AP ('ap')" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003120 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003121 cli_cmd_flag_none,
3122 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003123 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003124 cli_cmd_flag_none,
3125 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003126 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003127 cli_cmd_flag_none,
3128 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003129 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003130 cli_cmd_flag_none,
3131 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003132 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003133 cli_cmd_flag_none,
3134 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003135 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003136 cli_cmd_flag_none,
3137 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003138 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07003139 cli_cmd_flag_none,
3140 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003141 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003142 cli_cmd_flag_none,
3143 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003144 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145 cli_cmd_flag_none,
3146 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003147 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003148 cli_cmd_flag_none,
3149 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003150 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003151 cli_cmd_flag_sensitive,
3152 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3153 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003154 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003155 cli_cmd_flag_sensitive,
3156 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003157 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003158 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003159#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003160 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003161 cli_cmd_flag_none,
3162 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003163 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3164 cli_cmd_flag_none,
3165 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003166 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003167 cli_cmd_flag_none,
3168 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003169 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003170 cli_cmd_flag_sensitive,
3171 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003172 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3173 cli_cmd_flag_none,
3174 "<NDEF> <WPS> = create NFC handover request" },
3175 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3176 cli_cmd_flag_none,
3177 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003178 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3179 cli_cmd_flag_none,
3180 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3181 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003182#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003183 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 cli_cmd_flag_sensitive,
3185 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003186 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003187 cli_cmd_flag_sensitive,
3188 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003189 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003190 cli_cmd_flag_none,
3191 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003192 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003193 cli_cmd_flag_none,
3194 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003195 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196 cli_cmd_flag_sensitive,
3197 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003198 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003199 cli_cmd_flag_none,
3200 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003201 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 cli_cmd_flag_sensitive,
3203 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003204 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 cli_cmd_flag_none,
3206 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003207 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208 cli_cmd_flag_sensitive,
3209 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003210#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003211 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003212 cli_cmd_flag_none,
3213 "<WPS/NDEF> <UUID> = build NFC configuration token" },
3214#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003215 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 cli_cmd_flag_none,
3217 "<addr> = request RSN authentication with <addr> in IBSS" },
3218#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003219 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220 cli_cmd_flag_none,
3221 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003222 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223 cli_cmd_flag_none,
3224 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003225 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003226 cli_cmd_flag_none,
3227 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003228 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003229 cli_cmd_flag_none,
3230 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003231 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3232 cli_cmd_flag_none,
3233 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3234 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3235 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003237 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003238 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003239 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003240 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07003241#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003242 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003243 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07003244#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003245 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246 cli_cmd_flag_none,
3247 "<addr> = roam to the specified BSS" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003248#ifdef CONFIG_MESH
3249 { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3250 cli_cmd_flag_none,
3251 "[ifname] = Create a new mesh interface" },
3252 { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3253 cli_cmd_flag_none,
3254 "<network id> = join a mesh network (disable others)" },
3255 { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3256 cli_cmd_flag_none,
3257 "<ifname> = Remove mesh group interface" },
Dmitry Shmidte4663042016-04-04 10:07:49 -07003258 { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
3259 cli_cmd_flag_none,
3260 "<addr> = Remove a mesh peer" },
3261 { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
3262 cli_cmd_flag_none,
3263 "<addr> [duration=<seconds>] = Add a mesh peer" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003264#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003266 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3267 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003269 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270 "= stop P2P Devices search" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003271 { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3272 cli_cmd_flag_none,
3273 "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3274 { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3275 cli_cmd_flag_none,
3276 "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003277 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3278 cli_cmd_flag_none,
3279 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3280 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003282 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3283 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003285 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3286 "[ht40] = add a new P2P group (local end as GO)" },
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003287 { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL,
3288 cli_cmd_flag_none,
3289 "<dev_addr> = Get peer interface address on local GO using peer Device Address" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003290 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3291 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003293 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294 cli_cmd_flag_none,
3295 "= get the passphrase for a group (GO only)" },
3296 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003297 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 "<addr> <TLVs> = schedule service discovery request" },
3299 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003300 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003301 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003302 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303 cli_cmd_flag_none,
3304 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003305 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003306 cli_cmd_flag_none,
3307 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003308 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 cli_cmd_flag_none,
3310 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003311 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003312 cli_cmd_flag_none,
3313 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003314 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003315 cli_cmd_flag_none,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003316 "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003317 "service" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003318 { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3319 cli_cmd_flag_none,
3320 "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3321 "local ASP service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003322 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323 cli_cmd_flag_none,
3324 "<bonjour|upnp> <query|version> [|service] = remove a local "
3325 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003326 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327 cli_cmd_flag_none,
3328 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003329 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003330 cli_cmd_flag_none,
3331 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003332 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003333 "[discovered] = list known (optionally, only fully discovered) P2P "
3334 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003335 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3336 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003337 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003338 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3339 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003340 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003341 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003343 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003345 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3346 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003347 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003348 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3349 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003350 "[<duration> <interval>] [<duration> <interval>] = request GO "
3351 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003352 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3353 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003355 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3356 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3357 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003358 { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
3359 cli_cmd_flag_none,
3360 "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
3361 VENDOR_ELEM_FRAME_ID },
3362 { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
3363 cli_cmd_flag_none,
3364 "<frame id> = get vendor specific IE(s) to frame(s)\n"
3365 VENDOR_ELEM_FRAME_ID },
3366 { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
3367 cli_cmd_flag_none,
3368 "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
3369 VENDOR_ELEM_FRAME_ID },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003371#ifdef CONFIG_WIFI_DISPLAY
3372 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3373 cli_cmd_flag_none,
3374 "<subelem> [contents] = set Wi-Fi Display subelement" },
3375 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3376 cli_cmd_flag_none,
3377 "<subelem> = get Wi-Fi Display subelement" },
3378#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003379#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003380 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003381 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003382 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3383 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003384 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003385 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003386 cli_cmd_flag_none,
3387 "[auto] = perform Interworking network selection" },
3388 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003389 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003390 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003391 { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3392 wpa_cli_complete_bss, cli_cmd_flag_none,
3393 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003394 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3395 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003396 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003397 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3398 cli_cmd_flag_none,
3399 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3400 { "gas_response_get", wpa_cli_cmd_gas_response_get,
3401 wpa_cli_complete_bss, cli_cmd_flag_none,
3402 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003403#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003404#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003405 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3406 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003407 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3408 },
3409 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003410 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003411 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003412 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3413 wpa_cli_complete_bss, cli_cmd_flag_none,
3414 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3415 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3416 "= fetch OSU provider information from all APs" },
3417 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3418 cli_cmd_flag_none,
3419 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003420#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003421 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3422 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003424 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425 cli_cmd_flag_none,
3426 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003427 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428 cli_cmd_flag_none,
3429 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003430 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431 cli_cmd_flag_none,
3432 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07003433 { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
3434 cli_cmd_flag_none,
3435 "<addr> = TDLS link status with <addr>" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003436 { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3437 cli_cmd_flag_none,
3438 "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3439 "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3440 "= add WMM-AC traffic stream" },
3441 { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3442 cli_cmd_flag_none,
3443 "<tsid> = delete WMM-AC traffic stream" },
3444 { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3445 cli_cmd_flag_none,
3446 "= show status for Wireless Multi-Media Admission-Control" },
3447 { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3448 cli_cmd_flag_none,
3449 "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3450 "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3451 "with TDLS peer" },
3452 { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3453 cli_cmd_flag_none,
3454 "<addr> = disable channel switching with TDLS peer <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003455 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003456 cli_cmd_flag_none,
3457 "= get signal parameters" },
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08003458 { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
3459 cli_cmd_flag_none,
3460 "= set signal monitor parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003461 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07003462 cli_cmd_flag_none,
3463 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003464 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3465 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003466 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003467#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003468 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003469 "[params] = Set or unset (if none) autoscan parameters" },
3470#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003471#ifdef CONFIG_WNM
3472 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3473 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07003474 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003475 "<query reason> [list] = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003476#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003477 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3478 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003479 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3480 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003481#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003482 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003483 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003484#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003485 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3486 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003487 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3488 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3489 },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003490 { "neighbor_rep_request",
3491 wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003492 "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003493 },
3494 { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3495 "= flush ERP keys" },
3496 { "mac_rand_scan",
3497 wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3498 "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3499 "mask=mac-address-mask] = scan MAC randomization"
3500 },
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003501 { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
3502 cli_cmd_flag_none,
3503 "<interface type> = retrieve preferred freq list for the specified interface type" },
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003504 { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
3505 cli_cmd_flag_none,
3506 "<freq> <period> <interval> <count> = start P2P listen offload" },
3507 { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
3508 cli_cmd_flag_none,
3509 "= stop P2P listen offload" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003510 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511};
3512
3513
3514/*
3515 * Prints command usage, lines are padded with the specified string.
3516 */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003517static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518{
3519 char c;
3520 size_t n;
3521
3522 printf("%s%s ", pad, cmd->cmd);
3523 for (n = 0; (c = cmd->usage[n]); n++) {
3524 printf("%c", c);
3525 if (c == '\n')
3526 printf("%s", pad);
3527 }
3528 printf("\n");
3529}
3530
3531
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003532static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533{
3534 int n;
3535 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003536 for (n = 0; wpa_cli_commands[n].cmd; n++) {
3537 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3538 print_cmd_help(&wpa_cli_commands[n], " ");
3539 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003540}
3541
3542
3543static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3544{
3545 const char *c, *delim;
3546 int n;
3547 size_t len;
3548
3549 delim = os_strchr(cmd, ' ');
3550 if (delim)
3551 len = delim - cmd;
3552 else
3553 len = os_strlen(cmd);
3554
3555 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3556 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3557 return (wpa_cli_commands[n].flags &
3558 cli_cmd_flag_sensitive);
3559 }
3560 return 0;
3561}
3562
3563
3564static char ** wpa_list_cmd_list(void)
3565{
3566 char **res;
3567 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003568 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003569
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003570 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003571 count += dl_list_len(&p2p_groups);
3572 count += dl_list_len(&ifnames);
3573 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003574 if (res == NULL)
3575 return NULL;
3576
3577 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3578 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3579 if (res[i] == NULL)
3580 break;
3581 }
3582
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003583 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3584 size_t len = 8 + os_strlen(e->txt);
3585 res[i] = os_malloc(len);
3586 if (res[i] == NULL)
3587 break;
3588 os_snprintf(res[i], len, "ifname=%s", e->txt);
3589 i++;
3590 }
3591
3592 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3593 res[i] = os_strdup(e->txt);
3594 if (res[i] == NULL)
3595 break;
3596 i++;
3597 }
3598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003599 return res;
3600}
3601
3602
3603static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3604 int pos)
3605{
3606 int i;
3607
3608 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3609 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003610 if (wpa_cli_commands[i].completion)
3611 return wpa_cli_commands[i].completion(str,
3612 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 edit_clear_line();
3614 printf("\r%s\n", wpa_cli_commands[i].usage);
3615 edit_redraw();
3616 break;
3617 }
3618 }
3619
3620 return NULL;
3621}
3622
3623
3624static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3625{
3626 char **res;
3627 const char *end;
3628 char *cmd;
3629
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003630 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3631 end = os_strchr(str, ' ');
3632 if (end && pos > end - str) {
3633 pos -= end - str + 1;
3634 str = end + 1;
3635 }
3636 }
3637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 end = os_strchr(str, ' ');
3639 if (end == NULL || str + pos < end)
3640 return wpa_list_cmd_list();
3641
3642 cmd = os_malloc(pos + 1);
3643 if (cmd == NULL)
3644 return NULL;
3645 os_memcpy(cmd, str, pos);
3646 cmd[end - str] = '\0';
3647 res = wpa_cli_cmd_completion(cmd, str, pos);
3648 os_free(cmd);
3649 return res;
3650}
3651
3652
3653static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3654{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003655 const struct wpa_cli_cmd *cmd, *match = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 int count;
3657 int ret = 0;
3658
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003659 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3660 ifname_prefix = argv[0] + 7;
3661 argv = &argv[1];
3662 argc--;
3663 } else
3664 ifname_prefix = NULL;
3665
3666 if (argc == 0)
3667 return -1;
3668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 count = 0;
3670 cmd = wpa_cli_commands;
3671 while (cmd->cmd) {
3672 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3673 {
3674 match = cmd;
3675 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3676 /* we have an exact match */
3677 count = 1;
3678 break;
3679 }
3680 count++;
3681 }
3682 cmd++;
3683 }
3684
3685 if (count > 1) {
3686 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3687 cmd = wpa_cli_commands;
3688 while (cmd->cmd) {
3689 if (os_strncasecmp(cmd->cmd, argv[0],
3690 os_strlen(argv[0])) == 0) {
3691 printf(" %s", cmd->cmd);
3692 }
3693 cmd++;
3694 }
3695 printf("\n");
3696 ret = 1;
3697 } else if (count == 0) {
3698 printf("Unknown command '%s'\n", argv[0]);
3699 ret = 1;
3700 } else {
3701 ret = match->handler(ctrl, argc - 1, &argv[1]);
3702 }
3703
3704 return ret;
3705}
3706
3707
3708static int str_match(const char *a, const char *b)
3709{
3710 return os_strncmp(a, b, os_strlen(b)) == 0;
3711}
3712
3713
3714static int wpa_cli_exec(const char *program, const char *arg1,
3715 const char *arg2)
3716{
Jouni Malinen772e12c2014-10-07 10:29:35 -07003717 char *arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718 size_t len;
3719 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003720
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003721 /* If no interface is specified, set the global */
3722 if (!arg1)
3723 arg1 = "global";
3724
Jouni Malinen772e12c2014-10-07 10:29:35 -07003725 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3726 arg = os_malloc(len);
3727 if (arg == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 return -1;
Jouni Malinen772e12c2014-10-07 10:29:35 -07003729 os_snprintf(arg, len, "%s %s", arg1, arg2);
3730 res = os_exec(program, arg, 1);
3731 os_free(arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732
Jouni Malinen772e12c2014-10-07 10:29:35 -07003733 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003734}
3735
3736
3737static void wpa_cli_action_process(const char *msg)
3738{
3739 const char *pos;
3740 char *copy = NULL, *id, *pos2;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003741 const char *ifname = ctrl_ifname;
3742 char ifname_buf[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003744 if (eloop_terminated())
3745 return;
3746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 pos = msg;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003748 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3749 const char *end;
3750 end = os_strchr(pos + 7, ' ');
3751 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3752 pos += 7;
3753 os_memcpy(ifname_buf, pos, end - pos);
3754 ifname_buf[end - pos] = '\0';
3755 ifname = ifname_buf;
3756 pos = end + 1;
3757 }
3758 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 if (*pos == '<') {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003760 const char *prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 /* skip priority */
3762 pos = os_strchr(pos, '>');
3763 if (pos)
3764 pos++;
3765 else
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003766 pos = prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 }
3768
3769 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3770 int new_id = -1;
3771 os_unsetenv("WPA_ID");
3772 os_unsetenv("WPA_ID_STR");
3773 os_unsetenv("WPA_CTRL_DIR");
3774
3775 pos = os_strstr(pos, "[id=");
3776 if (pos)
3777 copy = os_strdup(pos + 4);
3778
3779 if (copy) {
3780 pos2 = id = copy;
3781 while (*pos2 && *pos2 != ' ')
3782 pos2++;
3783 *pos2++ = '\0';
3784 new_id = atoi(id);
3785 os_setenv("WPA_ID", id, 1);
3786 while (*pos2 && *pos2 != '=')
3787 pos2++;
3788 if (*pos2 == '=')
3789 pos2++;
3790 id = pos2;
3791 while (*pos2 && *pos2 != ']')
3792 pos2++;
3793 *pos2 = '\0';
3794 os_setenv("WPA_ID_STR", id, 1);
3795 os_free(copy);
3796 }
3797
3798 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3799
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003800 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 wpa_cli_connected = 1;
3802 wpa_cli_last_id = new_id;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003803 wpa_cli_exec(action_file, ifname, "CONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 }
3805 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3806 if (wpa_cli_connected) {
3807 wpa_cli_connected = 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003808 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003809 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003810 } else if (str_match(pos, AP_EVENT_ENABLED)) {
3811 wpa_cli_exec(action_file, ctrl_ifname, pos);
3812 } else if (str_match(pos, AP_EVENT_DISABLED)) {
3813 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003814 } else if (str_match(pos, MESH_GROUP_STARTED)) {
3815 wpa_cli_exec(action_file, ctrl_ifname, pos);
3816 } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3817 wpa_cli_exec(action_file, ctrl_ifname, pos);
3818 } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3819 wpa_cli_exec(action_file, ctrl_ifname, pos);
3820 } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3821 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003823 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003824 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003825 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003826 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003827 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003829 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003830 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003831 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003833 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003834 } else if (str_match(pos, WPS_EVENT_FAIL)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003835 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003836 } else if (str_match(pos, AP_STA_CONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003837 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003838 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003839 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003840 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003841 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003842 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003843 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003844 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003845 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003846 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3847 printf("wpa_supplicant is terminating - stop monitoring\n");
3848 wpa_cli_quit = 1;
3849 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003850}
3851
3852
3853#ifndef CONFIG_ANSI_C_EXTRA
3854static void wpa_cli_action_cb(char *msg, size_t len)
3855{
3856 wpa_cli_action_process(msg);
3857}
3858#endif /* CONFIG_ANSI_C_EXTRA */
3859
3860
3861static void wpa_cli_reconnect(void)
3862{
3863 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003864 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3865 return;
3866
3867 if (interactive) {
3868 edit_clear_line();
3869 printf("\rConnection to wpa_supplicant re-established\n");
3870 edit_redraw();
3871 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003872}
3873
3874
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003875static void cli_event(const char *str)
3876{
3877 const char *start, *s;
3878
3879 start = os_strchr(str, '>');
3880 if (start == NULL)
3881 return;
3882
3883 start++;
3884
3885 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3886 s = os_strchr(start, ' ');
3887 if (s == NULL)
3888 return;
3889 s = os_strchr(s + 1, ' ');
3890 if (s == NULL)
3891 return;
3892 cli_txt_list_add(&bsses, s + 1);
3893 return;
3894 }
3895
3896 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3897 s = os_strchr(start, ' ');
3898 if (s == NULL)
3899 return;
3900 s = os_strchr(s + 1, ' ');
3901 if (s == NULL)
3902 return;
3903 cli_txt_list_del_addr(&bsses, s + 1);
3904 return;
3905 }
3906
3907#ifdef CONFIG_P2P
3908 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3909 s = os_strstr(start, " p2p_dev_addr=");
3910 if (s == NULL)
3911 return;
3912 cli_txt_list_add_addr(&p2p_peers, s + 14);
3913 return;
3914 }
3915
3916 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3917 s = os_strstr(start, " p2p_dev_addr=");
3918 if (s == NULL)
3919 return;
3920 cli_txt_list_del_addr(&p2p_peers, s + 14);
3921 return;
3922 }
3923
3924 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3925 s = os_strchr(start, ' ');
3926 if (s == NULL)
3927 return;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003928 cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003929 return;
3930 }
3931
3932 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3933 s = os_strchr(start, ' ');
3934 if (s == NULL)
3935 return;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003936 cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003937 return;
3938 }
3939#endif /* CONFIG_P2P */
3940}
3941
3942
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003943static int check_terminating(const char *msg)
3944{
3945 const char *pos = msg;
3946
3947 if (*pos == '<') {
3948 /* skip priority */
3949 pos = os_strchr(pos, '>');
3950 if (pos)
3951 pos++;
3952 else
3953 pos = msg;
3954 }
3955
3956 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3957 edit_clear_line();
3958 printf("\rConnection to wpa_supplicant lost - trying to "
3959 "reconnect\n");
3960 edit_redraw();
3961 wpa_cli_attached = 0;
3962 wpa_cli_close_connection();
3963 return 1;
3964 }
3965
3966 return 0;
3967}
3968
3969
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003970static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3971{
3972 if (ctrl_conn == NULL) {
3973 wpa_cli_reconnect();
3974 return;
3975 }
3976 while (wpa_ctrl_pending(ctrl) > 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003977 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978 size_t len = sizeof(buf) - 1;
3979 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3980 buf[len] = '\0';
3981 if (action_monitor)
3982 wpa_cli_action_process(buf);
3983 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003984 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003985 if (wpa_cli_show_event(buf)) {
3986 edit_clear_line();
3987 printf("\r%s\n", buf);
3988 edit_redraw();
3989 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003990
3991 if (interactive && check_terminating(buf) > 0)
3992 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993 }
3994 } else {
3995 printf("Could not read pending message.\n");
3996 break;
3997 }
3998 }
3999
4000 if (wpa_ctrl_pending(ctrl) < 0) {
4001 printf("Connection to wpa_supplicant lost - trying to "
4002 "reconnect\n");
4003 wpa_cli_reconnect();
4004 }
4005}
4006
4007#define max_args 10
4008
4009static int tokenize_cmd(char *cmd, char *argv[])
4010{
4011 char *pos;
4012 int argc = 0;
4013
4014 pos = cmd;
4015 for (;;) {
4016 while (*pos == ' ')
4017 pos++;
4018 if (*pos == '\0')
4019 break;
4020 argv[argc] = pos;
4021 argc++;
4022 if (argc == max_args)
4023 break;
4024 if (*pos == '"') {
4025 char *pos2 = os_strrchr(pos, '"');
4026 if (pos2)
4027 pos = pos2 + 1;
4028 }
4029 while (*pos != '\0' && *pos != ' ')
4030 pos++;
4031 if (*pos == ' ')
4032 *pos++ = '\0';
4033 }
4034
4035 return argc;
4036}
4037
4038
4039static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
4040{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004041 if (ctrl_conn) {
4042 int res;
4043 char *prefix = ifname_prefix;
4044
4045 ifname_prefix = NULL;
4046 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
4047 ifname_prefix = prefix;
4048 if (res) {
4049 printf("Connection to wpa_supplicant lost - trying to "
4050 "reconnect\n");
4051 wpa_cli_close_connection();
4052 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004053 }
4054 if (!ctrl_conn)
4055 wpa_cli_reconnect();
4056 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4057}
4058
4059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
4061{
4062 wpa_cli_recv_pending(mon_conn, 0);
4063}
4064
4065
4066static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
4067{
4068 char *argv[max_args];
4069 int argc;
4070 argc = tokenize_cmd(cmd, argv);
4071 if (argc)
4072 wpa_request(ctrl_conn, argc, argv);
4073}
4074
4075
4076static void wpa_cli_edit_eof_cb(void *ctx)
4077{
4078 eloop_terminate();
4079}
4080
4081
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004082static int warning_displayed = 0;
4083static char *hfile = NULL;
4084static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004086static void start_edit(void)
4087{
4088 char *home;
4089 char *ps = NULL;
4090
4091#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4092 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
4093#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004095#ifdef CONFIG_WPA_CLI_HISTORY_DIR
4096 home = CONFIG_WPA_CLI_HISTORY_DIR;
4097#else /* CONFIG_WPA_CLI_HISTORY_DIR */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 home = getenv("HOME");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004099#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004100 if (home) {
4101 const char *fname = ".wpa_cli_history";
4102 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
4103 hfile = os_malloc(hfile_len);
4104 if (hfile)
4105 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
4106 }
4107
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004108 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
4109 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4110 eloop_terminate();
4111 return;
4112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004114 edit_started = 1;
4115 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4116}
4117
4118
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004119static void update_bssid_list(struct wpa_ctrl *ctrl)
4120{
4121 char buf[4096];
4122 size_t len = sizeof(buf);
4123 int ret;
4124 char *cmd = "BSS RANGE=ALL MASK=0x2";
4125 char *pos, *end;
4126
4127 if (ctrl == NULL)
4128 return;
4129 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4130 if (ret < 0)
4131 return;
4132 buf[len] = '\0';
4133
4134 pos = buf;
4135 while (pos) {
4136 pos = os_strstr(pos, "bssid=");
4137 if (pos == NULL)
4138 break;
4139 pos += 6;
4140 end = os_strchr(pos, '\n');
4141 if (end == NULL)
4142 break;
4143 *end = '\0';
4144 cli_txt_list_add(&bsses, pos);
4145 pos = end + 1;
4146 }
4147}
4148
4149
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004150static void update_ifnames(struct wpa_ctrl *ctrl)
4151{
4152 char buf[4096];
4153 size_t len = sizeof(buf);
4154 int ret;
4155 char *cmd = "INTERFACES";
4156 char *pos, *end;
4157 char txt[200];
4158
4159 cli_txt_list_flush(&ifnames);
4160
4161 if (ctrl == NULL)
4162 return;
4163 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4164 if (ret < 0)
4165 return;
4166 buf[len] = '\0';
4167
4168 pos = buf;
4169 while (pos) {
4170 end = os_strchr(pos, '\n');
4171 if (end == NULL)
4172 break;
4173 *end = '\0';
4174 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004175 if (!os_snprintf_error(sizeof(txt), ret))
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004176 cli_txt_list_add(&ifnames, txt);
4177 pos = end + 1;
4178 }
4179}
4180
4181
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004182static void update_networks(struct wpa_ctrl *ctrl)
4183{
4184 char buf[4096];
4185 size_t len = sizeof(buf);
4186 int ret;
4187 char *cmd = "LIST_NETWORKS";
4188 char *pos, *end;
4189 int header = 1;
4190
4191 cli_txt_list_flush(&networks);
4192
4193 if (ctrl == NULL)
4194 return;
4195 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4196 if (ret < 0)
4197 return;
4198 buf[len] = '\0';
4199
4200 pos = buf;
4201 while (pos) {
4202 end = os_strchr(pos, '\n');
4203 if (end == NULL)
4204 break;
4205 *end = '\0';
4206 if (!header)
4207 cli_txt_list_add_word(&networks, pos, '\t');
4208 header = 0;
4209 pos = end + 1;
4210 }
4211}
4212
4213
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004214static void try_connection(void *eloop_ctx, void *timeout_ctx)
4215{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004216 if (ctrl_conn)
4217 goto done;
4218
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004219 if (ctrl_ifname == NULL)
4220 ctrl_ifname = wpa_cli_get_default_ifname();
4221
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004222 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004223 if (!warning_displayed) {
4224 printf("Could not connect to wpa_supplicant: "
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004225 "%s - re-trying\n",
4226 ctrl_ifname ? ctrl_ifname : "(nil)");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004227 warning_displayed = 1;
4228 }
4229 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4230 return;
4231 }
4232
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004233 update_bssid_list(ctrl_conn);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004234 update_networks(ctrl_conn);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004235
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004236 if (warning_displayed)
4237 printf("Connection established.\n");
4238
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004239done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004240 start_edit();
4241}
4242
4243
4244static void wpa_cli_interactive(void)
4245{
4246 printf("\nInteractive mode\n\n");
4247
4248 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004249 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004250 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004251
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004252 cli_txt_list_flush(&p2p_peers);
4253 cli_txt_list_flush(&p2p_groups);
4254 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004255 cli_txt_list_flush(&ifnames);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004256 cli_txt_list_flush(&networks);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004257 if (edit_started)
4258 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004259 os_free(hfile);
4260 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4261 wpa_cli_close_connection();
4262}
4263
4264
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07004265static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
4266{
4267 struct wpa_ctrl *ctrl = eloop_ctx;
4268 char buf[256];
4269 size_t len;
4270
4271 /* verify that connection is still working */
4272 len = sizeof(buf) - 1;
4273 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4274 wpa_cli_action_cb) < 0 ||
4275 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4276 printf("wpa_supplicant did not reply to PING command - exiting\n");
4277 eloop_terminate();
4278 return;
4279 }
4280 eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4281 ctrl, NULL);
4282}
4283
4284
4285static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
4286{
4287 struct wpa_ctrl *ctrl = eloop_ctx;
4288
4289 wpa_cli_recv_pending(ctrl, 1);
4290}
4291
4292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004293static void wpa_cli_action(struct wpa_ctrl *ctrl)
4294{
4295#ifdef CONFIG_ANSI_C_EXTRA
4296 /* TODO: ANSI C version(?) */
4297 printf("Action processing not supported in ANSI C build.\n");
4298#else /* CONFIG_ANSI_C_EXTRA */
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07004299 int fd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300
4301 fd = wpa_ctrl_get_fd(ctrl);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07004302 eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4303 ctrl, NULL);
4304 eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
4305 eloop_run();
4306 eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
4307 eloop_unregister_read_sock(fd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004308#endif /* CONFIG_ANSI_C_EXTRA */
4309}
4310
4311
4312static void wpa_cli_cleanup(void)
4313{
4314 wpa_cli_close_connection();
4315 if (pid_file)
4316 os_daemonize_terminate(pid_file);
4317
4318 os_program_deinit();
4319}
4320
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004321
4322static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004324 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004325}
4326
4327
4328static char * wpa_cli_get_default_ifname(void)
4329{
4330 char *ifname = NULL;
4331
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004332#ifdef ANDROID
4333 char ifprop[PROPERTY_VALUE_MAX];
4334 if (property_get("wifi.interface", ifprop, NULL) != 0) {
4335 ifname = os_strdup(ifprop);
4336 printf("Using interface '%s'\n", ifname ? ifname : "N/A");
4337 }
4338#else /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339#ifdef CONFIG_CTRL_IFACE_UNIX
4340 struct dirent *dent;
4341 DIR *dir = opendir(ctrl_iface_dir);
4342 if (!dir) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343 return NULL;
4344 }
4345 while ((dent = readdir(dir))) {
4346#ifdef _DIRENT_HAVE_D_TYPE
4347 /*
4348 * Skip the file if it is not a socket. Also accept
4349 * DT_UNKNOWN (0) in case the C library or underlying
4350 * file system does not support d_type.
4351 */
4352 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4353 continue;
4354#endif /* _DIRENT_HAVE_D_TYPE */
4355 if (os_strcmp(dent->d_name, ".") == 0 ||
4356 os_strcmp(dent->d_name, "..") == 0)
4357 continue;
4358 printf("Selected interface '%s'\n", dent->d_name);
4359 ifname = os_strdup(dent->d_name);
4360 break;
4361 }
4362 closedir(dir);
4363#endif /* CONFIG_CTRL_IFACE_UNIX */
4364
4365#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004366 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 size_t len;
4368 struct wpa_ctrl *ctrl;
4369 int ret;
4370
4371 ctrl = wpa_ctrl_open(NULL);
4372 if (ctrl == NULL)
4373 return NULL;
4374
4375 len = sizeof(buf) - 1;
4376 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4377 if (ret >= 0) {
4378 buf[len] = '\0';
4379 pos = os_strchr(buf, '\n');
4380 if (pos)
4381 *pos = '\0';
4382 ifname = os_strdup(buf);
4383 }
4384 wpa_ctrl_close(ctrl);
4385#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004386#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004387
4388 return ifname;
4389}
4390
4391
4392int main(int argc, char *argv[])
4393{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 int c;
4395 int daemonize = 0;
4396 int ret = 0;
4397 const char *global = NULL;
4398
4399 if (os_program_init())
4400 return -1;
4401
4402 for (;;) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004403 c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 if (c < 0)
4405 break;
4406 switch (c) {
4407 case 'a':
4408 action_file = optarg;
4409 break;
4410 case 'B':
4411 daemonize = 1;
4412 break;
4413 case 'g':
4414 global = optarg;
4415 break;
4416 case 'G':
4417 ping_interval = atoi(optarg);
4418 break;
4419 case 'h':
4420 usage();
4421 return 0;
4422 case 'v':
4423 printf("%s\n", wpa_cli_version);
4424 return 0;
4425 case 'i':
4426 os_free(ctrl_ifname);
4427 ctrl_ifname = os_strdup(optarg);
4428 break;
4429 case 'p':
4430 ctrl_iface_dir = optarg;
4431 break;
4432 case 'P':
4433 pid_file = optarg;
4434 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004435 case 's':
4436 client_socket_dir = optarg;
4437 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004438 default:
4439 usage();
4440 return -1;
4441 }
4442 }
4443
4444 interactive = (argc == optind) && (action_file == NULL);
4445
4446 if (interactive)
4447 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4448
4449 if (eloop_init())
4450 return -1;
4451
4452 if (global) {
4453#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4454 ctrl_conn = wpa_ctrl_open(NULL);
4455#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4456 ctrl_conn = wpa_ctrl_open(global);
4457#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4458 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004459 fprintf(stderr, "Failed to connect to wpa_supplicant "
4460 "global interface: %s error: %s\n",
4461 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004462 return -1;
4463 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004464
4465 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004466 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004467 mon_conn = wpa_ctrl_open(global);
4468 if (mon_conn) {
4469 if (wpa_ctrl_attach(mon_conn) == 0) {
4470 wpa_cli_attached = 1;
4471 eloop_register_read_sock(
4472 wpa_ctrl_get_fd(mon_conn),
4473 wpa_cli_mon_receive,
4474 NULL, NULL);
4475 } else {
4476 printf("Failed to open monitor "
4477 "connection through global "
4478 "control interface\n");
4479 }
4480 }
4481 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004482 }
4483
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004484 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485
4486 if (ctrl_ifname == NULL)
4487 ctrl_ifname = wpa_cli_get_default_ifname();
4488
4489 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004490 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491 } else {
4492 if (!global &&
4493 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004494 fprintf(stderr, "Failed to connect to non-global "
4495 "ctrl_ifname: %s error: %s\n",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004496 ctrl_ifname ? ctrl_ifname : "(nil)",
4497 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004498 return -1;
4499 }
4500
4501 if (action_file) {
4502 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4503 wpa_cli_attached = 1;
4504 } else {
4505 printf("Warning: Failed to attach to "
4506 "wpa_supplicant.\n");
4507 return -1;
4508 }
4509 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004510
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08004511 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004512 return -1;
4513
4514 if (action_file)
4515 wpa_cli_action(ctrl_conn);
4516 else
4517 ret = wpa_request(ctrl_conn, argc - optind,
4518 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519 }
4520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004521 os_free(ctrl_ifname);
4522 eloop_destroy();
4523 wpa_cli_cleanup();
4524
4525 return ret;
4526}
4527
4528#else /* CONFIG_CTRL_IFACE */
4529int main(int argc, char *argv[])
4530{
4531 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4532 return -1;
4533}
4534#endif /* CONFIG_CTRL_IFACE */