blob: 83817f9937934ef71536f406e196501a99327189 [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",
631 "tdls_external_control"
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 Shmidtd5e49232012-12-03 15:08:10 -0800845static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 int ret;
849 char *buf;
850 size_t buflen;
851
852 if (argc != 1) {
853 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
854 "is required.\n");
855 return -1;
856 }
857
858 buflen = 21 + os_strlen(argv[0]);
859 buf = os_malloc(buflen);
860 if (buf == NULL)
861 return -1;
862 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
863
864 ret = wpa_ctrl_command(ctrl, buf);
865 os_free(buf);
866
867 return ret;
868}
869
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800870
871static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
872 char *argv[])
873{
874 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
875}
876
Dmitry Shmidt04949592012-07-19 12:16:46 -0700877#endif /* CONFIG_WPS_NFC */
878
879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
881{
882 char cmd[256];
883 int res;
884
885 if (argc == 2)
886 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
887 argv[0], argv[1]);
888 else if (argc == 5 || argc == 6) {
889 char ssid_hex[2 * 32 + 1];
890 char key_hex[2 * 64 + 1];
891 int i;
892
893 ssid_hex[0] = '\0';
894 for (i = 0; i < 32; i++) {
895 if (argv[2][i] == '\0')
896 break;
897 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
898 }
899
900 key_hex[0] = '\0';
901 if (argc == 6) {
902 for (i = 0; i < 64; i++) {
903 if (argv[5][i] == '\0')
904 break;
905 os_snprintf(&key_hex[i * 2], 3, "%02x",
906 argv[5][i]);
907 }
908 }
909
910 res = os_snprintf(cmd, sizeof(cmd),
911 "WPS_REG %s %s %s %s %s %s",
912 argv[0], argv[1], ssid_hex, argv[3], argv[4],
913 key_hex);
914 } else {
915 printf("Invalid WPS_REG command: need two arguments:\n"
916 "- BSSID of the target AP\n"
917 "- AP PIN\n");
918 printf("Alternatively, six arguments can be used to "
919 "reconfigure the AP:\n"
920 "- BSSID of the target AP\n"
921 "- AP PIN\n"
922 "- new SSID\n"
923 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
924 "- new encr (NONE, WEP, TKIP, CCMP)\n"
925 "- new key\n");
926 return -1;
927 }
928
929 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
930 printf("Too long WPS_REG command.\n");
931 return -1;
932 }
933 return wpa_ctrl_command(ctrl, cmd);
934}
935
936
937static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
938 char *argv[])
939{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700940 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941}
942
943
944static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
945 char *argv[])
946{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700947 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948}
949
950
951static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
952 char *argv[])
953{
954 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
955
956}
957
958
959static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
960 char *argv[])
961{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 if (argc < 2) {
963 printf("Invalid WPS_ER_PIN command: need at least two "
964 "arguments:\n"
965 "- UUID: use 'any' to select any\n"
966 "- PIN: Enrollee PIN\n"
967 "optional: - Enrollee MAC address\n");
968 return -1;
969 }
970
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700971 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972}
973
974
975static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
976 char *argv[])
977{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700978 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979}
980
981
982static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
983 char *argv[])
984{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700985 if (argc != 2) {
986 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
987 "- UUID: specify which AP to use\n"
988 "- PIN: AP PIN\n");
989 return -1;
990 }
991
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700992 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993}
994
995
996static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
997 char *argv[])
998{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 if (argc != 2) {
1000 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1001 "arguments:\n"
1002 "- UUID: specify which AP to use\n"
1003 "- Network configuration id\n");
1004 return -1;
1005 }
1006
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008}
1009
1010
1011static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1012 char *argv[])
1013{
1014 char cmd[256];
1015 int res;
1016
1017 if (argc == 5 || argc == 6) {
1018 char ssid_hex[2 * 32 + 1];
1019 char key_hex[2 * 64 + 1];
1020 int i;
1021
1022 ssid_hex[0] = '\0';
1023 for (i = 0; i < 32; i++) {
1024 if (argv[2][i] == '\0')
1025 break;
1026 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1027 }
1028
1029 key_hex[0] = '\0';
1030 if (argc == 6) {
1031 for (i = 0; i < 64; i++) {
1032 if (argv[5][i] == '\0')
1033 break;
1034 os_snprintf(&key_hex[i * 2], 3, "%02x",
1035 argv[5][i]);
1036 }
1037 }
1038
1039 res = os_snprintf(cmd, sizeof(cmd),
1040 "WPS_ER_CONFIG %s %s %s %s %s %s",
1041 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1042 key_hex);
1043 } else {
1044 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1045 "- AP UUID\n"
1046 "- AP PIN\n"
1047 "- new SSID\n"
1048 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1049 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1050 "- new key\n");
1051 return -1;
1052 }
1053
1054 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1055 printf("Too long WPS_ER_CONFIG command.\n");
1056 return -1;
1057 }
1058 return wpa_ctrl_command(ctrl, cmd);
1059}
1060
1061
Dmitry Shmidt04949592012-07-19 12:16:46 -07001062#ifdef CONFIG_WPS_NFC
1063static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1064 char *argv[])
1065{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001066 if (argc != 2) {
1067 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1068 "arguments:\n"
1069 "- WPS/NDEF: token format\n"
1070 "- UUID: specify which AP to use\n");
1071 return -1;
1072 }
1073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001074 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001075}
1076#endif /* CONFIG_WPS_NFC */
1077
1078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001081 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001087 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088}
1089
1090
1091static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1092{
1093 char cmd[256], *pos, *end;
1094 int i, ret;
1095
1096 if (argc < 2) {
1097 printf("Invalid IDENTITY command: needs two arguments "
1098 "(network id and identity)\n");
1099 return -1;
1100 }
1101
1102 end = cmd + sizeof(cmd);
1103 pos = cmd;
1104 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1105 argv[0], argv[1]);
1106 if (ret < 0 || ret >= end - pos) {
1107 printf("Too long IDENTITY command.\n");
1108 return -1;
1109 }
1110 pos += ret;
1111 for (i = 2; i < argc; i++) {
1112 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long IDENTITY command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 }
1119
1120 return wpa_ctrl_command(ctrl, cmd);
1121}
1122
1123
1124static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1125{
1126 char cmd[256], *pos, *end;
1127 int i, ret;
1128
1129 if (argc < 2) {
1130 printf("Invalid PASSWORD command: needs two arguments "
1131 "(network id and password)\n");
1132 return -1;
1133 }
1134
1135 end = cmd + sizeof(cmd);
1136 pos = cmd;
1137 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1138 argv[0], argv[1]);
1139 if (ret < 0 || ret >= end - pos) {
1140 printf("Too long PASSWORD command.\n");
1141 return -1;
1142 }
1143 pos += ret;
1144 for (i = 2; i < argc; i++) {
1145 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1146 if (ret < 0 || ret >= end - pos) {
1147 printf("Too long PASSWORD command.\n");
1148 return -1;
1149 }
1150 pos += ret;
1151 }
1152
1153 return wpa_ctrl_command(ctrl, cmd);
1154}
1155
1156
1157static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1158 char *argv[])
1159{
1160 char cmd[256], *pos, *end;
1161 int i, ret;
1162
1163 if (argc < 2) {
1164 printf("Invalid NEW_PASSWORD command: needs two arguments "
1165 "(network id and password)\n");
1166 return -1;
1167 }
1168
1169 end = cmd + sizeof(cmd);
1170 pos = cmd;
1171 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1172 argv[0], argv[1]);
1173 if (ret < 0 || ret >= end - pos) {
1174 printf("Too long NEW_PASSWORD command.\n");
1175 return -1;
1176 }
1177 pos += ret;
1178 for (i = 2; i < argc; i++) {
1179 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1180 if (ret < 0 || ret >= end - pos) {
1181 printf("Too long NEW_PASSWORD command.\n");
1182 return -1;
1183 }
1184 pos += ret;
1185 }
1186
1187 return wpa_ctrl_command(ctrl, cmd);
1188}
1189
1190
1191static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1192{
1193 char cmd[256], *pos, *end;
1194 int i, ret;
1195
1196 if (argc < 2) {
1197 printf("Invalid PIN command: needs two arguments "
1198 "(network id and pin)\n");
1199 return -1;
1200 }
1201
1202 end = cmd + sizeof(cmd);
1203 pos = cmd;
1204 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1205 argv[0], argv[1]);
1206 if (ret < 0 || ret >= end - pos) {
1207 printf("Too long PIN command.\n");
1208 return -1;
1209 }
1210 pos += ret;
1211 for (i = 2; i < argc; i++) {
1212 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1213 if (ret < 0 || ret >= end - pos) {
1214 printf("Too long PIN command.\n");
1215 return -1;
1216 }
1217 pos += ret;
1218 }
1219 return wpa_ctrl_command(ctrl, cmd);
1220}
1221
1222
1223static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1224{
1225 char cmd[256], *pos, *end;
1226 int i, ret;
1227
1228 if (argc < 2) {
1229 printf("Invalid OTP command: needs two arguments (network "
1230 "id and password)\n");
1231 return -1;
1232 }
1233
1234 end = cmd + sizeof(cmd);
1235 pos = cmd;
1236 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1237 argv[0], argv[1]);
1238 if (ret < 0 || ret >= end - pos) {
1239 printf("Too long OTP command.\n");
1240 return -1;
1241 }
1242 pos += ret;
1243 for (i = 2; i < argc; i++) {
1244 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1245 if (ret < 0 || ret >= end - pos) {
1246 printf("Too long OTP command.\n");
1247 return -1;
1248 }
1249 pos += ret;
1250 }
1251
1252 return wpa_ctrl_command(ctrl, cmd);
1253}
1254
1255
Dmitry Shmidt051af732013-10-22 13:52:46 -07001256static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1257{
1258 char cmd[256], *pos, *end;
1259 int i, ret;
1260
1261 if (argc < 2) {
1262 printf("Invalid SIM command: needs two arguments "
1263 "(network id and SIM operation response)\n");
1264 return -1;
1265 }
1266
1267 end = cmd + sizeof(cmd);
1268 pos = cmd;
1269 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1270 argv[0], argv[1]);
1271 if (ret < 0 || ret >= end - pos) {
1272 printf("Too long SIM command.\n");
1273 return -1;
1274 }
1275 pos += ret;
1276 for (i = 2; i < argc; i++) {
1277 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1278 if (ret < 0 || ret >= end - pos) {
1279 printf("Too long SIM command.\n");
1280 return -1;
1281 }
1282 pos += ret;
1283 }
1284 return wpa_ctrl_command(ctrl, cmd);
1285}
1286
1287
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1289 char *argv[])
1290{
1291 char cmd[256], *pos, *end;
1292 int i, ret;
1293
1294 if (argc < 2) {
1295 printf("Invalid PASSPHRASE command: needs two arguments "
1296 "(network id and passphrase)\n");
1297 return -1;
1298 }
1299
1300 end = cmd + sizeof(cmd);
1301 pos = cmd;
1302 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1303 argv[0], argv[1]);
1304 if (ret < 0 || ret >= end - pos) {
1305 printf("Too long PASSPHRASE command.\n");
1306 return -1;
1307 }
1308 pos += ret;
1309 for (i = 2; i < argc; i++) {
1310 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1311 if (ret < 0 || ret >= end - pos) {
1312 printf("Too long PASSPHRASE command.\n");
1313 return -1;
1314 }
1315 pos += ret;
1316 }
1317
1318 return wpa_ctrl_command(ctrl, cmd);
1319}
1320
1321
1322static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1323{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001324 if (argc < 2) {
1325 printf("Invalid BSSID command: needs two arguments (network "
1326 "id and BSSID)\n");
1327 return -1;
1328 }
1329
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001330 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331}
1332
1333
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001334static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1335{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001336 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001337}
1338
1339
1340static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1341{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001342 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001343}
1344
1345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1347 char *argv[])
1348{
1349 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1350}
1351
1352
1353static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1354 char *argv[])
1355{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001356 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001357}
1358
1359
1360static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1361 char *argv[])
1362{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001363 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001364}
1365
1366
1367static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1368 char *argv[])
1369{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001370 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001371}
1372
1373
1374static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1375 char *argv[])
1376{
1377 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1378}
1379
1380
1381static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1382 char *argv[])
1383{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001384 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385}
1386
1387
1388static void wpa_cli_show_network_variables(void)
1389{
1390 printf("set_network variables:\n"
1391 " ssid (network name, SSID)\n"
1392 " psk (WPA passphrase or pre-shared key)\n"
1393 " key_mgmt (key management protocol)\n"
1394 " identity (EAP identity)\n"
1395 " password (EAP password)\n"
1396 " ...\n"
1397 "\n"
1398 "Note: Values are entered in the same format as the "
1399 "configuration file is using,\n"
1400 "i.e., strings values need to be inside double quotation "
1401 "marks.\n"
1402 "For example: set_network 1 ssid \"network name\"\n"
1403 "\n"
1404 "Please see wpa_supplicant.conf documentation for full list "
1405 "of\navailable variables.\n");
1406}
1407
1408
1409static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1410 char *argv[])
1411{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 if (argc == 0) {
1413 wpa_cli_show_network_variables();
1414 return 0;
1415 }
1416
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001417 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001418 printf("Invalid SET_NETWORK command: needs three arguments\n"
1419 "(network id, variable name, and value)\n");
1420 return -1;
1421 }
1422
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001423 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424}
1425
1426
1427static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1428 char *argv[])
1429{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 if (argc == 0) {
1431 wpa_cli_show_network_variables();
1432 return 0;
1433 }
1434
1435 if (argc != 2) {
1436 printf("Invalid GET_NETWORK command: needs two arguments\n"
1437 "(network id and variable name)\n");
1438 return -1;
1439 }
1440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001441 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442}
1443
1444
Dmitry Shmidt04949592012-07-19 12:16:46 -07001445static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1446 char *argv[])
1447{
1448 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1449}
1450
1451
1452static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1453{
1454 return wpa_ctrl_command(ctrl, "ADD_CRED");
1455}
1456
1457
1458static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1459 char *argv[])
1460{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001461 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001462}
1463
1464
1465static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1466{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001467 if (argc != 3) {
1468 printf("Invalid SET_CRED command: needs three arguments\n"
1469 "(cred id, variable name, and value)\n");
1470 return -1;
1471 }
1472
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001473 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001474}
1475
1476
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001477static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1478{
1479 if (argc != 2) {
1480 printf("Invalid GET_CRED command: needs two arguments\n"
1481 "(cred id, variable name)\n");
1482 return -1;
1483 }
1484
1485 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1486}
1487
1488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1490 char *argv[])
1491{
1492 return wpa_ctrl_command(ctrl, "DISCONNECT");
1493}
1494
1495
1496static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1497 char *argv[])
1498{
1499 return wpa_ctrl_command(ctrl, "RECONNECT");
1500}
1501
1502
1503static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1504 char *argv[])
1505{
1506 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1507}
1508
1509
1510static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1511{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001512 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001513}
1514
1515
1516static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1517 char *argv[])
1518{
1519 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1520}
1521
1522
1523static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1524{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001525 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526}
1527
1528
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001529static char ** wpa_cli_complete_bss(const char *str, int pos)
1530{
1531 int arg = get_cmd_arg_num(str, pos);
1532 char **res = NULL;
1533
1534 switch (arg) {
1535 case 1:
1536 res = cli_txt_list_array(&bsses);
1537 break;
1538 }
1539
1540 return res;
1541}
1542
1543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001544static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1545 char *argv[])
1546{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001547 if (argc < 1 || argc > 2) {
1548 printf("Invalid GET_CAPABILITY command: need either one or "
1549 "two arguments\n");
1550 return -1;
1551 }
1552
1553 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1554 printf("Invalid GET_CAPABILITY command: second argument, "
1555 "if any, must be 'strict'\n");
1556 return -1;
1557 }
1558
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001559 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560}
1561
1562
1563static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1564{
1565 printf("Available interfaces:\n");
1566 return wpa_ctrl_command(ctrl, "INTERFACES");
1567}
1568
1569
1570static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1571{
1572 if (argc < 1) {
1573 wpa_cli_list_interfaces(ctrl);
1574 return 0;
1575 }
1576
1577 wpa_cli_close_connection();
1578 os_free(ctrl_ifname);
1579 ctrl_ifname = os_strdup(argv[0]);
1580
1581 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1582 printf("Connected to interface '%s.\n", ctrl_ifname);
1583 } else {
1584 printf("Could not connect to interface '%s' - re-trying\n",
1585 ctrl_ifname);
1586 }
1587 return 0;
1588}
1589
1590
1591static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1592 char *argv[])
1593{
1594 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1595}
1596
1597
1598static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1599 char *argv[])
1600{
1601 return wpa_ctrl_command(ctrl, "TERMINATE");
1602}
1603
1604
1605static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1606 char *argv[])
1607{
1608 char cmd[256];
1609 int res;
1610
1611 if (argc < 1) {
1612 printf("Invalid INTERFACE_ADD command: needs at least one "
1613 "argument (interface name)\n"
1614 "All arguments: ifname confname driver ctrl_interface "
1615 "driver_param bridge_name\n");
1616 return -1;
1617 }
1618
1619 /*
1620 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1621 * <driver_param>TAB<bridge_name>
1622 */
1623 res = os_snprintf(cmd, sizeof(cmd),
1624 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1625 argv[0],
1626 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1627 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1628 argc > 5 ? argv[5] : "");
1629 if (res < 0 || (size_t) res >= sizeof(cmd))
1630 return -1;
1631 cmd[sizeof(cmd) - 1] = '\0';
1632 return wpa_ctrl_command(ctrl, cmd);
1633}
1634
1635
1636static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1637 char *argv[])
1638{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001639 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001640}
1641
1642
1643static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1644 char *argv[])
1645{
1646 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1647}
1648
1649
1650#ifdef CONFIG_AP
1651static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1652{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001653 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654}
1655
1656
1657static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1658 char *addr, size_t addr_len)
1659{
1660 char buf[4096], *pos;
1661 size_t len;
1662 int ret;
1663
1664 if (ctrl_conn == NULL) {
1665 printf("Not connected to hostapd - command dropped.\n");
1666 return -1;
1667 }
1668 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001669 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 wpa_cli_msg_cb);
1671 if (ret == -2) {
1672 printf("'%s' command timed out.\n", cmd);
1673 return -2;
1674 } else if (ret < 0) {
1675 printf("'%s' command failed.\n", cmd);
1676 return -1;
1677 }
1678
1679 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001680 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 return -1;
1682 printf("%s", buf);
1683
1684 pos = buf;
1685 while (*pos != '\0' && *pos != '\n')
1686 pos++;
1687 *pos = '\0';
1688 os_strlcpy(addr, buf, addr_len);
1689 return 0;
1690}
1691
1692
1693static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1694{
1695 char addr[32], cmd[64];
1696
1697 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1698 return 0;
1699 do {
1700 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1701 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1702
1703 return -1;
1704}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001705
1706
1707static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1708 char *argv[])
1709{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001710 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001711}
1712
1713
1714static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1715 char *argv[])
1716{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001717 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001718}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001719
1720static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1721 char *argv[])
1722{
1723 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1724}
1725
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726#endif /* CONFIG_AP */
1727
1728
1729static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1730{
1731 return wpa_ctrl_command(ctrl, "SUSPEND");
1732}
1733
1734
1735static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1736{
1737 return wpa_ctrl_command(ctrl, "RESUME");
1738}
1739
1740
1741static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
1743 return wpa_ctrl_command(ctrl, "DROP_SA");
1744}
1745
1746
1747static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1748{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001749 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750}
1751
1752
1753#ifdef CONFIG_P2P
1754
1755static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1756{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001757 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1758}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001761static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1762{
1763 char **res = NULL;
1764 int arg = get_cmd_arg_num(str, pos);
1765
1766 res = os_calloc(6, sizeof(char *));
1767 if (res == NULL)
1768 return NULL;
1769 res[0] = os_strdup("type=social");
1770 if (res[0] == NULL) {
1771 os_free(res);
1772 return NULL;
1773 }
1774 res[1] = os_strdup("type=progressive");
1775 if (res[1] == NULL)
1776 return res;
1777 res[2] = os_strdup("delay=");
1778 if (res[2] == NULL)
1779 return res;
1780 res[3] = os_strdup("dev_id=");
1781 if (res[3] == NULL)
1782 return res;
1783 if (arg == 1)
1784 res[4] = os_strdup("[timeout]");
1785
1786 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
1790static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1791 char *argv[])
1792{
1793 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1794}
1795
1796
1797static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1798 char *argv[])
1799{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001800 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801}
1802
1803
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001804static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1805{
1806 int arg = get_cmd_arg_num(str, pos);
1807 char **res = NULL;
1808
1809 switch (arg) {
1810 case 1:
1811 res = cli_txt_list_array(&p2p_peers);
1812 break;
1813 }
1814
1815 return res;
1816}
1817
1818
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001822 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823}
1824
1825
1826static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1827 char *argv[])
1828{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001829 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830}
1831
1832
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001833static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1834{
1835 int arg = get_cmd_arg_num(str, pos);
1836 char **res = NULL;
1837
1838 switch (arg) {
1839 case 1:
1840 res = cli_txt_list_array(&p2p_groups);
1841 break;
1842 }
1843
1844 return res;
1845}
1846
1847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1849 char *argv[])
1850{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001851 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852}
1853
1854
1855static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1856 char *argv[])
1857{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001858 if (argc != 2 && argc != 3) {
1859 printf("Invalid P2P_PROV_DISC command: needs at least "
1860 "two arguments, address and config method\n"
1861 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862 return -1;
1863 }
1864
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001865 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866}
1867
1868
1869static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1870 char *argv[])
1871{
1872 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1873}
1874
1875
1876static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1877 char *argv[])
1878{
1879 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880
1881 if (argc != 2 && argc != 4) {
1882 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1883 "arguments (address and TLVs) or four arguments "
1884 "(address, \"upnp\", version, search target "
1885 "(SSDP ST:)\n");
1886 return -1;
1887 }
1888
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001889 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 return wpa_ctrl_command(ctrl, cmd);
1892}
1893
1894
1895static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1896 int argc, char *argv[])
1897{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001898 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899}
1900
1901
1902static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1903 char *argv[])
1904{
1905 char cmd[4096];
1906 int res;
1907
1908 if (argc != 4) {
1909 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1910 "arguments (freq, address, dialog token, and TLVs)\n");
1911 return -1;
1912 }
1913
1914 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1915 argv[0], argv[1], argv[2], argv[3]);
1916 if (res < 0 || (size_t) res >= sizeof(cmd))
1917 return -1;
1918 cmd[sizeof(cmd) - 1] = '\0';
1919 return wpa_ctrl_command(ctrl, cmd);
1920}
1921
1922
1923static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1924 char *argv[])
1925{
1926 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1927}
1928
1929
1930static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1931 int argc, char *argv[])
1932{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001933 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934}
1935
1936
1937static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1938 char *argv[])
1939{
1940 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1941}
1942
1943
1944static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1945 char *argv[])
1946{
1947 char cmd[4096];
1948 int res;
1949
1950 if (argc != 3 && argc != 4) {
1951 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1952 "arguments\n");
1953 return -1;
1954 }
1955
1956 if (argc == 4)
1957 res = os_snprintf(cmd, sizeof(cmd),
1958 "P2P_SERVICE_ADD %s %s %s %s",
1959 argv[0], argv[1], argv[2], argv[3]);
1960 else
1961 res = os_snprintf(cmd, sizeof(cmd),
1962 "P2P_SERVICE_ADD %s %s %s",
1963 argv[0], argv[1], argv[2]);
1964 if (res < 0 || (size_t) res >= sizeof(cmd))
1965 return -1;
1966 cmd[sizeof(cmd) - 1] = '\0';
1967 return wpa_ctrl_command(ctrl, cmd);
1968}
1969
1970
1971static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1972 char *argv[])
1973{
1974 char cmd[4096];
1975 int res;
1976
1977 if (argc != 2 && argc != 3) {
1978 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1979 "arguments\n");
1980 return -1;
1981 }
1982
1983 if (argc == 3)
1984 res = os_snprintf(cmd, sizeof(cmd),
1985 "P2P_SERVICE_DEL %s %s %s",
1986 argv[0], argv[1], argv[2]);
1987 else
1988 res = os_snprintf(cmd, sizeof(cmd),
1989 "P2P_SERVICE_DEL %s %s",
1990 argv[0], argv[1]);
1991 if (res < 0 || (size_t) res >= sizeof(cmd))
1992 return -1;
1993 cmd[sizeof(cmd) - 1] = '\0';
1994 return wpa_ctrl_command(ctrl, cmd);
1995}
1996
1997
1998static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1999 int argc, char *argv[])
2000{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002001 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002}
2003
2004
2005static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2006 int argc, char *argv[])
2007{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002008 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009}
2010
2011
2012static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2013{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002014 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015}
2016
2017
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002018static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2019{
2020 int arg = get_cmd_arg_num(str, pos);
2021 char **res = NULL;
2022
2023 switch (arg) {
2024 case 1:
2025 res = cli_txt_list_array(&p2p_peers);
2026 break;
2027 }
2028
2029 return res;
2030}
2031
2032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002033static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2034 char *addr, size_t addr_len,
2035 int discovered)
2036{
2037 char buf[4096], *pos;
2038 size_t len;
2039 int ret;
2040
2041 if (ctrl_conn == NULL)
2042 return -1;
2043 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002044 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 wpa_cli_msg_cb);
2046 if (ret == -2) {
2047 printf("'%s' command timed out.\n", cmd);
2048 return -2;
2049 } else if (ret < 0) {
2050 printf("'%s' command failed.\n", cmd);
2051 return -1;
2052 }
2053
2054 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002055 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056 return -1;
2057
2058 pos = buf;
2059 while (*pos != '\0' && *pos != '\n')
2060 pos++;
2061 *pos++ = '\0';
2062 os_strlcpy(addr, buf, addr_len);
2063 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2064 printf("%s\n", addr);
2065 return 0;
2066}
2067
2068
2069static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2070{
2071 char addr[32], cmd[64];
2072 int discovered;
2073
2074 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2075
2076 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2077 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002078 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079 do {
2080 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2081 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2082 discovered) == 0);
2083
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002084 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085}
2086
2087
2088static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2089{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002090 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091}
2092
2093
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002094static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2095{
2096 int arg = get_cmd_arg_num(str, pos);
2097 const char *fields[] = {
2098 "discoverability",
2099 "managed",
2100 "listen_channel",
2101 "ssid_postfix",
2102 "noa",
2103 "ps",
2104 "oppps",
2105 "ctwindow",
2106 "disabled",
2107 "conc_pref",
2108 "force_long_sd",
2109 "peer_filter",
2110 "cross_connect",
2111 "go_apsd",
2112 "client_apsd",
2113 "disallow_freq",
2114 "disc_int",
2115 "per_sta_psk",
2116 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002117 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002118
2119 if (arg == 1) {
2120 char **res = os_calloc(num_fields + 1, sizeof(char *));
2121 if (res == NULL)
2122 return NULL;
2123 for (i = 0; i < num_fields; i++) {
2124 res[i] = os_strdup(fields[i]);
2125 if (res[i] == NULL)
2126 return res;
2127 }
2128 return res;
2129 }
2130
2131 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2132 return cli_txt_list_array(&p2p_peers);
2133
2134 return NULL;
2135}
2136
2137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2139{
2140 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2141}
2142
2143
2144static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2145 char *argv[])
2146{
2147 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2148}
2149
2150
2151static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2152 char *argv[])
2153{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002154 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155}
2156
2157
2158static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2159 char *argv[])
2160{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002161 if (argc != 0 && argc != 2 && argc != 4) {
2162 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2163 "(preferred duration, interval; in microsecods).\n"
2164 "Optional second pair can be used to provide "
2165 "acceptable values.\n");
2166 return -1;
2167 }
2168
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002169 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170}
2171
2172
2173static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2174 char *argv[])
2175{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 if (argc != 0 && argc != 2) {
2177 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2178 "(availability period, availability interval; in "
2179 "millisecods).\n"
2180 "Extended Listen Timing can be cancelled with this "
2181 "command when used without parameters.\n");
2182 return -1;
2183 }
2184
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002185 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2186}
2187
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002188
2189static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2190 char *argv[])
2191{
2192 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2193}
2194
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002195#endif /* CONFIG_P2P */
2196
2197#ifdef CONFIG_WIFI_DISPLAY
2198
2199static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2200 char *argv[])
2201{
2202 char cmd[100];
2203 int res;
2204
2205 if (argc != 1 && argc != 2) {
2206 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2207 "arguments (subelem, hexdump)\n");
2208 return -1;
2209 }
2210
2211 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2212 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 if (res < 0 || (size_t) res >= sizeof(cmd))
2214 return -1;
2215 cmd[sizeof(cmd) - 1] = '\0';
2216 return wpa_ctrl_command(ctrl, cmd);
2217}
2218
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002219
2220static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2221 char *argv[])
2222{
2223 char cmd[100];
2224 int res;
2225
2226 if (argc != 1) {
2227 printf("Invalid WFD_SUBELEM_GET command: needs one "
2228 "argument (subelem)\n");
2229 return -1;
2230 }
2231
2232 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2233 argv[0]);
2234 if (res < 0 || (size_t) res >= sizeof(cmd))
2235 return -1;
2236 cmd[sizeof(cmd) - 1] = '\0';
2237 return wpa_ctrl_command(ctrl, cmd);
2238}
2239#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240
2241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002242#ifdef CONFIG_INTERWORKING
2243static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2244 char *argv[])
2245{
2246 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2247}
2248
2249
2250static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2251 char *argv[])
2252{
2253 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2254}
2255
2256
2257static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2258 char *argv[])
2259{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002260 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002261}
2262
2263
2264static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2265 char *argv[])
2266{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002267 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002268}
2269
2270
2271static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2272{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002273 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2274}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002277static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2278 char *argv[])
2279{
2280 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2281}
2282
2283
2284static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2285 char *argv[])
2286{
2287 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002288}
2289#endif /* CONFIG_INTERWORKING */
2290
2291
Dmitry Shmidt04949592012-07-19 12:16:46 -07002292#ifdef CONFIG_HS20
2293
2294static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2295 char *argv[])
2296{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002297 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002298}
2299
2300
2301static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2302 char *argv[])
2303{
2304 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002305
2306 if (argc == 0) {
2307 printf("Command needs one or two arguments (dst mac addr and "
2308 "optional home realm)\n");
2309 return -1;
2310 }
2311
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002312 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2313 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002314 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002315
2316 return wpa_ctrl_command(ctrl, cmd);
2317}
2318
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002319
2320static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2321 char *argv[])
2322{
2323 char cmd[512];
2324
2325 if (argc < 2) {
2326 printf("Command needs two arguments (dst mac addr and "
2327 "icon name)\n");
2328 return -1;
2329 }
2330
2331 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2332 return -1;
2333
2334 return wpa_ctrl_command(ctrl, cmd);
2335}
2336
2337
2338static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2339{
2340 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2341}
2342
2343
2344static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2345 char *argv[])
2346{
2347 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2348}
2349
Dmitry Shmidt04949592012-07-19 12:16:46 -07002350#endif /* CONFIG_HS20 */
2351
2352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2354 char *argv[])
2355{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002356 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357}
2358
2359
2360static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2361 char *argv[])
2362{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002363 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364}
2365
2366
2367static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2368 char *argv[])
2369{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371}
2372
2373
2374static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2375 char *argv[])
2376{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002377 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378}
2379
2380
2381static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2382 char *argv[])
2383{
2384 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2385}
2386
2387
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002388static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2389 char *argv[])
2390{
2391 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2392}
2393
2394
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002395static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2396 char *argv[])
2397{
2398 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2399}
2400
Dmitry Shmidt04949592012-07-19 12:16:46 -07002401
2402#ifdef CONFIG_AUTOSCAN
2403
2404static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2405{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002406 if (argc == 0)
2407 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2408
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002410}
2411
2412#endif /* CONFIG_AUTOSCAN */
2413
2414
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002415#ifdef CONFIG_WNM
2416
2417static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2418{
2419 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2420}
2421
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002422
2423static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2424{
2425 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2426}
2427
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002428#endif /* CONFIG_WNM */
2429
2430
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002431static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2432{
2433 if (argc == 0)
2434 return -1;
2435 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2436}
2437
2438
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002439#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002440static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2441{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002442 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002443}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002444#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002445
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002447static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2448{
2449 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2450}
2451
2452
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002453static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2454{
2455 return wpa_ctrl_command(ctrl, "FLUSH");
2456}
2457
2458
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002459static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2460{
2461 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2462}
2463
2464
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465enum wpa_cli_cmd_flags {
2466 cli_cmd_flag_none = 0x00,
2467 cli_cmd_flag_sensitive = 0x01
2468};
2469
2470struct wpa_cli_cmd {
2471 const char *cmd;
2472 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 enum wpa_cli_cmd_flags flags;
2475 const char *usage;
2476};
2477
2478static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "ifname", wpa_cli_cmd_ifname, NULL,
2483 cli_cmd_flag_none,
2484 "= get current interface name" },
2485 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002499 "[command] = show usage help" },
2500 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002512 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "= set variables (shows list of variables when run without "
2515 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_none,
2521 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_none,
2524 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002531 { "reattach", wpa_cli_cmd_reattach, NULL,
2532 cli_cmd_flag_none,
2533 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535 cli_cmd_flag_none,
2536 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 cli_cmd_flag_none,
2539 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 cli_cmd_flag_sensitive,
2542 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_sensitive,
2545 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002546 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547 cli_cmd_flag_sensitive,
2548 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550 cli_cmd_flag_sensitive,
2551 "<network id> <password> = configure one-time-password for an SSID"
2552 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_sensitive,
2555 "<network id> <passphrase> = configure private key passphrase\n"
2556 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002557 { "sim", wpa_cli_cmd_sim, NULL,
2558 cli_cmd_flag_sensitive,
2559 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002564 cli_cmd_flag_none,
2565 "<BSSID> = add a BSSID to the blacklist\n"
2566 "blacklist clear = clear the blacklist\n"
2567 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002569 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002570 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002571 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 cli_cmd_flag_none,
2574 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_none,
2577 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_none,
2580 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 cli_cmd_flag_none,
2583 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 cli_cmd_flag_none,
2586 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 cli_cmd_flag_none,
2589 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 cli_cmd_flag_sensitive,
2592 "<network id> <variable> <value> = set network variables (shows\n"
2593 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_none,
2596 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002597 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002598 cli_cmd_flag_none,
2599 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002601 cli_cmd_flag_none,
2602 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002603 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002604 cli_cmd_flag_none,
2605 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002607 cli_cmd_flag_sensitive,
2608 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002609 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2610 cli_cmd_flag_none,
2611 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 cli_cmd_flag_none,
2614 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 cli_cmd_flag_none,
2617 "= disconnect and wait for reassociate/reconnect command before\n"
2618 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 cli_cmd_flag_none,
2621 "= like reassociate, but only takes effect if already disconnected"
2622 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_none,
2625 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002626 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 cli_cmd_flag_none,
2628 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002629 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 cli_cmd_flag_none,
2631 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002634 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002635 "= get capabilies" },
2636 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 cli_cmd_flag_none,
2638 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002639 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 cli_cmd_flag_none,
2641 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 cli_cmd_flag_none,
2644 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2645 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2646 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_none,
2649 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 cli_cmd_flag_none,
2652 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 cli_cmd_flag_none,
2655 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 cli_cmd_flag_none,
2658 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 cli_cmd_flag_none,
2661 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 cli_cmd_flag_none,
2664 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002666 cli_cmd_flag_none,
2667 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_none,
2670 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 cli_cmd_flag_none,
2673 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 cli_cmd_flag_sensitive,
2679 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2680 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002681 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 cli_cmd_flag_sensitive,
2683 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002686#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002688 cli_cmd_flag_none,
2689 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002690 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2691 cli_cmd_flag_none,
2692 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002693 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002694 cli_cmd_flag_none,
2695 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002696 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002697 cli_cmd_flag_sensitive,
2698 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002699 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2700 cli_cmd_flag_none,
2701 "<NDEF> <WPS> = create NFC handover request" },
2702 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2703 cli_cmd_flag_none,
2704 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002705 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2706 cli_cmd_flag_none,
2707 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002708 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2709 cli_cmd_flag_none,
2710 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2711 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002712#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 cli_cmd_flag_sensitive,
2715 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 cli_cmd_flag_sensitive,
2718 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 cli_cmd_flag_none,
2721 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002722 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002723 cli_cmd_flag_none,
2724 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 cli_cmd_flag_sensitive,
2727 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 cli_cmd_flag_none,
2730 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 cli_cmd_flag_sensitive,
2733 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 cli_cmd_flag_none,
2736 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 cli_cmd_flag_sensitive,
2739 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002740#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002742 cli_cmd_flag_none,
2743 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2744#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 cli_cmd_flag_none,
2747 "<addr> = request RSN authentication with <addr> in IBSS" },
2748#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 cli_cmd_flag_none,
2751 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002752 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753 cli_cmd_flag_none,
2754 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002755 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002756 cli_cmd_flag_none,
2757 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002759 cli_cmd_flag_none,
2760 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002761 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2762 cli_cmd_flag_none,
2763 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2764 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2765 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002769 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002770 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002773 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 cli_cmd_flag_none,
2775 "<addr> = roam to the specified BSS" },
2776#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2778 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2783 cli_cmd_flag_none,
2784 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2785 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2788 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002790 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2791 "[ht40] = add a new P2P group (local end as GO)" },
2792 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2793 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002794 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 cli_cmd_flag_none,
2797 "= get the passphrase for a group (GO only)" },
2798 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 "<addr> <TLVs> = schedule service discovery request" },
2801 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805 cli_cmd_flag_none,
2806 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808 cli_cmd_flag_none,
2809 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002810 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 cli_cmd_flag_none,
2812 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002813 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 cli_cmd_flag_none,
2815 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002816 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002817 cli_cmd_flag_none,
2818 "<bonjour|upnp> <query|version> <response|service> = add a local "
2819 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002820 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821 cli_cmd_flag_none,
2822 "<bonjour|upnp> <query|version> [|service] = remove a local "
2823 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002824 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002825 cli_cmd_flag_none,
2826 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 cli_cmd_flag_none,
2829 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002830 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831 "[discovered] = list known (optionally, only fully discovered) P2P "
2832 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002833 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2834 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002836 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2837 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002839 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002841 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2844 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002846 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2847 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848 "[<duration> <interval>] [<duration> <interval>] = request GO "
2849 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002850 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2851 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002852 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002853 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2854 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2855 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002857#ifdef CONFIG_WIFI_DISPLAY
2858 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2859 cli_cmd_flag_none,
2860 "<subelem> [contents] = set Wi-Fi Display subelement" },
2861 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2862 cli_cmd_flag_none,
2863 "<subelem> = get Wi-Fi Display subelement" },
2864#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002865#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002866 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002867 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002868 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2869 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002870 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002871 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002872 cli_cmd_flag_none,
2873 "[auto] = perform Interworking network selection" },
2874 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002875 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002876 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002877 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2878 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002879 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002880 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2881 cli_cmd_flag_none,
2882 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2883 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2884 wpa_cli_complete_bss, cli_cmd_flag_none,
2885 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002886#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002887#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002888 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2889 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002890 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2891 },
2892 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002893 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002894 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002895 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2896 wpa_cli_complete_bss, cli_cmd_flag_none,
2897 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2898 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2899 "= fetch OSU provider information from all APs" },
2900 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2901 cli_cmd_flag_none,
2902 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002903#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002904 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2905 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002907 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 cli_cmd_flag_none,
2909 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002910 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002911 cli_cmd_flag_none,
2912 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002913 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002914 cli_cmd_flag_none,
2915 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002916 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917 cli_cmd_flag_none,
2918 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002919 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002920 cli_cmd_flag_none,
2921 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002922 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2923 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002924 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002925#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002926 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002927 "[params] = Set or unset (if none) autoscan parameters" },
2928#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002929#ifdef CONFIG_WNM
2930 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2931 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002932 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2933 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002934#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002935 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2936 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002937 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2938 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002939#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002940 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002941 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002942#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002943 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2944 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002945 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2946 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2947 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002948 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949};
2950
2951
2952/*
2953 * Prints command usage, lines are padded with the specified string.
2954 */
2955static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2956{
2957 char c;
2958 size_t n;
2959
2960 printf("%s%s ", pad, cmd->cmd);
2961 for (n = 0; (c = cmd->usage[n]); n++) {
2962 printf("%c", c);
2963 if (c == '\n')
2964 printf("%s", pad);
2965 }
2966 printf("\n");
2967}
2968
2969
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002970static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971{
2972 int n;
2973 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002974 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2975 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2976 print_cmd_help(&wpa_cli_commands[n], " ");
2977 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002978}
2979
2980
2981static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2982{
2983 const char *c, *delim;
2984 int n;
2985 size_t len;
2986
2987 delim = os_strchr(cmd, ' ');
2988 if (delim)
2989 len = delim - cmd;
2990 else
2991 len = os_strlen(cmd);
2992
2993 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2994 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2995 return (wpa_cli_commands[n].flags &
2996 cli_cmd_flag_sensitive);
2997 }
2998 return 0;
2999}
3000
3001
3002static char ** wpa_list_cmd_list(void)
3003{
3004 char **res;
3005 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003006 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003008 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003009 count += dl_list_len(&p2p_groups);
3010 count += dl_list_len(&ifnames);
3011 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003012 if (res == NULL)
3013 return NULL;
3014
3015 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3016 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3017 if (res[i] == NULL)
3018 break;
3019 }
3020
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003021 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3022 size_t len = 8 + os_strlen(e->txt);
3023 res[i] = os_malloc(len);
3024 if (res[i] == NULL)
3025 break;
3026 os_snprintf(res[i], len, "ifname=%s", e->txt);
3027 i++;
3028 }
3029
3030 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3031 res[i] = os_strdup(e->txt);
3032 if (res[i] == NULL)
3033 break;
3034 i++;
3035 }
3036
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037 return res;
3038}
3039
3040
3041static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3042 int pos)
3043{
3044 int i;
3045
3046 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3047 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003048 if (wpa_cli_commands[i].completion)
3049 return wpa_cli_commands[i].completion(str,
3050 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 edit_clear_line();
3052 printf("\r%s\n", wpa_cli_commands[i].usage);
3053 edit_redraw();
3054 break;
3055 }
3056 }
3057
3058 return NULL;
3059}
3060
3061
3062static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3063{
3064 char **res;
3065 const char *end;
3066 char *cmd;
3067
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003068 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3069 end = os_strchr(str, ' ');
3070 if (end && pos > end - str) {
3071 pos -= end - str + 1;
3072 str = end + 1;
3073 }
3074 }
3075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 end = os_strchr(str, ' ');
3077 if (end == NULL || str + pos < end)
3078 return wpa_list_cmd_list();
3079
3080 cmd = os_malloc(pos + 1);
3081 if (cmd == NULL)
3082 return NULL;
3083 os_memcpy(cmd, str, pos);
3084 cmd[end - str] = '\0';
3085 res = wpa_cli_cmd_completion(cmd, str, pos);
3086 os_free(cmd);
3087 return res;
3088}
3089
3090
3091static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3092{
3093 struct wpa_cli_cmd *cmd, *match = NULL;
3094 int count;
3095 int ret = 0;
3096
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003097 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3098 ifname_prefix = argv[0] + 7;
3099 argv = &argv[1];
3100 argc--;
3101 } else
3102 ifname_prefix = NULL;
3103
3104 if (argc == 0)
3105 return -1;
3106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003107 count = 0;
3108 cmd = wpa_cli_commands;
3109 while (cmd->cmd) {
3110 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3111 {
3112 match = cmd;
3113 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3114 /* we have an exact match */
3115 count = 1;
3116 break;
3117 }
3118 count++;
3119 }
3120 cmd++;
3121 }
3122
3123 if (count > 1) {
3124 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3125 cmd = wpa_cli_commands;
3126 while (cmd->cmd) {
3127 if (os_strncasecmp(cmd->cmd, argv[0],
3128 os_strlen(argv[0])) == 0) {
3129 printf(" %s", cmd->cmd);
3130 }
3131 cmd++;
3132 }
3133 printf("\n");
3134 ret = 1;
3135 } else if (count == 0) {
3136 printf("Unknown command '%s'\n", argv[0]);
3137 ret = 1;
3138 } else {
3139 ret = match->handler(ctrl, argc - 1, &argv[1]);
3140 }
3141
3142 return ret;
3143}
3144
3145
3146static int str_match(const char *a, const char *b)
3147{
3148 return os_strncmp(a, b, os_strlen(b)) == 0;
3149}
3150
3151
3152static int wpa_cli_exec(const char *program, const char *arg1,
3153 const char *arg2)
3154{
3155 char *cmd;
3156 size_t len;
3157 int res;
3158 int ret = 0;
3159
3160 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3161 cmd = os_malloc(len);
3162 if (cmd == NULL)
3163 return -1;
3164 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3165 if (res < 0 || (size_t) res >= len) {
3166 os_free(cmd);
3167 return -1;
3168 }
3169 cmd[len - 1] = '\0';
3170#ifndef _WIN32_WCE
3171 if (system(cmd) < 0)
3172 ret = -1;
3173#endif /* _WIN32_WCE */
3174 os_free(cmd);
3175
3176 return ret;
3177}
3178
3179
3180static void wpa_cli_action_process(const char *msg)
3181{
3182 const char *pos;
3183 char *copy = NULL, *id, *pos2;
3184
3185 pos = msg;
3186 if (*pos == '<') {
3187 /* skip priority */
3188 pos = os_strchr(pos, '>');
3189 if (pos)
3190 pos++;
3191 else
3192 pos = msg;
3193 }
3194
3195 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3196 int new_id = -1;
3197 os_unsetenv("WPA_ID");
3198 os_unsetenv("WPA_ID_STR");
3199 os_unsetenv("WPA_CTRL_DIR");
3200
3201 pos = os_strstr(pos, "[id=");
3202 if (pos)
3203 copy = os_strdup(pos + 4);
3204
3205 if (copy) {
3206 pos2 = id = copy;
3207 while (*pos2 && *pos2 != ' ')
3208 pos2++;
3209 *pos2++ = '\0';
3210 new_id = atoi(id);
3211 os_setenv("WPA_ID", id, 1);
3212 while (*pos2 && *pos2 != '=')
3213 pos2++;
3214 if (*pos2 == '=')
3215 pos2++;
3216 id = pos2;
3217 while (*pos2 && *pos2 != ']')
3218 pos2++;
3219 *pos2 = '\0';
3220 os_setenv("WPA_ID_STR", id, 1);
3221 os_free(copy);
3222 }
3223
3224 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3225
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003226 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003227 wpa_cli_connected = 1;
3228 wpa_cli_last_id = new_id;
3229 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3230 }
3231 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3232 if (wpa_cli_connected) {
3233 wpa_cli_connected = 0;
3234 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3235 }
3236 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3237 wpa_cli_exec(action_file, ctrl_ifname, pos);
3238 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3239 wpa_cli_exec(action_file, ctrl_ifname, pos);
3240 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3241 wpa_cli_exec(action_file, ctrl_ifname, pos);
3242 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3243 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003244 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3245 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3247 wpa_cli_exec(action_file, ctrl_ifname, pos);
3248 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3249 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003250 } else if (str_match(pos, AP_STA_CONNECTED)) {
3251 wpa_cli_exec(action_file, ctrl_ifname, pos);
3252 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3253 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003254 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3255 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003256 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3257 wpa_cli_exec(action_file, ctrl_ifname, pos);
3258 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3259 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3261 printf("wpa_supplicant is terminating - stop monitoring\n");
3262 wpa_cli_quit = 1;
3263 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003264}
3265
3266
3267#ifndef CONFIG_ANSI_C_EXTRA
3268static void wpa_cli_action_cb(char *msg, size_t len)
3269{
3270 wpa_cli_action_process(msg);
3271}
3272#endif /* CONFIG_ANSI_C_EXTRA */
3273
3274
3275static void wpa_cli_reconnect(void)
3276{
3277 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003278 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3279 return;
3280
3281 if (interactive) {
3282 edit_clear_line();
3283 printf("\rConnection to wpa_supplicant re-established\n");
3284 edit_redraw();
3285 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003286}
3287
3288
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003289static void cli_event(const char *str)
3290{
3291 const char *start, *s;
3292
3293 start = os_strchr(str, '>');
3294 if (start == NULL)
3295 return;
3296
3297 start++;
3298
3299 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3300 s = os_strchr(start, ' ');
3301 if (s == NULL)
3302 return;
3303 s = os_strchr(s + 1, ' ');
3304 if (s == NULL)
3305 return;
3306 cli_txt_list_add(&bsses, s + 1);
3307 return;
3308 }
3309
3310 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3311 s = os_strchr(start, ' ');
3312 if (s == NULL)
3313 return;
3314 s = os_strchr(s + 1, ' ');
3315 if (s == NULL)
3316 return;
3317 cli_txt_list_del_addr(&bsses, s + 1);
3318 return;
3319 }
3320
3321#ifdef CONFIG_P2P
3322 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3323 s = os_strstr(start, " p2p_dev_addr=");
3324 if (s == NULL)
3325 return;
3326 cli_txt_list_add_addr(&p2p_peers, s + 14);
3327 return;
3328 }
3329
3330 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3331 s = os_strstr(start, " p2p_dev_addr=");
3332 if (s == NULL)
3333 return;
3334 cli_txt_list_del_addr(&p2p_peers, s + 14);
3335 return;
3336 }
3337
3338 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3339 s = os_strchr(start, ' ');
3340 if (s == NULL)
3341 return;
3342 cli_txt_list_add_word(&p2p_groups, s + 1);
3343 return;
3344 }
3345
3346 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3347 s = os_strchr(start, ' ');
3348 if (s == NULL)
3349 return;
3350 cli_txt_list_del_word(&p2p_groups, s + 1);
3351 return;
3352 }
3353#endif /* CONFIG_P2P */
3354}
3355
3356
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003357static int check_terminating(const char *msg)
3358{
3359 const char *pos = msg;
3360
3361 if (*pos == '<') {
3362 /* skip priority */
3363 pos = os_strchr(pos, '>');
3364 if (pos)
3365 pos++;
3366 else
3367 pos = msg;
3368 }
3369
3370 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3371 edit_clear_line();
3372 printf("\rConnection to wpa_supplicant lost - trying to "
3373 "reconnect\n");
3374 edit_redraw();
3375 wpa_cli_attached = 0;
3376 wpa_cli_close_connection();
3377 return 1;
3378 }
3379
3380 return 0;
3381}
3382
3383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003384static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3385{
3386 if (ctrl_conn == NULL) {
3387 wpa_cli_reconnect();
3388 return;
3389 }
3390 while (wpa_ctrl_pending(ctrl) > 0) {
3391 char buf[256];
3392 size_t len = sizeof(buf) - 1;
3393 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3394 buf[len] = '\0';
3395 if (action_monitor)
3396 wpa_cli_action_process(buf);
3397 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003398 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003399 if (wpa_cli_show_event(buf)) {
3400 edit_clear_line();
3401 printf("\r%s\n", buf);
3402 edit_redraw();
3403 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003404
3405 if (interactive && check_terminating(buf) > 0)
3406 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407 }
3408 } else {
3409 printf("Could not read pending message.\n");
3410 break;
3411 }
3412 }
3413
3414 if (wpa_ctrl_pending(ctrl) < 0) {
3415 printf("Connection to wpa_supplicant lost - trying to "
3416 "reconnect\n");
3417 wpa_cli_reconnect();
3418 }
3419}
3420
3421#define max_args 10
3422
3423static int tokenize_cmd(char *cmd, char *argv[])
3424{
3425 char *pos;
3426 int argc = 0;
3427
3428 pos = cmd;
3429 for (;;) {
3430 while (*pos == ' ')
3431 pos++;
3432 if (*pos == '\0')
3433 break;
3434 argv[argc] = pos;
3435 argc++;
3436 if (argc == max_args)
3437 break;
3438 if (*pos == '"') {
3439 char *pos2 = os_strrchr(pos, '"');
3440 if (pos2)
3441 pos = pos2 + 1;
3442 }
3443 while (*pos != '\0' && *pos != ' ')
3444 pos++;
3445 if (*pos == ' ')
3446 *pos++ = '\0';
3447 }
3448
3449 return argc;
3450}
3451
3452
3453static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3454{
3455 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3456 printf("Connection to wpa_supplicant lost - trying to "
3457 "reconnect\n");
3458 wpa_cli_close_connection();
3459 }
3460 if (!ctrl_conn)
3461 wpa_cli_reconnect();
3462 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3463}
3464
3465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3467{
3468 wpa_cli_recv_pending(mon_conn, 0);
3469}
3470
3471
3472static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3473{
3474 char *argv[max_args];
3475 int argc;
3476 argc = tokenize_cmd(cmd, argv);
3477 if (argc)
3478 wpa_request(ctrl_conn, argc, argv);
3479}
3480
3481
3482static void wpa_cli_edit_eof_cb(void *ctx)
3483{
3484 eloop_terminate();
3485}
3486
3487
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003488static int warning_displayed = 0;
3489static char *hfile = NULL;
3490static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003492static void start_edit(void)
3493{
3494 char *home;
3495 char *ps = NULL;
3496
3497#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3498 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3499#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003500
3501 home = getenv("HOME");
3502 if (home) {
3503 const char *fname = ".wpa_cli_history";
3504 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3505 hfile = os_malloc(hfile_len);
3506 if (hfile)
3507 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3508 }
3509
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003510 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3511 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3512 eloop_terminate();
3513 return;
3514 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003516 edit_started = 1;
3517 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3518}
3519
3520
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003521static void update_bssid_list(struct wpa_ctrl *ctrl)
3522{
3523 char buf[4096];
3524 size_t len = sizeof(buf);
3525 int ret;
3526 char *cmd = "BSS RANGE=ALL MASK=0x2";
3527 char *pos, *end;
3528
3529 if (ctrl == NULL)
3530 return;
3531 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3532 if (ret < 0)
3533 return;
3534 buf[len] = '\0';
3535
3536 pos = buf;
3537 while (pos) {
3538 pos = os_strstr(pos, "bssid=");
3539 if (pos == NULL)
3540 break;
3541 pos += 6;
3542 end = os_strchr(pos, '\n');
3543 if (end == NULL)
3544 break;
3545 *end = '\0';
3546 cli_txt_list_add(&bsses, pos);
3547 pos = end + 1;
3548 }
3549}
3550
3551
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003552static void update_ifnames(struct wpa_ctrl *ctrl)
3553{
3554 char buf[4096];
3555 size_t len = sizeof(buf);
3556 int ret;
3557 char *cmd = "INTERFACES";
3558 char *pos, *end;
3559 char txt[200];
3560
3561 cli_txt_list_flush(&ifnames);
3562
3563 if (ctrl == NULL)
3564 return;
3565 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3566 if (ret < 0)
3567 return;
3568 buf[len] = '\0';
3569
3570 pos = buf;
3571 while (pos) {
3572 end = os_strchr(pos, '\n');
3573 if (end == NULL)
3574 break;
3575 *end = '\0';
3576 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3577 if (ret > 0 && ret < (int) sizeof(txt))
3578 cli_txt_list_add(&ifnames, txt);
3579 pos = end + 1;
3580 }
3581}
3582
3583
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003584static void try_connection(void *eloop_ctx, void *timeout_ctx)
3585{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003586 if (ctrl_conn)
3587 goto done;
3588
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003589 if (ctrl_ifname == NULL)
3590 ctrl_ifname = wpa_cli_get_default_ifname();
3591
3592 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3593 if (!warning_displayed) {
3594 printf("Could not connect to wpa_supplicant: "
3595 "%s - re-trying\n", ctrl_ifname);
3596 warning_displayed = 1;
3597 }
3598 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3599 return;
3600 }
3601
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003602 update_bssid_list(ctrl_conn);
3603
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003604 if (warning_displayed)
3605 printf("Connection established.\n");
3606
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003607done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003608 start_edit();
3609}
3610
3611
3612static void wpa_cli_interactive(void)
3613{
3614 printf("\nInteractive mode\n\n");
3615
3616 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003618 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003620 cli_txt_list_flush(&p2p_peers);
3621 cli_txt_list_flush(&p2p_groups);
3622 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003623 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003624 if (edit_started)
3625 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003626 os_free(hfile);
3627 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3628 wpa_cli_close_connection();
3629}
3630
3631
3632static void wpa_cli_action(struct wpa_ctrl *ctrl)
3633{
3634#ifdef CONFIG_ANSI_C_EXTRA
3635 /* TODO: ANSI C version(?) */
3636 printf("Action processing not supported in ANSI C build.\n");
3637#else /* CONFIG_ANSI_C_EXTRA */
3638 fd_set rfds;
3639 int fd, res;
3640 struct timeval tv;
3641 char buf[256]; /* note: large enough to fit in unsolicited messages */
3642 size_t len;
3643
3644 fd = wpa_ctrl_get_fd(ctrl);
3645
3646 while (!wpa_cli_quit) {
3647 FD_ZERO(&rfds);
3648 FD_SET(fd, &rfds);
3649 tv.tv_sec = ping_interval;
3650 tv.tv_usec = 0;
3651 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3652 if (res < 0 && errno != EINTR) {
3653 perror("select");
3654 break;
3655 }
3656
3657 if (FD_ISSET(fd, &rfds))
3658 wpa_cli_recv_pending(ctrl, 1);
3659 else {
3660 /* verify that connection is still working */
3661 len = sizeof(buf) - 1;
3662 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3663 wpa_cli_action_cb) < 0 ||
3664 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3665 printf("wpa_supplicant did not reply to PING "
3666 "command - exiting\n");
3667 break;
3668 }
3669 }
3670 }
3671#endif /* CONFIG_ANSI_C_EXTRA */
3672}
3673
3674
3675static void wpa_cli_cleanup(void)
3676{
3677 wpa_cli_close_connection();
3678 if (pid_file)
3679 os_daemonize_terminate(pid_file);
3680
3681 os_program_deinit();
3682}
3683
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003684
3685static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003687 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003688}
3689
3690
3691static char * wpa_cli_get_default_ifname(void)
3692{
3693 char *ifname = NULL;
3694
3695#ifdef CONFIG_CTRL_IFACE_UNIX
3696 struct dirent *dent;
3697 DIR *dir = opendir(ctrl_iface_dir);
3698 if (!dir) {
3699#ifdef ANDROID
3700 char ifprop[PROPERTY_VALUE_MAX];
3701 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3702 ifname = os_strdup(ifprop);
3703 printf("Using interface '%s'\n", ifname);
3704 return ifname;
3705 }
3706#endif /* ANDROID */
3707 return NULL;
3708 }
3709 while ((dent = readdir(dir))) {
3710#ifdef _DIRENT_HAVE_D_TYPE
3711 /*
3712 * Skip the file if it is not a socket. Also accept
3713 * DT_UNKNOWN (0) in case the C library or underlying
3714 * file system does not support d_type.
3715 */
3716 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3717 continue;
3718#endif /* _DIRENT_HAVE_D_TYPE */
3719 if (os_strcmp(dent->d_name, ".") == 0 ||
3720 os_strcmp(dent->d_name, "..") == 0)
3721 continue;
3722 printf("Selected interface '%s'\n", dent->d_name);
3723 ifname = os_strdup(dent->d_name);
3724 break;
3725 }
3726 closedir(dir);
3727#endif /* CONFIG_CTRL_IFACE_UNIX */
3728
3729#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003730 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 size_t len;
3732 struct wpa_ctrl *ctrl;
3733 int ret;
3734
3735 ctrl = wpa_ctrl_open(NULL);
3736 if (ctrl == NULL)
3737 return NULL;
3738
3739 len = sizeof(buf) - 1;
3740 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3741 if (ret >= 0) {
3742 buf[len] = '\0';
3743 pos = os_strchr(buf, '\n');
3744 if (pos)
3745 *pos = '\0';
3746 ifname = os_strdup(buf);
3747 }
3748 wpa_ctrl_close(ctrl);
3749#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3750
3751 return ifname;
3752}
3753
3754
3755int main(int argc, char *argv[])
3756{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 int c;
3758 int daemonize = 0;
3759 int ret = 0;
3760 const char *global = NULL;
3761
3762 if (os_program_init())
3763 return -1;
3764
3765 for (;;) {
3766 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3767 if (c < 0)
3768 break;
3769 switch (c) {
3770 case 'a':
3771 action_file = optarg;
3772 break;
3773 case 'B':
3774 daemonize = 1;
3775 break;
3776 case 'g':
3777 global = optarg;
3778 break;
3779 case 'G':
3780 ping_interval = atoi(optarg);
3781 break;
3782 case 'h':
3783 usage();
3784 return 0;
3785 case 'v':
3786 printf("%s\n", wpa_cli_version);
3787 return 0;
3788 case 'i':
3789 os_free(ctrl_ifname);
3790 ctrl_ifname = os_strdup(optarg);
3791 break;
3792 case 'p':
3793 ctrl_iface_dir = optarg;
3794 break;
3795 case 'P':
3796 pid_file = optarg;
3797 break;
3798 default:
3799 usage();
3800 return -1;
3801 }
3802 }
3803
3804 interactive = (argc == optind) && (action_file == NULL);
3805
3806 if (interactive)
3807 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3808
3809 if (eloop_init())
3810 return -1;
3811
3812 if (global) {
3813#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3814 ctrl_conn = wpa_ctrl_open(NULL);
3815#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3816 ctrl_conn = wpa_ctrl_open(global);
3817#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3818 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003819 fprintf(stderr, "Failed to connect to wpa_supplicant "
3820 "global interface: %s error: %s\n",
3821 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822 return -1;
3823 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003824
3825 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003826 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003827 mon_conn = wpa_ctrl_open(global);
3828 if (mon_conn) {
3829 if (wpa_ctrl_attach(mon_conn) == 0) {
3830 wpa_cli_attached = 1;
3831 eloop_register_read_sock(
3832 wpa_ctrl_get_fd(mon_conn),
3833 wpa_cli_mon_receive,
3834 NULL, NULL);
3835 } else {
3836 printf("Failed to open monitor "
3837 "connection through global "
3838 "control interface\n");
3839 }
3840 }
3841 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003842 }
3843
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003844 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845
3846 if (ctrl_ifname == NULL)
3847 ctrl_ifname = wpa_cli_get_default_ifname();
3848
3849 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003850 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003851 } else {
3852 if (!global &&
3853 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003854 fprintf(stderr, "Failed to connect to non-global "
3855 "ctrl_ifname: %s error: %s\n",
3856 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003857 return -1;
3858 }
3859
3860 if (action_file) {
3861 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3862 wpa_cli_attached = 1;
3863 } else {
3864 printf("Warning: Failed to attach to "
3865 "wpa_supplicant.\n");
3866 return -1;
3867 }
3868 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003869
3870 if (daemonize && os_daemonize(pid_file))
3871 return -1;
3872
3873 if (action_file)
3874 wpa_cli_action(ctrl_conn);
3875 else
3876 ret = wpa_request(ctrl_conn, argc - optind,
3877 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003878 }
3879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003880 os_free(ctrl_ifname);
3881 eloop_destroy();
3882 wpa_cli_cleanup();
3883
3884 return ret;
3885}
3886
3887#else /* CONFIG_CTRL_IFACE */
3888int main(int argc, char *argv[])
3889{
3890 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3891 return -1;
3892}
3893#endif /* CONFIG_CTRL_IFACE */