blob: 63ea1df9361902edd315d52ed16f8d3f0495bdb2 [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
679static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
680 char *argv[])
681{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700682 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683}
684
685
686static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689}
690
691
692static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
693 char *argv[])
694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696}
697
698
699static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
700 char *argv[])
701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700702 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700703}
704
705
706static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
707 char *argv[])
708{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700709 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700710}
711
712
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700713static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
714{
715 char cmd[256];
716 int res;
717
718 if (argc < 1)
719 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
720 else
721 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
722 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
723 printf("Too long BSS_FLUSH command.\n");
724 return -1;
725 }
726 return wpa_ctrl_command(ctrl, cmd);
727}
728
729
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
731 char *argv[])
732{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734}
735
736
737static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
738{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700739 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740}
741
742
743static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700745 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746}
747
748
749static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751 if (argc == 0) {
752 printf("Invalid WPS_PIN command: need one or two arguments:\n"
753 "- BSSID: use 'any' to select any\n"
754 "- PIN: optional, used only with devices that have no "
755 "display\n");
756 return -1;
757 }
758
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700759 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760}
761
762
763static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
764 char *argv[])
765{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700766 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767}
768
769
770static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
771 char *argv[])
772{
773 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
774}
775
776
Dmitry Shmidt04949592012-07-19 12:16:46 -0700777#ifdef CONFIG_WPS_NFC
778
779static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
780{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700781 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700782}
783
784
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800785static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
786 char *argv[])
787{
788 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
789}
790
791
Dmitry Shmidt04949592012-07-19 12:16:46 -0700792static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
793 char *argv[])
794{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700795 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700796}
797
798
799static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
800 char *argv[])
801{
802 int ret;
803 char *buf;
804 size_t buflen;
805
806 if (argc != 1) {
807 printf("Invalid 'wps_nfc_tag_read' command - one argument "
808 "is required.\n");
809 return -1;
810 }
811
812 buflen = 18 + os_strlen(argv[0]);
813 buf = os_malloc(buflen);
814 if (buf == NULL)
815 return -1;
816 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
817
818 ret = wpa_ctrl_command(ctrl, buf);
819 os_free(buf);
820
821 return ret;
822}
823
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800824
825static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
826 char *argv[])
827{
828 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
829}
830
831
832static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
833 char *argv[])
834{
835 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
836}
837
838
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800839static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
840 char *argv[])
841{
842 int ret;
843 char *buf;
844 size_t buflen;
845
846 if (argc != 1) {
847 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
848 "is required.\n");
849 return -1;
850 }
851
852 buflen = 21 + os_strlen(argv[0]);
853 buf = os_malloc(buflen);
854 if (buf == NULL)
855 return -1;
856 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
857
858 ret = wpa_ctrl_command(ctrl, buf);
859 os_free(buf);
860
861 return ret;
862}
863
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800864
865static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
866 char *argv[])
867{
868 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
869}
870
Dmitry Shmidt04949592012-07-19 12:16:46 -0700871#endif /* CONFIG_WPS_NFC */
872
873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
875{
876 char cmd[256];
877 int res;
878
879 if (argc == 2)
880 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
881 argv[0], argv[1]);
882 else if (argc == 5 || argc == 6) {
883 char ssid_hex[2 * 32 + 1];
884 char key_hex[2 * 64 + 1];
885 int i;
886
887 ssid_hex[0] = '\0';
888 for (i = 0; i < 32; i++) {
889 if (argv[2][i] == '\0')
890 break;
891 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
892 }
893
894 key_hex[0] = '\0';
895 if (argc == 6) {
896 for (i = 0; i < 64; i++) {
897 if (argv[5][i] == '\0')
898 break;
899 os_snprintf(&key_hex[i * 2], 3, "%02x",
900 argv[5][i]);
901 }
902 }
903
904 res = os_snprintf(cmd, sizeof(cmd),
905 "WPS_REG %s %s %s %s %s %s",
906 argv[0], argv[1], ssid_hex, argv[3], argv[4],
907 key_hex);
908 } else {
909 printf("Invalid WPS_REG command: need two arguments:\n"
910 "- BSSID of the target AP\n"
911 "- AP PIN\n");
912 printf("Alternatively, six arguments can be used to "
913 "reconfigure the AP:\n"
914 "- BSSID of the target AP\n"
915 "- AP PIN\n"
916 "- new SSID\n"
917 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
918 "- new encr (NONE, WEP, TKIP, CCMP)\n"
919 "- new key\n");
920 return -1;
921 }
922
923 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
924 printf("Too long WPS_REG command.\n");
925 return -1;
926 }
927 return wpa_ctrl_command(ctrl, cmd);
928}
929
930
931static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
932 char *argv[])
933{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700934 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935}
936
937
938static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700941 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942}
943
944
945static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947{
948 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
949
950}
951
952
953static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
954 char *argv[])
955{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956 if (argc < 2) {
957 printf("Invalid WPS_ER_PIN command: need at least two "
958 "arguments:\n"
959 "- UUID: use 'any' to select any\n"
960 "- PIN: Enrollee PIN\n"
961 "optional: - Enrollee MAC address\n");
962 return -1;
963 }
964
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700965 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966}
967
968
969static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
970 char *argv[])
971{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700972 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973}
974
975
976static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
977 char *argv[])
978{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 if (argc != 2) {
980 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
981 "- UUID: specify which AP to use\n"
982 "- PIN: AP PIN\n");
983 return -1;
984 }
985
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700986 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987}
988
989
990static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
991 char *argv[])
992{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 if (argc != 2) {
994 printf("Invalid WPS_ER_SET_CONFIG command: need two "
995 "arguments:\n"
996 "- UUID: specify which AP to use\n"
997 "- Network configuration id\n");
998 return -1;
999 }
1000
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001001 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002}
1003
1004
1005static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1006 char *argv[])
1007{
1008 char cmd[256];
1009 int res;
1010
1011 if (argc == 5 || argc == 6) {
1012 char ssid_hex[2 * 32 + 1];
1013 char key_hex[2 * 64 + 1];
1014 int i;
1015
1016 ssid_hex[0] = '\0';
1017 for (i = 0; i < 32; i++) {
1018 if (argv[2][i] == '\0')
1019 break;
1020 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1021 }
1022
1023 key_hex[0] = '\0';
1024 if (argc == 6) {
1025 for (i = 0; i < 64; i++) {
1026 if (argv[5][i] == '\0')
1027 break;
1028 os_snprintf(&key_hex[i * 2], 3, "%02x",
1029 argv[5][i]);
1030 }
1031 }
1032
1033 res = os_snprintf(cmd, sizeof(cmd),
1034 "WPS_ER_CONFIG %s %s %s %s %s %s",
1035 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1036 key_hex);
1037 } else {
1038 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1039 "- AP UUID\n"
1040 "- AP PIN\n"
1041 "- new SSID\n"
1042 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1043 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1044 "- new key\n");
1045 return -1;
1046 }
1047
1048 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1049 printf("Too long WPS_ER_CONFIG command.\n");
1050 return -1;
1051 }
1052 return wpa_ctrl_command(ctrl, cmd);
1053}
1054
1055
Dmitry Shmidt04949592012-07-19 12:16:46 -07001056#ifdef CONFIG_WPS_NFC
1057static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1058 char *argv[])
1059{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001060 if (argc != 2) {
1061 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1062 "arguments:\n"
1063 "- WPS/NDEF: token format\n"
1064 "- UUID: specify which AP to use\n");
1065 return -1;
1066 }
1067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001068 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001069}
1070#endif /* CONFIG_WPS_NFC */
1071
1072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1074{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001075 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076}
1077
1078
1079static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001081 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086{
1087 char cmd[256], *pos, *end;
1088 int i, ret;
1089
1090 if (argc < 2) {
1091 printf("Invalid IDENTITY command: needs two arguments "
1092 "(network id and identity)\n");
1093 return -1;
1094 }
1095
1096 end = cmd + sizeof(cmd);
1097 pos = cmd;
1098 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1099 argv[0], argv[1]);
1100 if (ret < 0 || ret >= end - pos) {
1101 printf("Too long IDENTITY command.\n");
1102 return -1;
1103 }
1104 pos += ret;
1105 for (i = 2; i < argc; i++) {
1106 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1107 if (ret < 0 || ret >= end - pos) {
1108 printf("Too long IDENTITY command.\n");
1109 return -1;
1110 }
1111 pos += ret;
1112 }
1113
1114 return wpa_ctrl_command(ctrl, cmd);
1115}
1116
1117
1118static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1119{
1120 char cmd[256], *pos, *end;
1121 int i, ret;
1122
1123 if (argc < 2) {
1124 printf("Invalid PASSWORD command: needs two arguments "
1125 "(network id and password)\n");
1126 return -1;
1127 }
1128
1129 end = cmd + sizeof(cmd);
1130 pos = cmd;
1131 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1132 argv[0], argv[1]);
1133 if (ret < 0 || ret >= end - pos) {
1134 printf("Too long PASSWORD command.\n");
1135 return -1;
1136 }
1137 pos += ret;
1138 for (i = 2; i < argc; i++) {
1139 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1140 if (ret < 0 || ret >= end - pos) {
1141 printf("Too long PASSWORD command.\n");
1142 return -1;
1143 }
1144 pos += ret;
1145 }
1146
1147 return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1152 char *argv[])
1153{
1154 char cmd[256], *pos, *end;
1155 int i, ret;
1156
1157 if (argc < 2) {
1158 printf("Invalid NEW_PASSWORD command: needs two arguments "
1159 "(network id and password)\n");
1160 return -1;
1161 }
1162
1163 end = cmd + sizeof(cmd);
1164 pos = cmd;
1165 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1166 argv[0], argv[1]);
1167 if (ret < 0 || ret >= end - pos) {
1168 printf("Too long NEW_PASSWORD command.\n");
1169 return -1;
1170 }
1171 pos += ret;
1172 for (i = 2; i < argc; i++) {
1173 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1174 if (ret < 0 || ret >= end - pos) {
1175 printf("Too long NEW_PASSWORD command.\n");
1176 return -1;
1177 }
1178 pos += ret;
1179 }
1180
1181 return wpa_ctrl_command(ctrl, cmd);
1182}
1183
1184
1185static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1186{
1187 char cmd[256], *pos, *end;
1188 int i, ret;
1189
1190 if (argc < 2) {
1191 printf("Invalid PIN command: needs two arguments "
1192 "(network id and pin)\n");
1193 return -1;
1194 }
1195
1196 end = cmd + sizeof(cmd);
1197 pos = cmd;
1198 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1199 argv[0], argv[1]);
1200 if (ret < 0 || ret >= end - pos) {
1201 printf("Too long PIN command.\n");
1202 return -1;
1203 }
1204 pos += ret;
1205 for (i = 2; i < argc; i++) {
1206 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1207 if (ret < 0 || ret >= end - pos) {
1208 printf("Too long PIN command.\n");
1209 return -1;
1210 }
1211 pos += ret;
1212 }
1213 return wpa_ctrl_command(ctrl, cmd);
1214}
1215
1216
1217static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1218{
1219 char cmd[256], *pos, *end;
1220 int i, ret;
1221
1222 if (argc < 2) {
1223 printf("Invalid OTP command: needs two arguments (network "
1224 "id and password)\n");
1225 return -1;
1226 }
1227
1228 end = cmd + sizeof(cmd);
1229 pos = cmd;
1230 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1231 argv[0], argv[1]);
1232 if (ret < 0 || ret >= end - pos) {
1233 printf("Too long OTP command.\n");
1234 return -1;
1235 }
1236 pos += ret;
1237 for (i = 2; i < argc; i++) {
1238 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1239 if (ret < 0 || ret >= end - pos) {
1240 printf("Too long OTP command.\n");
1241 return -1;
1242 }
1243 pos += ret;
1244 }
1245
1246 return wpa_ctrl_command(ctrl, cmd);
1247}
1248
1249
Dmitry Shmidt051af732013-10-22 13:52:46 -07001250static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1251{
1252 char cmd[256], *pos, *end;
1253 int i, ret;
1254
1255 if (argc < 2) {
1256 printf("Invalid SIM command: needs two arguments "
1257 "(network id and SIM operation response)\n");
1258 return -1;
1259 }
1260
1261 end = cmd + sizeof(cmd);
1262 pos = cmd;
1263 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1264 argv[0], argv[1]);
1265 if (ret < 0 || ret >= end - pos) {
1266 printf("Too long SIM command.\n");
1267 return -1;
1268 }
1269 pos += ret;
1270 for (i = 2; i < argc; i++) {
1271 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1272 if (ret < 0 || ret >= end - pos) {
1273 printf("Too long SIM command.\n");
1274 return -1;
1275 }
1276 pos += ret;
1277 }
1278 return wpa_ctrl_command(ctrl, cmd);
1279}
1280
1281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001282static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1283 char *argv[])
1284{
1285 char cmd[256], *pos, *end;
1286 int i, ret;
1287
1288 if (argc < 2) {
1289 printf("Invalid PASSPHRASE command: needs two arguments "
1290 "(network id and passphrase)\n");
1291 return -1;
1292 }
1293
1294 end = cmd + sizeof(cmd);
1295 pos = cmd;
1296 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1297 argv[0], argv[1]);
1298 if (ret < 0 || ret >= end - pos) {
1299 printf("Too long PASSPHRASE command.\n");
1300 return -1;
1301 }
1302 pos += ret;
1303 for (i = 2; i < argc; i++) {
1304 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1305 if (ret < 0 || ret >= end - pos) {
1306 printf("Too long PASSPHRASE command.\n");
1307 return -1;
1308 }
1309 pos += ret;
1310 }
1311
1312 return wpa_ctrl_command(ctrl, cmd);
1313}
1314
1315
1316static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1317{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318 if (argc < 2) {
1319 printf("Invalid BSSID command: needs two arguments (network "
1320 "id and BSSID)\n");
1321 return -1;
1322 }
1323
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001324 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325}
1326
1327
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001328static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1329{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001330 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001331}
1332
1333
1334static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1335{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001336 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001337}
1338
1339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1341 char *argv[])
1342{
1343 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1344}
1345
1346
1347static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1348 char *argv[])
1349{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001350 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001351}
1352
1353
1354static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1355 char *argv[])
1356{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001357 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001358}
1359
1360
1361static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1362 char *argv[])
1363{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001364 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365}
1366
1367
1368static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1369 char *argv[])
1370{
1371 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1372}
1373
1374
1375static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1376 char *argv[])
1377{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001378 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379}
1380
1381
1382static void wpa_cli_show_network_variables(void)
1383{
1384 printf("set_network variables:\n"
1385 " ssid (network name, SSID)\n"
1386 " psk (WPA passphrase or pre-shared key)\n"
1387 " key_mgmt (key management protocol)\n"
1388 " identity (EAP identity)\n"
1389 " password (EAP password)\n"
1390 " ...\n"
1391 "\n"
1392 "Note: Values are entered in the same format as the "
1393 "configuration file is using,\n"
1394 "i.e., strings values need to be inside double quotation "
1395 "marks.\n"
1396 "For example: set_network 1 ssid \"network name\"\n"
1397 "\n"
1398 "Please see wpa_supplicant.conf documentation for full list "
1399 "of\navailable variables.\n");
1400}
1401
1402
1403static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1404 char *argv[])
1405{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 if (argc == 0) {
1407 wpa_cli_show_network_variables();
1408 return 0;
1409 }
1410
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001411 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 printf("Invalid SET_NETWORK command: needs three arguments\n"
1413 "(network id, variable name, and value)\n");
1414 return -1;
1415 }
1416
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001417 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001418}
1419
1420
1421static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1422 char *argv[])
1423{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424 if (argc == 0) {
1425 wpa_cli_show_network_variables();
1426 return 0;
1427 }
1428
1429 if (argc != 2) {
1430 printf("Invalid GET_NETWORK command: needs two arguments\n"
1431 "(network id and variable name)\n");
1432 return -1;
1433 }
1434
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001435 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001436}
1437
1438
Dmitry Shmidt04949592012-07-19 12:16:46 -07001439static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1440 char *argv[])
1441{
1442 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1443}
1444
1445
1446static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1447{
1448 return wpa_ctrl_command(ctrl, "ADD_CRED");
1449}
1450
1451
1452static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1453 char *argv[])
1454{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001455 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001456}
1457
1458
1459static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1460{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001461 if (argc != 3) {
1462 printf("Invalid SET_CRED command: needs three arguments\n"
1463 "(cred id, variable name, and value)\n");
1464 return -1;
1465 }
1466
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001467 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001468}
1469
1470
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001471static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1472 char *argv[])
1473{
1474 return wpa_ctrl_command(ctrl, "DISCONNECT");
1475}
1476
1477
1478static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1479 char *argv[])
1480{
1481 return wpa_ctrl_command(ctrl, "RECONNECT");
1482}
1483
1484
1485static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1486 char *argv[])
1487{
1488 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1489}
1490
1491
1492static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1493{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001494 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001495}
1496
1497
1498static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1499 char *argv[])
1500{
1501 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1502}
1503
1504
1505static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1506{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001507 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508}
1509
1510
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001511static char ** wpa_cli_complete_bss(const char *str, int pos)
1512{
1513 int arg = get_cmd_arg_num(str, pos);
1514 char **res = NULL;
1515
1516 switch (arg) {
1517 case 1:
1518 res = cli_txt_list_array(&bsses);
1519 break;
1520 }
1521
1522 return res;
1523}
1524
1525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1527 char *argv[])
1528{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 if (argc < 1 || argc > 2) {
1530 printf("Invalid GET_CAPABILITY command: need either one or "
1531 "two arguments\n");
1532 return -1;
1533 }
1534
1535 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1536 printf("Invalid GET_CAPABILITY command: second argument, "
1537 "if any, must be 'strict'\n");
1538 return -1;
1539 }
1540
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001541 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542}
1543
1544
1545static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1546{
1547 printf("Available interfaces:\n");
1548 return wpa_ctrl_command(ctrl, "INTERFACES");
1549}
1550
1551
1552static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1553{
1554 if (argc < 1) {
1555 wpa_cli_list_interfaces(ctrl);
1556 return 0;
1557 }
1558
1559 wpa_cli_close_connection();
1560 os_free(ctrl_ifname);
1561 ctrl_ifname = os_strdup(argv[0]);
1562
1563 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1564 printf("Connected to interface '%s.\n", ctrl_ifname);
1565 } else {
1566 printf("Could not connect to interface '%s' - re-trying\n",
1567 ctrl_ifname);
1568 }
1569 return 0;
1570}
1571
1572
1573static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1574 char *argv[])
1575{
1576 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1577}
1578
1579
1580static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1581 char *argv[])
1582{
1583 return wpa_ctrl_command(ctrl, "TERMINATE");
1584}
1585
1586
1587static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1588 char *argv[])
1589{
1590 char cmd[256];
1591 int res;
1592
1593 if (argc < 1) {
1594 printf("Invalid INTERFACE_ADD command: needs at least one "
1595 "argument (interface name)\n"
1596 "All arguments: ifname confname driver ctrl_interface "
1597 "driver_param bridge_name\n");
1598 return -1;
1599 }
1600
1601 /*
1602 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1603 * <driver_param>TAB<bridge_name>
1604 */
1605 res = os_snprintf(cmd, sizeof(cmd),
1606 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1607 argv[0],
1608 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1609 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1610 argc > 5 ? argv[5] : "");
1611 if (res < 0 || (size_t) res >= sizeof(cmd))
1612 return -1;
1613 cmd[sizeof(cmd) - 1] = '\0';
1614 return wpa_ctrl_command(ctrl, cmd);
1615}
1616
1617
1618static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1619 char *argv[])
1620{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001621 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622}
1623
1624
1625static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1626 char *argv[])
1627{
1628 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1629}
1630
1631
1632#ifdef CONFIG_AP
1633static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1634{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001635 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001636}
1637
1638
1639static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1640 char *addr, size_t addr_len)
1641{
1642 char buf[4096], *pos;
1643 size_t len;
1644 int ret;
1645
1646 if (ctrl_conn == NULL) {
1647 printf("Not connected to hostapd - command dropped.\n");
1648 return -1;
1649 }
1650 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001651 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 wpa_cli_msg_cb);
1653 if (ret == -2) {
1654 printf("'%s' command timed out.\n", cmd);
1655 return -2;
1656 } else if (ret < 0) {
1657 printf("'%s' command failed.\n", cmd);
1658 return -1;
1659 }
1660
1661 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001662 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001663 return -1;
1664 printf("%s", buf);
1665
1666 pos = buf;
1667 while (*pos != '\0' && *pos != '\n')
1668 pos++;
1669 *pos = '\0';
1670 os_strlcpy(addr, buf, addr_len);
1671 return 0;
1672}
1673
1674
1675static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1676{
1677 char addr[32], cmd[64];
1678
1679 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1680 return 0;
1681 do {
1682 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1683 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1684
1685 return -1;
1686}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001687
1688
1689static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1690 char *argv[])
1691{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001692 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001693}
1694
1695
1696static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1697 char *argv[])
1698{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001699 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001700}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001701
1702static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1703 char *argv[])
1704{
1705 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1706}
1707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708#endif /* CONFIG_AP */
1709
1710
1711static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1712{
1713 return wpa_ctrl_command(ctrl, "SUSPEND");
1714}
1715
1716
1717static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1718{
1719 return wpa_ctrl_command(ctrl, "RESUME");
1720}
1721
1722
1723static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1724{
1725 return wpa_ctrl_command(ctrl, "DROP_SA");
1726}
1727
1728
1729static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1730{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001731 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732}
1733
1734
1735#ifdef CONFIG_P2P
1736
1737static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1738{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001739 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1740}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001742
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001743static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1744{
1745 char **res = NULL;
1746 int arg = get_cmd_arg_num(str, pos);
1747
1748 res = os_calloc(6, sizeof(char *));
1749 if (res == NULL)
1750 return NULL;
1751 res[0] = os_strdup("type=social");
1752 if (res[0] == NULL) {
1753 os_free(res);
1754 return NULL;
1755 }
1756 res[1] = os_strdup("type=progressive");
1757 if (res[1] == NULL)
1758 return res;
1759 res[2] = os_strdup("delay=");
1760 if (res[2] == NULL)
1761 return res;
1762 res[3] = os_strdup("dev_id=");
1763 if (res[3] == NULL)
1764 return res;
1765 if (arg == 1)
1766 res[4] = os_strdup("[timeout]");
1767
1768 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769}
1770
1771
1772static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1773 char *argv[])
1774{
1775 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1776}
1777
1778
1779static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1780 char *argv[])
1781{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001782 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783}
1784
1785
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001786static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1787{
1788 int arg = get_cmd_arg_num(str, pos);
1789 char **res = NULL;
1790
1791 switch (arg) {
1792 case 1:
1793 res = cli_txt_list_array(&p2p_peers);
1794 break;
1795 }
1796
1797 return res;
1798}
1799
1800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1802 char *argv[])
1803{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001804 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805}
1806
1807
1808static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1809 char *argv[])
1810{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001811 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812}
1813
1814
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001815static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1816{
1817 int arg = get_cmd_arg_num(str, pos);
1818 char **res = NULL;
1819
1820 switch (arg) {
1821 case 1:
1822 res = cli_txt_list_array(&p2p_groups);
1823 break;
1824 }
1825
1826 return res;
1827}
1828
1829
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1831 char *argv[])
1832{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001833 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834}
1835
1836
1837static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1838 char *argv[])
1839{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001840 if (argc != 2 && argc != 3) {
1841 printf("Invalid P2P_PROV_DISC command: needs at least "
1842 "two arguments, address and config method\n"
1843 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844 return -1;
1845 }
1846
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001847 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848}
1849
1850
1851static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1852 char *argv[])
1853{
1854 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1855}
1856
1857
1858static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1859 char *argv[])
1860{
1861 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862
1863 if (argc != 2 && argc != 4) {
1864 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1865 "arguments (address and TLVs) or four arguments "
1866 "(address, \"upnp\", version, search target "
1867 "(SSDP ST:)\n");
1868 return -1;
1869 }
1870
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001871 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001873 return wpa_ctrl_command(ctrl, cmd);
1874}
1875
1876
1877static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1878 int argc, char *argv[])
1879{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001880 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881}
1882
1883
1884static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1885 char *argv[])
1886{
1887 char cmd[4096];
1888 int res;
1889
1890 if (argc != 4) {
1891 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1892 "arguments (freq, address, dialog token, and TLVs)\n");
1893 return -1;
1894 }
1895
1896 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1897 argv[0], argv[1], argv[2], argv[3]);
1898 if (res < 0 || (size_t) res >= sizeof(cmd))
1899 return -1;
1900 cmd[sizeof(cmd) - 1] = '\0';
1901 return wpa_ctrl_command(ctrl, cmd);
1902}
1903
1904
1905static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1906 char *argv[])
1907{
1908 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1909}
1910
1911
1912static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1913 int argc, char *argv[])
1914{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001915 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916}
1917
1918
1919static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1920 char *argv[])
1921{
1922 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1923}
1924
1925
1926static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1927 char *argv[])
1928{
1929 char cmd[4096];
1930 int res;
1931
1932 if (argc != 3 && argc != 4) {
1933 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1934 "arguments\n");
1935 return -1;
1936 }
1937
1938 if (argc == 4)
1939 res = os_snprintf(cmd, sizeof(cmd),
1940 "P2P_SERVICE_ADD %s %s %s %s",
1941 argv[0], argv[1], argv[2], argv[3]);
1942 else
1943 res = os_snprintf(cmd, sizeof(cmd),
1944 "P2P_SERVICE_ADD %s %s %s",
1945 argv[0], argv[1], argv[2]);
1946 if (res < 0 || (size_t) res >= sizeof(cmd))
1947 return -1;
1948 cmd[sizeof(cmd) - 1] = '\0';
1949 return wpa_ctrl_command(ctrl, cmd);
1950}
1951
1952
1953static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1954 char *argv[])
1955{
1956 char cmd[4096];
1957 int res;
1958
1959 if (argc != 2 && argc != 3) {
1960 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1961 "arguments\n");
1962 return -1;
1963 }
1964
1965 if (argc == 3)
1966 res = os_snprintf(cmd, sizeof(cmd),
1967 "P2P_SERVICE_DEL %s %s %s",
1968 argv[0], argv[1], argv[2]);
1969 else
1970 res = os_snprintf(cmd, sizeof(cmd),
1971 "P2P_SERVICE_DEL %s %s",
1972 argv[0], argv[1]);
1973 if (res < 0 || (size_t) res >= sizeof(cmd))
1974 return -1;
1975 cmd[sizeof(cmd) - 1] = '\0';
1976 return wpa_ctrl_command(ctrl, cmd);
1977}
1978
1979
1980static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1981 int argc, char *argv[])
1982{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001983 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984}
1985
1986
1987static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1988 int argc, char *argv[])
1989{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001990 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991}
1992
1993
1994static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1995{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001996 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001997}
1998
1999
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002000static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2001{
2002 int arg = get_cmd_arg_num(str, pos);
2003 char **res = NULL;
2004
2005 switch (arg) {
2006 case 1:
2007 res = cli_txt_list_array(&p2p_peers);
2008 break;
2009 }
2010
2011 return res;
2012}
2013
2014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2016 char *addr, size_t addr_len,
2017 int discovered)
2018{
2019 char buf[4096], *pos;
2020 size_t len;
2021 int ret;
2022
2023 if (ctrl_conn == NULL)
2024 return -1;
2025 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002026 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 wpa_cli_msg_cb);
2028 if (ret == -2) {
2029 printf("'%s' command timed out.\n", cmd);
2030 return -2;
2031 } else if (ret < 0) {
2032 printf("'%s' command failed.\n", cmd);
2033 return -1;
2034 }
2035
2036 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002037 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038 return -1;
2039
2040 pos = buf;
2041 while (*pos != '\0' && *pos != '\n')
2042 pos++;
2043 *pos++ = '\0';
2044 os_strlcpy(addr, buf, addr_len);
2045 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2046 printf("%s\n", addr);
2047 return 0;
2048}
2049
2050
2051static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2052{
2053 char addr[32], cmd[64];
2054 int discovered;
2055
2056 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2057
2058 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2059 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002060 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 do {
2062 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2063 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2064 discovered) == 0);
2065
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002066 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002067}
2068
2069
2070static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2071{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002072 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073}
2074
2075
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002076static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2077{
2078 int arg = get_cmd_arg_num(str, pos);
2079 const char *fields[] = {
2080 "discoverability",
2081 "managed",
2082 "listen_channel",
2083 "ssid_postfix",
2084 "noa",
2085 "ps",
2086 "oppps",
2087 "ctwindow",
2088 "disabled",
2089 "conc_pref",
2090 "force_long_sd",
2091 "peer_filter",
2092 "cross_connect",
2093 "go_apsd",
2094 "client_apsd",
2095 "disallow_freq",
2096 "disc_int",
2097 "per_sta_psk",
2098 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002099 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002100
2101 if (arg == 1) {
2102 char **res = os_calloc(num_fields + 1, sizeof(char *));
2103 if (res == NULL)
2104 return NULL;
2105 for (i = 0; i < num_fields; i++) {
2106 res[i] = os_strdup(fields[i]);
2107 if (res[i] == NULL)
2108 return res;
2109 }
2110 return res;
2111 }
2112
2113 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2114 return cli_txt_list_array(&p2p_peers);
2115
2116 return NULL;
2117}
2118
2119
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2121{
2122 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2123}
2124
2125
2126static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2127 char *argv[])
2128{
2129 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2130}
2131
2132
2133static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2134 char *argv[])
2135{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002136 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137}
2138
2139
2140static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2141 char *argv[])
2142{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002143 if (argc != 0 && argc != 2 && argc != 4) {
2144 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2145 "(preferred duration, interval; in microsecods).\n"
2146 "Optional second pair can be used to provide "
2147 "acceptable values.\n");
2148 return -1;
2149 }
2150
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002151 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152}
2153
2154
2155static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2156 char *argv[])
2157{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002158 if (argc != 0 && argc != 2) {
2159 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2160 "(availability period, availability interval; in "
2161 "millisecods).\n"
2162 "Extended Listen Timing can be cancelled with this "
2163 "command when used without parameters.\n");
2164 return -1;
2165 }
2166
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002167 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2168}
2169
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002170
2171static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2172 char *argv[])
2173{
2174 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2175}
2176
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002177#endif /* CONFIG_P2P */
2178
2179#ifdef CONFIG_WIFI_DISPLAY
2180
2181static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2182 char *argv[])
2183{
2184 char cmd[100];
2185 int res;
2186
2187 if (argc != 1 && argc != 2) {
2188 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2189 "arguments (subelem, hexdump)\n");
2190 return -1;
2191 }
2192
2193 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2194 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 if (res < 0 || (size_t) res >= sizeof(cmd))
2196 return -1;
2197 cmd[sizeof(cmd) - 1] = '\0';
2198 return wpa_ctrl_command(ctrl, cmd);
2199}
2200
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002201
2202static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2203 char *argv[])
2204{
2205 char cmd[100];
2206 int res;
2207
2208 if (argc != 1) {
2209 printf("Invalid WFD_SUBELEM_GET command: needs one "
2210 "argument (subelem)\n");
2211 return -1;
2212 }
2213
2214 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2215 argv[0]);
2216 if (res < 0 || (size_t) res >= sizeof(cmd))
2217 return -1;
2218 cmd[sizeof(cmd) - 1] = '\0';
2219 return wpa_ctrl_command(ctrl, cmd);
2220}
2221#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002222
2223
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002224#ifdef CONFIG_INTERWORKING
2225static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2226 char *argv[])
2227{
2228 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2229}
2230
2231
2232static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2233 char *argv[])
2234{
2235 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2236}
2237
2238
2239static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2240 char *argv[])
2241{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002242 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002243}
2244
2245
2246static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2247 char *argv[])
2248{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002249 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002250}
2251
2252
2253static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2254{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002255 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2256}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002257
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002258
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002259static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2260 char *argv[])
2261{
2262 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2263}
2264
2265
2266static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2267 char *argv[])
2268{
2269 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002270}
2271#endif /* CONFIG_INTERWORKING */
2272
2273
Dmitry Shmidt04949592012-07-19 12:16:46 -07002274#ifdef CONFIG_HS20
2275
2276static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2277 char *argv[])
2278{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002279 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002280}
2281
2282
2283static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2284 char *argv[])
2285{
2286 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002287
2288 if (argc == 0) {
2289 printf("Command needs one or two arguments (dst mac addr and "
2290 "optional home realm)\n");
2291 return -1;
2292 }
2293
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002294 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2295 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002296 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002297
2298 return wpa_ctrl_command(ctrl, cmd);
2299}
2300
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002301
2302static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2303 char *argv[])
2304{
2305 char cmd[512];
2306
2307 if (argc < 2) {
2308 printf("Command needs two arguments (dst mac addr and "
2309 "icon name)\n");
2310 return -1;
2311 }
2312
2313 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2314 return -1;
2315
2316 return wpa_ctrl_command(ctrl, cmd);
2317}
2318
2319
2320static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2321{
2322 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2323}
2324
2325
2326static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2327 char *argv[])
2328{
2329 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2330}
2331
Dmitry Shmidt04949592012-07-19 12:16:46 -07002332#endif /* CONFIG_HS20 */
2333
2334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002335static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2336 char *argv[])
2337{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002338 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002339}
2340
2341
2342static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2343 char *argv[])
2344{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002345 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346}
2347
2348
2349static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2350 char *argv[])
2351{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002352 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353}
2354
2355
2356static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2357 char *argv[])
2358{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002359 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002360}
2361
2362
2363static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2364 char *argv[])
2365{
2366 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2367}
2368
2369
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002370static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2371 char *argv[])
2372{
2373 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2374}
2375
2376
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002377static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2378 char *argv[])
2379{
2380 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2381}
2382
Dmitry Shmidt04949592012-07-19 12:16:46 -07002383
2384#ifdef CONFIG_AUTOSCAN
2385
2386static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2387{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002388 if (argc == 0)
2389 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2390
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002391 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002392}
2393
2394#endif /* CONFIG_AUTOSCAN */
2395
2396
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002397#ifdef CONFIG_WNM
2398
2399static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2400{
2401 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2402}
2403
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002404
2405static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2406{
2407 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2408}
2409
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002410#endif /* CONFIG_WNM */
2411
2412
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002413static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2414{
2415 if (argc == 0)
2416 return -1;
2417 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2418}
2419
2420
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002421#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002422static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2423{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002424 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002425}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002426#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002427
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002429static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2430{
2431 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2432}
2433
2434
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002435static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2436{
2437 return wpa_ctrl_command(ctrl, "FLUSH");
2438}
2439
2440
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002441static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2442{
2443 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2444}
2445
2446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447enum wpa_cli_cmd_flags {
2448 cli_cmd_flag_none = 0x00,
2449 cli_cmd_flag_sensitive = 0x01
2450};
2451
2452struct wpa_cli_cmd {
2453 const char *cmd;
2454 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 enum wpa_cli_cmd_flags flags;
2457 const char *usage;
2458};
2459
2460static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 cli_cmd_flag_none,
2463 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "ifname", wpa_cli_cmd_ifname, NULL,
2465 cli_cmd_flag_none,
2466 "= get current interface name" },
2467 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 cli_cmd_flag_none,
2478 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 "[command] = show usage help" },
2482 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_none,
2484 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002494 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= set variables (shows list of variables when run without "
2497 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 cli_cmd_flag_none,
2509 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_sensitive,
2521 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_sensitive,
2524 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_sensitive,
2527 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_sensitive,
2530 "<network id> <password> = configure one-time-password for an SSID"
2531 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 cli_cmd_flag_sensitive,
2534 "<network id> <passphrase> = configure private key passphrase\n"
2535 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002536 { "sim", wpa_cli_cmd_sim, NULL,
2537 cli_cmd_flag_sensitive,
2538 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 cli_cmd_flag_none,
2541 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002542 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002543 cli_cmd_flag_none,
2544 "<BSSID> = add a BSSID to the blacklist\n"
2545 "blacklist clear = clear the blacklist\n"
2546 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002548 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002549 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002550 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_none,
2553 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_none,
2556 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 cli_cmd_flag_none,
2565 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 cli_cmd_flag_none,
2568 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 cli_cmd_flag_sensitive,
2571 "<network id> <variable> <value> = set network variables (shows\n"
2572 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 cli_cmd_flag_none,
2575 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002577 cli_cmd_flag_none,
2578 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580 cli_cmd_flag_none,
2581 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002583 cli_cmd_flag_none,
2584 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002586 cli_cmd_flag_sensitive,
2587 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_none,
2590 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 cli_cmd_flag_none,
2593 "= disconnect and wait for reassociate/reconnect command before\n"
2594 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596 cli_cmd_flag_none,
2597 "= like reassociate, but only takes effect if already disconnected"
2598 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002599 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 cli_cmd_flag_none,
2601 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_none,
2604 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_none,
2607 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002610 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 "= get capabilies" },
2612 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 cli_cmd_flag_none,
2614 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 cli_cmd_flag_none,
2617 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002618 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 cli_cmd_flag_none,
2620 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2621 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2622 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_none,
2625 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002626 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 cli_cmd_flag_none,
2628 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002629 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 cli_cmd_flag_none,
2631 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 cli_cmd_flag_none,
2634 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002635 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 cli_cmd_flag_none,
2637 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002638 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639 cli_cmd_flag_none,
2640 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002642 cli_cmd_flag_none,
2643 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 cli_cmd_flag_none,
2646 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_none,
2649 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 cli_cmd_flag_none,
2652 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 cli_cmd_flag_sensitive,
2655 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2656 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_sensitive,
2659 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002662#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002664 cli_cmd_flag_none,
2665 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002666 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2667 cli_cmd_flag_none,
2668 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002669 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002670 cli_cmd_flag_none,
2671 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002673 cli_cmd_flag_sensitive,
2674 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002675 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2676 cli_cmd_flag_none,
2677 "<NDEF> <WPS> = create NFC handover request" },
2678 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2679 cli_cmd_flag_none,
2680 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002681 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2682 cli_cmd_flag_none,
2683 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002684 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2685 cli_cmd_flag_none,
2686 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2687 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002688#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_sensitive,
2691 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 cli_cmd_flag_sensitive,
2694 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 cli_cmd_flag_none,
2697 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002698 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 cli_cmd_flag_none,
2700 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 cli_cmd_flag_sensitive,
2703 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 cli_cmd_flag_none,
2706 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 cli_cmd_flag_sensitive,
2709 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002710 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 cli_cmd_flag_none,
2712 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 cli_cmd_flag_sensitive,
2715 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002716#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002718 cli_cmd_flag_none,
2719 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2720#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 cli_cmd_flag_none,
2723 "<addr> = request RSN authentication with <addr> in IBSS" },
2724#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 cli_cmd_flag_none,
2727 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 cli_cmd_flag_none,
2730 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002732 cli_cmd_flag_none,
2733 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002735 cli_cmd_flag_none,
2736 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002737 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2738 cli_cmd_flag_none,
2739 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2740 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2741 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 cli_cmd_flag_none,
2751 "<addr> = roam to the specified BSS" },
2752#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2754 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2759 cli_cmd_flag_none,
2760 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2761 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2764 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002766 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2767 "[ht40] = add a new P2P group (local end as GO)" },
2768 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2769 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002770 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 cli_cmd_flag_none,
2773 "= get the passphrase for a group (GO only)" },
2774 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002775 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776 "<addr> <TLVs> = schedule service discovery request" },
2777 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002778 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 cli_cmd_flag_none,
2782 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002784 cli_cmd_flag_none,
2785 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002786 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787 cli_cmd_flag_none,
2788 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002789 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002790 cli_cmd_flag_none,
2791 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 cli_cmd_flag_none,
2794 "<bonjour|upnp> <query|version> <response|service> = add a local "
2795 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002796 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 cli_cmd_flag_none,
2798 "<bonjour|upnp> <query|version> [|service] = remove a local "
2799 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002800 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801 cli_cmd_flag_none,
2802 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002803 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804 cli_cmd_flag_none,
2805 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002806 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002807 "[discovered] = list known (optionally, only fully discovered) P2P "
2808 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2810 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002812 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2813 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002815 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002817 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002819 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2820 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002822 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2823 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 "[<duration> <interval>] [<duration> <interval>] = request GO "
2825 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002826 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2827 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002829 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2830 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2831 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002833#ifdef CONFIG_WIFI_DISPLAY
2834 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2835 cli_cmd_flag_none,
2836 "<subelem> [contents] = set Wi-Fi Display subelement" },
2837 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2838 cli_cmd_flag_none,
2839 "<subelem> = get Wi-Fi Display subelement" },
2840#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002841#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002842 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002843 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002844 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2845 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002846 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002847 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002848 cli_cmd_flag_none,
2849 "[auto] = perform Interworking network selection" },
2850 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002851 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002852 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002853 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2854 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002855 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2857 cli_cmd_flag_none,
2858 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2859 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2860 wpa_cli_complete_bss, cli_cmd_flag_none,
2861 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002862#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002863#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2865 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002866 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2867 },
2868 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002869 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002870 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002871 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2872 wpa_cli_complete_bss, cli_cmd_flag_none,
2873 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2874 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2875 "= fetch OSU provider information from all APs" },
2876 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2877 cli_cmd_flag_none,
2878 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002879#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002880 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2881 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002882 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002883 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002884 cli_cmd_flag_none,
2885 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002886 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002887 cli_cmd_flag_none,
2888 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002889 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890 cli_cmd_flag_none,
2891 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002892 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 cli_cmd_flag_none,
2894 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002895 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002896 cli_cmd_flag_none,
2897 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002898 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2899 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002900 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002901#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002902 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002903 "[params] = Set or unset (if none) autoscan parameters" },
2904#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002905#ifdef CONFIG_WNM
2906 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2907 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002908 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2909 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002910#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002911 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2912 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002913 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2914 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002915#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002916 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002917 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002918#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002919 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2920 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002921 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2922 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2923 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002924 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925};
2926
2927
2928/*
2929 * Prints command usage, lines are padded with the specified string.
2930 */
2931static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2932{
2933 char c;
2934 size_t n;
2935
2936 printf("%s%s ", pad, cmd->cmd);
2937 for (n = 0; (c = cmd->usage[n]); n++) {
2938 printf("%c", c);
2939 if (c == '\n')
2940 printf("%s", pad);
2941 }
2942 printf("\n");
2943}
2944
2945
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002946static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947{
2948 int n;
2949 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002950 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2951 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2952 print_cmd_help(&wpa_cli_commands[n], " ");
2953 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002954}
2955
2956
2957static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2958{
2959 const char *c, *delim;
2960 int n;
2961 size_t len;
2962
2963 delim = os_strchr(cmd, ' ');
2964 if (delim)
2965 len = delim - cmd;
2966 else
2967 len = os_strlen(cmd);
2968
2969 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2970 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2971 return (wpa_cli_commands[n].flags &
2972 cli_cmd_flag_sensitive);
2973 }
2974 return 0;
2975}
2976
2977
2978static char ** wpa_list_cmd_list(void)
2979{
2980 char **res;
2981 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002982 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002984 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002985 count += dl_list_len(&p2p_groups);
2986 count += dl_list_len(&ifnames);
2987 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002988 if (res == NULL)
2989 return NULL;
2990
2991 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2992 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2993 if (res[i] == NULL)
2994 break;
2995 }
2996
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002997 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2998 size_t len = 8 + os_strlen(e->txt);
2999 res[i] = os_malloc(len);
3000 if (res[i] == NULL)
3001 break;
3002 os_snprintf(res[i], len, "ifname=%s", e->txt);
3003 i++;
3004 }
3005
3006 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3007 res[i] = os_strdup(e->txt);
3008 if (res[i] == NULL)
3009 break;
3010 i++;
3011 }
3012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003013 return res;
3014}
3015
3016
3017static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3018 int pos)
3019{
3020 int i;
3021
3022 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3023 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003024 if (wpa_cli_commands[i].completion)
3025 return wpa_cli_commands[i].completion(str,
3026 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027 edit_clear_line();
3028 printf("\r%s\n", wpa_cli_commands[i].usage);
3029 edit_redraw();
3030 break;
3031 }
3032 }
3033
3034 return NULL;
3035}
3036
3037
3038static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3039{
3040 char **res;
3041 const char *end;
3042 char *cmd;
3043
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003044 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3045 end = os_strchr(str, ' ');
3046 if (end && pos > end - str) {
3047 pos -= end - str + 1;
3048 str = end + 1;
3049 }
3050 }
3051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 end = os_strchr(str, ' ');
3053 if (end == NULL || str + pos < end)
3054 return wpa_list_cmd_list();
3055
3056 cmd = os_malloc(pos + 1);
3057 if (cmd == NULL)
3058 return NULL;
3059 os_memcpy(cmd, str, pos);
3060 cmd[end - str] = '\0';
3061 res = wpa_cli_cmd_completion(cmd, str, pos);
3062 os_free(cmd);
3063 return res;
3064}
3065
3066
3067static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3068{
3069 struct wpa_cli_cmd *cmd, *match = NULL;
3070 int count;
3071 int ret = 0;
3072
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003073 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3074 ifname_prefix = argv[0] + 7;
3075 argv = &argv[1];
3076 argc--;
3077 } else
3078 ifname_prefix = NULL;
3079
3080 if (argc == 0)
3081 return -1;
3082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003083 count = 0;
3084 cmd = wpa_cli_commands;
3085 while (cmd->cmd) {
3086 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3087 {
3088 match = cmd;
3089 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3090 /* we have an exact match */
3091 count = 1;
3092 break;
3093 }
3094 count++;
3095 }
3096 cmd++;
3097 }
3098
3099 if (count > 1) {
3100 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3101 cmd = wpa_cli_commands;
3102 while (cmd->cmd) {
3103 if (os_strncasecmp(cmd->cmd, argv[0],
3104 os_strlen(argv[0])) == 0) {
3105 printf(" %s", cmd->cmd);
3106 }
3107 cmd++;
3108 }
3109 printf("\n");
3110 ret = 1;
3111 } else if (count == 0) {
3112 printf("Unknown command '%s'\n", argv[0]);
3113 ret = 1;
3114 } else {
3115 ret = match->handler(ctrl, argc - 1, &argv[1]);
3116 }
3117
3118 return ret;
3119}
3120
3121
3122static int str_match(const char *a, const char *b)
3123{
3124 return os_strncmp(a, b, os_strlen(b)) == 0;
3125}
3126
3127
3128static int wpa_cli_exec(const char *program, const char *arg1,
3129 const char *arg2)
3130{
3131 char *cmd;
3132 size_t len;
3133 int res;
3134 int ret = 0;
3135
3136 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3137 cmd = os_malloc(len);
3138 if (cmd == NULL)
3139 return -1;
3140 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3141 if (res < 0 || (size_t) res >= len) {
3142 os_free(cmd);
3143 return -1;
3144 }
3145 cmd[len - 1] = '\0';
3146#ifndef _WIN32_WCE
3147 if (system(cmd) < 0)
3148 ret = -1;
3149#endif /* _WIN32_WCE */
3150 os_free(cmd);
3151
3152 return ret;
3153}
3154
3155
3156static void wpa_cli_action_process(const char *msg)
3157{
3158 const char *pos;
3159 char *copy = NULL, *id, *pos2;
3160
3161 pos = msg;
3162 if (*pos == '<') {
3163 /* skip priority */
3164 pos = os_strchr(pos, '>');
3165 if (pos)
3166 pos++;
3167 else
3168 pos = msg;
3169 }
3170
3171 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3172 int new_id = -1;
3173 os_unsetenv("WPA_ID");
3174 os_unsetenv("WPA_ID_STR");
3175 os_unsetenv("WPA_CTRL_DIR");
3176
3177 pos = os_strstr(pos, "[id=");
3178 if (pos)
3179 copy = os_strdup(pos + 4);
3180
3181 if (copy) {
3182 pos2 = id = copy;
3183 while (*pos2 && *pos2 != ' ')
3184 pos2++;
3185 *pos2++ = '\0';
3186 new_id = atoi(id);
3187 os_setenv("WPA_ID", id, 1);
3188 while (*pos2 && *pos2 != '=')
3189 pos2++;
3190 if (*pos2 == '=')
3191 pos2++;
3192 id = pos2;
3193 while (*pos2 && *pos2 != ']')
3194 pos2++;
3195 *pos2 = '\0';
3196 os_setenv("WPA_ID_STR", id, 1);
3197 os_free(copy);
3198 }
3199
3200 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3201
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003202 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003203 wpa_cli_connected = 1;
3204 wpa_cli_last_id = new_id;
3205 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3206 }
3207 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3208 if (wpa_cli_connected) {
3209 wpa_cli_connected = 0;
3210 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3211 }
3212 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3213 wpa_cli_exec(action_file, ctrl_ifname, pos);
3214 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3215 wpa_cli_exec(action_file, ctrl_ifname, pos);
3216 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3217 wpa_cli_exec(action_file, ctrl_ifname, pos);
3218 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3219 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003220 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3221 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003222 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3223 wpa_cli_exec(action_file, ctrl_ifname, pos);
3224 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3225 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003226 } else if (str_match(pos, AP_STA_CONNECTED)) {
3227 wpa_cli_exec(action_file, ctrl_ifname, pos);
3228 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3229 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003230 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3231 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003232 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3233 wpa_cli_exec(action_file, ctrl_ifname, pos);
3234 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3235 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3237 printf("wpa_supplicant is terminating - stop monitoring\n");
3238 wpa_cli_quit = 1;
3239 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003240}
3241
3242
3243#ifndef CONFIG_ANSI_C_EXTRA
3244static void wpa_cli_action_cb(char *msg, size_t len)
3245{
3246 wpa_cli_action_process(msg);
3247}
3248#endif /* CONFIG_ANSI_C_EXTRA */
3249
3250
3251static void wpa_cli_reconnect(void)
3252{
3253 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003254 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3255 return;
3256
3257 if (interactive) {
3258 edit_clear_line();
3259 printf("\rConnection to wpa_supplicant re-established\n");
3260 edit_redraw();
3261 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003262}
3263
3264
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003265static void cli_event(const char *str)
3266{
3267 const char *start, *s;
3268
3269 start = os_strchr(str, '>');
3270 if (start == NULL)
3271 return;
3272
3273 start++;
3274
3275 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3276 s = os_strchr(start, ' ');
3277 if (s == NULL)
3278 return;
3279 s = os_strchr(s + 1, ' ');
3280 if (s == NULL)
3281 return;
3282 cli_txt_list_add(&bsses, s + 1);
3283 return;
3284 }
3285
3286 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3287 s = os_strchr(start, ' ');
3288 if (s == NULL)
3289 return;
3290 s = os_strchr(s + 1, ' ');
3291 if (s == NULL)
3292 return;
3293 cli_txt_list_del_addr(&bsses, s + 1);
3294 return;
3295 }
3296
3297#ifdef CONFIG_P2P
3298 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3299 s = os_strstr(start, " p2p_dev_addr=");
3300 if (s == NULL)
3301 return;
3302 cli_txt_list_add_addr(&p2p_peers, s + 14);
3303 return;
3304 }
3305
3306 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3307 s = os_strstr(start, " p2p_dev_addr=");
3308 if (s == NULL)
3309 return;
3310 cli_txt_list_del_addr(&p2p_peers, s + 14);
3311 return;
3312 }
3313
3314 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3315 s = os_strchr(start, ' ');
3316 if (s == NULL)
3317 return;
3318 cli_txt_list_add_word(&p2p_groups, s + 1);
3319 return;
3320 }
3321
3322 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3323 s = os_strchr(start, ' ');
3324 if (s == NULL)
3325 return;
3326 cli_txt_list_del_word(&p2p_groups, s + 1);
3327 return;
3328 }
3329#endif /* CONFIG_P2P */
3330}
3331
3332
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003333static int check_terminating(const char *msg)
3334{
3335 const char *pos = msg;
3336
3337 if (*pos == '<') {
3338 /* skip priority */
3339 pos = os_strchr(pos, '>');
3340 if (pos)
3341 pos++;
3342 else
3343 pos = msg;
3344 }
3345
3346 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3347 edit_clear_line();
3348 printf("\rConnection to wpa_supplicant lost - trying to "
3349 "reconnect\n");
3350 edit_redraw();
3351 wpa_cli_attached = 0;
3352 wpa_cli_close_connection();
3353 return 1;
3354 }
3355
3356 return 0;
3357}
3358
3359
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003360static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3361{
3362 if (ctrl_conn == NULL) {
3363 wpa_cli_reconnect();
3364 return;
3365 }
3366 while (wpa_ctrl_pending(ctrl) > 0) {
3367 char buf[256];
3368 size_t len = sizeof(buf) - 1;
3369 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3370 buf[len] = '\0';
3371 if (action_monitor)
3372 wpa_cli_action_process(buf);
3373 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003374 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003375 if (wpa_cli_show_event(buf)) {
3376 edit_clear_line();
3377 printf("\r%s\n", buf);
3378 edit_redraw();
3379 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003380
3381 if (interactive && check_terminating(buf) > 0)
3382 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003383 }
3384 } else {
3385 printf("Could not read pending message.\n");
3386 break;
3387 }
3388 }
3389
3390 if (wpa_ctrl_pending(ctrl) < 0) {
3391 printf("Connection to wpa_supplicant lost - trying to "
3392 "reconnect\n");
3393 wpa_cli_reconnect();
3394 }
3395}
3396
3397#define max_args 10
3398
3399static int tokenize_cmd(char *cmd, char *argv[])
3400{
3401 char *pos;
3402 int argc = 0;
3403
3404 pos = cmd;
3405 for (;;) {
3406 while (*pos == ' ')
3407 pos++;
3408 if (*pos == '\0')
3409 break;
3410 argv[argc] = pos;
3411 argc++;
3412 if (argc == max_args)
3413 break;
3414 if (*pos == '"') {
3415 char *pos2 = os_strrchr(pos, '"');
3416 if (pos2)
3417 pos = pos2 + 1;
3418 }
3419 while (*pos != '\0' && *pos != ' ')
3420 pos++;
3421 if (*pos == ' ')
3422 *pos++ = '\0';
3423 }
3424
3425 return argc;
3426}
3427
3428
3429static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3430{
3431 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3432 printf("Connection to wpa_supplicant lost - trying to "
3433 "reconnect\n");
3434 wpa_cli_close_connection();
3435 }
3436 if (!ctrl_conn)
3437 wpa_cli_reconnect();
3438 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3439}
3440
3441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3443{
3444 wpa_cli_recv_pending(mon_conn, 0);
3445}
3446
3447
3448static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3449{
3450 char *argv[max_args];
3451 int argc;
3452 argc = tokenize_cmd(cmd, argv);
3453 if (argc)
3454 wpa_request(ctrl_conn, argc, argv);
3455}
3456
3457
3458static void wpa_cli_edit_eof_cb(void *ctx)
3459{
3460 eloop_terminate();
3461}
3462
3463
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003464static int warning_displayed = 0;
3465static char *hfile = NULL;
3466static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003468static void start_edit(void)
3469{
3470 char *home;
3471 char *ps = NULL;
3472
3473#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3474 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3475#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476
3477 home = getenv("HOME");
3478 if (home) {
3479 const char *fname = ".wpa_cli_history";
3480 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3481 hfile = os_malloc(hfile_len);
3482 if (hfile)
3483 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3484 }
3485
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003486 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3487 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3488 eloop_terminate();
3489 return;
3490 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003492 edit_started = 1;
3493 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3494}
3495
3496
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003497static void update_bssid_list(struct wpa_ctrl *ctrl)
3498{
3499 char buf[4096];
3500 size_t len = sizeof(buf);
3501 int ret;
3502 char *cmd = "BSS RANGE=ALL MASK=0x2";
3503 char *pos, *end;
3504
3505 if (ctrl == NULL)
3506 return;
3507 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3508 if (ret < 0)
3509 return;
3510 buf[len] = '\0';
3511
3512 pos = buf;
3513 while (pos) {
3514 pos = os_strstr(pos, "bssid=");
3515 if (pos == NULL)
3516 break;
3517 pos += 6;
3518 end = os_strchr(pos, '\n');
3519 if (end == NULL)
3520 break;
3521 *end = '\0';
3522 cli_txt_list_add(&bsses, pos);
3523 pos = end + 1;
3524 }
3525}
3526
3527
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003528static void update_ifnames(struct wpa_ctrl *ctrl)
3529{
3530 char buf[4096];
3531 size_t len = sizeof(buf);
3532 int ret;
3533 char *cmd = "INTERFACES";
3534 char *pos, *end;
3535 char txt[200];
3536
3537 cli_txt_list_flush(&ifnames);
3538
3539 if (ctrl == NULL)
3540 return;
3541 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3542 if (ret < 0)
3543 return;
3544 buf[len] = '\0';
3545
3546 pos = buf;
3547 while (pos) {
3548 end = os_strchr(pos, '\n');
3549 if (end == NULL)
3550 break;
3551 *end = '\0';
3552 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3553 if (ret > 0 && ret < (int) sizeof(txt))
3554 cli_txt_list_add(&ifnames, txt);
3555 pos = end + 1;
3556 }
3557}
3558
3559
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003560static void try_connection(void *eloop_ctx, void *timeout_ctx)
3561{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003562 if (ctrl_conn)
3563 goto done;
3564
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003565 if (ctrl_ifname == NULL)
3566 ctrl_ifname = wpa_cli_get_default_ifname();
3567
3568 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3569 if (!warning_displayed) {
3570 printf("Could not connect to wpa_supplicant: "
3571 "%s - re-trying\n", ctrl_ifname);
3572 warning_displayed = 1;
3573 }
3574 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3575 return;
3576 }
3577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003578 update_bssid_list(ctrl_conn);
3579
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003580 if (warning_displayed)
3581 printf("Connection established.\n");
3582
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003583done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003584 start_edit();
3585}
3586
3587
3588static void wpa_cli_interactive(void)
3589{
3590 printf("\nInteractive mode\n\n");
3591
3592 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003593 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003594 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003596 cli_txt_list_flush(&p2p_peers);
3597 cli_txt_list_flush(&p2p_groups);
3598 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003599 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003600 if (edit_started)
3601 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003602 os_free(hfile);
3603 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3604 wpa_cli_close_connection();
3605}
3606
3607
3608static void wpa_cli_action(struct wpa_ctrl *ctrl)
3609{
3610#ifdef CONFIG_ANSI_C_EXTRA
3611 /* TODO: ANSI C version(?) */
3612 printf("Action processing not supported in ANSI C build.\n");
3613#else /* CONFIG_ANSI_C_EXTRA */
3614 fd_set rfds;
3615 int fd, res;
3616 struct timeval tv;
3617 char buf[256]; /* note: large enough to fit in unsolicited messages */
3618 size_t len;
3619
3620 fd = wpa_ctrl_get_fd(ctrl);
3621
3622 while (!wpa_cli_quit) {
3623 FD_ZERO(&rfds);
3624 FD_SET(fd, &rfds);
3625 tv.tv_sec = ping_interval;
3626 tv.tv_usec = 0;
3627 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3628 if (res < 0 && errno != EINTR) {
3629 perror("select");
3630 break;
3631 }
3632
3633 if (FD_ISSET(fd, &rfds))
3634 wpa_cli_recv_pending(ctrl, 1);
3635 else {
3636 /* verify that connection is still working */
3637 len = sizeof(buf) - 1;
3638 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3639 wpa_cli_action_cb) < 0 ||
3640 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3641 printf("wpa_supplicant did not reply to PING "
3642 "command - exiting\n");
3643 break;
3644 }
3645 }
3646 }
3647#endif /* CONFIG_ANSI_C_EXTRA */
3648}
3649
3650
3651static void wpa_cli_cleanup(void)
3652{
3653 wpa_cli_close_connection();
3654 if (pid_file)
3655 os_daemonize_terminate(pid_file);
3656
3657 os_program_deinit();
3658}
3659
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003660
3661static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003663 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664}
3665
3666
3667static char * wpa_cli_get_default_ifname(void)
3668{
3669 char *ifname = NULL;
3670
3671#ifdef CONFIG_CTRL_IFACE_UNIX
3672 struct dirent *dent;
3673 DIR *dir = opendir(ctrl_iface_dir);
3674 if (!dir) {
3675#ifdef ANDROID
3676 char ifprop[PROPERTY_VALUE_MAX];
3677 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3678 ifname = os_strdup(ifprop);
3679 printf("Using interface '%s'\n", ifname);
3680 return ifname;
3681 }
3682#endif /* ANDROID */
3683 return NULL;
3684 }
3685 while ((dent = readdir(dir))) {
3686#ifdef _DIRENT_HAVE_D_TYPE
3687 /*
3688 * Skip the file if it is not a socket. Also accept
3689 * DT_UNKNOWN (0) in case the C library or underlying
3690 * file system does not support d_type.
3691 */
3692 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3693 continue;
3694#endif /* _DIRENT_HAVE_D_TYPE */
3695 if (os_strcmp(dent->d_name, ".") == 0 ||
3696 os_strcmp(dent->d_name, "..") == 0)
3697 continue;
3698 printf("Selected interface '%s'\n", dent->d_name);
3699 ifname = os_strdup(dent->d_name);
3700 break;
3701 }
3702 closedir(dir);
3703#endif /* CONFIG_CTRL_IFACE_UNIX */
3704
3705#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003706 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707 size_t len;
3708 struct wpa_ctrl *ctrl;
3709 int ret;
3710
3711 ctrl = wpa_ctrl_open(NULL);
3712 if (ctrl == NULL)
3713 return NULL;
3714
3715 len = sizeof(buf) - 1;
3716 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3717 if (ret >= 0) {
3718 buf[len] = '\0';
3719 pos = os_strchr(buf, '\n');
3720 if (pos)
3721 *pos = '\0';
3722 ifname = os_strdup(buf);
3723 }
3724 wpa_ctrl_close(ctrl);
3725#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3726
3727 return ifname;
3728}
3729
3730
3731int main(int argc, char *argv[])
3732{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 int c;
3734 int daemonize = 0;
3735 int ret = 0;
3736 const char *global = NULL;
3737
3738 if (os_program_init())
3739 return -1;
3740
3741 for (;;) {
3742 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3743 if (c < 0)
3744 break;
3745 switch (c) {
3746 case 'a':
3747 action_file = optarg;
3748 break;
3749 case 'B':
3750 daemonize = 1;
3751 break;
3752 case 'g':
3753 global = optarg;
3754 break;
3755 case 'G':
3756 ping_interval = atoi(optarg);
3757 break;
3758 case 'h':
3759 usage();
3760 return 0;
3761 case 'v':
3762 printf("%s\n", wpa_cli_version);
3763 return 0;
3764 case 'i':
3765 os_free(ctrl_ifname);
3766 ctrl_ifname = os_strdup(optarg);
3767 break;
3768 case 'p':
3769 ctrl_iface_dir = optarg;
3770 break;
3771 case 'P':
3772 pid_file = optarg;
3773 break;
3774 default:
3775 usage();
3776 return -1;
3777 }
3778 }
3779
3780 interactive = (argc == optind) && (action_file == NULL);
3781
3782 if (interactive)
3783 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3784
3785 if (eloop_init())
3786 return -1;
3787
3788 if (global) {
3789#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3790 ctrl_conn = wpa_ctrl_open(NULL);
3791#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3792 ctrl_conn = wpa_ctrl_open(global);
3793#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3794 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003795 fprintf(stderr, "Failed to connect to wpa_supplicant "
3796 "global interface: %s error: %s\n",
3797 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798 return -1;
3799 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003800
3801 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003802 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003803 mon_conn = wpa_ctrl_open(global);
3804 if (mon_conn) {
3805 if (wpa_ctrl_attach(mon_conn) == 0) {
3806 wpa_cli_attached = 1;
3807 eloop_register_read_sock(
3808 wpa_ctrl_get_fd(mon_conn),
3809 wpa_cli_mon_receive,
3810 NULL, NULL);
3811 } else {
3812 printf("Failed to open monitor "
3813 "connection through global "
3814 "control interface\n");
3815 }
3816 }
3817 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818 }
3819
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003820 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821
3822 if (ctrl_ifname == NULL)
3823 ctrl_ifname = wpa_cli_get_default_ifname();
3824
3825 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003826 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827 } else {
3828 if (!global &&
3829 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003830 fprintf(stderr, "Failed to connect to non-global "
3831 "ctrl_ifname: %s error: %s\n",
3832 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 return -1;
3834 }
3835
3836 if (action_file) {
3837 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3838 wpa_cli_attached = 1;
3839 } else {
3840 printf("Warning: Failed to attach to "
3841 "wpa_supplicant.\n");
3842 return -1;
3843 }
3844 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003845
3846 if (daemonize && os_daemonize(pid_file))
3847 return -1;
3848
3849 if (action_file)
3850 wpa_cli_action(ctrl_conn);
3851 else
3852 ret = wpa_request(ctrl_conn, argc - optind,
3853 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003854 }
3855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003856 os_free(ctrl_ifname);
3857 eloop_destroy();
3858 wpa_cli_cleanup();
3859
3860 return ret;
3861}
3862
3863#else /* CONFIG_CTRL_IFACE */
3864int main(int argc, char *argv[])
3865{
3866 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3867 return -1;
3868}
3869#endif /* CONFIG_CTRL_IFACE */