blob: 8811d6fd735d3ba12602df71a21d8bb709586239 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003 * Copyright (c) 2004-2013, 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 Shmidtfb79edc2014-01-10 10:45:54 -080031"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700537 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 return 0;
539}
540
541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
567 if (interactive)
568 eloop_terminate();
569 return 0;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700618 "p2p_no_go_freq",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700619 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700620 "p2p_go_vht",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700621 "p2p_ignore_shared_freq", "country", "bss_max_count",
622 "bss_expiration_age", "bss_expiration_scan_count",
623 "filter_ssids", "filter_rssi", "max_num_sta",
624 "disassoc_low_ack", "hs20", "interworking", "hessid",
625 "access_network_type", "pbc_in_m1", "autoscan",
626 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
627 "wps_nfc_dev_pw", "ext_password_backend",
628 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
629 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt97672262014-02-03 13:02:54 -0800630 "ignore_old_scan_res", "freq_list", "external_sim",
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700631 "tdls_external_control", "p2p_search_delay"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700632 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700633 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700634
635 if (arg == 1) {
636 char **res = os_calloc(num_fields + 1, sizeof(char *));
637 if (res == NULL)
638 return NULL;
639 for (i = 0; i < num_fields; i++) {
640 res[i] = os_strdup(fields[i]);
641 if (res[i] == NULL)
642 return res;
643 }
644 return res;
645 }
646
647 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
648 return cli_txt_list_array(&bsses);
649
650 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651}
652
653
654static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700656 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657}
658
659
660static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
661{
662 return wpa_ctrl_command(ctrl, "LOGOFF");
663}
664
665
666static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
668 return wpa_ctrl_command(ctrl, "LOGON");
669}
670
671
672static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "REASSOCIATE");
676}
677
678
Dmitry Shmidt98660862014-03-11 17:26:21 -0700679static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
680{
681 return wpa_ctrl_command(ctrl, "REATTACH");
682}
683
684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
686 char *argv[])
687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689}
690
691
692static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700694 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695}
696
697
698static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702}
703
704
705static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
706 char *argv[])
707{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700708 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709}
710
711
712static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
713 char *argv[])
714{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700715 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716}
717
718
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700719static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
720{
721 char cmd[256];
722 int res;
723
724 if (argc < 1)
725 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
726 else
727 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
728 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
729 printf("Too long BSS_FLUSH command.\n");
730 return -1;
731 }
732 return wpa_ctrl_command(ctrl, cmd);
733}
734
735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
737 char *argv[])
738{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700739 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740}
741
742
743static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700745 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746}
747
748
749static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700751 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752}
753
754
755static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 if (argc == 0) {
758 printf("Invalid WPS_PIN command: need one or two arguments:\n"
759 "- BSSID: use 'any' to select any\n"
760 "- PIN: optional, used only with devices that have no "
761 "display\n");
762 return -1;
763 }
764
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700765 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766}
767
768
769static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
771{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700772 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773}
774
775
776static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
777 char *argv[])
778{
779 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
780}
781
782
Dmitry Shmidt04949592012-07-19 12:16:46 -0700783#ifdef CONFIG_WPS_NFC
784
785static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
786{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700787 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700788}
789
790
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800791static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
792 char *argv[])
793{
794 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
795}
796
797
Dmitry Shmidt04949592012-07-19 12:16:46 -0700798static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
799 char *argv[])
800{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700801 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700802}
803
804
805static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
808 int ret;
809 char *buf;
810 size_t buflen;
811
812 if (argc != 1) {
813 printf("Invalid 'wps_nfc_tag_read' command - one argument "
814 "is required.\n");
815 return -1;
816 }
817
818 buflen = 18 + os_strlen(argv[0]);
819 buf = os_malloc(buflen);
820 if (buf == NULL)
821 return -1;
822 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
823
824 ret = wpa_ctrl_command(ctrl, buf);
825 os_free(buf);
826
827 return ret;
828}
829
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800830
831static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
832 char *argv[])
833{
834 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
835}
836
837
838static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
839 char *argv[])
840{
841 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
842}
843
844
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800845static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
849}
850
Dmitry Shmidt04949592012-07-19 12:16:46 -0700851#endif /* CONFIG_WPS_NFC */
852
853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
855{
856 char cmd[256];
857 int res;
858
859 if (argc == 2)
860 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
861 argv[0], argv[1]);
862 else if (argc == 5 || argc == 6) {
863 char ssid_hex[2 * 32 + 1];
864 char key_hex[2 * 64 + 1];
865 int i;
866
867 ssid_hex[0] = '\0';
868 for (i = 0; i < 32; i++) {
869 if (argv[2][i] == '\0')
870 break;
871 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
872 }
873
874 key_hex[0] = '\0';
875 if (argc == 6) {
876 for (i = 0; i < 64; i++) {
877 if (argv[5][i] == '\0')
878 break;
879 os_snprintf(&key_hex[i * 2], 3, "%02x",
880 argv[5][i]);
881 }
882 }
883
884 res = os_snprintf(cmd, sizeof(cmd),
885 "WPS_REG %s %s %s %s %s %s",
886 argv[0], argv[1], ssid_hex, argv[3], argv[4],
887 key_hex);
888 } else {
889 printf("Invalid WPS_REG command: need two arguments:\n"
890 "- BSSID of the target AP\n"
891 "- AP PIN\n");
892 printf("Alternatively, six arguments can be used to "
893 "reconfigure the AP:\n"
894 "- BSSID of the target AP\n"
895 "- AP PIN\n"
896 "- new SSID\n"
897 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
898 "- new encr (NONE, WEP, TKIP, CCMP)\n"
899 "- new key\n");
900 return -1;
901 }
902
903 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
904 printf("Too long WPS_REG command.\n");
905 return -1;
906 }
907 return wpa_ctrl_command(ctrl, cmd);
908}
909
910
911static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700914 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915}
916
917
918static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700921 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922}
923
924
925static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
927{
928 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
929
930}
931
932
933static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
934 char *argv[])
935{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936 if (argc < 2) {
937 printf("Invalid WPS_ER_PIN command: need at least two "
938 "arguments:\n"
939 "- UUID: use 'any' to select any\n"
940 "- PIN: Enrollee PIN\n"
941 "optional: - Enrollee MAC address\n");
942 return -1;
943 }
944
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700945 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946}
947
948
949static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
950 char *argv[])
951{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700952 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700953}
954
955
956static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
957 char *argv[])
958{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959 if (argc != 2) {
960 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
961 "- UUID: specify which AP to use\n"
962 "- PIN: AP PIN\n");
963 return -1;
964 }
965
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700966 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967}
968
969
970static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
971 char *argv[])
972{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973 if (argc != 2) {
974 printf("Invalid WPS_ER_SET_CONFIG command: need two "
975 "arguments:\n"
976 "- UUID: specify which AP to use\n"
977 "- Network configuration id\n");
978 return -1;
979 }
980
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700981 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982}
983
984
985static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
986 char *argv[])
987{
988 char cmd[256];
989 int res;
990
991 if (argc == 5 || argc == 6) {
992 char ssid_hex[2 * 32 + 1];
993 char key_hex[2 * 64 + 1];
994 int i;
995
996 ssid_hex[0] = '\0';
997 for (i = 0; i < 32; i++) {
998 if (argv[2][i] == '\0')
999 break;
1000 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1001 }
1002
1003 key_hex[0] = '\0';
1004 if (argc == 6) {
1005 for (i = 0; i < 64; i++) {
1006 if (argv[5][i] == '\0')
1007 break;
1008 os_snprintf(&key_hex[i * 2], 3, "%02x",
1009 argv[5][i]);
1010 }
1011 }
1012
1013 res = os_snprintf(cmd, sizeof(cmd),
1014 "WPS_ER_CONFIG %s %s %s %s %s %s",
1015 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1016 key_hex);
1017 } else {
1018 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1019 "- AP UUID\n"
1020 "- AP PIN\n"
1021 "- new SSID\n"
1022 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1023 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1024 "- new key\n");
1025 return -1;
1026 }
1027
1028 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029 printf("Too long WPS_ER_CONFIG command.\n");
1030 return -1;
1031 }
1032 return wpa_ctrl_command(ctrl, cmd);
1033}
1034
1035
Dmitry Shmidt04949592012-07-19 12:16:46 -07001036#ifdef CONFIG_WPS_NFC
1037static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1038 char *argv[])
1039{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001040 if (argc != 2) {
1041 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1042 "arguments:\n"
1043 "- WPS/NDEF: token format\n"
1044 "- UUID: specify which AP to use\n");
1045 return -1;
1046 }
1047
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001048 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049}
1050#endif /* CONFIG_WPS_NFC */
1051
1052
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1054{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001055 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056}
1057
1058
1059static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001061 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062}
1063
1064
1065static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1066{
1067 char cmd[256], *pos, *end;
1068 int i, ret;
1069
1070 if (argc < 2) {
1071 printf("Invalid IDENTITY command: needs two arguments "
1072 "(network id and identity)\n");
1073 return -1;
1074 }
1075
1076 end = cmd + sizeof(cmd);
1077 pos = cmd;
1078 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1079 argv[0], argv[1]);
1080 if (ret < 0 || ret >= end - pos) {
1081 printf("Too long IDENTITY command.\n");
1082 return -1;
1083 }
1084 pos += ret;
1085 for (i = 2; i < argc; i++) {
1086 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1087 if (ret < 0 || ret >= end - pos) {
1088 printf("Too long IDENTITY command.\n");
1089 return -1;
1090 }
1091 pos += ret;
1092 }
1093
1094 return wpa_ctrl_command(ctrl, cmd);
1095}
1096
1097
1098static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099{
1100 char cmd[256], *pos, *end;
1101 int i, ret;
1102
1103 if (argc < 2) {
1104 printf("Invalid PASSWORD command: needs two arguments "
1105 "(network id and password)\n");
1106 return -1;
1107 }
1108
1109 end = cmd + sizeof(cmd);
1110 pos = cmd;
1111 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1112 argv[0], argv[1]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long PASSWORD command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 for (i = 2; i < argc; i++) {
1119 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1120 if (ret < 0 || ret >= end - pos) {
1121 printf("Too long PASSWORD command.\n");
1122 return -1;
1123 }
1124 pos += ret;
1125 }
1126
1127 return wpa_ctrl_command(ctrl, cmd);
1128}
1129
1130
1131static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1132 char *argv[])
1133{
1134 char cmd[256], *pos, *end;
1135 int i, ret;
1136
1137 if (argc < 2) {
1138 printf("Invalid NEW_PASSWORD command: needs two arguments "
1139 "(network id and password)\n");
1140 return -1;
1141 }
1142
1143 end = cmd + sizeof(cmd);
1144 pos = cmd;
1145 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1146 argv[0], argv[1]);
1147 if (ret < 0 || ret >= end - pos) {
1148 printf("Too long NEW_PASSWORD command.\n");
1149 return -1;
1150 }
1151 pos += ret;
1152 for (i = 2; i < argc; i++) {
1153 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long NEW_PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 }
1160
1161 return wpa_ctrl_command(ctrl, cmd);
1162}
1163
1164
1165static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1166{
1167 char cmd[256], *pos, *end;
1168 int i, ret;
1169
1170 if (argc < 2) {
1171 printf("Invalid PIN command: needs two arguments "
1172 "(network id and pin)\n");
1173 return -1;
1174 }
1175
1176 end = cmd + sizeof(cmd);
1177 pos = cmd;
1178 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1179 argv[0], argv[1]);
1180 if (ret < 0 || ret >= end - pos) {
1181 printf("Too long PIN command.\n");
1182 return -1;
1183 }
1184 pos += ret;
1185 for (i = 2; i < argc; i++) {
1186 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1187 if (ret < 0 || ret >= end - pos) {
1188 printf("Too long PIN command.\n");
1189 return -1;
1190 }
1191 pos += ret;
1192 }
1193 return wpa_ctrl_command(ctrl, cmd);
1194}
1195
1196
1197static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1198{
1199 char cmd[256], *pos, *end;
1200 int i, ret;
1201
1202 if (argc < 2) {
1203 printf("Invalid OTP command: needs two arguments (network "
1204 "id and password)\n");
1205 return -1;
1206 }
1207
1208 end = cmd + sizeof(cmd);
1209 pos = cmd;
1210 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1211 argv[0], argv[1]);
1212 if (ret < 0 || ret >= end - pos) {
1213 printf("Too long OTP command.\n");
1214 return -1;
1215 }
1216 pos += ret;
1217 for (i = 2; i < argc; i++) {
1218 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1219 if (ret < 0 || ret >= end - pos) {
1220 printf("Too long OTP command.\n");
1221 return -1;
1222 }
1223 pos += ret;
1224 }
1225
1226 return wpa_ctrl_command(ctrl, cmd);
1227}
1228
1229
Dmitry Shmidt051af732013-10-22 13:52:46 -07001230static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1231{
1232 char cmd[256], *pos, *end;
1233 int i, ret;
1234
1235 if (argc < 2) {
1236 printf("Invalid SIM command: needs two arguments "
1237 "(network id and SIM operation response)\n");
1238 return -1;
1239 }
1240
1241 end = cmd + sizeof(cmd);
1242 pos = cmd;
1243 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1244 argv[0], argv[1]);
1245 if (ret < 0 || ret >= end - pos) {
1246 printf("Too long SIM command.\n");
1247 return -1;
1248 }
1249 pos += ret;
1250 for (i = 2; i < argc; i++) {
1251 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1252 if (ret < 0 || ret >= end - pos) {
1253 printf("Too long SIM command.\n");
1254 return -1;
1255 }
1256 pos += ret;
1257 }
1258 return wpa_ctrl_command(ctrl, cmd);
1259}
1260
1261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1263 char *argv[])
1264{
1265 char cmd[256], *pos, *end;
1266 int i, ret;
1267
1268 if (argc < 2) {
1269 printf("Invalid PASSPHRASE command: needs two arguments "
1270 "(network id and passphrase)\n");
1271 return -1;
1272 }
1273
1274 end = cmd + sizeof(cmd);
1275 pos = cmd;
1276 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1277 argv[0], argv[1]);
1278 if (ret < 0 || ret >= end - pos) {
1279 printf("Too long PASSPHRASE command.\n");
1280 return -1;
1281 }
1282 pos += ret;
1283 for (i = 2; i < argc; i++) {
1284 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1285 if (ret < 0 || ret >= end - pos) {
1286 printf("Too long PASSPHRASE command.\n");
1287 return -1;
1288 }
1289 pos += ret;
1290 }
1291
1292 return wpa_ctrl_command(ctrl, cmd);
1293}
1294
1295
1296static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 if (argc < 2) {
1299 printf("Invalid BSSID command: needs two arguments (network "
1300 "id and BSSID)\n");
1301 return -1;
1302 }
1303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305}
1306
1307
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001308static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1309{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001310 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001311}
1312
1313
1314static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1315{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001316 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001317}
1318
1319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1321 char *argv[])
1322{
1323 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1324}
1325
1326
1327static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001330 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331}
1332
1333
1334static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1335 char *argv[])
1336{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001337 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338}
1339
1340
1341static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1342 char *argv[])
1343{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001344 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345}
1346
1347
1348static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1349 char *argv[])
1350{
1351 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1352}
1353
1354
1355static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1356 char *argv[])
1357{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001358 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001359}
1360
1361
1362static void wpa_cli_show_network_variables(void)
1363{
1364 printf("set_network variables:\n"
1365 " ssid (network name, SSID)\n"
1366 " psk (WPA passphrase or pre-shared key)\n"
1367 " key_mgmt (key management protocol)\n"
1368 " identity (EAP identity)\n"
1369 " password (EAP password)\n"
1370 " ...\n"
1371 "\n"
1372 "Note: Values are entered in the same format as the "
1373 "configuration file is using,\n"
1374 "i.e., strings values need to be inside double quotation "
1375 "marks.\n"
1376 "For example: set_network 1 ssid \"network name\"\n"
1377 "\n"
1378 "Please see wpa_supplicant.conf documentation for full list "
1379 "of\navailable variables.\n");
1380}
1381
1382
1383static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1384 char *argv[])
1385{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 if (argc == 0) {
1387 wpa_cli_show_network_variables();
1388 return 0;
1389 }
1390
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001391 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 printf("Invalid SET_NETWORK command: needs three arguments\n"
1393 "(network id, variable name, and value)\n");
1394 return -1;
1395 }
1396
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001397 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398}
1399
1400
1401static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1402 char *argv[])
1403{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404 if (argc == 0) {
1405 wpa_cli_show_network_variables();
1406 return 0;
1407 }
1408
1409 if (argc != 2) {
1410 printf("Invalid GET_NETWORK command: needs two arguments\n"
1411 "(network id and variable name)\n");
1412 return -1;
1413 }
1414
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001415 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416}
1417
1418
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001419static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1420 char *argv[])
1421{
1422 if (argc == 0) {
1423 wpa_cli_show_network_variables();
1424 return 0;
1425 }
1426
1427 if (argc < 3) {
1428 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1429 "(src netid, dest netid, and variable name)\n");
1430 return -1;
1431 }
1432
1433 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1434}
1435
1436
Dmitry Shmidt04949592012-07-19 12:16:46 -07001437static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1438 char *argv[])
1439{
1440 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1441}
1442
1443
1444static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1445{
1446 return wpa_ctrl_command(ctrl, "ADD_CRED");
1447}
1448
1449
1450static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1451 char *argv[])
1452{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001453 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001454}
1455
1456
1457static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001459 if (argc != 3) {
1460 printf("Invalid SET_CRED command: needs three arguments\n"
1461 "(cred id, variable name, and value)\n");
1462 return -1;
1463 }
1464
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001465 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001466}
1467
1468
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001469static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1470{
1471 if (argc != 2) {
1472 printf("Invalid GET_CRED command: needs two arguments\n"
1473 "(cred id, variable name)\n");
1474 return -1;
1475 }
1476
1477 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1478}
1479
1480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001481static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1482 char *argv[])
1483{
1484 return wpa_ctrl_command(ctrl, "DISCONNECT");
1485}
1486
1487
1488static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1489 char *argv[])
1490{
1491 return wpa_ctrl_command(ctrl, "RECONNECT");
1492}
1493
1494
1495static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1496 char *argv[])
1497{
1498 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1499}
1500
1501
1502static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1503{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001504 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505}
1506
1507
1508static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1509 char *argv[])
1510{
1511 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1512}
1513
1514
1515static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001517 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001518}
1519
1520
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001521static char ** wpa_cli_complete_bss(const char *str, int pos)
1522{
1523 int arg = get_cmd_arg_num(str, pos);
1524 char **res = NULL;
1525
1526 switch (arg) {
1527 case 1:
1528 res = cli_txt_list_array(&bsses);
1529 break;
1530 }
1531
1532 return res;
1533}
1534
1535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1537 char *argv[])
1538{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539 if (argc < 1 || argc > 2) {
1540 printf("Invalid GET_CAPABILITY command: need either one or "
1541 "two arguments\n");
1542 return -1;
1543 }
1544
1545 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1546 printf("Invalid GET_CAPABILITY command: second argument, "
1547 "if any, must be 'strict'\n");
1548 return -1;
1549 }
1550
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001551 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552}
1553
1554
1555static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1556{
1557 printf("Available interfaces:\n");
1558 return wpa_ctrl_command(ctrl, "INTERFACES");
1559}
1560
1561
1562static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1563{
1564 if (argc < 1) {
1565 wpa_cli_list_interfaces(ctrl);
1566 return 0;
1567 }
1568
1569 wpa_cli_close_connection();
1570 os_free(ctrl_ifname);
1571 ctrl_ifname = os_strdup(argv[0]);
1572
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001573 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574 printf("Connected to interface '%s.\n", ctrl_ifname);
1575 } else {
1576 printf("Could not connect to interface '%s' - re-trying\n",
1577 ctrl_ifname);
1578 }
1579 return 0;
1580}
1581
1582
1583static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1584 char *argv[])
1585{
1586 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1587}
1588
1589
1590static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1591 char *argv[])
1592{
1593 return wpa_ctrl_command(ctrl, "TERMINATE");
1594}
1595
1596
1597static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1598 char *argv[])
1599{
1600 char cmd[256];
1601 int res;
1602
1603 if (argc < 1) {
1604 printf("Invalid INTERFACE_ADD command: needs at least one "
1605 "argument (interface name)\n"
1606 "All arguments: ifname confname driver ctrl_interface "
1607 "driver_param bridge_name\n");
1608 return -1;
1609 }
1610
1611 /*
1612 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1613 * <driver_param>TAB<bridge_name>
1614 */
1615 res = os_snprintf(cmd, sizeof(cmd),
1616 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1617 argv[0],
1618 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1619 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1620 argc > 5 ? argv[5] : "");
1621 if (res < 0 || (size_t) res >= sizeof(cmd))
1622 return -1;
1623 cmd[sizeof(cmd) - 1] = '\0';
1624 return wpa_ctrl_command(ctrl, cmd);
1625}
1626
1627
1628static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1629 char *argv[])
1630{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001631 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001632}
1633
1634
1635static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1636 char *argv[])
1637{
1638 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1639}
1640
1641
1642#ifdef CONFIG_AP
1643static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1644{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001645 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001646}
1647
1648
1649static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1650 char *addr, size_t addr_len)
1651{
1652 char buf[4096], *pos;
1653 size_t len;
1654 int ret;
1655
1656 if (ctrl_conn == NULL) {
1657 printf("Not connected to hostapd - command dropped.\n");
1658 return -1;
1659 }
1660 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001661 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 wpa_cli_msg_cb);
1663 if (ret == -2) {
1664 printf("'%s' command timed out.\n", cmd);
1665 return -2;
1666 } else if (ret < 0) {
1667 printf("'%s' command failed.\n", cmd);
1668 return -1;
1669 }
1670
1671 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001672 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001673 return -1;
1674 printf("%s", buf);
1675
1676 pos = buf;
1677 while (*pos != '\0' && *pos != '\n')
1678 pos++;
1679 *pos = '\0';
1680 os_strlcpy(addr, buf, addr_len);
1681 return 0;
1682}
1683
1684
1685static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1686{
1687 char addr[32], cmd[64];
1688
1689 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1690 return 0;
1691 do {
1692 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1693 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1694
1695 return -1;
1696}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001697
1698
1699static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1700 char *argv[])
1701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001702 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001703}
1704
1705
1706static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1707 char *argv[])
1708{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001709 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001710}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001711
1712static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1713 char *argv[])
1714{
1715 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1716}
1717
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718#endif /* CONFIG_AP */
1719
1720
1721static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722{
1723 return wpa_ctrl_command(ctrl, "SUSPEND");
1724}
1725
1726
1727static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728{
1729 return wpa_ctrl_command(ctrl, "RESUME");
1730}
1731
1732
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001733#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1735{
1736 return wpa_ctrl_command(ctrl, "DROP_SA");
1737}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001738#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739
1740
1741static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001743 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744}
1745
1746
1747#ifdef CONFIG_P2P
1748
1749static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1750{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001751 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1752}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001754
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001755static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1756{
1757 char **res = NULL;
1758 int arg = get_cmd_arg_num(str, pos);
1759
1760 res = os_calloc(6, sizeof(char *));
1761 if (res == NULL)
1762 return NULL;
1763 res[0] = os_strdup("type=social");
1764 if (res[0] == NULL) {
1765 os_free(res);
1766 return NULL;
1767 }
1768 res[1] = os_strdup("type=progressive");
1769 if (res[1] == NULL)
1770 return res;
1771 res[2] = os_strdup("delay=");
1772 if (res[2] == NULL)
1773 return res;
1774 res[3] = os_strdup("dev_id=");
1775 if (res[3] == NULL)
1776 return res;
1777 if (arg == 1)
1778 res[4] = os_strdup("[timeout]");
1779
1780 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781}
1782
1783
1784static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1785 char *argv[])
1786{
1787 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1788}
1789
1790
1791static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1792 char *argv[])
1793{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001794 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795}
1796
1797
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001798static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1799{
1800 int arg = get_cmd_arg_num(str, pos);
1801 char **res = NULL;
1802
1803 switch (arg) {
1804 case 1:
1805 res = cli_txt_list_array(&p2p_peers);
1806 break;
1807 }
1808
1809 return res;
1810}
1811
1812
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001813static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1814 char *argv[])
1815{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001816 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001817}
1818
1819
1820static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1821 char *argv[])
1822{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001823 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824}
1825
1826
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001827static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1828{
1829 int arg = get_cmd_arg_num(str, pos);
1830 char **res = NULL;
1831
1832 switch (arg) {
1833 case 1:
1834 res = cli_txt_list_array(&p2p_groups);
1835 break;
1836 }
1837
1838 return res;
1839}
1840
1841
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1843 char *argv[])
1844{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001845 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846}
1847
1848
1849static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1850 char *argv[])
1851{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001852 if (argc != 2 && argc != 3) {
1853 printf("Invalid P2P_PROV_DISC command: needs at least "
1854 "two arguments, address and config method\n"
1855 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 return -1;
1857 }
1858
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001859 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860}
1861
1862
1863static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1864 char *argv[])
1865{
1866 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1867}
1868
1869
1870static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1871 char *argv[])
1872{
1873 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001874
1875 if (argc != 2 && argc != 4) {
1876 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1877 "arguments (address and TLVs) or four arguments "
1878 "(address, \"upnp\", version, search target "
1879 "(SSDP ST:)\n");
1880 return -1;
1881 }
1882
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001883 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 return wpa_ctrl_command(ctrl, cmd);
1886}
1887
1888
1889static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1890 int argc, char *argv[])
1891{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001892 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893}
1894
1895
1896static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1897 char *argv[])
1898{
1899 char cmd[4096];
1900 int res;
1901
1902 if (argc != 4) {
1903 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1904 "arguments (freq, address, dialog token, and TLVs)\n");
1905 return -1;
1906 }
1907
1908 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1909 argv[0], argv[1], argv[2], argv[3]);
1910 if (res < 0 || (size_t) res >= sizeof(cmd))
1911 return -1;
1912 cmd[sizeof(cmd) - 1] = '\0';
1913 return wpa_ctrl_command(ctrl, cmd);
1914}
1915
1916
1917static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1918 char *argv[])
1919{
1920 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1921}
1922
1923
1924static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1925 int argc, char *argv[])
1926{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001927 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928}
1929
1930
1931static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1932 char *argv[])
1933{
1934 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1935}
1936
1937
1938static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1939 char *argv[])
1940{
1941 char cmd[4096];
1942 int res;
1943
1944 if (argc != 3 && argc != 4) {
1945 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1946 "arguments\n");
1947 return -1;
1948 }
1949
1950 if (argc == 4)
1951 res = os_snprintf(cmd, sizeof(cmd),
1952 "P2P_SERVICE_ADD %s %s %s %s",
1953 argv[0], argv[1], argv[2], argv[3]);
1954 else
1955 res = os_snprintf(cmd, sizeof(cmd),
1956 "P2P_SERVICE_ADD %s %s %s",
1957 argv[0], argv[1], argv[2]);
1958 if (res < 0 || (size_t) res >= sizeof(cmd))
1959 return -1;
1960 cmd[sizeof(cmd) - 1] = '\0';
1961 return wpa_ctrl_command(ctrl, cmd);
1962}
1963
1964
1965static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1966 char *argv[])
1967{
1968 char cmd[4096];
1969 int res;
1970
1971 if (argc != 2 && argc != 3) {
1972 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1973 "arguments\n");
1974 return -1;
1975 }
1976
1977 if (argc == 3)
1978 res = os_snprintf(cmd, sizeof(cmd),
1979 "P2P_SERVICE_DEL %s %s %s",
1980 argv[0], argv[1], argv[2]);
1981 else
1982 res = os_snprintf(cmd, sizeof(cmd),
1983 "P2P_SERVICE_DEL %s %s",
1984 argv[0], argv[1]);
1985 if (res < 0 || (size_t) res >= sizeof(cmd))
1986 return -1;
1987 cmd[sizeof(cmd) - 1] = '\0';
1988 return wpa_ctrl_command(ctrl, cmd);
1989}
1990
1991
1992static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1993 int argc, char *argv[])
1994{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001995 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996}
1997
1998
1999static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2000 int argc, char *argv[])
2001{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002002 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002003}
2004
2005
2006static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2007{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002008 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009}
2010
2011
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002012static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2013{
2014 int arg = get_cmd_arg_num(str, pos);
2015 char **res = NULL;
2016
2017 switch (arg) {
2018 case 1:
2019 res = cli_txt_list_array(&p2p_peers);
2020 break;
2021 }
2022
2023 return res;
2024}
2025
2026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2028 char *addr, size_t addr_len,
2029 int discovered)
2030{
2031 char buf[4096], *pos;
2032 size_t len;
2033 int ret;
2034
2035 if (ctrl_conn == NULL)
2036 return -1;
2037 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002038 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039 wpa_cli_msg_cb);
2040 if (ret == -2) {
2041 printf("'%s' command timed out.\n", cmd);
2042 return -2;
2043 } else if (ret < 0) {
2044 printf("'%s' command failed.\n", cmd);
2045 return -1;
2046 }
2047
2048 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002049 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 return -1;
2051
2052 pos = buf;
2053 while (*pos != '\0' && *pos != '\n')
2054 pos++;
2055 *pos++ = '\0';
2056 os_strlcpy(addr, buf, addr_len);
2057 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2058 printf("%s\n", addr);
2059 return 0;
2060}
2061
2062
2063static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2064{
2065 char addr[32], cmd[64];
2066 int discovered;
2067
2068 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2069
2070 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2071 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002072 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073 do {
2074 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2075 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2076 discovered) == 0);
2077
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002078 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079}
2080
2081
2082static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2083{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002084 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085}
2086
2087
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002088static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2089{
2090 int arg = get_cmd_arg_num(str, pos);
2091 const char *fields[] = {
2092 "discoverability",
2093 "managed",
2094 "listen_channel",
2095 "ssid_postfix",
2096 "noa",
2097 "ps",
2098 "oppps",
2099 "ctwindow",
2100 "disabled",
2101 "conc_pref",
2102 "force_long_sd",
2103 "peer_filter",
2104 "cross_connect",
2105 "go_apsd",
2106 "client_apsd",
2107 "disallow_freq",
2108 "disc_int",
2109 "per_sta_psk",
2110 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002111 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002112
2113 if (arg == 1) {
2114 char **res = os_calloc(num_fields + 1, sizeof(char *));
2115 if (res == NULL)
2116 return NULL;
2117 for (i = 0; i < num_fields; i++) {
2118 res[i] = os_strdup(fields[i]);
2119 if (res[i] == NULL)
2120 return res;
2121 }
2122 return res;
2123 }
2124
2125 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2126 return cli_txt_list_array(&p2p_peers);
2127
2128 return NULL;
2129}
2130
2131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2133{
2134 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2135}
2136
2137
2138static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2139 char *argv[])
2140{
2141 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2142}
2143
2144
2145static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2146 char *argv[])
2147{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002148 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149}
2150
2151
2152static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2153 char *argv[])
2154{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155 if (argc != 0 && argc != 2 && argc != 4) {
2156 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2157 "(preferred duration, interval; in microsecods).\n"
2158 "Optional second pair can be used to provide "
2159 "acceptable values.\n");
2160 return -1;
2161 }
2162
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002163 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002164}
2165
2166
2167static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2168 char *argv[])
2169{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170 if (argc != 0 && argc != 2) {
2171 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2172 "(availability period, availability interval; in "
2173 "millisecods).\n"
2174 "Extended Listen Timing can be cancelled with this "
2175 "command when used without parameters.\n");
2176 return -1;
2177 }
2178
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002179 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2180}
2181
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002182
2183static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2184 char *argv[])
2185{
2186 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2187}
2188
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002189#endif /* CONFIG_P2P */
2190
2191#ifdef CONFIG_WIFI_DISPLAY
2192
2193static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195{
2196 char cmd[100];
2197 int res;
2198
2199 if (argc != 1 && argc != 2) {
2200 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2201 "arguments (subelem, hexdump)\n");
2202 return -1;
2203 }
2204
2205 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2206 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 if (res < 0 || (size_t) res >= sizeof(cmd))
2208 return -1;
2209 cmd[sizeof(cmd) - 1] = '\0';
2210 return wpa_ctrl_command(ctrl, cmd);
2211}
2212
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002213
2214static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
2217 char cmd[100];
2218 int res;
2219
2220 if (argc != 1) {
2221 printf("Invalid WFD_SUBELEM_GET command: needs one "
2222 "argument (subelem)\n");
2223 return -1;
2224 }
2225
2226 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2227 argv[0]);
2228 if (res < 0 || (size_t) res >= sizeof(cmd))
2229 return -1;
2230 cmd[sizeof(cmd) - 1] = '\0';
2231 return wpa_ctrl_command(ctrl, cmd);
2232}
2233#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234
2235
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002236#ifdef CONFIG_INTERWORKING
2237static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2238 char *argv[])
2239{
2240 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2241}
2242
2243
2244static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2245 char *argv[])
2246{
2247 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2248}
2249
2250
2251static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2252 char *argv[])
2253{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002254 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002255}
2256
2257
2258static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002261 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002262}
2263
2264
2265static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2266{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002267 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2268}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002269
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002270
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002271static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2272 char *argv[])
2273{
2274 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2275}
2276
2277
2278static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280{
2281 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002282}
2283#endif /* CONFIG_INTERWORKING */
2284
2285
Dmitry Shmidt04949592012-07-19 12:16:46 -07002286#ifdef CONFIG_HS20
2287
2288static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2289 char *argv[])
2290{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002291 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002292}
2293
2294
2295static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2296 char *argv[])
2297{
2298 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002299
2300 if (argc == 0) {
2301 printf("Command needs one or two arguments (dst mac addr and "
2302 "optional home realm)\n");
2303 return -1;
2304 }
2305
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002306 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2307 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002308 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002309
2310 return wpa_ctrl_command(ctrl, cmd);
2311}
2312
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002313
2314static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2315 char *argv[])
2316{
2317 char cmd[512];
2318
2319 if (argc < 2) {
2320 printf("Command needs two arguments (dst mac addr and "
2321 "icon name)\n");
2322 return -1;
2323 }
2324
2325 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2326 return -1;
2327
2328 return wpa_ctrl_command(ctrl, cmd);
2329}
2330
2331
2332static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2333{
2334 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2335}
2336
2337
2338static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2339 char *argv[])
2340{
2341 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2342}
2343
Dmitry Shmidt04949592012-07-19 12:16:46 -07002344#endif /* CONFIG_HS20 */
2345
2346
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2348 char *argv[])
2349{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351}
2352
2353
2354static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2355 char *argv[])
2356{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358}
2359
2360
2361static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2362 char *argv[])
2363{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365}
2366
2367
2368static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2369 char *argv[])
2370{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372}
2373
2374
2375static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2376 char *argv[])
2377{
2378 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2379}
2380
2381
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002382static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2383 char *argv[])
2384{
2385 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2386}
2387
2388
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002389static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2390 char *argv[])
2391{
2392 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2393}
2394
Dmitry Shmidt04949592012-07-19 12:16:46 -07002395
2396#ifdef CONFIG_AUTOSCAN
2397
2398static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2399{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002400 if (argc == 0)
2401 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2402
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002404}
2405
2406#endif /* CONFIG_AUTOSCAN */
2407
2408
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002409#ifdef CONFIG_WNM
2410
2411static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2412{
2413 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2414}
2415
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002416
2417static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2418{
2419 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2420}
2421
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002422#endif /* CONFIG_WNM */
2423
2424
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2426{
2427 if (argc == 0)
2428 return -1;
2429 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2430}
2431
2432
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002433#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002434static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2435{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002436 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002437}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002438#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002439
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002440
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002441static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2442{
2443 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2444}
2445
2446
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002447static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2448{
2449 return wpa_ctrl_command(ctrl, "FLUSH");
2450}
2451
2452
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002453static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2454{
2455 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2456}
2457
2458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002459enum wpa_cli_cmd_flags {
2460 cli_cmd_flag_none = 0x00,
2461 cli_cmd_flag_sensitive = 0x01
2462};
2463
2464struct wpa_cli_cmd {
2465 const char *cmd;
2466 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 enum wpa_cli_cmd_flags flags;
2469 const char *usage;
2470};
2471
2472static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 { "ifname", wpa_cli_cmd_ifname, NULL,
2477 cli_cmd_flag_none,
2478 "= get current interface name" },
2479 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_none,
2484 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002493 "[command] = show usage help" },
2494 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
2499 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002506 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "= set variables (shows list of variables when run without "
2509 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_none,
2521 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_none,
2524 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002525 { "reattach", wpa_cli_cmd_reattach, NULL,
2526 cli_cmd_flag_none,
2527 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 cli_cmd_flag_none,
2533 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535 cli_cmd_flag_sensitive,
2536 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 cli_cmd_flag_sensitive,
2539 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 cli_cmd_flag_sensitive,
2542 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_sensitive,
2545 "<network id> <password> = configure one-time-password for an SSID"
2546 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_sensitive,
2549 "<network id> <passphrase> = configure private key passphrase\n"
2550 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002551 { "sim", wpa_cli_cmd_sim, NULL,
2552 cli_cmd_flag_sensitive,
2553 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_none,
2556 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002558 cli_cmd_flag_none,
2559 "<BSSID> = add a BSSID to the blacklist\n"
2560 "blacklist clear = clear the blacklist\n"
2561 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002563 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002564 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002565 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 cli_cmd_flag_none,
2568 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 cli_cmd_flag_none,
2571 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 cli_cmd_flag_none,
2574 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_none,
2577 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_none,
2580 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 cli_cmd_flag_none,
2583 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 cli_cmd_flag_sensitive,
2586 "<network id> <variable> <value> = set network variables (shows\n"
2587 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_none,
2590 "<network id> <variable> = get network variables" },
Dmitry Shmidt684785c2014-05-12 13:34:29 -07002591 { "dup_network", wpa_cli_cmd_dup_network, NULL,
2592 cli_cmd_flag_none,
2593 "<src network id> <dst network id> <variable> = duplicate network variables"
2594 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002596 cli_cmd_flag_none,
2597 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002599 cli_cmd_flag_none,
2600 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002601 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002602 cli_cmd_flag_none,
2603 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002605 cli_cmd_flag_sensitive,
2606 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002607 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2608 cli_cmd_flag_none,
2609 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 cli_cmd_flag_none,
2612 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 cli_cmd_flag_none,
2615 "= disconnect and wait for reassociate/reconnect command before\n"
2616 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 cli_cmd_flag_none,
2619 "= like reassociate, but only takes effect if already disconnected"
2620 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 cli_cmd_flag_none,
2623 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002624 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 cli_cmd_flag_none,
2626 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002632 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 "= get capabilies" },
2634 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 cli_cmd_flag_none,
2636 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_none,
2639 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 cli_cmd_flag_none,
2642 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2643 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2644 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 cli_cmd_flag_none,
2647 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002648 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 cli_cmd_flag_none,
2650 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 cli_cmd_flag_none,
2653 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 cli_cmd_flag_none,
2656 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_none,
2659 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_none,
2662 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002664 cli_cmd_flag_none,
2665 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 cli_cmd_flag_none,
2668 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002669 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 cli_cmd_flag_none,
2671 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 cli_cmd_flag_none,
2674 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002675 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 cli_cmd_flag_sensitive,
2677 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2678 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002679 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 cli_cmd_flag_sensitive,
2681 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002684#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002686 cli_cmd_flag_none,
2687 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002688 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2689 cli_cmd_flag_none,
2690 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002692 cli_cmd_flag_none,
2693 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002695 cli_cmd_flag_sensitive,
2696 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002697 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2698 cli_cmd_flag_none,
2699 "<NDEF> <WPS> = create NFC handover request" },
2700 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2701 cli_cmd_flag_none,
2702 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002703 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2704 cli_cmd_flag_none,
2705 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2706 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002707#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 cli_cmd_flag_sensitive,
2710 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 cli_cmd_flag_sensitive,
2713 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002715 cli_cmd_flag_none,
2716 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 cli_cmd_flag_none,
2719 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 cli_cmd_flag_sensitive,
2722 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 cli_cmd_flag_none,
2725 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727 cli_cmd_flag_sensitive,
2728 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002729 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730 cli_cmd_flag_none,
2731 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 cli_cmd_flag_sensitive,
2734 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002735#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002737 cli_cmd_flag_none,
2738 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2739#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002741 cli_cmd_flag_none,
2742 "<addr> = request RSN authentication with <addr> in IBSS" },
2743#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 cli_cmd_flag_none,
2746 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 cli_cmd_flag_none,
2749 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002751 cli_cmd_flag_none,
2752 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002754 cli_cmd_flag_none,
2755 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002756 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2757 cli_cmd_flag_none,
2758 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2759 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2760 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002764 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002766#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002769#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 cli_cmd_flag_none,
2772 "<addr> = roam to the specified BSS" },
2773#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2775 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2780 cli_cmd_flag_none,
2781 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2782 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002784 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2785 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2788 "[ht40] = add a new P2P group (local end as GO)" },
2789 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2790 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 cli_cmd_flag_none,
2794 "= get the passphrase for a group (GO only)" },
2795 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002796 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 "<addr> <TLVs> = schedule service discovery request" },
2798 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 cli_cmd_flag_none,
2803 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805 cli_cmd_flag_none,
2806 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808 cli_cmd_flag_none,
2809 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002810 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 cli_cmd_flag_none,
2812 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002813 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 cli_cmd_flag_none,
2815 "<bonjour|upnp> <query|version> <response|service> = add a local "
2816 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002817 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 cli_cmd_flag_none,
2819 "<bonjour|upnp> <query|version> [|service] = remove a local "
2820 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002821 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002822 cli_cmd_flag_none,
2823 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002824 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002825 cli_cmd_flag_none,
2826 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 "[discovered] = list known (optionally, only fully discovered) P2P "
2829 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002830 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2831 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002833 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2834 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002836 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002837 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002838 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2841 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2844 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845 "[<duration> <interval>] [<duration> <interval>] = request GO "
2846 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002847 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2848 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002850 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2851 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2852 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002853#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002854#ifdef CONFIG_WIFI_DISPLAY
2855 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2856 cli_cmd_flag_none,
2857 "<subelem> [contents] = set Wi-Fi Display subelement" },
2858 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2859 cli_cmd_flag_none,
2860 "<subelem> = get Wi-Fi Display subelement" },
2861#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002862#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002863 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002864 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002865 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2866 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002867 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002868 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002869 cli_cmd_flag_none,
2870 "[auto] = perform Interworking network selection" },
2871 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002872 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002873 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002874 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2875 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002876 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002877 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2878 cli_cmd_flag_none,
2879 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2880 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2881 wpa_cli_complete_bss, cli_cmd_flag_none,
2882 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002883#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002884#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002885 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2886 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002887 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2888 },
2889 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002890 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002891 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002892 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2893 wpa_cli_complete_bss, cli_cmd_flag_none,
2894 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2895 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2896 "= fetch OSU provider information from all APs" },
2897 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2898 cli_cmd_flag_none,
2899 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002900#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002901 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2902 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002903 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002904 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002905 cli_cmd_flag_none,
2906 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002907 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 cli_cmd_flag_none,
2909 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002910 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002911 cli_cmd_flag_none,
2912 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002913 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002914 cli_cmd_flag_none,
2915 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002916 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002917 cli_cmd_flag_none,
2918 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002919 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2920 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002921 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002922#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002923 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002924 "[params] = Set or unset (if none) autoscan parameters" },
2925#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002926#ifdef CONFIG_WNM
2927 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2928 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002929 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2930 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002931#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002932 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2933 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002934 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2935 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002936#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002937 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002938 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002939#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002940 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2941 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002942 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2943 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2944 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002945 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002946};
2947
2948
2949/*
2950 * Prints command usage, lines are padded with the specified string.
2951 */
2952static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2953{
2954 char c;
2955 size_t n;
2956
2957 printf("%s%s ", pad, cmd->cmd);
2958 for (n = 0; (c = cmd->usage[n]); n++) {
2959 printf("%c", c);
2960 if (c == '\n')
2961 printf("%s", pad);
2962 }
2963 printf("\n");
2964}
2965
2966
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002967static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968{
2969 int n;
2970 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002971 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2972 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2973 print_cmd_help(&wpa_cli_commands[n], " ");
2974 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002975}
2976
2977
2978static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2979{
2980 const char *c, *delim;
2981 int n;
2982 size_t len;
2983
2984 delim = os_strchr(cmd, ' ');
2985 if (delim)
2986 len = delim - cmd;
2987 else
2988 len = os_strlen(cmd);
2989
2990 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2991 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2992 return (wpa_cli_commands[n].flags &
2993 cli_cmd_flag_sensitive);
2994 }
2995 return 0;
2996}
2997
2998
2999static char ** wpa_list_cmd_list(void)
3000{
3001 char **res;
3002 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003003 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003004
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003005 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003006 count += dl_list_len(&p2p_groups);
3007 count += dl_list_len(&ifnames);
3008 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003009 if (res == NULL)
3010 return NULL;
3011
3012 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3013 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3014 if (res[i] == NULL)
3015 break;
3016 }
3017
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003018 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3019 size_t len = 8 + os_strlen(e->txt);
3020 res[i] = os_malloc(len);
3021 if (res[i] == NULL)
3022 break;
3023 os_snprintf(res[i], len, "ifname=%s", e->txt);
3024 i++;
3025 }
3026
3027 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3028 res[i] = os_strdup(e->txt);
3029 if (res[i] == NULL)
3030 break;
3031 i++;
3032 }
3033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 return res;
3035}
3036
3037
3038static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3039 int pos)
3040{
3041 int i;
3042
3043 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3044 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003045 if (wpa_cli_commands[i].completion)
3046 return wpa_cli_commands[i].completion(str,
3047 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 edit_clear_line();
3049 printf("\r%s\n", wpa_cli_commands[i].usage);
3050 edit_redraw();
3051 break;
3052 }
3053 }
3054
3055 return NULL;
3056}
3057
3058
3059static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3060{
3061 char **res;
3062 const char *end;
3063 char *cmd;
3064
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003065 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3066 end = os_strchr(str, ' ');
3067 if (end && pos > end - str) {
3068 pos -= end - str + 1;
3069 str = end + 1;
3070 }
3071 }
3072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073 end = os_strchr(str, ' ');
3074 if (end == NULL || str + pos < end)
3075 return wpa_list_cmd_list();
3076
3077 cmd = os_malloc(pos + 1);
3078 if (cmd == NULL)
3079 return NULL;
3080 os_memcpy(cmd, str, pos);
3081 cmd[end - str] = '\0';
3082 res = wpa_cli_cmd_completion(cmd, str, pos);
3083 os_free(cmd);
3084 return res;
3085}
3086
3087
3088static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3089{
3090 struct wpa_cli_cmd *cmd, *match = NULL;
3091 int count;
3092 int ret = 0;
3093
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003094 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3095 ifname_prefix = argv[0] + 7;
3096 argv = &argv[1];
3097 argc--;
3098 } else
3099 ifname_prefix = NULL;
3100
3101 if (argc == 0)
3102 return -1;
3103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003104 count = 0;
3105 cmd = wpa_cli_commands;
3106 while (cmd->cmd) {
3107 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3108 {
3109 match = cmd;
3110 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3111 /* we have an exact match */
3112 count = 1;
3113 break;
3114 }
3115 count++;
3116 }
3117 cmd++;
3118 }
3119
3120 if (count > 1) {
3121 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3122 cmd = wpa_cli_commands;
3123 while (cmd->cmd) {
3124 if (os_strncasecmp(cmd->cmd, argv[0],
3125 os_strlen(argv[0])) == 0) {
3126 printf(" %s", cmd->cmd);
3127 }
3128 cmd++;
3129 }
3130 printf("\n");
3131 ret = 1;
3132 } else if (count == 0) {
3133 printf("Unknown command '%s'\n", argv[0]);
3134 ret = 1;
3135 } else {
3136 ret = match->handler(ctrl, argc - 1, &argv[1]);
3137 }
3138
3139 return ret;
3140}
3141
3142
3143static int str_match(const char *a, const char *b)
3144{
3145 return os_strncmp(a, b, os_strlen(b)) == 0;
3146}
3147
3148
3149static int wpa_cli_exec(const char *program, const char *arg1,
3150 const char *arg2)
3151{
3152 char *cmd;
3153 size_t len;
3154 int res;
3155 int ret = 0;
3156
3157 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3158 cmd = os_malloc(len);
3159 if (cmd == NULL)
3160 return -1;
3161 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3162 if (res < 0 || (size_t) res >= len) {
3163 os_free(cmd);
3164 return -1;
3165 }
3166 cmd[len - 1] = '\0';
3167#ifndef _WIN32_WCE
3168 if (system(cmd) < 0)
3169 ret = -1;
3170#endif /* _WIN32_WCE */
3171 os_free(cmd);
3172
3173 return ret;
3174}
3175
3176
3177static void wpa_cli_action_process(const char *msg)
3178{
3179 const char *pos;
3180 char *copy = NULL, *id, *pos2;
3181
3182 pos = msg;
3183 if (*pos == '<') {
3184 /* skip priority */
3185 pos = os_strchr(pos, '>');
3186 if (pos)
3187 pos++;
3188 else
3189 pos = msg;
3190 }
3191
3192 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3193 int new_id = -1;
3194 os_unsetenv("WPA_ID");
3195 os_unsetenv("WPA_ID_STR");
3196 os_unsetenv("WPA_CTRL_DIR");
3197
3198 pos = os_strstr(pos, "[id=");
3199 if (pos)
3200 copy = os_strdup(pos + 4);
3201
3202 if (copy) {
3203 pos2 = id = copy;
3204 while (*pos2 && *pos2 != ' ')
3205 pos2++;
3206 *pos2++ = '\0';
3207 new_id = atoi(id);
3208 os_setenv("WPA_ID", id, 1);
3209 while (*pos2 && *pos2 != '=')
3210 pos2++;
3211 if (*pos2 == '=')
3212 pos2++;
3213 id = pos2;
3214 while (*pos2 && *pos2 != ']')
3215 pos2++;
3216 *pos2 = '\0';
3217 os_setenv("WPA_ID_STR", id, 1);
3218 os_free(copy);
3219 }
3220
3221 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3222
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003223 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224 wpa_cli_connected = 1;
3225 wpa_cli_last_id = new_id;
3226 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3227 }
3228 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3229 if (wpa_cli_connected) {
3230 wpa_cli_connected = 0;
3231 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3232 }
3233 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3234 wpa_cli_exec(action_file, ctrl_ifname, pos);
3235 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3236 wpa_cli_exec(action_file, ctrl_ifname, pos);
3237 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3238 wpa_cli_exec(action_file, ctrl_ifname, pos);
3239 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3240 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003241 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3242 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003243 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3244 wpa_cli_exec(action_file, ctrl_ifname, pos);
3245 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3246 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003247 } else if (str_match(pos, AP_STA_CONNECTED)) {
3248 wpa_cli_exec(action_file, ctrl_ifname, pos);
3249 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3250 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003251 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3252 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003253 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3254 wpa_cli_exec(action_file, ctrl_ifname, pos);
3255 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3256 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003257 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3258 printf("wpa_supplicant is terminating - stop monitoring\n");
3259 wpa_cli_quit = 1;
3260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261}
3262
3263
3264#ifndef CONFIG_ANSI_C_EXTRA
3265static void wpa_cli_action_cb(char *msg, size_t len)
3266{
3267 wpa_cli_action_process(msg);
3268}
3269#endif /* CONFIG_ANSI_C_EXTRA */
3270
3271
3272static void wpa_cli_reconnect(void)
3273{
3274 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003275 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3276 return;
3277
3278 if (interactive) {
3279 edit_clear_line();
3280 printf("\rConnection to wpa_supplicant re-established\n");
3281 edit_redraw();
3282 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283}
3284
3285
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003286static void cli_event(const char *str)
3287{
3288 const char *start, *s;
3289
3290 start = os_strchr(str, '>');
3291 if (start == NULL)
3292 return;
3293
3294 start++;
3295
3296 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3297 s = os_strchr(start, ' ');
3298 if (s == NULL)
3299 return;
3300 s = os_strchr(s + 1, ' ');
3301 if (s == NULL)
3302 return;
3303 cli_txt_list_add(&bsses, s + 1);
3304 return;
3305 }
3306
3307 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3308 s = os_strchr(start, ' ');
3309 if (s == NULL)
3310 return;
3311 s = os_strchr(s + 1, ' ');
3312 if (s == NULL)
3313 return;
3314 cli_txt_list_del_addr(&bsses, s + 1);
3315 return;
3316 }
3317
3318#ifdef CONFIG_P2P
3319 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3320 s = os_strstr(start, " p2p_dev_addr=");
3321 if (s == NULL)
3322 return;
3323 cli_txt_list_add_addr(&p2p_peers, s + 14);
3324 return;
3325 }
3326
3327 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3328 s = os_strstr(start, " p2p_dev_addr=");
3329 if (s == NULL)
3330 return;
3331 cli_txt_list_del_addr(&p2p_peers, s + 14);
3332 return;
3333 }
3334
3335 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3336 s = os_strchr(start, ' ');
3337 if (s == NULL)
3338 return;
3339 cli_txt_list_add_word(&p2p_groups, s + 1);
3340 return;
3341 }
3342
3343 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3344 s = os_strchr(start, ' ');
3345 if (s == NULL)
3346 return;
3347 cli_txt_list_del_word(&p2p_groups, s + 1);
3348 return;
3349 }
3350#endif /* CONFIG_P2P */
3351}
3352
3353
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003354static int check_terminating(const char *msg)
3355{
3356 const char *pos = msg;
3357
3358 if (*pos == '<') {
3359 /* skip priority */
3360 pos = os_strchr(pos, '>');
3361 if (pos)
3362 pos++;
3363 else
3364 pos = msg;
3365 }
3366
3367 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3368 edit_clear_line();
3369 printf("\rConnection to wpa_supplicant lost - trying to "
3370 "reconnect\n");
3371 edit_redraw();
3372 wpa_cli_attached = 0;
3373 wpa_cli_close_connection();
3374 return 1;
3375 }
3376
3377 return 0;
3378}
3379
3380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003381static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3382{
3383 if (ctrl_conn == NULL) {
3384 wpa_cli_reconnect();
3385 return;
3386 }
3387 while (wpa_ctrl_pending(ctrl) > 0) {
3388 char buf[256];
3389 size_t len = sizeof(buf) - 1;
3390 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3391 buf[len] = '\0';
3392 if (action_monitor)
3393 wpa_cli_action_process(buf);
3394 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003395 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003396 if (wpa_cli_show_event(buf)) {
3397 edit_clear_line();
3398 printf("\r%s\n", buf);
3399 edit_redraw();
3400 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003401
3402 if (interactive && check_terminating(buf) > 0)
3403 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404 }
3405 } else {
3406 printf("Could not read pending message.\n");
3407 break;
3408 }
3409 }
3410
3411 if (wpa_ctrl_pending(ctrl) < 0) {
3412 printf("Connection to wpa_supplicant lost - trying to "
3413 "reconnect\n");
3414 wpa_cli_reconnect();
3415 }
3416}
3417
3418#define max_args 10
3419
3420static int tokenize_cmd(char *cmd, char *argv[])
3421{
3422 char *pos;
3423 int argc = 0;
3424
3425 pos = cmd;
3426 for (;;) {
3427 while (*pos == ' ')
3428 pos++;
3429 if (*pos == '\0')
3430 break;
3431 argv[argc] = pos;
3432 argc++;
3433 if (argc == max_args)
3434 break;
3435 if (*pos == '"') {
3436 char *pos2 = os_strrchr(pos, '"');
3437 if (pos2)
3438 pos = pos2 + 1;
3439 }
3440 while (*pos != '\0' && *pos != ' ')
3441 pos++;
3442 if (*pos == ' ')
3443 *pos++ = '\0';
3444 }
3445
3446 return argc;
3447}
3448
3449
3450static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3451{
3452 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3453 printf("Connection to wpa_supplicant lost - trying to "
3454 "reconnect\n");
3455 wpa_cli_close_connection();
3456 }
3457 if (!ctrl_conn)
3458 wpa_cli_reconnect();
3459 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3460}
3461
3462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3464{
3465 wpa_cli_recv_pending(mon_conn, 0);
3466}
3467
3468
3469static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3470{
3471 char *argv[max_args];
3472 int argc;
3473 argc = tokenize_cmd(cmd, argv);
3474 if (argc)
3475 wpa_request(ctrl_conn, argc, argv);
3476}
3477
3478
3479static void wpa_cli_edit_eof_cb(void *ctx)
3480{
3481 eloop_terminate();
3482}
3483
3484
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003485static int warning_displayed = 0;
3486static char *hfile = NULL;
3487static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003488
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003489static void start_edit(void)
3490{
3491 char *home;
3492 char *ps = NULL;
3493
3494#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3495 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3496#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497
3498 home = getenv("HOME");
3499 if (home) {
3500 const char *fname = ".wpa_cli_history";
3501 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3502 hfile = os_malloc(hfile_len);
3503 if (hfile)
3504 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3505 }
3506
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003507 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3508 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3509 eloop_terminate();
3510 return;
3511 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003512
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003513 edit_started = 1;
3514 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3515}
3516
3517
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003518static void update_bssid_list(struct wpa_ctrl *ctrl)
3519{
3520 char buf[4096];
3521 size_t len = sizeof(buf);
3522 int ret;
3523 char *cmd = "BSS RANGE=ALL MASK=0x2";
3524 char *pos, *end;
3525
3526 if (ctrl == NULL)
3527 return;
3528 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3529 if (ret < 0)
3530 return;
3531 buf[len] = '\0';
3532
3533 pos = buf;
3534 while (pos) {
3535 pos = os_strstr(pos, "bssid=");
3536 if (pos == NULL)
3537 break;
3538 pos += 6;
3539 end = os_strchr(pos, '\n');
3540 if (end == NULL)
3541 break;
3542 *end = '\0';
3543 cli_txt_list_add(&bsses, pos);
3544 pos = end + 1;
3545 }
3546}
3547
3548
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003549static void update_ifnames(struct wpa_ctrl *ctrl)
3550{
3551 char buf[4096];
3552 size_t len = sizeof(buf);
3553 int ret;
3554 char *cmd = "INTERFACES";
3555 char *pos, *end;
3556 char txt[200];
3557
3558 cli_txt_list_flush(&ifnames);
3559
3560 if (ctrl == NULL)
3561 return;
3562 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3563 if (ret < 0)
3564 return;
3565 buf[len] = '\0';
3566
3567 pos = buf;
3568 while (pos) {
3569 end = os_strchr(pos, '\n');
3570 if (end == NULL)
3571 break;
3572 *end = '\0';
3573 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3574 if (ret > 0 && ret < (int) sizeof(txt))
3575 cli_txt_list_add(&ifnames, txt);
3576 pos = end + 1;
3577 }
3578}
3579
3580
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003581static void try_connection(void *eloop_ctx, void *timeout_ctx)
3582{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003583 if (ctrl_conn)
3584 goto done;
3585
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003586 if (ctrl_ifname == NULL)
3587 ctrl_ifname = wpa_cli_get_default_ifname();
3588
3589 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3590 if (!warning_displayed) {
3591 printf("Could not connect to wpa_supplicant: "
3592 "%s - re-trying\n", ctrl_ifname);
3593 warning_displayed = 1;
3594 }
3595 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3596 return;
3597 }
3598
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003599 update_bssid_list(ctrl_conn);
3600
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003601 if (warning_displayed)
3602 printf("Connection established.\n");
3603
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003604done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003605 start_edit();
3606}
3607
3608
3609static void wpa_cli_interactive(void)
3610{
3611 printf("\nInteractive mode\n\n");
3612
3613 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003615 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003616
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003617 cli_txt_list_flush(&p2p_peers);
3618 cli_txt_list_flush(&p2p_groups);
3619 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003620 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003621 if (edit_started)
3622 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623 os_free(hfile);
3624 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3625 wpa_cli_close_connection();
3626}
3627
3628
3629static void wpa_cli_action(struct wpa_ctrl *ctrl)
3630{
3631#ifdef CONFIG_ANSI_C_EXTRA
3632 /* TODO: ANSI C version(?) */
3633 printf("Action processing not supported in ANSI C build.\n");
3634#else /* CONFIG_ANSI_C_EXTRA */
3635 fd_set rfds;
3636 int fd, res;
3637 struct timeval tv;
3638 char buf[256]; /* note: large enough to fit in unsolicited messages */
3639 size_t len;
3640
3641 fd = wpa_ctrl_get_fd(ctrl);
3642
3643 while (!wpa_cli_quit) {
3644 FD_ZERO(&rfds);
3645 FD_SET(fd, &rfds);
3646 tv.tv_sec = ping_interval;
3647 tv.tv_usec = 0;
3648 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3649 if (res < 0 && errno != EINTR) {
3650 perror("select");
3651 break;
3652 }
3653
3654 if (FD_ISSET(fd, &rfds))
3655 wpa_cli_recv_pending(ctrl, 1);
3656 else {
3657 /* verify that connection is still working */
3658 len = sizeof(buf) - 1;
3659 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3660 wpa_cli_action_cb) < 0 ||
3661 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3662 printf("wpa_supplicant did not reply to PING "
3663 "command - exiting\n");
3664 break;
3665 }
3666 }
3667 }
3668#endif /* CONFIG_ANSI_C_EXTRA */
3669}
3670
3671
3672static void wpa_cli_cleanup(void)
3673{
3674 wpa_cli_close_connection();
3675 if (pid_file)
3676 os_daemonize_terminate(pid_file);
3677
3678 os_program_deinit();
3679}
3680
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003681
3682static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003683{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003684 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003685}
3686
3687
3688static char * wpa_cli_get_default_ifname(void)
3689{
3690 char *ifname = NULL;
3691
3692#ifdef CONFIG_CTRL_IFACE_UNIX
3693 struct dirent *dent;
3694 DIR *dir = opendir(ctrl_iface_dir);
3695 if (!dir) {
3696#ifdef ANDROID
3697 char ifprop[PROPERTY_VALUE_MAX];
3698 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3699 ifname = os_strdup(ifprop);
3700 printf("Using interface '%s'\n", ifname);
3701 return ifname;
3702 }
3703#endif /* ANDROID */
3704 return NULL;
3705 }
3706 while ((dent = readdir(dir))) {
3707#ifdef _DIRENT_HAVE_D_TYPE
3708 /*
3709 * Skip the file if it is not a socket. Also accept
3710 * DT_UNKNOWN (0) in case the C library or underlying
3711 * file system does not support d_type.
3712 */
3713 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3714 continue;
3715#endif /* _DIRENT_HAVE_D_TYPE */
3716 if (os_strcmp(dent->d_name, ".") == 0 ||
3717 os_strcmp(dent->d_name, "..") == 0)
3718 continue;
3719 printf("Selected interface '%s'\n", dent->d_name);
3720 ifname = os_strdup(dent->d_name);
3721 break;
3722 }
3723 closedir(dir);
3724#endif /* CONFIG_CTRL_IFACE_UNIX */
3725
3726#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003727 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 size_t len;
3729 struct wpa_ctrl *ctrl;
3730 int ret;
3731
3732 ctrl = wpa_ctrl_open(NULL);
3733 if (ctrl == NULL)
3734 return NULL;
3735
3736 len = sizeof(buf) - 1;
3737 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3738 if (ret >= 0) {
3739 buf[len] = '\0';
3740 pos = os_strchr(buf, '\n');
3741 if (pos)
3742 *pos = '\0';
3743 ifname = os_strdup(buf);
3744 }
3745 wpa_ctrl_close(ctrl);
3746#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3747
3748 return ifname;
3749}
3750
3751
3752int main(int argc, char *argv[])
3753{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754 int c;
3755 int daemonize = 0;
3756 int ret = 0;
3757 const char *global = NULL;
3758
3759 if (os_program_init())
3760 return -1;
3761
3762 for (;;) {
3763 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3764 if (c < 0)
3765 break;
3766 switch (c) {
3767 case 'a':
3768 action_file = optarg;
3769 break;
3770 case 'B':
3771 daemonize = 1;
3772 break;
3773 case 'g':
3774 global = optarg;
3775 break;
3776 case 'G':
3777 ping_interval = atoi(optarg);
3778 break;
3779 case 'h':
3780 usage();
3781 return 0;
3782 case 'v':
3783 printf("%s\n", wpa_cli_version);
3784 return 0;
3785 case 'i':
3786 os_free(ctrl_ifname);
3787 ctrl_ifname = os_strdup(optarg);
3788 break;
3789 case 'p':
3790 ctrl_iface_dir = optarg;
3791 break;
3792 case 'P':
3793 pid_file = optarg;
3794 break;
3795 default:
3796 usage();
3797 return -1;
3798 }
3799 }
3800
3801 interactive = (argc == optind) && (action_file == NULL);
3802
3803 if (interactive)
3804 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3805
3806 if (eloop_init())
3807 return -1;
3808
3809 if (global) {
3810#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3811 ctrl_conn = wpa_ctrl_open(NULL);
3812#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3813 ctrl_conn = wpa_ctrl_open(global);
3814#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3815 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003816 fprintf(stderr, "Failed to connect to wpa_supplicant "
3817 "global interface: %s error: %s\n",
3818 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819 return -1;
3820 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003821
3822 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003823 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003824 mon_conn = wpa_ctrl_open(global);
3825 if (mon_conn) {
3826 if (wpa_ctrl_attach(mon_conn) == 0) {
3827 wpa_cli_attached = 1;
3828 eloop_register_read_sock(
3829 wpa_ctrl_get_fd(mon_conn),
3830 wpa_cli_mon_receive,
3831 NULL, NULL);
3832 } else {
3833 printf("Failed to open monitor "
3834 "connection through global "
3835 "control interface\n");
3836 }
3837 }
3838 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003839 }
3840
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003841 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003842
3843 if (ctrl_ifname == NULL)
3844 ctrl_ifname = wpa_cli_get_default_ifname();
3845
3846 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003847 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003848 } else {
3849 if (!global &&
3850 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003851 fprintf(stderr, "Failed to connect to non-global "
3852 "ctrl_ifname: %s error: %s\n",
3853 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003854 return -1;
3855 }
3856
3857 if (action_file) {
3858 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3859 wpa_cli_attached = 1;
3860 } else {
3861 printf("Warning: Failed to attach to "
3862 "wpa_supplicant.\n");
3863 return -1;
3864 }
3865 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003866
3867 if (daemonize && os_daemonize(pid_file))
3868 return -1;
3869
3870 if (action_file)
3871 wpa_cli_action(ctrl_conn);
3872 else
3873 ret = wpa_request(ctrl_conn, argc - optind,
3874 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003875 }
3876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877 os_free(ctrl_ifname);
3878 eloop_destroy();
3879 wpa_cli_cleanup();
3880
3881 return ret;
3882}
3883
3884#else /* CONFIG_CTRL_IFACE */
3885int main(int argc, char *argv[])
3886{
3887 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3888 return -1;
3889}
3890#endif /* CONFIG_CTRL_IFACE */