blob: 77c52954f60dd7717145e159ea16a286b607a55b [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003 * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080031"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700537 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 return 0;
539}
540
541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
567 if (interactive)
568 eloop_terminate();
569 return 0;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700618 "p2p_no_go_freq",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700619 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700620 "p2p_go_vht",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700621 "p2p_ignore_shared_freq", "country", "bss_max_count",
622 "bss_expiration_age", "bss_expiration_scan_count",
623 "filter_ssids", "filter_rssi", "max_num_sta",
624 "disassoc_low_ack", "hs20", "interworking", "hessid",
625 "access_network_type", "pbc_in_m1", "autoscan",
626 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
627 "wps_nfc_dev_pw", "ext_password_backend",
628 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
629 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt97672262014-02-03 13:02:54 -0800630 "ignore_old_scan_res", "freq_list", "external_sim",
631 "tdls_external_control"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700632 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700633 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700634
635 if (arg == 1) {
636 char **res = os_calloc(num_fields + 1, sizeof(char *));
637 if (res == NULL)
638 return NULL;
639 for (i = 0; i < num_fields; i++) {
640 res[i] = os_strdup(fields[i]);
641 if (res[i] == NULL)
642 return res;
643 }
644 return res;
645 }
646
647 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
648 return cli_txt_list_array(&bsses);
649
650 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651}
652
653
654static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700656 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657}
658
659
660static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
661{
662 return wpa_ctrl_command(ctrl, "LOGOFF");
663}
664
665
666static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
668 return wpa_ctrl_command(ctrl, "LOGON");
669}
670
671
672static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "REASSOCIATE");
676}
677
678
Dmitry Shmidt98660862014-03-11 17:26:21 -0700679static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
680{
681 return wpa_ctrl_command(ctrl, "REATTACH");
682}
683
684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
686 char *argv[])
687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689}
690
691
692static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700694 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695}
696
697
698static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702}
703
704
705static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
706 char *argv[])
707{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700708 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709}
710
711
712static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
713 char *argv[])
714{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700715 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716}
717
718
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700719static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
720{
721 char cmd[256];
722 int res;
723
724 if (argc < 1)
725 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
726 else
727 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
728 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
729 printf("Too long BSS_FLUSH command.\n");
730 return -1;
731 }
732 return wpa_ctrl_command(ctrl, cmd);
733}
734
735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
737 char *argv[])
738{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700739 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740}
741
742
743static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700745 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746}
747
748
749static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700751 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752}
753
754
755static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 if (argc == 0) {
758 printf("Invalid WPS_PIN command: need one or two arguments:\n"
759 "- BSSID: use 'any' to select any\n"
760 "- PIN: optional, used only with devices that have no "
761 "display\n");
762 return -1;
763 }
764
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700765 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766}
767
768
769static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
771{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700772 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773}
774
775
776static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
777 char *argv[])
778{
779 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
780}
781
782
Dmitry Shmidt04949592012-07-19 12:16:46 -0700783#ifdef CONFIG_WPS_NFC
784
785static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
786{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700787 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700788}
789
790
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800791static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
792 char *argv[])
793{
794 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
795}
796
797
Dmitry Shmidt04949592012-07-19 12:16:46 -0700798static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
799 char *argv[])
800{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700801 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700802}
803
804
805static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
808 int ret;
809 char *buf;
810 size_t buflen;
811
812 if (argc != 1) {
813 printf("Invalid 'wps_nfc_tag_read' command - one argument "
814 "is required.\n");
815 return -1;
816 }
817
818 buflen = 18 + os_strlen(argv[0]);
819 buf = os_malloc(buflen);
820 if (buf == NULL)
821 return -1;
822 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
823
824 ret = wpa_ctrl_command(ctrl, buf);
825 os_free(buf);
826
827 return ret;
828}
829
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800830
831static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
832 char *argv[])
833{
834 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
835}
836
837
838static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
839 char *argv[])
840{
841 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
842}
843
844
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800845static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
849}
850
Dmitry Shmidt04949592012-07-19 12:16:46 -0700851#endif /* CONFIG_WPS_NFC */
852
853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
855{
856 char cmd[256];
857 int res;
858
859 if (argc == 2)
860 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
861 argv[0], argv[1]);
862 else if (argc == 5 || argc == 6) {
863 char ssid_hex[2 * 32 + 1];
864 char key_hex[2 * 64 + 1];
865 int i;
866
867 ssid_hex[0] = '\0';
868 for (i = 0; i < 32; i++) {
869 if (argv[2][i] == '\0')
870 break;
871 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
872 }
873
874 key_hex[0] = '\0';
875 if (argc == 6) {
876 for (i = 0; i < 64; i++) {
877 if (argv[5][i] == '\0')
878 break;
879 os_snprintf(&key_hex[i * 2], 3, "%02x",
880 argv[5][i]);
881 }
882 }
883
884 res = os_snprintf(cmd, sizeof(cmd),
885 "WPS_REG %s %s %s %s %s %s",
886 argv[0], argv[1], ssid_hex, argv[3], argv[4],
887 key_hex);
888 } else {
889 printf("Invalid WPS_REG command: need two arguments:\n"
890 "- BSSID of the target AP\n"
891 "- AP PIN\n");
892 printf("Alternatively, six arguments can be used to "
893 "reconfigure the AP:\n"
894 "- BSSID of the target AP\n"
895 "- AP PIN\n"
896 "- new SSID\n"
897 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
898 "- new encr (NONE, WEP, TKIP, CCMP)\n"
899 "- new key\n");
900 return -1;
901 }
902
903 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
904 printf("Too long WPS_REG command.\n");
905 return -1;
906 }
907 return wpa_ctrl_command(ctrl, cmd);
908}
909
910
911static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700914 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915}
916
917
918static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700921 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922}
923
924
925static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
927{
928 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
929
930}
931
932
933static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
934 char *argv[])
935{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936 if (argc < 2) {
937 printf("Invalid WPS_ER_PIN command: need at least two "
938 "arguments:\n"
939 "- UUID: use 'any' to select any\n"
940 "- PIN: Enrollee PIN\n"
941 "optional: - Enrollee MAC address\n");
942 return -1;
943 }
944
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700945 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946}
947
948
949static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
950 char *argv[])
951{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700952 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700953}
954
955
956static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
957 char *argv[])
958{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959 if (argc != 2) {
960 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
961 "- UUID: specify which AP to use\n"
962 "- PIN: AP PIN\n");
963 return -1;
964 }
965
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700966 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967}
968
969
970static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
971 char *argv[])
972{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973 if (argc != 2) {
974 printf("Invalid WPS_ER_SET_CONFIG command: need two "
975 "arguments:\n"
976 "- UUID: specify which AP to use\n"
977 "- Network configuration id\n");
978 return -1;
979 }
980
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700981 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982}
983
984
985static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
986 char *argv[])
987{
988 char cmd[256];
989 int res;
990
991 if (argc == 5 || argc == 6) {
992 char ssid_hex[2 * 32 + 1];
993 char key_hex[2 * 64 + 1];
994 int i;
995
996 ssid_hex[0] = '\0';
997 for (i = 0; i < 32; i++) {
998 if (argv[2][i] == '\0')
999 break;
1000 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1001 }
1002
1003 key_hex[0] = '\0';
1004 if (argc == 6) {
1005 for (i = 0; i < 64; i++) {
1006 if (argv[5][i] == '\0')
1007 break;
1008 os_snprintf(&key_hex[i * 2], 3, "%02x",
1009 argv[5][i]);
1010 }
1011 }
1012
1013 res = os_snprintf(cmd, sizeof(cmd),
1014 "WPS_ER_CONFIG %s %s %s %s %s %s",
1015 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1016 key_hex);
1017 } else {
1018 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1019 "- AP UUID\n"
1020 "- AP PIN\n"
1021 "- new SSID\n"
1022 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1023 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1024 "- new key\n");
1025 return -1;
1026 }
1027
1028 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029 printf("Too long WPS_ER_CONFIG command.\n");
1030 return -1;
1031 }
1032 return wpa_ctrl_command(ctrl, cmd);
1033}
1034
1035
Dmitry Shmidt04949592012-07-19 12:16:46 -07001036#ifdef CONFIG_WPS_NFC
1037static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1038 char *argv[])
1039{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001040 if (argc != 2) {
1041 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1042 "arguments:\n"
1043 "- WPS/NDEF: token format\n"
1044 "- UUID: specify which AP to use\n");
1045 return -1;
1046 }
1047
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001048 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049}
1050#endif /* CONFIG_WPS_NFC */
1051
1052
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1054{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001055 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056}
1057
1058
1059static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001061 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062}
1063
1064
1065static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1066{
1067 char cmd[256], *pos, *end;
1068 int i, ret;
1069
1070 if (argc < 2) {
1071 printf("Invalid IDENTITY command: needs two arguments "
1072 "(network id and identity)\n");
1073 return -1;
1074 }
1075
1076 end = cmd + sizeof(cmd);
1077 pos = cmd;
1078 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1079 argv[0], argv[1]);
1080 if (ret < 0 || ret >= end - pos) {
1081 printf("Too long IDENTITY command.\n");
1082 return -1;
1083 }
1084 pos += ret;
1085 for (i = 2; i < argc; i++) {
1086 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1087 if (ret < 0 || ret >= end - pos) {
1088 printf("Too long IDENTITY command.\n");
1089 return -1;
1090 }
1091 pos += ret;
1092 }
1093
1094 return wpa_ctrl_command(ctrl, cmd);
1095}
1096
1097
1098static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099{
1100 char cmd[256], *pos, *end;
1101 int i, ret;
1102
1103 if (argc < 2) {
1104 printf("Invalid PASSWORD command: needs two arguments "
1105 "(network id and password)\n");
1106 return -1;
1107 }
1108
1109 end = cmd + sizeof(cmd);
1110 pos = cmd;
1111 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1112 argv[0], argv[1]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long PASSWORD command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 for (i = 2; i < argc; i++) {
1119 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1120 if (ret < 0 || ret >= end - pos) {
1121 printf("Too long PASSWORD command.\n");
1122 return -1;
1123 }
1124 pos += ret;
1125 }
1126
1127 return wpa_ctrl_command(ctrl, cmd);
1128}
1129
1130
1131static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1132 char *argv[])
1133{
1134 char cmd[256], *pos, *end;
1135 int i, ret;
1136
1137 if (argc < 2) {
1138 printf("Invalid NEW_PASSWORD command: needs two arguments "
1139 "(network id and password)\n");
1140 return -1;
1141 }
1142
1143 end = cmd + sizeof(cmd);
1144 pos = cmd;
1145 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1146 argv[0], argv[1]);
1147 if (ret < 0 || ret >= end - pos) {
1148 printf("Too long NEW_PASSWORD command.\n");
1149 return -1;
1150 }
1151 pos += ret;
1152 for (i = 2; i < argc; i++) {
1153 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long NEW_PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 }
1160
1161 return wpa_ctrl_command(ctrl, cmd);
1162}
1163
1164
1165static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1166{
1167 char cmd[256], *pos, *end;
1168 int i, ret;
1169
1170 if (argc < 2) {
1171 printf("Invalid PIN command: needs two arguments "
1172 "(network id and pin)\n");
1173 return -1;
1174 }
1175
1176 end = cmd + sizeof(cmd);
1177 pos = cmd;
1178 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1179 argv[0], argv[1]);
1180 if (ret < 0 || ret >= end - pos) {
1181 printf("Too long PIN command.\n");
1182 return -1;
1183 }
1184 pos += ret;
1185 for (i = 2; i < argc; i++) {
1186 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1187 if (ret < 0 || ret >= end - pos) {
1188 printf("Too long PIN command.\n");
1189 return -1;
1190 }
1191 pos += ret;
1192 }
1193 return wpa_ctrl_command(ctrl, cmd);
1194}
1195
1196
1197static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1198{
1199 char cmd[256], *pos, *end;
1200 int i, ret;
1201
1202 if (argc < 2) {
1203 printf("Invalid OTP command: needs two arguments (network "
1204 "id and password)\n");
1205 return -1;
1206 }
1207
1208 end = cmd + sizeof(cmd);
1209 pos = cmd;
1210 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1211 argv[0], argv[1]);
1212 if (ret < 0 || ret >= end - pos) {
1213 printf("Too long OTP command.\n");
1214 return -1;
1215 }
1216 pos += ret;
1217 for (i = 2; i < argc; i++) {
1218 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1219 if (ret < 0 || ret >= end - pos) {
1220 printf("Too long OTP command.\n");
1221 return -1;
1222 }
1223 pos += ret;
1224 }
1225
1226 return wpa_ctrl_command(ctrl, cmd);
1227}
1228
1229
Dmitry Shmidt051af732013-10-22 13:52:46 -07001230static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1231{
1232 char cmd[256], *pos, *end;
1233 int i, ret;
1234
1235 if (argc < 2) {
1236 printf("Invalid SIM command: needs two arguments "
1237 "(network id and SIM operation response)\n");
1238 return -1;
1239 }
1240
1241 end = cmd + sizeof(cmd);
1242 pos = cmd;
1243 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1244 argv[0], argv[1]);
1245 if (ret < 0 || ret >= end - pos) {
1246 printf("Too long SIM command.\n");
1247 return -1;
1248 }
1249 pos += ret;
1250 for (i = 2; i < argc; i++) {
1251 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1252 if (ret < 0 || ret >= end - pos) {
1253 printf("Too long SIM command.\n");
1254 return -1;
1255 }
1256 pos += ret;
1257 }
1258 return wpa_ctrl_command(ctrl, cmd);
1259}
1260
1261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1263 char *argv[])
1264{
1265 char cmd[256], *pos, *end;
1266 int i, ret;
1267
1268 if (argc < 2) {
1269 printf("Invalid PASSPHRASE command: needs two arguments "
1270 "(network id and passphrase)\n");
1271 return -1;
1272 }
1273
1274 end = cmd + sizeof(cmd);
1275 pos = cmd;
1276 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1277 argv[0], argv[1]);
1278 if (ret < 0 || ret >= end - pos) {
1279 printf("Too long PASSPHRASE command.\n");
1280 return -1;
1281 }
1282 pos += ret;
1283 for (i = 2; i < argc; i++) {
1284 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1285 if (ret < 0 || ret >= end - pos) {
1286 printf("Too long PASSPHRASE command.\n");
1287 return -1;
1288 }
1289 pos += ret;
1290 }
1291
1292 return wpa_ctrl_command(ctrl, cmd);
1293}
1294
1295
1296static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 if (argc < 2) {
1299 printf("Invalid BSSID command: needs two arguments (network "
1300 "id and BSSID)\n");
1301 return -1;
1302 }
1303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305}
1306
1307
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001308static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1309{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001310 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001311}
1312
1313
1314static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1315{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001316 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001317}
1318
1319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1321 char *argv[])
1322{
1323 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1324}
1325
1326
1327static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001330 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331}
1332
1333
1334static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1335 char *argv[])
1336{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001337 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338}
1339
1340
1341static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1342 char *argv[])
1343{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001344 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345}
1346
1347
1348static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1349 char *argv[])
1350{
1351 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1352}
1353
1354
1355static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1356 char *argv[])
1357{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001358 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001359}
1360
1361
1362static void wpa_cli_show_network_variables(void)
1363{
1364 printf("set_network variables:\n"
1365 " ssid (network name, SSID)\n"
1366 " psk (WPA passphrase or pre-shared key)\n"
1367 " key_mgmt (key management protocol)\n"
1368 " identity (EAP identity)\n"
1369 " password (EAP password)\n"
1370 " ...\n"
1371 "\n"
1372 "Note: Values are entered in the same format as the "
1373 "configuration file is using,\n"
1374 "i.e., strings values need to be inside double quotation "
1375 "marks.\n"
1376 "For example: set_network 1 ssid \"network name\"\n"
1377 "\n"
1378 "Please see wpa_supplicant.conf documentation for full list "
1379 "of\navailable variables.\n");
1380}
1381
1382
1383static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1384 char *argv[])
1385{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 if (argc == 0) {
1387 wpa_cli_show_network_variables();
1388 return 0;
1389 }
1390
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001391 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 printf("Invalid SET_NETWORK command: needs three arguments\n"
1393 "(network id, variable name, and value)\n");
1394 return -1;
1395 }
1396
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001397 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398}
1399
1400
1401static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1402 char *argv[])
1403{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404 if (argc == 0) {
1405 wpa_cli_show_network_variables();
1406 return 0;
1407 }
1408
1409 if (argc != 2) {
1410 printf("Invalid GET_NETWORK command: needs two arguments\n"
1411 "(network id and variable name)\n");
1412 return -1;
1413 }
1414
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001415 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416}
1417
1418
Dmitry Shmidt04949592012-07-19 12:16:46 -07001419static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1420 char *argv[])
1421{
1422 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1423}
1424
1425
1426static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1427{
1428 return wpa_ctrl_command(ctrl, "ADD_CRED");
1429}
1430
1431
1432static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1433 char *argv[])
1434{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001435 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001436}
1437
1438
1439static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1440{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001441 if (argc != 3) {
1442 printf("Invalid SET_CRED command: needs three arguments\n"
1443 "(cred id, variable name, and value)\n");
1444 return -1;
1445 }
1446
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001447 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001448}
1449
1450
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001451static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1452{
1453 if (argc != 2) {
1454 printf("Invalid GET_CRED command: needs two arguments\n"
1455 "(cred id, variable name)\n");
1456 return -1;
1457 }
1458
1459 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1460}
1461
1462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001463static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1464 char *argv[])
1465{
1466 return wpa_ctrl_command(ctrl, "DISCONNECT");
1467}
1468
1469
1470static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1471 char *argv[])
1472{
1473 return wpa_ctrl_command(ctrl, "RECONNECT");
1474}
1475
1476
1477static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1478 char *argv[])
1479{
1480 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1481}
1482
1483
1484static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1485{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001486 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001487}
1488
1489
1490static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1491 char *argv[])
1492{
1493 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1494}
1495
1496
1497static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1498{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001499 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500}
1501
1502
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001503static char ** wpa_cli_complete_bss(const char *str, int pos)
1504{
1505 int arg = get_cmd_arg_num(str, pos);
1506 char **res = NULL;
1507
1508 switch (arg) {
1509 case 1:
1510 res = cli_txt_list_array(&bsses);
1511 break;
1512 }
1513
1514 return res;
1515}
1516
1517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001518static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1519 char *argv[])
1520{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 if (argc < 1 || argc > 2) {
1522 printf("Invalid GET_CAPABILITY command: need either one or "
1523 "two arguments\n");
1524 return -1;
1525 }
1526
1527 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1528 printf("Invalid GET_CAPABILITY command: second argument, "
1529 "if any, must be 'strict'\n");
1530 return -1;
1531 }
1532
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001533 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534}
1535
1536
1537static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1538{
1539 printf("Available interfaces:\n");
1540 return wpa_ctrl_command(ctrl, "INTERFACES");
1541}
1542
1543
1544static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1545{
1546 if (argc < 1) {
1547 wpa_cli_list_interfaces(ctrl);
1548 return 0;
1549 }
1550
1551 wpa_cli_close_connection();
1552 os_free(ctrl_ifname);
1553 ctrl_ifname = os_strdup(argv[0]);
1554
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001555 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 printf("Connected to interface '%s.\n", ctrl_ifname);
1557 } else {
1558 printf("Could not connect to interface '%s' - re-trying\n",
1559 ctrl_ifname);
1560 }
1561 return 0;
1562}
1563
1564
1565static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1566 char *argv[])
1567{
1568 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1569}
1570
1571
1572static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1573 char *argv[])
1574{
1575 return wpa_ctrl_command(ctrl, "TERMINATE");
1576}
1577
1578
1579static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1580 char *argv[])
1581{
1582 char cmd[256];
1583 int res;
1584
1585 if (argc < 1) {
1586 printf("Invalid INTERFACE_ADD command: needs at least one "
1587 "argument (interface name)\n"
1588 "All arguments: ifname confname driver ctrl_interface "
1589 "driver_param bridge_name\n");
1590 return -1;
1591 }
1592
1593 /*
1594 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1595 * <driver_param>TAB<bridge_name>
1596 */
1597 res = os_snprintf(cmd, sizeof(cmd),
1598 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1599 argv[0],
1600 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1601 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1602 argc > 5 ? argv[5] : "");
1603 if (res < 0 || (size_t) res >= sizeof(cmd))
1604 return -1;
1605 cmd[sizeof(cmd) - 1] = '\0';
1606 return wpa_ctrl_command(ctrl, cmd);
1607}
1608
1609
1610static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1611 char *argv[])
1612{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001613 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614}
1615
1616
1617static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1618 char *argv[])
1619{
1620 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1621}
1622
1623
1624#ifdef CONFIG_AP
1625static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1626{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001627 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628}
1629
1630
1631static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1632 char *addr, size_t addr_len)
1633{
1634 char buf[4096], *pos;
1635 size_t len;
1636 int ret;
1637
1638 if (ctrl_conn == NULL) {
1639 printf("Not connected to hostapd - command dropped.\n");
1640 return -1;
1641 }
1642 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001643 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001644 wpa_cli_msg_cb);
1645 if (ret == -2) {
1646 printf("'%s' command timed out.\n", cmd);
1647 return -2;
1648 } else if (ret < 0) {
1649 printf("'%s' command failed.\n", cmd);
1650 return -1;
1651 }
1652
1653 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001654 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655 return -1;
1656 printf("%s", buf);
1657
1658 pos = buf;
1659 while (*pos != '\0' && *pos != '\n')
1660 pos++;
1661 *pos = '\0';
1662 os_strlcpy(addr, buf, addr_len);
1663 return 0;
1664}
1665
1666
1667static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1668{
1669 char addr[32], cmd[64];
1670
1671 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1672 return 0;
1673 do {
1674 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1675 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1676
1677 return -1;
1678}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001679
1680
1681static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1682 char *argv[])
1683{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001684 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001685}
1686
1687
1688static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1689 char *argv[])
1690{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001691 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001692}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001693
1694static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1695 char *argv[])
1696{
1697 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1698}
1699
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001700#endif /* CONFIG_AP */
1701
1702
1703static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1704{
1705 return wpa_ctrl_command(ctrl, "SUSPEND");
1706}
1707
1708
1709static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1710{
1711 return wpa_ctrl_command(ctrl, "RESUME");
1712}
1713
1714
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001715#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1717{
1718 return wpa_ctrl_command(ctrl, "DROP_SA");
1719}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001720#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721
1722
1723static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1724{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001725 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726}
1727
1728
1729#ifdef CONFIG_P2P
1730
1731static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1732{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001733 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1734}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001737static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1738{
1739 char **res = NULL;
1740 int arg = get_cmd_arg_num(str, pos);
1741
1742 res = os_calloc(6, sizeof(char *));
1743 if (res == NULL)
1744 return NULL;
1745 res[0] = os_strdup("type=social");
1746 if (res[0] == NULL) {
1747 os_free(res);
1748 return NULL;
1749 }
1750 res[1] = os_strdup("type=progressive");
1751 if (res[1] == NULL)
1752 return res;
1753 res[2] = os_strdup("delay=");
1754 if (res[2] == NULL)
1755 return res;
1756 res[3] = os_strdup("dev_id=");
1757 if (res[3] == NULL)
1758 return res;
1759 if (arg == 1)
1760 res[4] = os_strdup("[timeout]");
1761
1762 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763}
1764
1765
1766static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1767 char *argv[])
1768{
1769 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1770}
1771
1772
1773static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1774 char *argv[])
1775{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001776 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777}
1778
1779
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001780static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1781{
1782 int arg = get_cmd_arg_num(str, pos);
1783 char **res = NULL;
1784
1785 switch (arg) {
1786 case 1:
1787 res = cli_txt_list_array(&p2p_peers);
1788 break;
1789 }
1790
1791 return res;
1792}
1793
1794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1796 char *argv[])
1797{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001798 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799}
1800
1801
1802static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1803 char *argv[])
1804{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001805 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806}
1807
1808
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001809static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1810{
1811 int arg = get_cmd_arg_num(str, pos);
1812 char **res = NULL;
1813
1814 switch (arg) {
1815 case 1:
1816 res = cli_txt_list_array(&p2p_groups);
1817 break;
1818 }
1819
1820 return res;
1821}
1822
1823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1825 char *argv[])
1826{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001827 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828}
1829
1830
1831static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1832 char *argv[])
1833{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001834 if (argc != 2 && argc != 3) {
1835 printf("Invalid P2P_PROV_DISC command: needs at least "
1836 "two arguments, address and config method\n"
1837 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838 return -1;
1839 }
1840
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001841 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842}
1843
1844
1845static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1846 char *argv[])
1847{
1848 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1849}
1850
1851
1852static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1853 char *argv[])
1854{
1855 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856
1857 if (argc != 2 && argc != 4) {
1858 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1859 "arguments (address and TLVs) or four arguments "
1860 "(address, \"upnp\", version, search target "
1861 "(SSDP ST:)\n");
1862 return -1;
1863 }
1864
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001865 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867 return wpa_ctrl_command(ctrl, cmd);
1868}
1869
1870
1871static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1872 int argc, char *argv[])
1873{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001874 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001875}
1876
1877
1878static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1879 char *argv[])
1880{
1881 char cmd[4096];
1882 int res;
1883
1884 if (argc != 4) {
1885 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1886 "arguments (freq, address, dialog token, and TLVs)\n");
1887 return -1;
1888 }
1889
1890 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1891 argv[0], argv[1], argv[2], argv[3]);
1892 if (res < 0 || (size_t) res >= sizeof(cmd))
1893 return -1;
1894 cmd[sizeof(cmd) - 1] = '\0';
1895 return wpa_ctrl_command(ctrl, cmd);
1896}
1897
1898
1899static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1900 char *argv[])
1901{
1902 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1903}
1904
1905
1906static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1907 int argc, char *argv[])
1908{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001909 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001910}
1911
1912
1913static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1914 char *argv[])
1915{
1916 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1917}
1918
1919
1920static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1921 char *argv[])
1922{
1923 char cmd[4096];
1924 int res;
1925
1926 if (argc != 3 && argc != 4) {
1927 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1928 "arguments\n");
1929 return -1;
1930 }
1931
1932 if (argc == 4)
1933 res = os_snprintf(cmd, sizeof(cmd),
1934 "P2P_SERVICE_ADD %s %s %s %s",
1935 argv[0], argv[1], argv[2], argv[3]);
1936 else
1937 res = os_snprintf(cmd, sizeof(cmd),
1938 "P2P_SERVICE_ADD %s %s %s",
1939 argv[0], argv[1], argv[2]);
1940 if (res < 0 || (size_t) res >= sizeof(cmd))
1941 return -1;
1942 cmd[sizeof(cmd) - 1] = '\0';
1943 return wpa_ctrl_command(ctrl, cmd);
1944}
1945
1946
1947static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1948 char *argv[])
1949{
1950 char cmd[4096];
1951 int res;
1952
1953 if (argc != 2 && argc != 3) {
1954 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1955 "arguments\n");
1956 return -1;
1957 }
1958
1959 if (argc == 3)
1960 res = os_snprintf(cmd, sizeof(cmd),
1961 "P2P_SERVICE_DEL %s %s %s",
1962 argv[0], argv[1], argv[2]);
1963 else
1964 res = os_snprintf(cmd, sizeof(cmd),
1965 "P2P_SERVICE_DEL %s %s",
1966 argv[0], argv[1]);
1967 if (res < 0 || (size_t) res >= sizeof(cmd))
1968 return -1;
1969 cmd[sizeof(cmd) - 1] = '\0';
1970 return wpa_ctrl_command(ctrl, cmd);
1971}
1972
1973
1974static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1975 int argc, char *argv[])
1976{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001977 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978}
1979
1980
1981static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1982 int argc, char *argv[])
1983{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001984 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985}
1986
1987
1988static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1989{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001990 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991}
1992
1993
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001994static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1995{
1996 int arg = get_cmd_arg_num(str, pos);
1997 char **res = NULL;
1998
1999 switch (arg) {
2000 case 1:
2001 res = cli_txt_list_array(&p2p_peers);
2002 break;
2003 }
2004
2005 return res;
2006}
2007
2008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2010 char *addr, size_t addr_len,
2011 int discovered)
2012{
2013 char buf[4096], *pos;
2014 size_t len;
2015 int ret;
2016
2017 if (ctrl_conn == NULL)
2018 return -1;
2019 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002020 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002021 wpa_cli_msg_cb);
2022 if (ret == -2) {
2023 printf("'%s' command timed out.\n", cmd);
2024 return -2;
2025 } else if (ret < 0) {
2026 printf("'%s' command failed.\n", cmd);
2027 return -1;
2028 }
2029
2030 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002031 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002032 return -1;
2033
2034 pos = buf;
2035 while (*pos != '\0' && *pos != '\n')
2036 pos++;
2037 *pos++ = '\0';
2038 os_strlcpy(addr, buf, addr_len);
2039 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2040 printf("%s\n", addr);
2041 return 0;
2042}
2043
2044
2045static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2046{
2047 char addr[32], cmd[64];
2048 int discovered;
2049
2050 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2051
2052 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2053 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002054 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055 do {
2056 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2057 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2058 discovered) == 0);
2059
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002060 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061}
2062
2063
2064static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2065{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002066 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002067}
2068
2069
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002070static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2071{
2072 int arg = get_cmd_arg_num(str, pos);
2073 const char *fields[] = {
2074 "discoverability",
2075 "managed",
2076 "listen_channel",
2077 "ssid_postfix",
2078 "noa",
2079 "ps",
2080 "oppps",
2081 "ctwindow",
2082 "disabled",
2083 "conc_pref",
2084 "force_long_sd",
2085 "peer_filter",
2086 "cross_connect",
2087 "go_apsd",
2088 "client_apsd",
2089 "disallow_freq",
2090 "disc_int",
2091 "per_sta_psk",
2092 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002093 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002094
2095 if (arg == 1) {
2096 char **res = os_calloc(num_fields + 1, sizeof(char *));
2097 if (res == NULL)
2098 return NULL;
2099 for (i = 0; i < num_fields; i++) {
2100 res[i] = os_strdup(fields[i]);
2101 if (res[i] == NULL)
2102 return res;
2103 }
2104 return res;
2105 }
2106
2107 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2108 return cli_txt_list_array(&p2p_peers);
2109
2110 return NULL;
2111}
2112
2113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002114static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2115{
2116 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2117}
2118
2119
2120static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2121 char *argv[])
2122{
2123 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2124}
2125
2126
2127static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2128 char *argv[])
2129{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002130 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131}
2132
2133
2134static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2135 char *argv[])
2136{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 if (argc != 0 && argc != 2 && argc != 4) {
2138 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2139 "(preferred duration, interval; in microsecods).\n"
2140 "Optional second pair can be used to provide "
2141 "acceptable values.\n");
2142 return -1;
2143 }
2144
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002145 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146}
2147
2148
2149static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 if (argc != 0 && argc != 2) {
2153 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2154 "(availability period, availability interval; in "
2155 "millisecods).\n"
2156 "Extended Listen Timing can be cancelled with this "
2157 "command when used without parameters.\n");
2158 return -1;
2159 }
2160
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002161 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2162}
2163
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002164
2165static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2166 char *argv[])
2167{
2168 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2169}
2170
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002171#endif /* CONFIG_P2P */
2172
2173#ifdef CONFIG_WIFI_DISPLAY
2174
2175static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2176 char *argv[])
2177{
2178 char cmd[100];
2179 int res;
2180
2181 if (argc != 1 && argc != 2) {
2182 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2183 "arguments (subelem, hexdump)\n");
2184 return -1;
2185 }
2186
2187 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2188 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002189 if (res < 0 || (size_t) res >= sizeof(cmd))
2190 return -1;
2191 cmd[sizeof(cmd) - 1] = '\0';
2192 return wpa_ctrl_command(ctrl, cmd);
2193}
2194
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002195
2196static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2197 char *argv[])
2198{
2199 char cmd[100];
2200 int res;
2201
2202 if (argc != 1) {
2203 printf("Invalid WFD_SUBELEM_GET command: needs one "
2204 "argument (subelem)\n");
2205 return -1;
2206 }
2207
2208 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2209 argv[0]);
2210 if (res < 0 || (size_t) res >= sizeof(cmd))
2211 return -1;
2212 cmd[sizeof(cmd) - 1] = '\0';
2213 return wpa_ctrl_command(ctrl, cmd);
2214}
2215#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216
2217
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002218#ifdef CONFIG_INTERWORKING
2219static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2220 char *argv[])
2221{
2222 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2223}
2224
2225
2226static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2227 char *argv[])
2228{
2229 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2230}
2231
2232
2233static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2234 char *argv[])
2235{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002236 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002237}
2238
2239
2240static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2241 char *argv[])
2242{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002243 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002244}
2245
2246
2247static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2248{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002249 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2250}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002251
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002252
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002253static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2254 char *argv[])
2255{
2256 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2257}
2258
2259
2260static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2261 char *argv[])
2262{
2263 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002264}
2265#endif /* CONFIG_INTERWORKING */
2266
2267
Dmitry Shmidt04949592012-07-19 12:16:46 -07002268#ifdef CONFIG_HS20
2269
2270static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2271 char *argv[])
2272{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002273 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002274}
2275
2276
2277static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2278 char *argv[])
2279{
2280 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002281
2282 if (argc == 0) {
2283 printf("Command needs one or two arguments (dst mac addr and "
2284 "optional home realm)\n");
2285 return -1;
2286 }
2287
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002288 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2289 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002290 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002291
2292 return wpa_ctrl_command(ctrl, cmd);
2293}
2294
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002295
2296static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2297 char *argv[])
2298{
2299 char cmd[512];
2300
2301 if (argc < 2) {
2302 printf("Command needs two arguments (dst mac addr and "
2303 "icon name)\n");
2304 return -1;
2305 }
2306
2307 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2308 return -1;
2309
2310 return wpa_ctrl_command(ctrl, cmd);
2311}
2312
2313
2314static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2315{
2316 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2317}
2318
2319
2320static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2321 char *argv[])
2322{
2323 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2324}
2325
Dmitry Shmidt04949592012-07-19 12:16:46 -07002326#endif /* CONFIG_HS20 */
2327
2328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002329static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2330 char *argv[])
2331{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002332 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333}
2334
2335
2336static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2337 char *argv[])
2338{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002339 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340}
2341
2342
2343static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2344 char *argv[])
2345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002346 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347}
2348
2349
2350static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2351 char *argv[])
2352{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002353 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354}
2355
2356
2357static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2358 char *argv[])
2359{
2360 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2361}
2362
2363
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002364static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2365 char *argv[])
2366{
2367 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2368}
2369
2370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002371static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2372 char *argv[])
2373{
2374 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2375}
2376
Dmitry Shmidt04949592012-07-19 12:16:46 -07002377
2378#ifdef CONFIG_AUTOSCAN
2379
2380static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2381{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002382 if (argc == 0)
2383 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2384
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002385 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002386}
2387
2388#endif /* CONFIG_AUTOSCAN */
2389
2390
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002391#ifdef CONFIG_WNM
2392
2393static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2394{
2395 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2396}
2397
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002398
2399static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2400{
2401 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2402}
2403
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002404#endif /* CONFIG_WNM */
2405
2406
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2408{
2409 if (argc == 0)
2410 return -1;
2411 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2412}
2413
2414
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002415#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002416static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2417{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002418 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002419}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002420#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002421
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002423static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2424{
2425 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2426}
2427
2428
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002429static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2430{
2431 return wpa_ctrl_command(ctrl, "FLUSH");
2432}
2433
2434
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002435static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2436{
2437 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2438}
2439
2440
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441enum wpa_cli_cmd_flags {
2442 cli_cmd_flag_none = 0x00,
2443 cli_cmd_flag_sensitive = 0x01
2444};
2445
2446struct wpa_cli_cmd {
2447 const char *cmd;
2448 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002449 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 enum wpa_cli_cmd_flags flags;
2451 const char *usage;
2452};
2453
2454static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 cli_cmd_flag_none,
2457 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002458 { "ifname", wpa_cli_cmd_ifname, NULL,
2459 cli_cmd_flag_none,
2460 "= get current interface name" },
2461 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 cli_cmd_flag_none,
2463 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 cli_cmd_flag_none,
2466 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 "[command] = show usage help" },
2476 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 cli_cmd_flag_none,
2478 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_none,
2484 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002488 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= set variables (shows list of variables when run without "
2491 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 cli_cmd_flag_none,
2494 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 cli_cmd_flag_none,
2497 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002507 { "reattach", wpa_cli_cmd_reattach, NULL,
2508 cli_cmd_flag_none,
2509 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_sensitive,
2518 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_sensitive,
2521 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_sensitive,
2524 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_sensitive,
2527 "<network id> <password> = configure one-time-password for an SSID"
2528 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 cli_cmd_flag_sensitive,
2531 "<network id> <passphrase> = configure private key passphrase\n"
2532 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002533 { "sim", wpa_cli_cmd_sim, NULL,
2534 cli_cmd_flag_sensitive,
2535 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 cli_cmd_flag_none,
2538 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002540 cli_cmd_flag_none,
2541 "<BSSID> = add a BSSID to the blacklist\n"
2542 "blacklist clear = clear the blacklist\n"
2543 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002544 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002545 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002546 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002547 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 cli_cmd_flag_none,
2550 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_none,
2553 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_none,
2556 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 cli_cmd_flag_none,
2565 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 cli_cmd_flag_sensitive,
2568 "<network id> <variable> <value> = set network variables (shows\n"
2569 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002570 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 cli_cmd_flag_none,
2572 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002574 cli_cmd_flag_none,
2575 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002577 cli_cmd_flag_none,
2578 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580 cli_cmd_flag_none,
2581 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002583 cli_cmd_flag_sensitive,
2584 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002585 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2586 cli_cmd_flag_none,
2587 "<cred id> <variable> = get 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 Shmidtf8623282013-02-20 14:34:59 -08002681 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2682 cli_cmd_flag_none,
2683 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2684 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002685#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 cli_cmd_flag_sensitive,
2688 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_sensitive,
2691 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 cli_cmd_flag_none,
2694 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 cli_cmd_flag_none,
2697 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002698 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 cli_cmd_flag_sensitive,
2700 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 cli_cmd_flag_none,
2703 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 cli_cmd_flag_sensitive,
2706 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 cli_cmd_flag_none,
2709 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002710 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 cli_cmd_flag_sensitive,
2712 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002713#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002715 cli_cmd_flag_none,
2716 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2717#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 cli_cmd_flag_none,
2720 "<addr> = request RSN authentication with <addr> in IBSS" },
2721#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002722 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002723 cli_cmd_flag_none,
2724 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 cli_cmd_flag_none,
2727 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002729 cli_cmd_flag_none,
2730 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002732 cli_cmd_flag_none,
2733 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002734 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2735 cli_cmd_flag_none,
2736 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2737 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2738 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002741 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002742 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002743 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002744#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002747#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 cli_cmd_flag_none,
2750 "<addr> = roam to the specified BSS" },
2751#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002752 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2753 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002755 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2758 cli_cmd_flag_none,
2759 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2760 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2763 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2766 "[ht40] = add a new P2P group (local end as GO)" },
2767 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2768 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 cli_cmd_flag_none,
2772 "= get the passphrase for a group (GO only)" },
2773 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 "<addr> <TLVs> = schedule service discovery request" },
2776 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 cli_cmd_flag_none,
2781 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 cli_cmd_flag_none,
2784 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 cli_cmd_flag_none,
2787 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 cli_cmd_flag_none,
2790 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002791 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792 cli_cmd_flag_none,
2793 "<bonjour|upnp> <query|version> <response|service> = add a local "
2794 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 cli_cmd_flag_none,
2797 "<bonjour|upnp> <query|version> [|service] = remove a local "
2798 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 cli_cmd_flag_none,
2801 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 cli_cmd_flag_none,
2804 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 "[discovered] = list known (optionally, only fully discovered) P2P "
2807 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002808 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2809 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002810 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002811 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2812 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002815 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002816 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002817 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002818 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2819 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002820 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002821 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2822 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002823 "[<duration> <interval>] [<duration> <interval>] = request GO "
2824 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002825 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2826 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002828 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2829 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2830 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002832#ifdef CONFIG_WIFI_DISPLAY
2833 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2834 cli_cmd_flag_none,
2835 "<subelem> [contents] = set Wi-Fi Display subelement" },
2836 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2837 cli_cmd_flag_none,
2838 "<subelem> = get Wi-Fi Display subelement" },
2839#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002840#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002841 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002842 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2844 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002845 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002846 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002847 cli_cmd_flag_none,
2848 "[auto] = perform Interworking network selection" },
2849 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002850 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002851 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002852 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2853 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002854 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002855 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2856 cli_cmd_flag_none,
2857 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2858 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2859 wpa_cli_complete_bss, cli_cmd_flag_none,
2860 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002861#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002862#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002863 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2864 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002865 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2866 },
2867 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002868 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002869 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002870 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2871 wpa_cli_complete_bss, cli_cmd_flag_none,
2872 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2873 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2874 "= fetch OSU provider information from all APs" },
2875 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2876 cli_cmd_flag_none,
2877 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002878#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2880 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002881 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 cli_cmd_flag_none,
2884 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002885 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 cli_cmd_flag_none,
2887 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002888 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889 cli_cmd_flag_none,
2890 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002891 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002892 cli_cmd_flag_none,
2893 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002894 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002895 cli_cmd_flag_none,
2896 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002897 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2898 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002899 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002900#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002901 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002902 "[params] = Set or unset (if none) autoscan parameters" },
2903#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002904#ifdef CONFIG_WNM
2905 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2906 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002907 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2908 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002909#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002910 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2911 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002912 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2913 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002914#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002915 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002916 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002917#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002918 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2919 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002920 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2921 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2922 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002923 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924};
2925
2926
2927/*
2928 * Prints command usage, lines are padded with the specified string.
2929 */
2930static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2931{
2932 char c;
2933 size_t n;
2934
2935 printf("%s%s ", pad, cmd->cmd);
2936 for (n = 0; (c = cmd->usage[n]); n++) {
2937 printf("%c", c);
2938 if (c == '\n')
2939 printf("%s", pad);
2940 }
2941 printf("\n");
2942}
2943
2944
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002945static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002946{
2947 int n;
2948 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002949 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2950 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2951 print_cmd_help(&wpa_cli_commands[n], " ");
2952 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002953}
2954
2955
2956static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2957{
2958 const char *c, *delim;
2959 int n;
2960 size_t len;
2961
2962 delim = os_strchr(cmd, ' ');
2963 if (delim)
2964 len = delim - cmd;
2965 else
2966 len = os_strlen(cmd);
2967
2968 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2969 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2970 return (wpa_cli_commands[n].flags &
2971 cli_cmd_flag_sensitive);
2972 }
2973 return 0;
2974}
2975
2976
2977static char ** wpa_list_cmd_list(void)
2978{
2979 char **res;
2980 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002981 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002982
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002983 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002984 count += dl_list_len(&p2p_groups);
2985 count += dl_list_len(&ifnames);
2986 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002987 if (res == NULL)
2988 return NULL;
2989
2990 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2991 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2992 if (res[i] == NULL)
2993 break;
2994 }
2995
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002996 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2997 size_t len = 8 + os_strlen(e->txt);
2998 res[i] = os_malloc(len);
2999 if (res[i] == NULL)
3000 break;
3001 os_snprintf(res[i], len, "ifname=%s", e->txt);
3002 i++;
3003 }
3004
3005 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3006 res[i] = os_strdup(e->txt);
3007 if (res[i] == NULL)
3008 break;
3009 i++;
3010 }
3011
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003012 return res;
3013}
3014
3015
3016static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3017 int pos)
3018{
3019 int i;
3020
3021 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3022 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003023 if (wpa_cli_commands[i].completion)
3024 return wpa_cli_commands[i].completion(str,
3025 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 edit_clear_line();
3027 printf("\r%s\n", wpa_cli_commands[i].usage);
3028 edit_redraw();
3029 break;
3030 }
3031 }
3032
3033 return NULL;
3034}
3035
3036
3037static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3038{
3039 char **res;
3040 const char *end;
3041 char *cmd;
3042
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003043 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3044 end = os_strchr(str, ' ');
3045 if (end && pos > end - str) {
3046 pos -= end - str + 1;
3047 str = end + 1;
3048 }
3049 }
3050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 end = os_strchr(str, ' ');
3052 if (end == NULL || str + pos < end)
3053 return wpa_list_cmd_list();
3054
3055 cmd = os_malloc(pos + 1);
3056 if (cmd == NULL)
3057 return NULL;
3058 os_memcpy(cmd, str, pos);
3059 cmd[end - str] = '\0';
3060 res = wpa_cli_cmd_completion(cmd, str, pos);
3061 os_free(cmd);
3062 return res;
3063}
3064
3065
3066static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3067{
3068 struct wpa_cli_cmd *cmd, *match = NULL;
3069 int count;
3070 int ret = 0;
3071
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003072 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3073 ifname_prefix = argv[0] + 7;
3074 argv = &argv[1];
3075 argc--;
3076 } else
3077 ifname_prefix = NULL;
3078
3079 if (argc == 0)
3080 return -1;
3081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082 count = 0;
3083 cmd = wpa_cli_commands;
3084 while (cmd->cmd) {
3085 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3086 {
3087 match = cmd;
3088 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3089 /* we have an exact match */
3090 count = 1;
3091 break;
3092 }
3093 count++;
3094 }
3095 cmd++;
3096 }
3097
3098 if (count > 1) {
3099 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3100 cmd = wpa_cli_commands;
3101 while (cmd->cmd) {
3102 if (os_strncasecmp(cmd->cmd, argv[0],
3103 os_strlen(argv[0])) == 0) {
3104 printf(" %s", cmd->cmd);
3105 }
3106 cmd++;
3107 }
3108 printf("\n");
3109 ret = 1;
3110 } else if (count == 0) {
3111 printf("Unknown command '%s'\n", argv[0]);
3112 ret = 1;
3113 } else {
3114 ret = match->handler(ctrl, argc - 1, &argv[1]);
3115 }
3116
3117 return ret;
3118}
3119
3120
3121static int str_match(const char *a, const char *b)
3122{
3123 return os_strncmp(a, b, os_strlen(b)) == 0;
3124}
3125
3126
3127static int wpa_cli_exec(const char *program, const char *arg1,
3128 const char *arg2)
3129{
3130 char *cmd;
3131 size_t len;
3132 int res;
3133 int ret = 0;
3134
3135 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3136 cmd = os_malloc(len);
3137 if (cmd == NULL)
3138 return -1;
3139 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3140 if (res < 0 || (size_t) res >= len) {
3141 os_free(cmd);
3142 return -1;
3143 }
3144 cmd[len - 1] = '\0';
3145#ifndef _WIN32_WCE
3146 if (system(cmd) < 0)
3147 ret = -1;
3148#endif /* _WIN32_WCE */
3149 os_free(cmd);
3150
3151 return ret;
3152}
3153
3154
3155static void wpa_cli_action_process(const char *msg)
3156{
3157 const char *pos;
3158 char *copy = NULL, *id, *pos2;
3159
3160 pos = msg;
3161 if (*pos == '<') {
3162 /* skip priority */
3163 pos = os_strchr(pos, '>');
3164 if (pos)
3165 pos++;
3166 else
3167 pos = msg;
3168 }
3169
3170 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3171 int new_id = -1;
3172 os_unsetenv("WPA_ID");
3173 os_unsetenv("WPA_ID_STR");
3174 os_unsetenv("WPA_CTRL_DIR");
3175
3176 pos = os_strstr(pos, "[id=");
3177 if (pos)
3178 copy = os_strdup(pos + 4);
3179
3180 if (copy) {
3181 pos2 = id = copy;
3182 while (*pos2 && *pos2 != ' ')
3183 pos2++;
3184 *pos2++ = '\0';
3185 new_id = atoi(id);
3186 os_setenv("WPA_ID", id, 1);
3187 while (*pos2 && *pos2 != '=')
3188 pos2++;
3189 if (*pos2 == '=')
3190 pos2++;
3191 id = pos2;
3192 while (*pos2 && *pos2 != ']')
3193 pos2++;
3194 *pos2 = '\0';
3195 os_setenv("WPA_ID_STR", id, 1);
3196 os_free(copy);
3197 }
3198
3199 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3200
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003201 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 wpa_cli_connected = 1;
3203 wpa_cli_last_id = new_id;
3204 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3205 }
3206 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3207 if (wpa_cli_connected) {
3208 wpa_cli_connected = 0;
3209 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3210 }
3211 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3212 wpa_cli_exec(action_file, ctrl_ifname, pos);
3213 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3214 wpa_cli_exec(action_file, ctrl_ifname, pos);
3215 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3216 wpa_cli_exec(action_file, ctrl_ifname, pos);
3217 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3218 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003219 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3220 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003221 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3222 wpa_cli_exec(action_file, ctrl_ifname, pos);
3223 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3224 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003225 } else if (str_match(pos, AP_STA_CONNECTED)) {
3226 wpa_cli_exec(action_file, ctrl_ifname, pos);
3227 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3228 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003229 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3230 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003231 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3232 wpa_cli_exec(action_file, ctrl_ifname, pos);
3233 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3234 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003235 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3236 printf("wpa_supplicant is terminating - stop monitoring\n");
3237 wpa_cli_quit = 1;
3238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239}
3240
3241
3242#ifndef CONFIG_ANSI_C_EXTRA
3243static void wpa_cli_action_cb(char *msg, size_t len)
3244{
3245 wpa_cli_action_process(msg);
3246}
3247#endif /* CONFIG_ANSI_C_EXTRA */
3248
3249
3250static void wpa_cli_reconnect(void)
3251{
3252 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003253 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3254 return;
3255
3256 if (interactive) {
3257 edit_clear_line();
3258 printf("\rConnection to wpa_supplicant re-established\n");
3259 edit_redraw();
3260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261}
3262
3263
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003264static void cli_event(const char *str)
3265{
3266 const char *start, *s;
3267
3268 start = os_strchr(str, '>');
3269 if (start == NULL)
3270 return;
3271
3272 start++;
3273
3274 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3275 s = os_strchr(start, ' ');
3276 if (s == NULL)
3277 return;
3278 s = os_strchr(s + 1, ' ');
3279 if (s == NULL)
3280 return;
3281 cli_txt_list_add(&bsses, s + 1);
3282 return;
3283 }
3284
3285 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3286 s = os_strchr(start, ' ');
3287 if (s == NULL)
3288 return;
3289 s = os_strchr(s + 1, ' ');
3290 if (s == NULL)
3291 return;
3292 cli_txt_list_del_addr(&bsses, s + 1);
3293 return;
3294 }
3295
3296#ifdef CONFIG_P2P
3297 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3298 s = os_strstr(start, " p2p_dev_addr=");
3299 if (s == NULL)
3300 return;
3301 cli_txt_list_add_addr(&p2p_peers, s + 14);
3302 return;
3303 }
3304
3305 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3306 s = os_strstr(start, " p2p_dev_addr=");
3307 if (s == NULL)
3308 return;
3309 cli_txt_list_del_addr(&p2p_peers, s + 14);
3310 return;
3311 }
3312
3313 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3314 s = os_strchr(start, ' ');
3315 if (s == NULL)
3316 return;
3317 cli_txt_list_add_word(&p2p_groups, s + 1);
3318 return;
3319 }
3320
3321 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3322 s = os_strchr(start, ' ');
3323 if (s == NULL)
3324 return;
3325 cli_txt_list_del_word(&p2p_groups, s + 1);
3326 return;
3327 }
3328#endif /* CONFIG_P2P */
3329}
3330
3331
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003332static int check_terminating(const char *msg)
3333{
3334 const char *pos = msg;
3335
3336 if (*pos == '<') {
3337 /* skip priority */
3338 pos = os_strchr(pos, '>');
3339 if (pos)
3340 pos++;
3341 else
3342 pos = msg;
3343 }
3344
3345 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3346 edit_clear_line();
3347 printf("\rConnection to wpa_supplicant lost - trying to "
3348 "reconnect\n");
3349 edit_redraw();
3350 wpa_cli_attached = 0;
3351 wpa_cli_close_connection();
3352 return 1;
3353 }
3354
3355 return 0;
3356}
3357
3358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003359static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3360{
3361 if (ctrl_conn == NULL) {
3362 wpa_cli_reconnect();
3363 return;
3364 }
3365 while (wpa_ctrl_pending(ctrl) > 0) {
3366 char buf[256];
3367 size_t len = sizeof(buf) - 1;
3368 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3369 buf[len] = '\0';
3370 if (action_monitor)
3371 wpa_cli_action_process(buf);
3372 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003373 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 if (wpa_cli_show_event(buf)) {
3375 edit_clear_line();
3376 printf("\r%s\n", buf);
3377 edit_redraw();
3378 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003379
3380 if (interactive && check_terminating(buf) > 0)
3381 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382 }
3383 } else {
3384 printf("Could not read pending message.\n");
3385 break;
3386 }
3387 }
3388
3389 if (wpa_ctrl_pending(ctrl) < 0) {
3390 printf("Connection to wpa_supplicant lost - trying to "
3391 "reconnect\n");
3392 wpa_cli_reconnect();
3393 }
3394}
3395
3396#define max_args 10
3397
3398static int tokenize_cmd(char *cmd, char *argv[])
3399{
3400 char *pos;
3401 int argc = 0;
3402
3403 pos = cmd;
3404 for (;;) {
3405 while (*pos == ' ')
3406 pos++;
3407 if (*pos == '\0')
3408 break;
3409 argv[argc] = pos;
3410 argc++;
3411 if (argc == max_args)
3412 break;
3413 if (*pos == '"') {
3414 char *pos2 = os_strrchr(pos, '"');
3415 if (pos2)
3416 pos = pos2 + 1;
3417 }
3418 while (*pos != '\0' && *pos != ' ')
3419 pos++;
3420 if (*pos == ' ')
3421 *pos++ = '\0';
3422 }
3423
3424 return argc;
3425}
3426
3427
3428static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3429{
3430 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3431 printf("Connection to wpa_supplicant lost - trying to "
3432 "reconnect\n");
3433 wpa_cli_close_connection();
3434 }
3435 if (!ctrl_conn)
3436 wpa_cli_reconnect();
3437 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3438}
3439
3440
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003441static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3442{
3443 wpa_cli_recv_pending(mon_conn, 0);
3444}
3445
3446
3447static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3448{
3449 char *argv[max_args];
3450 int argc;
3451 argc = tokenize_cmd(cmd, argv);
3452 if (argc)
3453 wpa_request(ctrl_conn, argc, argv);
3454}
3455
3456
3457static void wpa_cli_edit_eof_cb(void *ctx)
3458{
3459 eloop_terminate();
3460}
3461
3462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003463static int warning_displayed = 0;
3464static char *hfile = NULL;
3465static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003467static void start_edit(void)
3468{
3469 char *home;
3470 char *ps = NULL;
3471
3472#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3473 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3474#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475
3476 home = getenv("HOME");
3477 if (home) {
3478 const char *fname = ".wpa_cli_history";
3479 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3480 hfile = os_malloc(hfile_len);
3481 if (hfile)
3482 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3483 }
3484
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003485 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3486 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3487 eloop_terminate();
3488 return;
3489 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003490
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003491 edit_started = 1;
3492 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3493}
3494
3495
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003496static void update_bssid_list(struct wpa_ctrl *ctrl)
3497{
3498 char buf[4096];
3499 size_t len = sizeof(buf);
3500 int ret;
3501 char *cmd = "BSS RANGE=ALL MASK=0x2";
3502 char *pos, *end;
3503
3504 if (ctrl == NULL)
3505 return;
3506 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3507 if (ret < 0)
3508 return;
3509 buf[len] = '\0';
3510
3511 pos = buf;
3512 while (pos) {
3513 pos = os_strstr(pos, "bssid=");
3514 if (pos == NULL)
3515 break;
3516 pos += 6;
3517 end = os_strchr(pos, '\n');
3518 if (end == NULL)
3519 break;
3520 *end = '\0';
3521 cli_txt_list_add(&bsses, pos);
3522 pos = end + 1;
3523 }
3524}
3525
3526
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003527static void update_ifnames(struct wpa_ctrl *ctrl)
3528{
3529 char buf[4096];
3530 size_t len = sizeof(buf);
3531 int ret;
3532 char *cmd = "INTERFACES";
3533 char *pos, *end;
3534 char txt[200];
3535
3536 cli_txt_list_flush(&ifnames);
3537
3538 if (ctrl == NULL)
3539 return;
3540 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3541 if (ret < 0)
3542 return;
3543 buf[len] = '\0';
3544
3545 pos = buf;
3546 while (pos) {
3547 end = os_strchr(pos, '\n');
3548 if (end == NULL)
3549 break;
3550 *end = '\0';
3551 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3552 if (ret > 0 && ret < (int) sizeof(txt))
3553 cli_txt_list_add(&ifnames, txt);
3554 pos = end + 1;
3555 }
3556}
3557
3558
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003559static void try_connection(void *eloop_ctx, void *timeout_ctx)
3560{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003561 if (ctrl_conn)
3562 goto done;
3563
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003564 if (ctrl_ifname == NULL)
3565 ctrl_ifname = wpa_cli_get_default_ifname();
3566
3567 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3568 if (!warning_displayed) {
3569 printf("Could not connect to wpa_supplicant: "
3570 "%s - re-trying\n", ctrl_ifname);
3571 warning_displayed = 1;
3572 }
3573 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3574 return;
3575 }
3576
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003577 update_bssid_list(ctrl_conn);
3578
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003579 if (warning_displayed)
3580 printf("Connection established.\n");
3581
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003582done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003583 start_edit();
3584}
3585
3586
3587static void wpa_cli_interactive(void)
3588{
3589 printf("\nInteractive mode\n\n");
3590
3591 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003593 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003595 cli_txt_list_flush(&p2p_peers);
3596 cli_txt_list_flush(&p2p_groups);
3597 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003598 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003599 if (edit_started)
3600 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003601 os_free(hfile);
3602 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3603 wpa_cli_close_connection();
3604}
3605
3606
3607static void wpa_cli_action(struct wpa_ctrl *ctrl)
3608{
3609#ifdef CONFIG_ANSI_C_EXTRA
3610 /* TODO: ANSI C version(?) */
3611 printf("Action processing not supported in ANSI C build.\n");
3612#else /* CONFIG_ANSI_C_EXTRA */
3613 fd_set rfds;
3614 int fd, res;
3615 struct timeval tv;
3616 char buf[256]; /* note: large enough to fit in unsolicited messages */
3617 size_t len;
3618
3619 fd = wpa_ctrl_get_fd(ctrl);
3620
3621 while (!wpa_cli_quit) {
3622 FD_ZERO(&rfds);
3623 FD_SET(fd, &rfds);
3624 tv.tv_sec = ping_interval;
3625 tv.tv_usec = 0;
3626 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3627 if (res < 0 && errno != EINTR) {
3628 perror("select");
3629 break;
3630 }
3631
3632 if (FD_ISSET(fd, &rfds))
3633 wpa_cli_recv_pending(ctrl, 1);
3634 else {
3635 /* verify that connection is still working */
3636 len = sizeof(buf) - 1;
3637 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3638 wpa_cli_action_cb) < 0 ||
3639 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3640 printf("wpa_supplicant did not reply to PING "
3641 "command - exiting\n");
3642 break;
3643 }
3644 }
3645 }
3646#endif /* CONFIG_ANSI_C_EXTRA */
3647}
3648
3649
3650static void wpa_cli_cleanup(void)
3651{
3652 wpa_cli_close_connection();
3653 if (pid_file)
3654 os_daemonize_terminate(pid_file);
3655
3656 os_program_deinit();
3657}
3658
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003659
3660static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003661{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003662 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663}
3664
3665
3666static char * wpa_cli_get_default_ifname(void)
3667{
3668 char *ifname = NULL;
3669
3670#ifdef CONFIG_CTRL_IFACE_UNIX
3671 struct dirent *dent;
3672 DIR *dir = opendir(ctrl_iface_dir);
3673 if (!dir) {
3674#ifdef ANDROID
3675 char ifprop[PROPERTY_VALUE_MAX];
3676 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3677 ifname = os_strdup(ifprop);
3678 printf("Using interface '%s'\n", ifname);
3679 return ifname;
3680 }
3681#endif /* ANDROID */
3682 return NULL;
3683 }
3684 while ((dent = readdir(dir))) {
3685#ifdef _DIRENT_HAVE_D_TYPE
3686 /*
3687 * Skip the file if it is not a socket. Also accept
3688 * DT_UNKNOWN (0) in case the C library or underlying
3689 * file system does not support d_type.
3690 */
3691 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3692 continue;
3693#endif /* _DIRENT_HAVE_D_TYPE */
3694 if (os_strcmp(dent->d_name, ".") == 0 ||
3695 os_strcmp(dent->d_name, "..") == 0)
3696 continue;
3697 printf("Selected interface '%s'\n", dent->d_name);
3698 ifname = os_strdup(dent->d_name);
3699 break;
3700 }
3701 closedir(dir);
3702#endif /* CONFIG_CTRL_IFACE_UNIX */
3703
3704#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003705 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 size_t len;
3707 struct wpa_ctrl *ctrl;
3708 int ret;
3709
3710 ctrl = wpa_ctrl_open(NULL);
3711 if (ctrl == NULL)
3712 return NULL;
3713
3714 len = sizeof(buf) - 1;
3715 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3716 if (ret >= 0) {
3717 buf[len] = '\0';
3718 pos = os_strchr(buf, '\n');
3719 if (pos)
3720 *pos = '\0';
3721 ifname = os_strdup(buf);
3722 }
3723 wpa_ctrl_close(ctrl);
3724#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3725
3726 return ifname;
3727}
3728
3729
3730int main(int argc, char *argv[])
3731{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 int c;
3733 int daemonize = 0;
3734 int ret = 0;
3735 const char *global = NULL;
3736
3737 if (os_program_init())
3738 return -1;
3739
3740 for (;;) {
3741 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3742 if (c < 0)
3743 break;
3744 switch (c) {
3745 case 'a':
3746 action_file = optarg;
3747 break;
3748 case 'B':
3749 daemonize = 1;
3750 break;
3751 case 'g':
3752 global = optarg;
3753 break;
3754 case 'G':
3755 ping_interval = atoi(optarg);
3756 break;
3757 case 'h':
3758 usage();
3759 return 0;
3760 case 'v':
3761 printf("%s\n", wpa_cli_version);
3762 return 0;
3763 case 'i':
3764 os_free(ctrl_ifname);
3765 ctrl_ifname = os_strdup(optarg);
3766 break;
3767 case 'p':
3768 ctrl_iface_dir = optarg;
3769 break;
3770 case 'P':
3771 pid_file = optarg;
3772 break;
3773 default:
3774 usage();
3775 return -1;
3776 }
3777 }
3778
3779 interactive = (argc == optind) && (action_file == NULL);
3780
3781 if (interactive)
3782 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3783
3784 if (eloop_init())
3785 return -1;
3786
3787 if (global) {
3788#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3789 ctrl_conn = wpa_ctrl_open(NULL);
3790#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3791 ctrl_conn = wpa_ctrl_open(global);
3792#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3793 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003794 fprintf(stderr, "Failed to connect to wpa_supplicant "
3795 "global interface: %s error: %s\n",
3796 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003797 return -1;
3798 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003799
3800 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003801 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003802 mon_conn = wpa_ctrl_open(global);
3803 if (mon_conn) {
3804 if (wpa_ctrl_attach(mon_conn) == 0) {
3805 wpa_cli_attached = 1;
3806 eloop_register_read_sock(
3807 wpa_ctrl_get_fd(mon_conn),
3808 wpa_cli_mon_receive,
3809 NULL, NULL);
3810 } else {
3811 printf("Failed to open monitor "
3812 "connection through global "
3813 "control interface\n");
3814 }
3815 }
3816 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003817 }
3818
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003819 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003820
3821 if (ctrl_ifname == NULL)
3822 ctrl_ifname = wpa_cli_get_default_ifname();
3823
3824 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003825 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003826 } else {
3827 if (!global &&
3828 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003829 fprintf(stderr, "Failed to connect to non-global "
3830 "ctrl_ifname: %s error: %s\n",
3831 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832 return -1;
3833 }
3834
3835 if (action_file) {
3836 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3837 wpa_cli_attached = 1;
3838 } else {
3839 printf("Warning: Failed to attach to "
3840 "wpa_supplicant.\n");
3841 return -1;
3842 }
3843 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003844
3845 if (daemonize && os_daemonize(pid_file))
3846 return -1;
3847
3848 if (action_file)
3849 wpa_cli_action(ctrl_conn);
3850 else
3851 ret = wpa_request(ctrl_conn, argc - optind,
3852 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 }
3854
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003855 os_free(ctrl_ifname);
3856 eloop_destroy();
3857 wpa_cli_cleanup();
3858
3859 return ret;
3860}
3861
3862#else /* CONFIG_CTRL_IFACE */
3863int main(int argc, char *argv[])
3864{
3865 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3866 return -1;
3867}
3868#endif /* CONFIG_CTRL_IFACE */