blob: 9fbc53286f5b86d20f5bc4a866f84b236b3f516d [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080031"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -070095static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070098static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void wpa_cli_close_connection(void);
101static char * wpa_cli_get_default_ifname(void);
102static char ** wpa_list_cmd_list(void);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700103static void update_networks(struct wpa_ctrl *ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104
105
106static void usage(void)
107{
108 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
109 "[-a<action file>] \\\n"
110 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
111 "[command..]\n"
112 " -h = help (show this usage text)\n"
113 " -v = shown version information\n"
114 " -a = run in daemon mode executing the action file based on "
115 "events from\n"
116 " wpa_supplicant\n"
117 " -B = run a daemon in the background\n"
118 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
119 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700120 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700121}
122
123
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800124static void cli_txt_list_free(struct cli_txt_entry *e)
125{
126 dl_list_del(&e->list);
127 os_free(e->txt);
128 os_free(e);
129}
130
131
132static void cli_txt_list_flush(struct dl_list *list)
133{
134 struct cli_txt_entry *e;
135 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
136 cli_txt_list_free(e);
137}
138
139
140static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
141 const char *txt)
142{
143 struct cli_txt_entry *e;
144 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
145 if (os_strcmp(e->txt, txt) == 0)
146 return e;
147 }
148 return NULL;
149}
150
151
152static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
153{
154 struct cli_txt_entry *e;
155 e = cli_txt_list_get(txt_list, txt);
156 if (e)
157 cli_txt_list_free(e);
158}
159
160
161static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
162{
163 u8 addr[ETH_ALEN];
164 char buf[18];
165 if (hwaddr_aton(txt, addr) < 0)
166 return;
167 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
168 cli_txt_list_del(txt_list, buf);
169}
170
171
172#ifdef CONFIG_P2P
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700173static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
174 int separator)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800175{
176 const char *end;
177 char *buf;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700178 end = os_strchr(txt, separator);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (end == NULL)
180 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700181 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800182 if (buf == NULL)
183 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800184 cli_txt_list_del(txt_list, buf);
185 os_free(buf);
186}
187#endif /* CONFIG_P2P */
188
189
190static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
191{
192 struct cli_txt_entry *e;
193 e = cli_txt_list_get(txt_list, txt);
194 if (e)
195 return 0;
196 e = os_zalloc(sizeof(*e));
197 if (e == NULL)
198 return -1;
199 e->txt = os_strdup(txt);
200 if (e->txt == NULL) {
201 os_free(e);
202 return -1;
203 }
204 dl_list_add(txt_list, &e->list);
205 return 0;
206}
207
208
209#ifdef CONFIG_P2P
210static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
211{
212 u8 addr[ETH_ALEN];
213 char buf[18];
214 if (hwaddr_aton(txt, addr) < 0)
215 return -1;
216 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
217 return cli_txt_list_add(txt_list, buf);
218}
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700219#endif /* CONFIG_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800220
221
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700222static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
223 int separator)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800224{
225 const char *end;
226 char *buf;
227 int ret;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700228 end = os_strchr(txt, separator);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 if (end == NULL)
230 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700231 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800232 if (buf == NULL)
233 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800234 ret = cli_txt_list_add(txt_list, buf);
235 os_free(buf);
236 return ret;
237}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800238
239
240static char ** cli_txt_list_array(struct dl_list *txt_list)
241{
242 unsigned int i, count = dl_list_len(txt_list);
243 char **res;
244 struct cli_txt_entry *e;
245
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700246 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800247 if (res == NULL)
248 return NULL;
249
250 i = 0;
251 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
252 res[i] = os_strdup(e->txt);
253 if (res[i] == NULL)
254 break;
255 i++;
256 }
257
258 return res;
259}
260
261
262static int get_cmd_arg_num(const char *str, int pos)
263{
264 int arg = 0, i;
265
266 for (i = 0; i <= pos; i++) {
267 if (str[i] != ' ') {
268 arg++;
269 while (i <= pos && str[i] != ' ')
270 i++;
271 }
272 }
273
274 if (arg > 0)
275 arg--;
276 return arg;
277}
278
279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700280static int str_starts(const char *src, const char *match)
281{
282 return os_strncmp(src, match, os_strlen(match)) == 0;
283}
284
285
286static int wpa_cli_show_event(const char *event)
287{
288 const char *start;
289
290 start = os_strchr(event, '>');
291 if (start == NULL)
292 return 1;
293
294 start++;
295 /*
296 * Skip BSS added/removed events since they can be relatively frequent
297 * and are likely of not much use for an interactive user.
298 */
299 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
300 str_starts(start, WPA_EVENT_BSS_REMOVED))
301 return 0;
302
303 return 1;
304}
305
306
307static int wpa_cli_open_connection(const char *ifname, int attach)
308{
309#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
310 ctrl_conn = wpa_ctrl_open(ifname);
311 if (ctrl_conn == NULL)
312 return -1;
313
314 if (attach && interactive)
315 mon_conn = wpa_ctrl_open(ifname);
316 else
317 mon_conn = NULL;
318#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
319 char *cfile = NULL;
320 int flen, res;
321
322 if (ifname == NULL)
323 return -1;
324
325#ifdef ANDROID
326 if (access(ctrl_iface_dir, F_OK) < 0) {
327 cfile = os_strdup(ifname);
328 if (cfile == NULL)
329 return -1;
330 }
331#endif /* ANDROID */
332
333 if (cfile == NULL) {
334 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
335 cfile = os_malloc(flen);
336 if (cfile == NULL)
337 return -1;
338 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
339 ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800340 if (os_snprintf_error(flen, res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700341 os_free(cfile);
342 return -1;
343 }
344 }
345
346 ctrl_conn = wpa_ctrl_open(cfile);
347 if (ctrl_conn == NULL) {
348 os_free(cfile);
349 return -1;
350 }
351
352 if (attach && interactive)
353 mon_conn = wpa_ctrl_open(cfile);
354 else
355 mon_conn = NULL;
356 os_free(cfile);
357#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
358
359 if (mon_conn) {
360 if (wpa_ctrl_attach(mon_conn) == 0) {
361 wpa_cli_attached = 1;
362 if (interactive)
363 eloop_register_read_sock(
364 wpa_ctrl_get_fd(mon_conn),
365 wpa_cli_mon_receive, NULL, NULL);
366 } else {
367 printf("Warning: Failed to attach to "
368 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700369 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700370 return -1;
371 }
372 }
373
374 return 0;
375}
376
377
378static void wpa_cli_close_connection(void)
379{
380 if (ctrl_conn == NULL)
381 return;
382
383 if (wpa_cli_attached) {
384 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
385 wpa_cli_attached = 0;
386 }
387 wpa_ctrl_close(ctrl_conn);
388 ctrl_conn = NULL;
389 if (mon_conn) {
390 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
391 wpa_ctrl_close(mon_conn);
392 mon_conn = NULL;
393 }
394}
395
396
397static void wpa_cli_msg_cb(char *msg, size_t len)
398{
399 printf("%s\n", msg);
400}
401
402
403static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
404{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700405 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 size_t len;
407 int ret;
408
409 if (ctrl_conn == NULL) {
410 printf("Not connected to wpa_supplicant - command dropped.\n");
411 return -1;
412 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700413 if (ifname_prefix) {
414 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
415 ifname_prefix, cmd);
416 buf[sizeof(buf) - 1] = '\0';
417 cmd = buf;
418 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 len = sizeof(buf) - 1;
420 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
421 wpa_cli_msg_cb);
422 if (ret == -2) {
423 printf("'%s' command timed out.\n", cmd);
424 return -2;
425 } else if (ret < 0) {
426 printf("'%s' command failed.\n", cmd);
427 return -1;
428 }
429 if (print) {
430 buf[len] = '\0';
431 printf("%s", buf);
432 if (interactive && len > 0 && buf[len - 1] != '\n')
433 printf("\n");
434 }
435 return 0;
436}
437
438
439static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
440{
441 return _wpa_ctrl_command(ctrl, cmd, 1);
442}
443
444
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700445static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
446 char *argv[])
447{
448 int i, res;
449 char *pos, *end;
450
451 pos = buf;
452 end = buf + buflen;
453
454 res = os_snprintf(pos, end - pos, "%s", cmd);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800455 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700456 goto fail;
457 pos += res;
458
459 for (i = 0; i < argc; i++) {
460 res = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800461 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700462 goto fail;
463 pos += res;
464 }
465
466 buf[buflen - 1] = '\0';
467 return 0;
468
469fail:
470 printf("Too long command\n");
471 return -1;
472}
473
474
475static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
476 int argc, char *argv[])
477{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700478 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700479 if (argc < min_args) {
480 printf("Invalid %s command - at least %d argument%s "
481 "required.\n", cmd, min_args,
482 min_args > 1 ? "s are" : " is");
483 return -1;
484 }
485 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
486 return -1;
487 return wpa_ctrl_command(ctrl, buf);
488}
489
490
491static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
492{
493 return wpa_ctrl_command(ctrl, "IFNAME");
494}
495
496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700497static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
498{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800499 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
501 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
502 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700503 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
504 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800505 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506}
507
508
509static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
511 return wpa_ctrl_command(ctrl, "PING");
512}
513
514
515static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
516{
517 return wpa_ctrl_command(ctrl, "RELOG");
518}
519
520
521static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
522{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700523 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700524}
525
526
527static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
528{
529 return wpa_ctrl_command(ctrl, "MIB");
530}
531
532
533static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
534{
535 return wpa_ctrl_command(ctrl, "PMKSA");
536}
537
538
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700539static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
540 char *argv[])
541{
542 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
543}
544
545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
547{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700548 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549 return 0;
550}
551
552
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700553static char ** wpa_cli_complete_help(const char *str, int pos)
554{
555 int arg = get_cmd_arg_num(str, pos);
556 char **res = NULL;
557
558 switch (arg) {
559 case 1:
560 res = wpa_list_cmd_list();
561 break;
562 }
563
564 return res;
565}
566
567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
569{
570 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
571 return 0;
572}
573
574
575static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
576{
577 wpa_cli_quit = 1;
578 if (interactive)
579 eloop_terminate();
580 return 0;
581}
582
583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700584static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
585{
586 char cmd[256];
587 int res;
588
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700589 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800590 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800591 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700592 printf("Too long SET command.\n");
593 return -1;
594 }
595 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700597
598 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
599}
600
601
602static char ** wpa_cli_complete_set(const char *str, int pos)
603{
604 int arg = get_cmd_arg_num(str, pos);
605 const char *fields[] = {
606 /* runtime values */
607 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
608 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
609 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
610 "wps_fragment_size", "wps_version_number", "ampdu",
611 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
612 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
613 "no_keep_alive",
614 /* global configuration parameters */
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700615#ifdef CONFIG_CTRL_IFACE
616 "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
617#endif /* CONFIG_CTRL_IFACE */
618 "eapol_version", "ap_scan", "bgscan",
619#ifdef CONFIG_MESH
620 "user_mpm", "max_peer_links", "mesh_max_inactivity",
621#endif /* CONFIG_MESH */
622 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
623 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
624 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
625 "dot11RSNAConfigPMKLifetime",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700626 "dot11RSNAConfigPMKReauthThreshold",
627 "dot11RSNAConfigSATimeout",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700628#ifndef CONFIG_NO_CONFIG_WRITE
629 "update_config",
630#endif /* CONFIG_NO_CONFIG_WRITE */
631 "load_dynamic_eap",
632#ifdef CONFIG_WPS
633 "uuid", "device_name", "manufacturer", "model_name",
634 "model_number", "serial_number", "device_type", "os_version",
635 "config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
636#endif /* CONFIG_WPS */
637#ifdef CONFIG_P2P
638 "sec_device_type",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700639 "p2p_listen_reg_class", "p2p_listen_channel",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700640 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
641 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
642 "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
643 "p2p_no_go_freq", "p2p_add_cli_chan",
644 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
645 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
646 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
647 "ip_addr_start", "ip_addr_end",
648#endif /* CONFIG_P2P */
649 "country", "bss_max_count", "bss_expiration_age",
650 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
651 "max_num_sta", "disassoc_low_ack",
652#ifdef CONFIG_HS20
653 "hs20",
654#endif /* CONFIG_HS20 */
655 "interworking", "hessid", "access_network_type", "pbc_in_m1",
656 "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
657 "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700658 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700659 "sae_groups", "dtim_period", "beacon_int",
660 "ap_vendor_elements", "ignore_old_scan_res", "freq_list",
661 "scan_cur_freq", "sched_scan_interval",
662 "tdls_external_control", "osu_dir", "wowlan_triggers",
663 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
664 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
665 "reassoc_same_bss_optim"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700666 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700667 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700668
669 if (arg == 1) {
670 char **res = os_calloc(num_fields + 1, sizeof(char *));
671 if (res == NULL)
672 return NULL;
673 for (i = 0; i < num_fields; i++) {
674 res[i] = os_strdup(fields[i]);
675 if (res[i] == NULL)
676 return res;
677 }
678 return res;
679 }
680
681 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
682 return cli_txt_list_array(&bsses);
683
684 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685}
686
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800687static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
688{
689 return wpa_ctrl_command(ctrl, "DUMP");
690}
691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692
693static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696}
697
698
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700699static char ** wpa_cli_complete_get(const char *str, int pos)
700{
701 int arg = get_cmd_arg_num(str, pos);
702 const char *fields[] = {
703#ifdef CONFIG_CTRL_IFACE
704 "ctrl_interface", "ctrl_interface_group",
705#endif /* CONFIG_CTRL_IFACE */
706 "eapol_version", "ap_scan",
707#ifdef CONFIG_MESH
708 "user_mpm", "max_peer_links", "mesh_max_inactivity",
709#endif /* CONFIG_MESH */
710 "disable_scan_offload", "fast_reauth", "opensc_engine_path",
711 "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
712 "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
713 "dot11RSNAConfigPMKLifetime",
714 "dot11RSNAConfigPMKReauthThreshold",
715 "dot11RSNAConfigSATimeout",
716#ifndef CONFIG_NO_CONFIG_WRITE
717 "update_config",
718#endif /* CONFIG_NO_CONFIG_WRITE */
719#ifdef CONFIG_WPS
720 "device_name", "manufacturer", "model_name", "model_number",
721 "serial_number", "config_methods", "wps_cred_processing",
722#endif /* CONFIG_WPS */
723#ifdef CONFIG_P2P
724 "p2p_listen_reg_class", "p2p_listen_channel",
725 "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
726 "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
727 "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
728 "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
729 "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
730 "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
731 "ip_addr_start", "ip_addr_end",
732#endif /* CONFIG_P2P */
733 "bss_max_count", "bss_expiration_age",
734 "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
735 "max_num_sta", "disassoc_low_ack",
736#ifdef CONFIG_HS20
737 "hs20",
738#endif /* CONFIG_HS20 */
739 "interworking", "access_network_type", "pbc_in_m1", "autoscan",
740 "wps_nfc_dev_pw_id", "ext_password_backend",
741 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
742 "dtim_period", "beacon_int", "ignore_old_scan_res",
743 "scan_cur_freq", "sched_scan_interval",
744 "tdls_external_control", "osu_dir", "wowlan_triggers",
745 "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
746 "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
747 "reassoc_same_bss_optim"
748 };
749 int i, num_fields = ARRAY_SIZE(fields);
750
751 if (arg == 1) {
752 char **res = os_calloc(num_fields + 1, sizeof(char *));
753 if (res == NULL)
754 return NULL;
755 for (i = 0; i < num_fields; i++) {
756 res[i] = os_strdup(fields[i]);
757 if (res[i] == NULL)
758 return res;
759 }
760 return res;
761 }
762
763 return NULL;
764}
765
766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
768{
769 return wpa_ctrl_command(ctrl, "LOGOFF");
770}
771
772
773static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
774{
775 return wpa_ctrl_command(ctrl, "LOGON");
776}
777
778
779static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781{
782 return wpa_ctrl_command(ctrl, "REASSOCIATE");
783}
784
785
Dmitry Shmidt98660862014-03-11 17:26:21 -0700786static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
787{
788 return wpa_ctrl_command(ctrl, "REATTACH");
789}
790
791
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
793 char *argv[])
794{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700795 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796}
797
798
799static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
800{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700801 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802}
803
804
805static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700808 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700809}
810
811
812static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
813 char *argv[])
814{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700815 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816}
817
818
819static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
820 char *argv[])
821{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700822 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823}
824
825
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700826static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
827{
828 char cmd[256];
829 int res;
830
831 if (argc < 1)
832 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
833 else
834 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800835 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700836 printf("Too long BSS_FLUSH command.\n");
837 return -1;
838 }
839 return wpa_ctrl_command(ctrl, cmd);
840}
841
842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
844 char *argv[])
845{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700846 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847}
848
849
850static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
851{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700852 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700853}
854
855
856static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
857{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700858 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859}
860
861
862static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
863{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 if (argc == 0) {
865 printf("Invalid WPS_PIN command: need one or two arguments:\n"
866 "- BSSID: use 'any' to select any\n"
867 "- PIN: optional, used only with devices that have no "
868 "display\n");
869 return -1;
870 }
871
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700872 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873}
874
875
876static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
877 char *argv[])
878{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700879 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880}
881
882
883static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
884 char *argv[])
885{
886 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
887}
888
889
Dmitry Shmidt04949592012-07-19 12:16:46 -0700890#ifdef CONFIG_WPS_NFC
891
892static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
893{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700894 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700895}
896
897
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800898static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
899 char *argv[])
900{
901 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
902}
903
904
Dmitry Shmidt04949592012-07-19 12:16:46 -0700905static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
906 char *argv[])
907{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700908 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700909}
910
911
912static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
913 char *argv[])
914{
915 int ret;
916 char *buf;
917 size_t buflen;
918
919 if (argc != 1) {
920 printf("Invalid 'wps_nfc_tag_read' command - one argument "
921 "is required.\n");
922 return -1;
923 }
924
925 buflen = 18 + os_strlen(argv[0]);
926 buf = os_malloc(buflen);
927 if (buf == NULL)
928 return -1;
929 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
930
931 ret = wpa_ctrl_command(ctrl, buf);
932 os_free(buf);
933
934 return ret;
935}
936
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800937
938static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
941 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
942}
943
944
945static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947{
948 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
949}
950
951
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800952static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
953 char *argv[])
954{
955 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
956}
957
Dmitry Shmidt04949592012-07-19 12:16:46 -0700958#endif /* CONFIG_WPS_NFC */
959
960
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
962{
963 char cmd[256];
964 int res;
965
966 if (argc == 2)
967 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
968 argv[0], argv[1]);
969 else if (argc == 5 || argc == 6) {
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700970 char ssid_hex[2 * SSID_MAX_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 char key_hex[2 * 64 + 1];
972 int i;
973
974 ssid_hex[0] = '\0';
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700975 for (i = 0; i < SSID_MAX_LEN; i++) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976 if (argv[2][i] == '\0')
977 break;
978 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
979 }
980
981 key_hex[0] = '\0';
982 if (argc == 6) {
983 for (i = 0; i < 64; i++) {
984 if (argv[5][i] == '\0')
985 break;
986 os_snprintf(&key_hex[i * 2], 3, "%02x",
987 argv[5][i]);
988 }
989 }
990
991 res = os_snprintf(cmd, sizeof(cmd),
992 "WPS_REG %s %s %s %s %s %s",
993 argv[0], argv[1], ssid_hex, argv[3], argv[4],
994 key_hex);
995 } else {
996 printf("Invalid WPS_REG command: need two arguments:\n"
997 "- BSSID of the target AP\n"
998 "- AP PIN\n");
999 printf("Alternatively, six arguments can be used to "
1000 "reconfigure the AP:\n"
1001 "- BSSID of the target AP\n"
1002 "- AP PIN\n"
1003 "- new SSID\n"
1004 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1005 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1006 "- new key\n");
1007 return -1;
1008 }
1009
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001010 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 printf("Too long WPS_REG command.\n");
1012 return -1;
1013 }
1014 return wpa_ctrl_command(ctrl, cmd);
1015}
1016
1017
1018static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
1019 char *argv[])
1020{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001021 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022}
1023
1024
1025static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
1026 char *argv[])
1027{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001028 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029}
1030
1031
1032static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
1033 char *argv[])
1034{
1035 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
1036
1037}
1038
1039
1040static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
1041 char *argv[])
1042{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043 if (argc < 2) {
1044 printf("Invalid WPS_ER_PIN command: need at least two "
1045 "arguments:\n"
1046 "- UUID: use 'any' to select any\n"
1047 "- PIN: Enrollee PIN\n"
1048 "optional: - Enrollee MAC address\n");
1049 return -1;
1050 }
1051
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001052 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053}
1054
1055
1056static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1057 char *argv[])
1058{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001059 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060}
1061
1062
1063static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1064 char *argv[])
1065{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 if (argc != 2) {
1067 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1068 "- UUID: specify which AP to use\n"
1069 "- PIN: AP PIN\n");
1070 return -1;
1071 }
1072
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001073 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074}
1075
1076
1077static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1078 char *argv[])
1079{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001080 if (argc != 2) {
1081 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1082 "arguments:\n"
1083 "- UUID: specify which AP to use\n"
1084 "- Network configuration id\n");
1085 return -1;
1086 }
1087
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001088 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089}
1090
1091
1092static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1093 char *argv[])
1094{
1095 char cmd[256];
1096 int res;
1097
1098 if (argc == 5 || argc == 6) {
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001099 char ssid_hex[2 * SSID_MAX_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001100 char key_hex[2 * 64 + 1];
1101 int i;
1102
1103 ssid_hex[0] = '\0';
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001104 for (i = 0; i < SSID_MAX_LEN; i++) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 if (argv[2][i] == '\0')
1106 break;
1107 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1108 }
1109
1110 key_hex[0] = '\0';
1111 if (argc == 6) {
1112 for (i = 0; i < 64; i++) {
1113 if (argv[5][i] == '\0')
1114 break;
1115 os_snprintf(&key_hex[i * 2], 3, "%02x",
1116 argv[5][i]);
1117 }
1118 }
1119
1120 res = os_snprintf(cmd, sizeof(cmd),
1121 "WPS_ER_CONFIG %s %s %s %s %s %s",
1122 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1123 key_hex);
1124 } else {
1125 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1126 "- AP UUID\n"
1127 "- AP PIN\n"
1128 "- new SSID\n"
1129 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1130 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1131 "- new key\n");
1132 return -1;
1133 }
1134
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001135 if (os_snprintf_error(sizeof(cmd), res)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 printf("Too long WPS_ER_CONFIG command.\n");
1137 return -1;
1138 }
1139 return wpa_ctrl_command(ctrl, cmd);
1140}
1141
1142
Dmitry Shmidt04949592012-07-19 12:16:46 -07001143#ifdef CONFIG_WPS_NFC
1144static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1145 char *argv[])
1146{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001147 if (argc != 2) {
1148 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1149 "arguments:\n"
1150 "- WPS/NDEF: token format\n"
1151 "- UUID: specify which AP to use\n");
1152 return -1;
1153 }
1154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001155 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001156}
1157#endif /* CONFIG_WPS_NFC */
1158
1159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1161{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001162 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001163}
1164
1165
1166static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1167{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001168 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169}
1170
1171
1172static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1173{
1174 char cmd[256], *pos, *end;
1175 int i, ret;
1176
1177 if (argc < 2) {
1178 printf("Invalid IDENTITY command: needs two arguments "
1179 "(network id and identity)\n");
1180 return -1;
1181 }
1182
1183 end = cmd + sizeof(cmd);
1184 pos = cmd;
1185 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1186 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001187 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 printf("Too long IDENTITY command.\n");
1189 return -1;
1190 }
1191 pos += ret;
1192 for (i = 2; i < argc; i++) {
1193 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001194 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 printf("Too long IDENTITY command.\n");
1196 return -1;
1197 }
1198 pos += ret;
1199 }
1200
1201 return wpa_ctrl_command(ctrl, cmd);
1202}
1203
1204
1205static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1206{
1207 char cmd[256], *pos, *end;
1208 int i, ret;
1209
1210 if (argc < 2) {
1211 printf("Invalid PASSWORD command: needs two arguments "
1212 "(network id and password)\n");
1213 return -1;
1214 }
1215
1216 end = cmd + sizeof(cmd);
1217 pos = cmd;
1218 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1219 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001220 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001221 printf("Too long PASSWORD command.\n");
1222 return -1;
1223 }
1224 pos += ret;
1225 for (i = 2; i < argc; i++) {
1226 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001227 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001228 printf("Too long PASSWORD command.\n");
1229 return -1;
1230 }
1231 pos += ret;
1232 }
1233
1234 return wpa_ctrl_command(ctrl, cmd);
1235}
1236
1237
1238static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1239 char *argv[])
1240{
1241 char cmd[256], *pos, *end;
1242 int i, ret;
1243
1244 if (argc < 2) {
1245 printf("Invalid NEW_PASSWORD command: needs two arguments "
1246 "(network id and password)\n");
1247 return -1;
1248 }
1249
1250 end = cmd + sizeof(cmd);
1251 pos = cmd;
1252 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1253 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001254 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255 printf("Too long NEW_PASSWORD command.\n");
1256 return -1;
1257 }
1258 pos += ret;
1259 for (i = 2; i < argc; i++) {
1260 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001261 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262 printf("Too long NEW_PASSWORD command.\n");
1263 return -1;
1264 }
1265 pos += ret;
1266 }
1267
1268 return wpa_ctrl_command(ctrl, cmd);
1269}
1270
1271
1272static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1273{
1274 char cmd[256], *pos, *end;
1275 int i, ret;
1276
1277 if (argc < 2) {
1278 printf("Invalid PIN command: needs two arguments "
1279 "(network id and pin)\n");
1280 return -1;
1281 }
1282
1283 end = cmd + sizeof(cmd);
1284 pos = cmd;
1285 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1286 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001287 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288 printf("Too long PIN command.\n");
1289 return -1;
1290 }
1291 pos += ret;
1292 for (i = 2; i < argc; i++) {
1293 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001294 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295 printf("Too long PIN command.\n");
1296 return -1;
1297 }
1298 pos += ret;
1299 }
1300 return wpa_ctrl_command(ctrl, cmd);
1301}
1302
1303
1304static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1305{
1306 char cmd[256], *pos, *end;
1307 int i, ret;
1308
1309 if (argc < 2) {
1310 printf("Invalid OTP command: needs two arguments (network "
1311 "id and password)\n");
1312 return -1;
1313 }
1314
1315 end = cmd + sizeof(cmd);
1316 pos = cmd;
1317 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1318 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001319 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320 printf("Too long OTP command.\n");
1321 return -1;
1322 }
1323 pos += ret;
1324 for (i = 2; i < argc; i++) {
1325 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001326 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 printf("Too long OTP command.\n");
1328 return -1;
1329 }
1330 pos += ret;
1331 }
1332
1333 return wpa_ctrl_command(ctrl, cmd);
1334}
1335
1336
Dmitry Shmidt051af732013-10-22 13:52:46 -07001337static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1338{
1339 char cmd[256], *pos, *end;
1340 int i, ret;
1341
1342 if (argc < 2) {
1343 printf("Invalid SIM command: needs two arguments "
1344 "(network id and SIM operation response)\n");
1345 return -1;
1346 }
1347
1348 end = cmd + sizeof(cmd);
1349 pos = cmd;
1350 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1351 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001352 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001353 printf("Too long SIM command.\n");
1354 return -1;
1355 }
1356 pos += ret;
1357 for (i = 2; i < argc; i++) {
1358 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001359 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001360 printf("Too long SIM command.\n");
1361 return -1;
1362 }
1363 pos += ret;
1364 }
1365 return wpa_ctrl_command(ctrl, cmd);
1366}
1367
1368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001369static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1370 char *argv[])
1371{
1372 char cmd[256], *pos, *end;
1373 int i, ret;
1374
1375 if (argc < 2) {
1376 printf("Invalid PASSPHRASE command: needs two arguments "
1377 "(network id and passphrase)\n");
1378 return -1;
1379 }
1380
1381 end = cmd + sizeof(cmd);
1382 pos = cmd;
1383 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1384 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001385 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 printf("Too long PASSPHRASE command.\n");
1387 return -1;
1388 }
1389 pos += ret;
1390 for (i = 2; i < argc; i++) {
1391 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001392 if (os_snprintf_error(end - pos, ret)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001393 printf("Too long PASSPHRASE command.\n");
1394 return -1;
1395 }
1396 pos += ret;
1397 }
1398
1399 return wpa_ctrl_command(ctrl, cmd);
1400}
1401
1402
1403static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1404{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 if (argc < 2) {
1406 printf("Invalid BSSID command: needs two arguments (network "
1407 "id and BSSID)\n");
1408 return -1;
1409 }
1410
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001411 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412}
1413
1414
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001415static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1416{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001417 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001418}
1419
1420
1421static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001423 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001424}
1425
1426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1428 char *argv[])
1429{
1430 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1431}
1432
1433
1434static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1435 char *argv[])
1436{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001437 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001438}
1439
1440
1441static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1442 char *argv[])
1443{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001444 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445}
1446
1447
1448static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1449 char *argv[])
1450{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001451 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452}
1453
1454
1455static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1456 char *argv[])
1457{
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001458 int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
1459 update_networks(ctrl);
1460 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461}
1462
1463
1464static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1465 char *argv[])
1466{
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001467 int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1468 update_networks(ctrl);
1469 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470}
1471
1472
1473static void wpa_cli_show_network_variables(void)
1474{
1475 printf("set_network variables:\n"
1476 " ssid (network name, SSID)\n"
1477 " psk (WPA passphrase or pre-shared key)\n"
1478 " key_mgmt (key management protocol)\n"
1479 " identity (EAP identity)\n"
1480 " password (EAP password)\n"
1481 " ...\n"
1482 "\n"
1483 "Note: Values are entered in the same format as the "
1484 "configuration file is using,\n"
1485 "i.e., strings values need to be inside double quotation "
1486 "marks.\n"
1487 "For example: set_network 1 ssid \"network name\"\n"
1488 "\n"
1489 "Please see wpa_supplicant.conf documentation for full list "
1490 "of\navailable variables.\n");
1491}
1492
1493
1494static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1495 char *argv[])
1496{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 if (argc == 0) {
1498 wpa_cli_show_network_variables();
1499 return 0;
1500 }
1501
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001502 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001503 printf("Invalid SET_NETWORK command: needs three arguments\n"
1504 "(network id, variable name, and value)\n");
1505 return -1;
1506 }
1507
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001508 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509}
1510
1511
1512static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1513 char *argv[])
1514{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515 if (argc == 0) {
1516 wpa_cli_show_network_variables();
1517 return 0;
1518 }
1519
1520 if (argc != 2) {
1521 printf("Invalid GET_NETWORK command: needs two arguments\n"
1522 "(network id and variable name)\n");
1523 return -1;
1524 }
1525
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001526 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001527}
1528
1529
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001530static const char *network_fields[] = {
1531 "ssid", "scan_ssid", "bssid", "bssid_blacklist",
1532 "bssid_whitelist", "psk", "proto", "key_mgmt",
1533 "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
1534 "freq_list",
1535#ifdef IEEE8021X_EAPOL
1536 "eap", "identity", "anonymous_identity", "password", "ca_cert",
1537 "ca_path", "client_cert", "private_key", "private_key_passwd",
1538 "dh_file", "subject_match", "altsubject_match",
1539 "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
1540 "client_cert2", "private_key2", "private_key2_passwd",
1541 "dh_file2", "subject_match2", "altsubject_match2",
1542 "domain_suffix_match2", "domain_match2", "phase1", "phase2",
1543 "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
1544 "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
1545 "engine", "engine2", "eapol_flags", "sim_num",
1546 "openssl_ciphers", "erp",
1547#endif /* IEEE8021X_EAPOL */
1548 "wep_key0", "wep_key1", "wep_key2", "wep_key3",
1549 "wep_tx_keyidx", "priority",
1550#ifdef IEEE8021X_EAPOL
1551 "eap_workaround", "pac_file", "fragment_size", "ocsp",
1552#endif /* IEEE8021X_EAPOL */
1553#ifdef CONFIG_MESH
1554 "mode", "no_auto_peer",
1555#else /* CONFIG_MESH */
1556 "mode",
1557#endif /* CONFIG_MESH */
1558 "proactive_key_caching", "disabled", "id_str",
1559#ifdef CONFIG_IEEE80211W
1560 "ieee80211w",
1561#endif /* CONFIG_IEEE80211W */
1562 "peerkey", "mixed_cell", "frequency", "fixed_freq",
1563#ifdef CONFIG_MESH
1564 "mesh_basic_rates", "dot11MeshMaxRetries",
1565 "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
1566 "dot11MeshHoldingTimeout",
1567#endif /* CONFIG_MESH */
1568 "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
1569#ifdef CONFIG_P2P
1570 "go_p2p_dev_addr", "p2p_client_list", "psk_list",
1571#endif /* CONFIG_P2P */
1572#ifdef CONFIG_HT_OVERRIDES
1573 "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
1574 "ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
1575 "ampdu_density", "ht_mcs",
1576#endif /* CONFIG_HT_OVERRIDES */
1577#ifdef CONFIG_VHT_OVERRIDES
1578 "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
1579 "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
1580 "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
1581 "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
1582 "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
1583 "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
1584#endif /* CONFIG_VHT_OVERRIDES */
1585 "ap_max_inactivity", "dtim_period", "beacon_int",
1586#ifdef CONFIG_MACSEC
1587 "macsec_policy",
1588#endif /* CONFIG_MACSEC */
1589#ifdef CONFIG_HS20
1590 "update_identifier",
1591#endif /* CONFIG_HS20 */
1592 "mac_addr"
1593};
1594
1595
1596static char ** wpa_cli_complete_network(const char *str, int pos)
1597{
1598 int arg = get_cmd_arg_num(str, pos);
1599 int i, num_fields = ARRAY_SIZE(network_fields);
1600 char **res = NULL;
1601
1602 switch (arg) {
1603 case 1:
1604 res = cli_txt_list_array(&networks);
1605 break;
1606 case 2:
1607 res = os_calloc(num_fields + 1, sizeof(char *));
1608 if (res == NULL)
1609 return NULL;
1610 for (i = 0; i < num_fields; i++) {
1611 res[i] = os_strdup(network_fields[i]);
1612 if (res[i] == NULL)
1613 break;
1614 }
1615 }
1616 return res;
1617}
1618
1619
1620static char ** wpa_cli_complete_network_id(const char *str, int pos)
1621{
1622 int arg = get_cmd_arg_num(str, pos);
1623 if (arg == 1)
1624 return cli_txt_list_array(&networks);
1625 return NULL;
1626}
1627
1628
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001629static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1630 char *argv[])
1631{
1632 if (argc == 0) {
1633 wpa_cli_show_network_variables();
1634 return 0;
1635 }
1636
1637 if (argc < 3) {
1638 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1639 "(src netid, dest netid, and variable name)\n");
1640 return -1;
1641 }
1642
1643 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1644}
1645
1646
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001647static char ** wpa_cli_complete_dup_network(const char *str, int pos)
1648{
1649 int arg = get_cmd_arg_num(str, pos);
1650 int i, num_fields = ARRAY_SIZE(network_fields);
1651 char **res = NULL;
1652
1653 switch (arg) {
1654 case 1:
1655 case 2:
1656 res = cli_txt_list_array(&networks);
1657 break;
1658 case 3:
1659 res = os_calloc(num_fields + 1, sizeof(char *));
1660 if (res == NULL)
1661 return NULL;
1662 for (i = 0; i < num_fields; i++) {
1663 res[i] = os_strdup(network_fields[i]);
1664 if (res[i] == NULL)
1665 break;
1666 }
1667 }
1668 return res;
1669}
1670
1671
Dmitry Shmidt04949592012-07-19 12:16:46 -07001672static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1673 char *argv[])
1674{
1675 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1676}
1677
1678
1679static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1680{
1681 return wpa_ctrl_command(ctrl, "ADD_CRED");
1682}
1683
1684
1685static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1686 char *argv[])
1687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001688 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001689}
1690
1691
1692static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1693{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001694 if (argc != 3) {
1695 printf("Invalid SET_CRED command: needs three arguments\n"
1696 "(cred id, variable name, and value)\n");
1697 return -1;
1698 }
1699
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001700 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001701}
1702
1703
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001704static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1705{
1706 if (argc != 2) {
1707 printf("Invalid GET_CRED command: needs two arguments\n"
1708 "(cred id, variable name)\n");
1709 return -1;
1710 }
1711
1712 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1713}
1714
1715
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1717 char *argv[])
1718{
1719 return wpa_ctrl_command(ctrl, "DISCONNECT");
1720}
1721
1722
1723static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1724 char *argv[])
1725{
1726 return wpa_ctrl_command(ctrl, "RECONNECT");
1727}
1728
1729
1730static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1731 char *argv[])
1732{
1733 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1734}
1735
1736
1737static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1738{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001739 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001740}
1741
1742
1743static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1744 char *argv[])
1745{
1746 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1747}
1748
1749
1750static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1751{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001752 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753}
1754
1755
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001756static char ** wpa_cli_complete_bss(const char *str, int pos)
1757{
1758 int arg = get_cmd_arg_num(str, pos);
1759 char **res = NULL;
1760
1761 switch (arg) {
1762 case 1:
1763 res = cli_txt_list_array(&bsses);
1764 break;
1765 }
1766
1767 return res;
1768}
1769
1770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001771static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1772 char *argv[])
1773{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001774 if (argc < 1 || argc > 2) {
1775 printf("Invalid GET_CAPABILITY command: need either one or "
1776 "two arguments\n");
1777 return -1;
1778 }
1779
1780 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1781 printf("Invalid GET_CAPABILITY command: second argument, "
1782 "if any, must be 'strict'\n");
1783 return -1;
1784 }
1785
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
1790static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1791{
1792 printf("Available interfaces:\n");
1793 return wpa_ctrl_command(ctrl, "INTERFACES");
1794}
1795
1796
1797static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1798{
1799 if (argc < 1) {
1800 wpa_cli_list_interfaces(ctrl);
1801 return 0;
1802 }
1803
1804 wpa_cli_close_connection();
1805 os_free(ctrl_ifname);
1806 ctrl_ifname = os_strdup(argv[0]);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001807 if (!ctrl_ifname) {
1808 printf("Failed to allocate memory\n");
1809 return 0;
1810 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001812 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001813 printf("Connected to interface '%s.\n", ctrl_ifname);
1814 } else {
1815 printf("Could not connect to interface '%s' - re-trying\n",
1816 ctrl_ifname);
1817 }
1818 return 0;
1819}
1820
1821
1822static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1823 char *argv[])
1824{
1825 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1826}
1827
1828
1829static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1830 char *argv[])
1831{
1832 return wpa_ctrl_command(ctrl, "TERMINATE");
1833}
1834
1835
1836static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1837 char *argv[])
1838{
1839 char cmd[256];
1840 int res;
1841
1842 if (argc < 1) {
1843 printf("Invalid INTERFACE_ADD command: needs at least one "
1844 "argument (interface name)\n"
1845 "All arguments: ifname confname driver ctrl_interface "
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001846 "driver_param bridge_name [create]\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847 return -1;
1848 }
1849
1850 /*
1851 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001852 * <driver_param>TAB<bridge_name>[TAB<create>]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 */
1854 res = os_snprintf(cmd, sizeof(cmd),
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001855 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 argv[0],
1857 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1858 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001859 argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001860 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 return -1;
1862 cmd[sizeof(cmd) - 1] = '\0';
1863 return wpa_ctrl_command(ctrl, cmd);
1864}
1865
1866
1867static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1868 char *argv[])
1869{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001870 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871}
1872
1873
1874static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1875 char *argv[])
1876{
1877 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1878}
1879
1880
1881#ifdef CONFIG_AP
1882static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1883{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001884 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885}
1886
1887
1888static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1889 char *addr, size_t addr_len)
1890{
1891 char buf[4096], *pos;
1892 size_t len;
1893 int ret;
1894
1895 if (ctrl_conn == NULL) {
1896 printf("Not connected to hostapd - command dropped.\n");
1897 return -1;
1898 }
1899 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001900 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901 wpa_cli_msg_cb);
1902 if (ret == -2) {
1903 printf("'%s' command timed out.\n", cmd);
1904 return -2;
1905 } else if (ret < 0) {
1906 printf("'%s' command failed.\n", cmd);
1907 return -1;
1908 }
1909
1910 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001911 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912 return -1;
1913 printf("%s", buf);
1914
1915 pos = buf;
1916 while (*pos != '\0' && *pos != '\n')
1917 pos++;
1918 *pos = '\0';
1919 os_strlcpy(addr, buf, addr_len);
1920 return 0;
1921}
1922
1923
1924static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1925{
1926 char addr[32], cmd[64];
1927
1928 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1929 return 0;
1930 do {
1931 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1932 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1933
1934 return -1;
1935}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001936
1937
1938static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1939 char *argv[])
1940{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001941 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001942}
1943
1944
1945static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1946 char *argv[])
1947{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001948 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001949}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001950
1951static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1952 char *argv[])
1953{
1954 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1955}
1956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957#endif /* CONFIG_AP */
1958
1959
1960static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1961{
1962 return wpa_ctrl_command(ctrl, "SUSPEND");
1963}
1964
1965
1966static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1967{
1968 return wpa_ctrl_command(ctrl, "RESUME");
1969}
1970
1971
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001972#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1974{
1975 return wpa_ctrl_command(ctrl, "DROP_SA");
1976}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001977#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978
1979
1980static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1981{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001982 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001983}
1984
1985
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001986#ifdef CONFIG_MESH
1987
1988static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
1989 char *argv[])
1990{
1991 return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
1992}
1993
1994
1995static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
1996 char *argv[])
1997{
1998 return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
1999}
2000
2001
2002static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
2003 char *argv[])
2004{
2005 return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
2006}
2007
2008#endif /* CONFIG_MESH */
2009
2010
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011#ifdef CONFIG_P2P
2012
2013static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2014{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002015 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2016}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002019static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2020{
2021 char **res = NULL;
2022 int arg = get_cmd_arg_num(str, pos);
2023
2024 res = os_calloc(6, sizeof(char *));
2025 if (res == NULL)
2026 return NULL;
2027 res[0] = os_strdup("type=social");
2028 if (res[0] == NULL) {
2029 os_free(res);
2030 return NULL;
2031 }
2032 res[1] = os_strdup("type=progressive");
2033 if (res[1] == NULL)
2034 return res;
2035 res[2] = os_strdup("delay=");
2036 if (res[2] == NULL)
2037 return res;
2038 res[3] = os_strdup("dev_id=");
2039 if (res[3] == NULL)
2040 return res;
2041 if (arg == 1)
2042 res[4] = os_strdup("[timeout]");
2043
2044 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045}
2046
2047
2048static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2049 char *argv[])
2050{
2051 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2052}
2053
2054
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002055static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
2056 char *argv[])
2057{
2058 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
2059}
2060
2061
2062static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
2063 char *argv[])
2064{
2065 return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
2066}
2067
2068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2070 char *argv[])
2071{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002072 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073}
2074
2075
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002076static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2077{
2078 int arg = get_cmd_arg_num(str, pos);
2079 char **res = NULL;
2080
2081 switch (arg) {
2082 case 1:
2083 res = cli_txt_list_array(&p2p_peers);
2084 break;
2085 }
2086
2087 return res;
2088}
2089
2090
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2092 char *argv[])
2093{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002094 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002095}
2096
2097
2098static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2099 char *argv[])
2100{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002101 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102}
2103
2104
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002105static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2106{
2107 int arg = get_cmd_arg_num(str, pos);
2108 char **res = NULL;
2109
2110 switch (arg) {
2111 case 1:
2112 res = cli_txt_list_array(&p2p_groups);
2113 break;
2114 }
2115
2116 return res;
2117}
2118
2119
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2121 char *argv[])
2122{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002123 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124}
2125
2126
2127static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2128 char *argv[])
2129{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002130 if (argc != 2 && argc != 3) {
2131 printf("Invalid P2P_PROV_DISC command: needs at least "
2132 "two arguments, address and config method\n"
2133 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 return -1;
2135 }
2136
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002137 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138}
2139
2140
2141static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2142 char *argv[])
2143{
2144 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2145}
2146
2147
2148static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2149 char *argv[])
2150{
2151 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002153 if (argc < 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002154 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002155 "or more arguments (address and TLVs)\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 return -1;
2157 }
2158
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002159 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002161 return wpa_ctrl_command(ctrl, cmd);
2162}
2163
2164
2165static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2166 int argc, char *argv[])
2167{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002168 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169}
2170
2171
2172static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2173 char *argv[])
2174{
2175 char cmd[4096];
2176 int res;
2177
2178 if (argc != 4) {
2179 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2180 "arguments (freq, address, dialog token, and TLVs)\n");
2181 return -1;
2182 }
2183
2184 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2185 argv[0], argv[1], argv[2], argv[3]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002186 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187 return -1;
2188 cmd[sizeof(cmd) - 1] = '\0';
2189 return wpa_ctrl_command(ctrl, cmd);
2190}
2191
2192
2193static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195{
2196 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2197}
2198
2199
2200static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2201 int argc, char *argv[])
2202{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002203 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204}
2205
2206
2207static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2208 char *argv[])
2209{
2210 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2211}
2212
2213
2214static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002217 if (argc < 3) {
2218 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2219 return -1;
2220 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002222 return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2223}
2224
2225
2226static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2227 char *argv[])
2228{
2229 if (argc < 5 || argc > 6) {
2230 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 "arguments\n");
2232 return -1;
2233 }
2234
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002235 return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236}
2237
2238
2239static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2240 char *argv[])
2241{
2242 char cmd[4096];
2243 int res;
2244
2245 if (argc != 2 && argc != 3) {
2246 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2247 "arguments\n");
2248 return -1;
2249 }
2250
2251 if (argc == 3)
2252 res = os_snprintf(cmd, sizeof(cmd),
2253 "P2P_SERVICE_DEL %s %s %s",
2254 argv[0], argv[1], argv[2]);
2255 else
2256 res = os_snprintf(cmd, sizeof(cmd),
2257 "P2P_SERVICE_DEL %s %s",
2258 argv[0], argv[1]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002259 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 return -1;
2261 cmd[sizeof(cmd) - 1] = '\0';
2262 return wpa_ctrl_command(ctrl, cmd);
2263}
2264
2265
2266static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2267 int argc, char *argv[])
2268{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002269 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002270}
2271
2272
2273static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2274 int argc, char *argv[])
2275{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002276 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277}
2278
2279
2280static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2281{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002282 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002283}
2284
2285
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002286static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2287{
2288 int arg = get_cmd_arg_num(str, pos);
2289 char **res = NULL;
2290
2291 switch (arg) {
2292 case 1:
2293 res = cli_txt_list_array(&p2p_peers);
2294 break;
2295 }
2296
2297 return res;
2298}
2299
2300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2302 char *addr, size_t addr_len,
2303 int discovered)
2304{
2305 char buf[4096], *pos;
2306 size_t len;
2307 int ret;
2308
2309 if (ctrl_conn == NULL)
2310 return -1;
2311 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002312 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 wpa_cli_msg_cb);
2314 if (ret == -2) {
2315 printf("'%s' command timed out.\n", cmd);
2316 return -2;
2317 } else if (ret < 0) {
2318 printf("'%s' command failed.\n", cmd);
2319 return -1;
2320 }
2321
2322 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002323 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002324 return -1;
2325
2326 pos = buf;
2327 while (*pos != '\0' && *pos != '\n')
2328 pos++;
2329 *pos++ = '\0';
2330 os_strlcpy(addr, buf, addr_len);
2331 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2332 printf("%s\n", addr);
2333 return 0;
2334}
2335
2336
2337static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2338{
2339 char addr[32], cmd[64];
2340 int discovered;
2341
2342 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2343
2344 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2345 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002346 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 do {
2348 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2349 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2350 discovered) == 0);
2351
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002352 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353}
2354
2355
2356static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2357{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002358 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359}
2360
2361
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002362static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2363{
2364 int arg = get_cmd_arg_num(str, pos);
2365 const char *fields[] = {
2366 "discoverability",
2367 "managed",
2368 "listen_channel",
2369 "ssid_postfix",
2370 "noa",
2371 "ps",
2372 "oppps",
2373 "ctwindow",
2374 "disabled",
2375 "conc_pref",
2376 "force_long_sd",
2377 "peer_filter",
2378 "cross_connect",
2379 "go_apsd",
2380 "client_apsd",
2381 "disallow_freq",
2382 "disc_int",
2383 "per_sta_psk",
2384 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002385 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002386
2387 if (arg == 1) {
2388 char **res = os_calloc(num_fields + 1, sizeof(char *));
2389 if (res == NULL)
2390 return NULL;
2391 for (i = 0; i < num_fields; i++) {
2392 res[i] = os_strdup(fields[i]);
2393 if (res[i] == NULL)
2394 return res;
2395 }
2396 return res;
2397 }
2398
2399 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2400 return cli_txt_list_array(&p2p_peers);
2401
2402 return NULL;
2403}
2404
2405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2407{
2408 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2409}
2410
2411
2412static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2413 char *argv[])
2414{
2415 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2416}
2417
2418
2419static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2420 char *argv[])
2421{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423}
2424
2425
2426static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2427 char *argv[])
2428{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 if (argc != 0 && argc != 2 && argc != 4) {
2430 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2431 "(preferred duration, interval; in microsecods).\n"
2432 "Optional second pair can be used to provide "
2433 "acceptable values.\n");
2434 return -1;
2435 }
2436
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002437 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438}
2439
2440
2441static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2442 char *argv[])
2443{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 if (argc != 0 && argc != 2) {
2445 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2446 "(availability period, availability interval; in "
2447 "millisecods).\n"
2448 "Extended Listen Timing can be cancelled with this "
2449 "command when used without parameters.\n");
2450 return -1;
2451 }
2452
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2454}
2455
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002456
2457static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2458 char *argv[])
2459{
2460 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2461}
2462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463#endif /* CONFIG_P2P */
2464
2465#ifdef CONFIG_WIFI_DISPLAY
2466
2467static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2468 char *argv[])
2469{
2470 char cmd[100];
2471 int res;
2472
2473 if (argc != 1 && argc != 2) {
2474 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2475 "arguments (subelem, hexdump)\n");
2476 return -1;
2477 }
2478
2479 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2480 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002481 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 return -1;
2483 cmd[sizeof(cmd) - 1] = '\0';
2484 return wpa_ctrl_command(ctrl, cmd);
2485}
2486
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487
2488static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2489 char *argv[])
2490{
2491 char cmd[100];
2492 int res;
2493
2494 if (argc != 1) {
2495 printf("Invalid WFD_SUBELEM_GET command: needs one "
2496 "argument (subelem)\n");
2497 return -1;
2498 }
2499
2500 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2501 argv[0]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002502 if (os_snprintf_error(sizeof(cmd), res))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 return -1;
2504 cmd[sizeof(cmd) - 1] = '\0';
2505 return wpa_ctrl_command(ctrl, cmd);
2506}
2507#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508
2509
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002510#ifdef CONFIG_INTERWORKING
2511static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2512 char *argv[])
2513{
2514 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2515}
2516
2517
2518static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2519 char *argv[])
2520{
2521 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2522}
2523
2524
2525static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2526 char *argv[])
2527{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002529}
2530
2531
2532static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2533 char *argv[])
2534{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002535 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002536}
2537
2538
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002539static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2540 char *argv[])
2541{
2542 return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2543}
2544
2545
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002546static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2547{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2549}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002550
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002551
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2553 char *argv[])
2554{
2555 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2556}
2557
2558
2559static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2560 char *argv[])
2561{
2562 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002563}
2564#endif /* CONFIG_INTERWORKING */
2565
2566
Dmitry Shmidt04949592012-07-19 12:16:46 -07002567#ifdef CONFIG_HS20
2568
2569static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2570 char *argv[])
2571{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002573}
2574
2575
2576static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2577 char *argv[])
2578{
2579 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580
2581 if (argc == 0) {
2582 printf("Command needs one or two arguments (dst mac addr and "
2583 "optional home realm)\n");
2584 return -1;
2585 }
2586
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2588 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002589 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002590
2591 return wpa_ctrl_command(ctrl, cmd);
2592}
2593
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002594
2595static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2596 char *argv[])
2597{
2598 char cmd[512];
2599
2600 if (argc < 2) {
2601 printf("Command needs two arguments (dst mac addr and "
2602 "icon name)\n");
2603 return -1;
2604 }
2605
2606 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2607 return -1;
2608
2609 return wpa_ctrl_command(ctrl, cmd);
2610}
2611
2612
2613static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2614{
2615 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2616}
2617
2618
2619static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2620 char *argv[])
2621{
2622 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2623}
2624
Dmitry Shmidt04949592012-07-19 12:16:46 -07002625#endif /* CONFIG_HS20 */
2626
2627
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2629 char *argv[])
2630{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632}
2633
2634
2635static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2636 char *argv[])
2637{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002638 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639}
2640
2641
2642static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2643 char *argv[])
2644{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646}
2647
2648
2649static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2650 char *argv[])
2651{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002652 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653}
2654
2655
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002656static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2657 char *argv[])
2658{
2659 return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2660}
2661
2662
2663static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2664 char *argv[])
2665{
2666 return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2667}
2668
2669
2670static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2671 char *argv[])
2672{
2673 return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2674}
2675
2676
2677static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2678 char *argv[])
2679{
2680 return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2681}
2682
2683
2684static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2685 char *argv[])
2686{
2687 return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2688}
2689
2690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2692 char *argv[])
2693{
2694 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2695}
2696
2697
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002698static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2699 char *argv[])
2700{
2701 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2702}
2703
2704
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002705static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2706 char *argv[])
2707{
2708 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2709}
2710
Dmitry Shmidt04949592012-07-19 12:16:46 -07002711
2712#ifdef CONFIG_AUTOSCAN
2713
2714static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2715{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002716 if (argc == 0)
2717 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2718
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002720}
2721
2722#endif /* CONFIG_AUTOSCAN */
2723
2724
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002725#ifdef CONFIG_WNM
2726
2727static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2728{
2729 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2730}
2731
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002732
2733static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2734{
2735 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2736}
2737
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002738#endif /* CONFIG_WNM */
2739
2740
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2742{
2743 if (argc == 0)
2744 return -1;
2745 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2746}
2747
2748
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002749#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002750static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2751{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002752 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002753}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002754#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002755
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002757static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2758{
2759 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2760}
2761
2762
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002763static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2764{
2765 return wpa_ctrl_command(ctrl, "FLUSH");
2766}
2767
2768
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002769static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2770{
2771 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2772}
2773
2774
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002775static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2776 char *argv[])
2777{
2778 return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2779}
2780
2781
2782static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2783{
2784 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2785}
2786
2787
2788static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2789 char *argv[])
2790{
2791 return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2792}
2793
2794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795enum wpa_cli_cmd_flags {
2796 cli_cmd_flag_none = 0x00,
2797 cli_cmd_flag_sensitive = 0x01
2798};
2799
2800struct wpa_cli_cmd {
2801 const char *cmd;
2802 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002803 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804 enum wpa_cli_cmd_flags flags;
2805 const char *usage;
2806};
2807
2808static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002810 cli_cmd_flag_none,
2811 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002812 { "ifname", wpa_cli_cmd_ifname, NULL,
2813 cli_cmd_flag_none,
2814 "= get current interface name" },
2815 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 cli_cmd_flag_none,
2817 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002818 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002819 cli_cmd_flag_none,
2820 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002821 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002822 cli_cmd_flag_none,
2823 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002824 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002825 cli_cmd_flag_none,
2826 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002829 "[command] = show usage help" },
2830 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831 cli_cmd_flag_none,
2832 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002833 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834 cli_cmd_flag_none,
2835 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002836 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002837 cli_cmd_flag_none,
2838 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002839 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840 cli_cmd_flag_none,
2841 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002842 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002843 cli_cmd_flag_none,
2844 "= set variables (shows list of variables when run without "
2845 "arguments)" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002846 { "dump", wpa_cli_cmd_dump, NULL,
2847 cli_cmd_flag_none,
2848 "= dump config variables" },
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07002849 { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002850 cli_cmd_flag_none,
2851 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002852 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002853 cli_cmd_flag_none,
2854 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002855 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856 cli_cmd_flag_none,
2857 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002858 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859 cli_cmd_flag_none,
2860 "= show PMKSA cache" },
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002861 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2862 cli_cmd_flag_none,
2863 "= flush PMKSA cache entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 cli_cmd_flag_none,
2866 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002867 { "reattach", wpa_cli_cmd_reattach, NULL,
2868 cli_cmd_flag_none,
2869 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002870 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002871 cli_cmd_flag_none,
2872 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002873 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002874 cli_cmd_flag_none,
2875 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002876 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 cli_cmd_flag_sensitive,
2878 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 cli_cmd_flag_sensitive,
2881 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 cli_cmd_flag_sensitive,
2884 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002885 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 cli_cmd_flag_sensitive,
2887 "<network id> <password> = configure one-time-password for an SSID"
2888 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002889 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890 cli_cmd_flag_sensitive,
2891 "<network id> <passphrase> = configure private key passphrase\n"
2892 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002893 { "sim", wpa_cli_cmd_sim, NULL,
2894 cli_cmd_flag_sensitive,
2895 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002896 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002897 cli_cmd_flag_none,
2898 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002899 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002900 cli_cmd_flag_none,
2901 "<BSSID> = add a BSSID to the blacklist\n"
2902 "blacklist clear = clear the blacklist\n"
2903 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002904 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002905 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002906 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002907 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002908 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909 cli_cmd_flag_none,
2910 "= list configured networks" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002911 { "select_network", wpa_cli_cmd_select_network,
2912 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 cli_cmd_flag_none,
2914 "<network id> = select a network (disable others)" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002915 { "enable_network", wpa_cli_cmd_enable_network,
2916 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917 cli_cmd_flag_none,
2918 "<network id> = enable a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002919 { "disable_network", wpa_cli_cmd_disable_network,
2920 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 cli_cmd_flag_none,
2922 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002923 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 cli_cmd_flag_none,
2925 "= add a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002926 { "remove_network", wpa_cli_cmd_remove_network,
2927 wpa_cli_complete_network_id,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 cli_cmd_flag_none,
2929 "<network id> = remove a network" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002930 { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931 cli_cmd_flag_sensitive,
2932 "<network id> <variable> <value> = set network variables (shows\n"
2933 " list of variables when run without arguments)" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002934 { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002935 cli_cmd_flag_none,
2936 "<network id> <variable> = get network variables" },
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002937 { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
Dmitry Shmidt684785c2014-05-12 13:34:29 -07002938 cli_cmd_flag_none,
2939 "<src network id> <dst network id> <variable> = duplicate network variables"
2940 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002941 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002942 cli_cmd_flag_none,
2943 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002944 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002945 cli_cmd_flag_none,
2946 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002947 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002948 cli_cmd_flag_none,
2949 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002950 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002951 cli_cmd_flag_sensitive,
2952 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002953 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2954 cli_cmd_flag_none,
2955 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002956 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957 cli_cmd_flag_none,
2958 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002959 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960 cli_cmd_flag_none,
2961 "= disconnect and wait for reassociate/reconnect command before\n"
2962 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002963 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 cli_cmd_flag_none,
2965 "= like reassociate, but only takes effect if already disconnected"
2966 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002967 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968 cli_cmd_flag_none,
2969 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002970 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971 cli_cmd_flag_none,
2972 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002973 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974 cli_cmd_flag_none,
2975 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002976 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002978 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07002979 "= get capabilities" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002980 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002981 cli_cmd_flag_none,
2982 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002983 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 cli_cmd_flag_none,
2985 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002986 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002987 cli_cmd_flag_none,
2988 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2989 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2990 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002991 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002992 cli_cmd_flag_none,
2993 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002994 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 cli_cmd_flag_none,
2996 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002997 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002998 cli_cmd_flag_none,
2999 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003000 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003001 cli_cmd_flag_none,
3002 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003003 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003004 cli_cmd_flag_none,
3005 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003006 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 cli_cmd_flag_none,
3008 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003009 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07003010 cli_cmd_flag_none,
3011 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003012 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003013 cli_cmd_flag_none,
3014 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003015 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 cli_cmd_flag_none,
3017 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003018 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019 cli_cmd_flag_none,
3020 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003021 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003022 cli_cmd_flag_sensitive,
3023 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3024 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003025 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 cli_cmd_flag_sensitive,
3027 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003028 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003030#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003031 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003032 cli_cmd_flag_none,
3033 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003034 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3035 cli_cmd_flag_none,
3036 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003037 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003038 cli_cmd_flag_none,
3039 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003040 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003041 cli_cmd_flag_sensitive,
3042 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003043 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3044 cli_cmd_flag_none,
3045 "<NDEF> <WPS> = create NFC handover request" },
3046 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3047 cli_cmd_flag_none,
3048 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003049 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3050 cli_cmd_flag_none,
3051 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3052 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003053#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003054 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055 cli_cmd_flag_sensitive,
3056 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003057 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 cli_cmd_flag_sensitive,
3059 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003060 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003061 cli_cmd_flag_none,
3062 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003063 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003064 cli_cmd_flag_none,
3065 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003066 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 cli_cmd_flag_sensitive,
3068 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003069 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003070 cli_cmd_flag_none,
3071 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003072 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073 cli_cmd_flag_sensitive,
3074 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003075 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 cli_cmd_flag_none,
3077 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003078 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003079 cli_cmd_flag_sensitive,
3080 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003081#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003082 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003083 cli_cmd_flag_none,
3084 "<WPS/NDEF> <UUID> = build NFC configuration token" },
3085#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003086 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 cli_cmd_flag_none,
3088 "<addr> = request RSN authentication with <addr> in IBSS" },
3089#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003090 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003091 cli_cmd_flag_none,
3092 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003093 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003094 cli_cmd_flag_none,
3095 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003096 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003097 cli_cmd_flag_none,
3098 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003099 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003100 cli_cmd_flag_none,
3101 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003102 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3103 cli_cmd_flag_none,
3104 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3105 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3106 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003107#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003108 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003109 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003110 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003111 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07003112#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003113 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003114 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07003115#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003116 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117 cli_cmd_flag_none,
3118 "<addr> = roam to the specified BSS" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003119#ifdef CONFIG_MESH
3120 { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3121 cli_cmd_flag_none,
3122 "[ifname] = Create a new mesh interface" },
3123 { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3124 cli_cmd_flag_none,
3125 "<network id> = join a mesh network (disable others)" },
3126 { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3127 cli_cmd_flag_none,
3128 "<ifname> = Remove mesh group interface" },
3129#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003130#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003131 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3132 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003133 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003134 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003135 "= stop P2P Devices search" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003136 { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3137 cli_cmd_flag_none,
3138 "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3139 { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3140 cli_cmd_flag_none,
3141 "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003142 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3143 cli_cmd_flag_none,
3144 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3145 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003146 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003147 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3148 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003149 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003150 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3151 "[ht40] = add a new P2P group (local end as GO)" },
3152 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3153 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003154 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003155 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003156 cli_cmd_flag_none,
3157 "= get the passphrase for a group (GO only)" },
3158 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003159 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003160 "<addr> <TLVs> = schedule service discovery request" },
3161 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003162 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003163 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003164 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003165 cli_cmd_flag_none,
3166 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003167 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003168 cli_cmd_flag_none,
3169 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003170 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003171 cli_cmd_flag_none,
3172 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003173 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003174 cli_cmd_flag_none,
3175 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003176 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003177 cli_cmd_flag_none,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003178 "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003179 "service" },
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003180 { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3181 cli_cmd_flag_none,
3182 "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3183 "local ASP service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003184 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003185 cli_cmd_flag_none,
3186 "<bonjour|upnp> <query|version> [|service] = remove a local "
3187 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003188 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003189 cli_cmd_flag_none,
3190 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003191 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003192 cli_cmd_flag_none,
3193 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003194 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195 "[discovered] = list known (optionally, only fully discovered) P2P "
3196 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003197 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3198 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003199 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003200 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3201 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003203 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003204 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003205 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003206 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003207 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3208 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003209 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003210 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3211 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003212 "[<duration> <interval>] [<duration> <interval>] = request GO "
3213 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003214 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3215 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003217 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3218 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3219 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003221#ifdef CONFIG_WIFI_DISPLAY
3222 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3223 cli_cmd_flag_none,
3224 "<subelem> [contents] = set Wi-Fi Display subelement" },
3225 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3226 cli_cmd_flag_none,
3227 "<subelem> = get Wi-Fi Display subelement" },
3228#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003229#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003230 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003231 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003232 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3233 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003234 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003235 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003236 cli_cmd_flag_none,
3237 "[auto] = perform Interworking network selection" },
3238 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003239 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003240 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003241 { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3242 wpa_cli_complete_bss, cli_cmd_flag_none,
3243 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003244 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3245 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003246 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003247 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3248 cli_cmd_flag_none,
3249 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3250 { "gas_response_get", wpa_cli_cmd_gas_response_get,
3251 wpa_cli_complete_bss, cli_cmd_flag_none,
3252 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003253#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003254#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003255 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3256 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003257 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3258 },
3259 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003260 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003261 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003262 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3263 wpa_cli_complete_bss, cli_cmd_flag_none,
3264 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3265 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3266 "= fetch OSU provider information from all APs" },
3267 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3268 cli_cmd_flag_none,
3269 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003270#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003271 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3272 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003273 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003274 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275 cli_cmd_flag_none,
3276 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003277 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278 cli_cmd_flag_none,
3279 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003280 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281 cli_cmd_flag_none,
3282 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003283 { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3284 cli_cmd_flag_none,
3285 "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3286 "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3287 "= add WMM-AC traffic stream" },
3288 { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3289 cli_cmd_flag_none,
3290 "<tsid> = delete WMM-AC traffic stream" },
3291 { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3292 cli_cmd_flag_none,
3293 "= show status for Wireless Multi-Media Admission-Control" },
3294 { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3295 cli_cmd_flag_none,
3296 "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3297 "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3298 "with TDLS peer" },
3299 { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3300 cli_cmd_flag_none,
3301 "<addr> = disable channel switching with TDLS peer <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003302 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303 cli_cmd_flag_none,
3304 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003305 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07003306 cli_cmd_flag_none,
3307 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003308 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3309 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003310 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07003311#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003312 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003313 "[params] = Set or unset (if none) autoscan parameters" },
3314#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003315#ifdef CONFIG_WNM
3316 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3317 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07003318 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3319 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003320#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003321 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3322 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003323 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3324 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003325#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003326 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07003327 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08003328#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003329 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3330 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003331 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3332 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3333 },
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003334 { "neighbor_rep_request",
3335 wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3336 "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3337 "(with optional given SSID, default: current SSID)"
3338 },
3339 { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3340 "= flush ERP keys" },
3341 { "mac_rand_scan",
3342 wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3343 "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3344 "mask=mac-address-mask] = scan MAC randomization"
3345 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003346 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003347};
3348
3349
3350/*
3351 * Prints command usage, lines are padded with the specified string.
3352 */
3353static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3354{
3355 char c;
3356 size_t n;
3357
3358 printf("%s%s ", pad, cmd->cmd);
3359 for (n = 0; (c = cmd->usage[n]); n++) {
3360 printf("%c", c);
3361 if (c == '\n')
3362 printf("%s", pad);
3363 }
3364 printf("\n");
3365}
3366
3367
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003368static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369{
3370 int n;
3371 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003372 for (n = 0; wpa_cli_commands[n].cmd; n++) {
3373 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3374 print_cmd_help(&wpa_cli_commands[n], " ");
3375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376}
3377
3378
3379static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3380{
3381 const char *c, *delim;
3382 int n;
3383 size_t len;
3384
3385 delim = os_strchr(cmd, ' ');
3386 if (delim)
3387 len = delim - cmd;
3388 else
3389 len = os_strlen(cmd);
3390
3391 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3392 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3393 return (wpa_cli_commands[n].flags &
3394 cli_cmd_flag_sensitive);
3395 }
3396 return 0;
3397}
3398
3399
3400static char ** wpa_list_cmd_list(void)
3401{
3402 char **res;
3403 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003404 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003406 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003407 count += dl_list_len(&p2p_groups);
3408 count += dl_list_len(&ifnames);
3409 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410 if (res == NULL)
3411 return NULL;
3412
3413 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3414 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3415 if (res[i] == NULL)
3416 break;
3417 }
3418
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003419 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3420 size_t len = 8 + os_strlen(e->txt);
3421 res[i] = os_malloc(len);
3422 if (res[i] == NULL)
3423 break;
3424 os_snprintf(res[i], len, "ifname=%s", e->txt);
3425 i++;
3426 }
3427
3428 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3429 res[i] = os_strdup(e->txt);
3430 if (res[i] == NULL)
3431 break;
3432 i++;
3433 }
3434
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 return res;
3436}
3437
3438
3439static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3440 int pos)
3441{
3442 int i;
3443
3444 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3445 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003446 if (wpa_cli_commands[i].completion)
3447 return wpa_cli_commands[i].completion(str,
3448 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003449 edit_clear_line();
3450 printf("\r%s\n", wpa_cli_commands[i].usage);
3451 edit_redraw();
3452 break;
3453 }
3454 }
3455
3456 return NULL;
3457}
3458
3459
3460static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3461{
3462 char **res;
3463 const char *end;
3464 char *cmd;
3465
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003466 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3467 end = os_strchr(str, ' ');
3468 if (end && pos > end - str) {
3469 pos -= end - str + 1;
3470 str = end + 1;
3471 }
3472 }
3473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003474 end = os_strchr(str, ' ');
3475 if (end == NULL || str + pos < end)
3476 return wpa_list_cmd_list();
3477
3478 cmd = os_malloc(pos + 1);
3479 if (cmd == NULL)
3480 return NULL;
3481 os_memcpy(cmd, str, pos);
3482 cmd[end - str] = '\0';
3483 res = wpa_cli_cmd_completion(cmd, str, pos);
3484 os_free(cmd);
3485 return res;
3486}
3487
3488
3489static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3490{
3491 struct wpa_cli_cmd *cmd, *match = NULL;
3492 int count;
3493 int ret = 0;
3494
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003495 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3496 ifname_prefix = argv[0] + 7;
3497 argv = &argv[1];
3498 argc--;
3499 } else
3500 ifname_prefix = NULL;
3501
3502 if (argc == 0)
3503 return -1;
3504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003505 count = 0;
3506 cmd = wpa_cli_commands;
3507 while (cmd->cmd) {
3508 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3509 {
3510 match = cmd;
3511 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3512 /* we have an exact match */
3513 count = 1;
3514 break;
3515 }
3516 count++;
3517 }
3518 cmd++;
3519 }
3520
3521 if (count > 1) {
3522 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3523 cmd = wpa_cli_commands;
3524 while (cmd->cmd) {
3525 if (os_strncasecmp(cmd->cmd, argv[0],
3526 os_strlen(argv[0])) == 0) {
3527 printf(" %s", cmd->cmd);
3528 }
3529 cmd++;
3530 }
3531 printf("\n");
3532 ret = 1;
3533 } else if (count == 0) {
3534 printf("Unknown command '%s'\n", argv[0]);
3535 ret = 1;
3536 } else {
3537 ret = match->handler(ctrl, argc - 1, &argv[1]);
3538 }
3539
3540 return ret;
3541}
3542
3543
3544static int str_match(const char *a, const char *b)
3545{
3546 return os_strncmp(a, b, os_strlen(b)) == 0;
3547}
3548
3549
3550static int wpa_cli_exec(const char *program, const char *arg1,
3551 const char *arg2)
3552{
Jouni Malinen772e12c2014-10-07 10:29:35 -07003553 char *arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 size_t len;
3555 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556
Jouni Malinen772e12c2014-10-07 10:29:35 -07003557 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3558 arg = os_malloc(len);
3559 if (arg == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560 return -1;
Jouni Malinen772e12c2014-10-07 10:29:35 -07003561 os_snprintf(arg, len, "%s %s", arg1, arg2);
3562 res = os_exec(program, arg, 1);
3563 os_free(arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564
Jouni Malinen772e12c2014-10-07 10:29:35 -07003565 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566}
3567
3568
3569static void wpa_cli_action_process(const char *msg)
3570{
3571 const char *pos;
3572 char *copy = NULL, *id, *pos2;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003573 const char *ifname = ctrl_ifname;
3574 char ifname_buf[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575
3576 pos = msg;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003577 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3578 const char *end;
3579 end = os_strchr(pos + 7, ' ');
3580 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3581 pos += 7;
3582 os_memcpy(ifname_buf, pos, end - pos);
3583 ifname_buf[end - pos] = '\0';
3584 ifname = ifname_buf;
3585 pos = end + 1;
3586 }
3587 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588 if (*pos == '<') {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003589 const char *prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 /* skip priority */
3591 pos = os_strchr(pos, '>');
3592 if (pos)
3593 pos++;
3594 else
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003595 pos = prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596 }
3597
3598 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3599 int new_id = -1;
3600 os_unsetenv("WPA_ID");
3601 os_unsetenv("WPA_ID_STR");
3602 os_unsetenv("WPA_CTRL_DIR");
3603
3604 pos = os_strstr(pos, "[id=");
3605 if (pos)
3606 copy = os_strdup(pos + 4);
3607
3608 if (copy) {
3609 pos2 = id = copy;
3610 while (*pos2 && *pos2 != ' ')
3611 pos2++;
3612 *pos2++ = '\0';
3613 new_id = atoi(id);
3614 os_setenv("WPA_ID", id, 1);
3615 while (*pos2 && *pos2 != '=')
3616 pos2++;
3617 if (*pos2 == '=')
3618 pos2++;
3619 id = pos2;
3620 while (*pos2 && *pos2 != ']')
3621 pos2++;
3622 *pos2 = '\0';
3623 os_setenv("WPA_ID_STR", id, 1);
3624 os_free(copy);
3625 }
3626
3627 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3628
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003629 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630 wpa_cli_connected = 1;
3631 wpa_cli_last_id = new_id;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003632 wpa_cli_exec(action_file, ifname, "CONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633 }
3634 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3635 if (wpa_cli_connected) {
3636 wpa_cli_connected = 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003637 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003639 } else if (str_match(pos, MESH_GROUP_STARTED)) {
3640 wpa_cli_exec(action_file, ctrl_ifname, pos);
3641 } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3642 wpa_cli_exec(action_file, ctrl_ifname, pos);
3643 } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3644 wpa_cli_exec(action_file, ctrl_ifname, pos);
3645 } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3646 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003647 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003648 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003650 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003651 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003652 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003653 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003654 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003655 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003656 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003657 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003658 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003659 } else if (str_match(pos, WPS_EVENT_FAIL)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003660 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003661 } else if (str_match(pos, AP_STA_CONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003662 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003663 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003664 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003665 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003666 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003667 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003668 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003669 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003670 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003671 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3672 printf("wpa_supplicant is terminating - stop monitoring\n");
3673 wpa_cli_quit = 1;
3674 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675}
3676
3677
3678#ifndef CONFIG_ANSI_C_EXTRA
3679static void wpa_cli_action_cb(char *msg, size_t len)
3680{
3681 wpa_cli_action_process(msg);
3682}
3683#endif /* CONFIG_ANSI_C_EXTRA */
3684
3685
3686static void wpa_cli_reconnect(void)
3687{
3688 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003689 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3690 return;
3691
3692 if (interactive) {
3693 edit_clear_line();
3694 printf("\rConnection to wpa_supplicant re-established\n");
3695 edit_redraw();
3696 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003697}
3698
3699
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003700static void cli_event(const char *str)
3701{
3702 const char *start, *s;
3703
3704 start = os_strchr(str, '>');
3705 if (start == NULL)
3706 return;
3707
3708 start++;
3709
3710 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3711 s = os_strchr(start, ' ');
3712 if (s == NULL)
3713 return;
3714 s = os_strchr(s + 1, ' ');
3715 if (s == NULL)
3716 return;
3717 cli_txt_list_add(&bsses, s + 1);
3718 return;
3719 }
3720
3721 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3722 s = os_strchr(start, ' ');
3723 if (s == NULL)
3724 return;
3725 s = os_strchr(s + 1, ' ');
3726 if (s == NULL)
3727 return;
3728 cli_txt_list_del_addr(&bsses, s + 1);
3729 return;
3730 }
3731
3732#ifdef CONFIG_P2P
3733 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3734 s = os_strstr(start, " p2p_dev_addr=");
3735 if (s == NULL)
3736 return;
3737 cli_txt_list_add_addr(&p2p_peers, s + 14);
3738 return;
3739 }
3740
3741 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3742 s = os_strstr(start, " p2p_dev_addr=");
3743 if (s == NULL)
3744 return;
3745 cli_txt_list_del_addr(&p2p_peers, s + 14);
3746 return;
3747 }
3748
3749 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3750 s = os_strchr(start, ' ');
3751 if (s == NULL)
3752 return;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003753 cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003754 return;
3755 }
3756
3757 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3758 s = os_strchr(start, ' ');
3759 if (s == NULL)
3760 return;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003761 cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003762 return;
3763 }
3764#endif /* CONFIG_P2P */
3765}
3766
3767
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003768static int check_terminating(const char *msg)
3769{
3770 const char *pos = msg;
3771
3772 if (*pos == '<') {
3773 /* skip priority */
3774 pos = os_strchr(pos, '>');
3775 if (pos)
3776 pos++;
3777 else
3778 pos = msg;
3779 }
3780
3781 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3782 edit_clear_line();
3783 printf("\rConnection to wpa_supplicant lost - trying to "
3784 "reconnect\n");
3785 edit_redraw();
3786 wpa_cli_attached = 0;
3787 wpa_cli_close_connection();
3788 return 1;
3789 }
3790
3791 return 0;
3792}
3793
3794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003795static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3796{
3797 if (ctrl_conn == NULL) {
3798 wpa_cli_reconnect();
3799 return;
3800 }
3801 while (wpa_ctrl_pending(ctrl) > 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003802 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003803 size_t len = sizeof(buf) - 1;
3804 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3805 buf[len] = '\0';
3806 if (action_monitor)
3807 wpa_cli_action_process(buf);
3808 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003809 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 if (wpa_cli_show_event(buf)) {
3811 edit_clear_line();
3812 printf("\r%s\n", buf);
3813 edit_redraw();
3814 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003815
3816 if (interactive && check_terminating(buf) > 0)
3817 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818 }
3819 } else {
3820 printf("Could not read pending message.\n");
3821 break;
3822 }
3823 }
3824
3825 if (wpa_ctrl_pending(ctrl) < 0) {
3826 printf("Connection to wpa_supplicant lost - trying to "
3827 "reconnect\n");
3828 wpa_cli_reconnect();
3829 }
3830}
3831
3832#define max_args 10
3833
3834static int tokenize_cmd(char *cmd, char *argv[])
3835{
3836 char *pos;
3837 int argc = 0;
3838
3839 pos = cmd;
3840 for (;;) {
3841 while (*pos == ' ')
3842 pos++;
3843 if (*pos == '\0')
3844 break;
3845 argv[argc] = pos;
3846 argc++;
3847 if (argc == max_args)
3848 break;
3849 if (*pos == '"') {
3850 char *pos2 = os_strrchr(pos, '"');
3851 if (pos2)
3852 pos = pos2 + 1;
3853 }
3854 while (*pos != '\0' && *pos != ' ')
3855 pos++;
3856 if (*pos == ' ')
3857 *pos++ = '\0';
3858 }
3859
3860 return argc;
3861}
3862
3863
3864static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3865{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003866 if (ctrl_conn) {
3867 int res;
3868 char *prefix = ifname_prefix;
3869
3870 ifname_prefix = NULL;
3871 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3872 ifname_prefix = prefix;
3873 if (res) {
3874 printf("Connection to wpa_supplicant lost - trying to "
3875 "reconnect\n");
3876 wpa_cli_close_connection();
3877 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003878 }
3879 if (!ctrl_conn)
3880 wpa_cli_reconnect();
3881 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3882}
3883
3884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003885static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3886{
3887 wpa_cli_recv_pending(mon_conn, 0);
3888}
3889
3890
3891static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3892{
3893 char *argv[max_args];
3894 int argc;
3895 argc = tokenize_cmd(cmd, argv);
3896 if (argc)
3897 wpa_request(ctrl_conn, argc, argv);
3898}
3899
3900
3901static void wpa_cli_edit_eof_cb(void *ctx)
3902{
3903 eloop_terminate();
3904}
3905
3906
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003907static int warning_displayed = 0;
3908static char *hfile = NULL;
3909static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003910
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003911static void start_edit(void)
3912{
3913 char *home;
3914 char *ps = NULL;
3915
3916#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3917 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3918#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003919
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003920#ifdef CONFIG_WPA_CLI_HISTORY_DIR
3921 home = CONFIG_WPA_CLI_HISTORY_DIR;
3922#else /* CONFIG_WPA_CLI_HISTORY_DIR */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 home = getenv("HOME");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07003924#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003925 if (home) {
3926 const char *fname = ".wpa_cli_history";
3927 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3928 hfile = os_malloc(hfile_len);
3929 if (hfile)
3930 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3931 }
3932
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003933 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3934 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3935 eloop_terminate();
3936 return;
3937 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003938
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003939 edit_started = 1;
3940 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3941}
3942
3943
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003944static void update_bssid_list(struct wpa_ctrl *ctrl)
3945{
3946 char buf[4096];
3947 size_t len = sizeof(buf);
3948 int ret;
3949 char *cmd = "BSS RANGE=ALL MASK=0x2";
3950 char *pos, *end;
3951
3952 if (ctrl == NULL)
3953 return;
3954 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3955 if (ret < 0)
3956 return;
3957 buf[len] = '\0';
3958
3959 pos = buf;
3960 while (pos) {
3961 pos = os_strstr(pos, "bssid=");
3962 if (pos == NULL)
3963 break;
3964 pos += 6;
3965 end = os_strchr(pos, '\n');
3966 if (end == NULL)
3967 break;
3968 *end = '\0';
3969 cli_txt_list_add(&bsses, pos);
3970 pos = end + 1;
3971 }
3972}
3973
3974
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003975static void update_ifnames(struct wpa_ctrl *ctrl)
3976{
3977 char buf[4096];
3978 size_t len = sizeof(buf);
3979 int ret;
3980 char *cmd = "INTERFACES";
3981 char *pos, *end;
3982 char txt[200];
3983
3984 cli_txt_list_flush(&ifnames);
3985
3986 if (ctrl == NULL)
3987 return;
3988 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3989 if (ret < 0)
3990 return;
3991 buf[len] = '\0';
3992
3993 pos = buf;
3994 while (pos) {
3995 end = os_strchr(pos, '\n');
3996 if (end == NULL)
3997 break;
3998 *end = '\0';
3999 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004000 if (!os_snprintf_error(sizeof(txt), ret))
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004001 cli_txt_list_add(&ifnames, txt);
4002 pos = end + 1;
4003 }
4004}
4005
4006
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004007static void update_networks(struct wpa_ctrl *ctrl)
4008{
4009 char buf[4096];
4010 size_t len = sizeof(buf);
4011 int ret;
4012 char *cmd = "LIST_NETWORKS";
4013 char *pos, *end;
4014 int header = 1;
4015
4016 cli_txt_list_flush(&networks);
4017
4018 if (ctrl == NULL)
4019 return;
4020 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4021 if (ret < 0)
4022 return;
4023 buf[len] = '\0';
4024
4025 pos = buf;
4026 while (pos) {
4027 end = os_strchr(pos, '\n');
4028 if (end == NULL)
4029 break;
4030 *end = '\0';
4031 if (!header)
4032 cli_txt_list_add_word(&networks, pos, '\t');
4033 header = 0;
4034 pos = end + 1;
4035 }
4036}
4037
4038
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004039static void try_connection(void *eloop_ctx, void *timeout_ctx)
4040{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004041 if (ctrl_conn)
4042 goto done;
4043
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004044 if (ctrl_ifname == NULL)
4045 ctrl_ifname = wpa_cli_get_default_ifname();
4046
4047 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
4048 if (!warning_displayed) {
4049 printf("Could not connect to wpa_supplicant: "
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004050 "%s - re-trying\n",
4051 ctrl_ifname ? ctrl_ifname : "(nil)");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004052 warning_displayed = 1;
4053 }
4054 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4055 return;
4056 }
4057
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004058 update_bssid_list(ctrl_conn);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004059 update_networks(ctrl_conn);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004060
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004061 if (warning_displayed)
4062 printf("Connection established.\n");
4063
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004064done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004065 start_edit();
4066}
4067
4068
4069static void wpa_cli_interactive(void)
4070{
4071 printf("\nInteractive mode\n\n");
4072
4073 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004075 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004077 cli_txt_list_flush(&p2p_peers);
4078 cli_txt_list_flush(&p2p_groups);
4079 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004080 cli_txt_list_flush(&ifnames);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004081 cli_txt_list_flush(&networks);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004082 if (edit_started)
4083 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084 os_free(hfile);
4085 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4086 wpa_cli_close_connection();
4087}
4088
4089
4090static void wpa_cli_action(struct wpa_ctrl *ctrl)
4091{
4092#ifdef CONFIG_ANSI_C_EXTRA
4093 /* TODO: ANSI C version(?) */
4094 printf("Action processing not supported in ANSI C build.\n");
4095#else /* CONFIG_ANSI_C_EXTRA */
4096 fd_set rfds;
4097 int fd, res;
4098 struct timeval tv;
4099 char buf[256]; /* note: large enough to fit in unsolicited messages */
4100 size_t len;
4101
4102 fd = wpa_ctrl_get_fd(ctrl);
4103
4104 while (!wpa_cli_quit) {
4105 FD_ZERO(&rfds);
4106 FD_SET(fd, &rfds);
4107 tv.tv_sec = ping_interval;
4108 tv.tv_usec = 0;
4109 res = select(fd + 1, &rfds, NULL, NULL, &tv);
4110 if (res < 0 && errno != EINTR) {
4111 perror("select");
4112 break;
4113 }
4114
4115 if (FD_ISSET(fd, &rfds))
4116 wpa_cli_recv_pending(ctrl, 1);
4117 else {
4118 /* verify that connection is still working */
4119 len = sizeof(buf) - 1;
4120 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4121 wpa_cli_action_cb) < 0 ||
4122 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4123 printf("wpa_supplicant did not reply to PING "
4124 "command - exiting\n");
4125 break;
4126 }
4127 }
4128 }
4129#endif /* CONFIG_ANSI_C_EXTRA */
4130}
4131
4132
4133static void wpa_cli_cleanup(void)
4134{
4135 wpa_cli_close_connection();
4136 if (pid_file)
4137 os_daemonize_terminate(pid_file);
4138
4139 os_program_deinit();
4140}
4141
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004142
4143static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004145 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146}
4147
4148
4149static char * wpa_cli_get_default_ifname(void)
4150{
4151 char *ifname = NULL;
4152
4153#ifdef CONFIG_CTRL_IFACE_UNIX
4154 struct dirent *dent;
4155 DIR *dir = opendir(ctrl_iface_dir);
4156 if (!dir) {
4157#ifdef ANDROID
4158 char ifprop[PROPERTY_VALUE_MAX];
4159 if (property_get("wifi.interface", ifprop, NULL) != 0) {
4160 ifname = os_strdup(ifprop);
4161 printf("Using interface '%s'\n", ifname);
4162 return ifname;
4163 }
4164#endif /* ANDROID */
4165 return NULL;
4166 }
4167 while ((dent = readdir(dir))) {
4168#ifdef _DIRENT_HAVE_D_TYPE
4169 /*
4170 * Skip the file if it is not a socket. Also accept
4171 * DT_UNKNOWN (0) in case the C library or underlying
4172 * file system does not support d_type.
4173 */
4174 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4175 continue;
4176#endif /* _DIRENT_HAVE_D_TYPE */
4177 if (os_strcmp(dent->d_name, ".") == 0 ||
4178 os_strcmp(dent->d_name, "..") == 0)
4179 continue;
4180 printf("Selected interface '%s'\n", dent->d_name);
4181 ifname = os_strdup(dent->d_name);
4182 break;
4183 }
4184 closedir(dir);
4185#endif /* CONFIG_CTRL_IFACE_UNIX */
4186
4187#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004188 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189 size_t len;
4190 struct wpa_ctrl *ctrl;
4191 int ret;
4192
4193 ctrl = wpa_ctrl_open(NULL);
4194 if (ctrl == NULL)
4195 return NULL;
4196
4197 len = sizeof(buf) - 1;
4198 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4199 if (ret >= 0) {
4200 buf[len] = '\0';
4201 pos = os_strchr(buf, '\n');
4202 if (pos)
4203 *pos = '\0';
4204 ifname = os_strdup(buf);
4205 }
4206 wpa_ctrl_close(ctrl);
4207#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4208
4209 return ifname;
4210}
4211
4212
4213int main(int argc, char *argv[])
4214{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215 int c;
4216 int daemonize = 0;
4217 int ret = 0;
4218 const char *global = NULL;
4219
4220 if (os_program_init())
4221 return -1;
4222
4223 for (;;) {
4224 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
4225 if (c < 0)
4226 break;
4227 switch (c) {
4228 case 'a':
4229 action_file = optarg;
4230 break;
4231 case 'B':
4232 daemonize = 1;
4233 break;
4234 case 'g':
4235 global = optarg;
4236 break;
4237 case 'G':
4238 ping_interval = atoi(optarg);
4239 break;
4240 case 'h':
4241 usage();
4242 return 0;
4243 case 'v':
4244 printf("%s\n", wpa_cli_version);
4245 return 0;
4246 case 'i':
4247 os_free(ctrl_ifname);
4248 ctrl_ifname = os_strdup(optarg);
4249 break;
4250 case 'p':
4251 ctrl_iface_dir = optarg;
4252 break;
4253 case 'P':
4254 pid_file = optarg;
4255 break;
4256 default:
4257 usage();
4258 return -1;
4259 }
4260 }
4261
4262 interactive = (argc == optind) && (action_file == NULL);
4263
4264 if (interactive)
4265 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4266
4267 if (eloop_init())
4268 return -1;
4269
4270 if (global) {
4271#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4272 ctrl_conn = wpa_ctrl_open(NULL);
4273#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4274 ctrl_conn = wpa_ctrl_open(global);
4275#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4276 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004277 fprintf(stderr, "Failed to connect to wpa_supplicant "
4278 "global interface: %s error: %s\n",
4279 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004280 return -1;
4281 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004282
4283 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004284 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004285 mon_conn = wpa_ctrl_open(global);
4286 if (mon_conn) {
4287 if (wpa_ctrl_attach(mon_conn) == 0) {
4288 wpa_cli_attached = 1;
4289 eloop_register_read_sock(
4290 wpa_ctrl_get_fd(mon_conn),
4291 wpa_cli_mon_receive,
4292 NULL, NULL);
4293 } else {
4294 printf("Failed to open monitor "
4295 "connection through global "
4296 "control interface\n");
4297 }
4298 }
4299 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300 }
4301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004302 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303
4304 if (ctrl_ifname == NULL)
4305 ctrl_ifname = wpa_cli_get_default_ifname();
4306
4307 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004308 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004309 } else {
4310 if (!global &&
4311 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004312 fprintf(stderr, "Failed to connect to non-global "
4313 "ctrl_ifname: %s error: %s\n",
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004314 ctrl_ifname ? ctrl_ifname : "(nil)",
4315 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004316 return -1;
4317 }
4318
4319 if (action_file) {
4320 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4321 wpa_cli_attached = 1;
4322 } else {
4323 printf("Warning: Failed to attach to "
4324 "wpa_supplicant.\n");
4325 return -1;
4326 }
4327 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004328
4329 if (daemonize && os_daemonize(pid_file))
4330 return -1;
4331
4332 if (action_file)
4333 wpa_cli_action(ctrl_conn);
4334 else
4335 ret = wpa_request(ctrl_conn, argc - optind,
4336 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004337 }
4338
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339 os_free(ctrl_ifname);
4340 eloop_destroy();
4341 wpa_cli_cleanup();
4342
4343 return ret;
4344}
4345
4346#else /* CONFIG_CTRL_IFACE */
4347int main(int argc, char *argv[])
4348{
4349 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4350 return -1;
4351}
4352#endif /* CONFIG_CTRL_IFACE */