blob: 66c4962ac3be4fa3859a76e8d23fd118550282e5 [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 Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, 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 Shmidt051af732013-10-22 13:52:46 -0700630 "ignore_old_scan_res", "freq_list", "external_sim"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700631 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700632 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700633
634 if (arg == 1) {
635 char **res = os_calloc(num_fields + 1, sizeof(char *));
636 if (res == NULL)
637 return NULL;
638 for (i = 0; i < num_fields; i++) {
639 res[i] = os_strdup(fields[i]);
640 if (res[i] == NULL)
641 return res;
642 }
643 return res;
644 }
645
646 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
647 return cli_txt_list_array(&bsses);
648
649 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700650}
651
652
653static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
654{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700655 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656}
657
658
659static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
660{
661 return wpa_ctrl_command(ctrl, "LOGOFF");
662}
663
664
665static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
666{
667 return wpa_ctrl_command(ctrl, "LOGON");
668}
669
670
671static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
672 char *argv[])
673{
674 return wpa_ctrl_command(ctrl, "REASSOCIATE");
675}
676
677
678static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
679 char *argv[])
680{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700681 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700682}
683
684
685static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
686{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700687 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688}
689
690
691static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
692 char *argv[])
693{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700694 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695}
696
697
698static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702}
703
704
705static int wpa_cli_cmd_bss_expire_count(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_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709}
710
711
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700712static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
713{
714 char cmd[256];
715 int res;
716
717 if (argc < 1)
718 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
719 else
720 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
721 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
722 printf("Too long BSS_FLUSH command.\n");
723 return -1;
724 }
725 return wpa_ctrl_command(ctrl, cmd);
726}
727
728
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
730 char *argv[])
731{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700732 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733}
734
735
736static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
737{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700738 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739}
740
741
742static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
743{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700744 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745}
746
747
748static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
749{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 if (argc == 0) {
751 printf("Invalid WPS_PIN command: need one or two arguments:\n"
752 "- BSSID: use 'any' to select any\n"
753 "- PIN: optional, used only with devices that have no "
754 "display\n");
755 return -1;
756 }
757
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700758 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759}
760
761
762static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
763 char *argv[])
764{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700765 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766}
767
768
769static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
771{
772 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
773}
774
775
Dmitry Shmidt04949592012-07-19 12:16:46 -0700776#ifdef CONFIG_WPS_NFC
777
778static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
779{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700780 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700781}
782
783
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800784static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
785 char *argv[])
786{
787 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
788}
789
790
Dmitry Shmidt04949592012-07-19 12:16:46 -0700791static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
792 char *argv[])
793{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700794 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700795}
796
797
798static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
799 char *argv[])
800{
801 int ret;
802 char *buf;
803 size_t buflen;
804
805 if (argc != 1) {
806 printf("Invalid 'wps_nfc_tag_read' command - one argument "
807 "is required.\n");
808 return -1;
809 }
810
811 buflen = 18 + os_strlen(argv[0]);
812 buf = os_malloc(buflen);
813 if (buf == NULL)
814 return -1;
815 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
816
817 ret = wpa_ctrl_command(ctrl, buf);
818 os_free(buf);
819
820 return ret;
821}
822
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800823
824static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
825 char *argv[])
826{
827 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
828}
829
830
831static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
832 char *argv[])
833{
834 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
835}
836
837
838static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
839 char *argv[])
840{
841 int ret;
842 char *buf;
843 size_t buflen;
844
845 if (argc != 1) {
846 printf("Invalid 'nfc_rx_handover_req' command - one argument "
847 "is required.\n");
848 return -1;
849 }
850
851 buflen = 21 + os_strlen(argv[0]);
852 buf = os_malloc(buflen);
853 if (buf == NULL)
854 return -1;
855 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
856
857 ret = wpa_ctrl_command(ctrl, buf);
858 os_free(buf);
859
860 return ret;
861}
862
863
864static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
865 char *argv[])
866{
867 int ret;
868 char *buf;
869 size_t buflen;
870
871 if (argc != 1) {
872 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
873 "is required.\n");
874 return -1;
875 }
876
877 buflen = 21 + os_strlen(argv[0]);
878 buf = os_malloc(buflen);
879 if (buf == NULL)
880 return -1;
881 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
882
883 ret = wpa_ctrl_command(ctrl, buf);
884 os_free(buf);
885
886 return ret;
887}
888
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800889
890static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
891 char *argv[])
892{
893 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
894}
895
Dmitry Shmidt04949592012-07-19 12:16:46 -0700896#endif /* CONFIG_WPS_NFC */
897
898
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
900{
901 char cmd[256];
902 int res;
903
904 if (argc == 2)
905 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
906 argv[0], argv[1]);
907 else if (argc == 5 || argc == 6) {
908 char ssid_hex[2 * 32 + 1];
909 char key_hex[2 * 64 + 1];
910 int i;
911
912 ssid_hex[0] = '\0';
913 for (i = 0; i < 32; i++) {
914 if (argv[2][i] == '\0')
915 break;
916 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
917 }
918
919 key_hex[0] = '\0';
920 if (argc == 6) {
921 for (i = 0; i < 64; i++) {
922 if (argv[5][i] == '\0')
923 break;
924 os_snprintf(&key_hex[i * 2], 3, "%02x",
925 argv[5][i]);
926 }
927 }
928
929 res = os_snprintf(cmd, sizeof(cmd),
930 "WPS_REG %s %s %s %s %s %s",
931 argv[0], argv[1], ssid_hex, argv[3], argv[4],
932 key_hex);
933 } else {
934 printf("Invalid WPS_REG command: need two arguments:\n"
935 "- BSSID of the target AP\n"
936 "- AP PIN\n");
937 printf("Alternatively, six arguments can be used to "
938 "reconfigure the AP:\n"
939 "- BSSID of the target AP\n"
940 "- AP PIN\n"
941 "- new SSID\n"
942 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
943 "- new encr (NONE, WEP, TKIP, CCMP)\n"
944 "- new key\n");
945 return -1;
946 }
947
948 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
949 printf("Too long WPS_REG command.\n");
950 return -1;
951 }
952 return wpa_ctrl_command(ctrl, cmd);
953}
954
955
956static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
957 char *argv[])
958{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700959 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700960}
961
962
963static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
964 char *argv[])
965{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700966 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967}
968
969
970static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
971 char *argv[])
972{
973 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
974
975}
976
977
978static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
979 char *argv[])
980{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981 if (argc < 2) {
982 printf("Invalid WPS_ER_PIN command: need at least two "
983 "arguments:\n"
984 "- UUID: use 'any' to select any\n"
985 "- PIN: Enrollee PIN\n"
986 "optional: - Enrollee MAC address\n");
987 return -1;
988 }
989
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700990 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991}
992
993
994static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
995 char *argv[])
996{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700997 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700998}
999
1000
1001static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1002 char *argv[])
1003{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 if (argc != 2) {
1005 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1006 "- UUID: specify which AP to use\n"
1007 "- PIN: AP PIN\n");
1008 return -1;
1009 }
1010
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001011 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012}
1013
1014
1015static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1016 char *argv[])
1017{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 if (argc != 2) {
1019 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1020 "arguments:\n"
1021 "- UUID: specify which AP to use\n"
1022 "- Network configuration id\n");
1023 return -1;
1024 }
1025
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001026 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027}
1028
1029
1030static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1031 char *argv[])
1032{
1033 char cmd[256];
1034 int res;
1035
1036 if (argc == 5 || argc == 6) {
1037 char ssid_hex[2 * 32 + 1];
1038 char key_hex[2 * 64 + 1];
1039 int i;
1040
1041 ssid_hex[0] = '\0';
1042 for (i = 0; i < 32; i++) {
1043 if (argv[2][i] == '\0')
1044 break;
1045 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1046 }
1047
1048 key_hex[0] = '\0';
1049 if (argc == 6) {
1050 for (i = 0; i < 64; i++) {
1051 if (argv[5][i] == '\0')
1052 break;
1053 os_snprintf(&key_hex[i * 2], 3, "%02x",
1054 argv[5][i]);
1055 }
1056 }
1057
1058 res = os_snprintf(cmd, sizeof(cmd),
1059 "WPS_ER_CONFIG %s %s %s %s %s %s",
1060 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1061 key_hex);
1062 } else {
1063 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1064 "- AP UUID\n"
1065 "- AP PIN\n"
1066 "- new SSID\n"
1067 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1068 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1069 "- new key\n");
1070 return -1;
1071 }
1072
1073 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1074 printf("Too long WPS_ER_CONFIG command.\n");
1075 return -1;
1076 }
1077 return wpa_ctrl_command(ctrl, cmd);
1078}
1079
1080
Dmitry Shmidt04949592012-07-19 12:16:46 -07001081#ifdef CONFIG_WPS_NFC
1082static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1083 char *argv[])
1084{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001085 if (argc != 2) {
1086 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1087 "arguments:\n"
1088 "- WPS/NDEF: token format\n"
1089 "- UUID: specify which AP to use\n");
1090 return -1;
1091 }
1092
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001093 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001094}
1095#endif /* CONFIG_WPS_NFC */
1096
1097
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001100 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101}
1102
1103
1104static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1105{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001106 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107}
1108
1109
1110static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1111{
1112 char cmd[256], *pos, *end;
1113 int i, ret;
1114
1115 if (argc < 2) {
1116 printf("Invalid IDENTITY command: needs two arguments "
1117 "(network id and identity)\n");
1118 return -1;
1119 }
1120
1121 end = cmd + sizeof(cmd);
1122 pos = cmd;
1123 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1124 argv[0], argv[1]);
1125 if (ret < 0 || ret >= end - pos) {
1126 printf("Too long IDENTITY command.\n");
1127 return -1;
1128 }
1129 pos += ret;
1130 for (i = 2; i < argc; i++) {
1131 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1132 if (ret < 0 || ret >= end - pos) {
1133 printf("Too long IDENTITY command.\n");
1134 return -1;
1135 }
1136 pos += ret;
1137 }
1138
1139 return wpa_ctrl_command(ctrl, cmd);
1140}
1141
1142
1143static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1144{
1145 char cmd[256], *pos, *end;
1146 int i, ret;
1147
1148 if (argc < 2) {
1149 printf("Invalid PASSWORD command: needs two arguments "
1150 "(network id and password)\n");
1151 return -1;
1152 }
1153
1154 end = cmd + sizeof(cmd);
1155 pos = cmd;
1156 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1157 argv[0], argv[1]);
1158 if (ret < 0 || ret >= end - pos) {
1159 printf("Too long PASSWORD command.\n");
1160 return -1;
1161 }
1162 pos += ret;
1163 for (i = 2; i < argc; i++) {
1164 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1165 if (ret < 0 || ret >= end - pos) {
1166 printf("Too long PASSWORD command.\n");
1167 return -1;
1168 }
1169 pos += ret;
1170 }
1171
1172 return wpa_ctrl_command(ctrl, cmd);
1173}
1174
1175
1176static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1177 char *argv[])
1178{
1179 char cmd[256], *pos, *end;
1180 int i, ret;
1181
1182 if (argc < 2) {
1183 printf("Invalid NEW_PASSWORD command: needs two arguments "
1184 "(network id and password)\n");
1185 return -1;
1186 }
1187
1188 end = cmd + sizeof(cmd);
1189 pos = cmd;
1190 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1191 argv[0], argv[1]);
1192 if (ret < 0 || ret >= end - pos) {
1193 printf("Too long NEW_PASSWORD command.\n");
1194 return -1;
1195 }
1196 pos += ret;
1197 for (i = 2; i < argc; i++) {
1198 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1199 if (ret < 0 || ret >= end - pos) {
1200 printf("Too long NEW_PASSWORD command.\n");
1201 return -1;
1202 }
1203 pos += ret;
1204 }
1205
1206 return wpa_ctrl_command(ctrl, cmd);
1207}
1208
1209
1210static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1211{
1212 char cmd[256], *pos, *end;
1213 int i, ret;
1214
1215 if (argc < 2) {
1216 printf("Invalid PIN command: needs two arguments "
1217 "(network id and pin)\n");
1218 return -1;
1219 }
1220
1221 end = cmd + sizeof(cmd);
1222 pos = cmd;
1223 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1224 argv[0], argv[1]);
1225 if (ret < 0 || ret >= end - pos) {
1226 printf("Too long PIN command.\n");
1227 return -1;
1228 }
1229 pos += ret;
1230 for (i = 2; i < argc; i++) {
1231 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1232 if (ret < 0 || ret >= end - pos) {
1233 printf("Too long PIN command.\n");
1234 return -1;
1235 }
1236 pos += ret;
1237 }
1238 return wpa_ctrl_command(ctrl, cmd);
1239}
1240
1241
1242static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1243{
1244 char cmd[256], *pos, *end;
1245 int i, ret;
1246
1247 if (argc < 2) {
1248 printf("Invalid OTP command: needs two arguments (network "
1249 "id and password)\n");
1250 return -1;
1251 }
1252
1253 end = cmd + sizeof(cmd);
1254 pos = cmd;
1255 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1256 argv[0], argv[1]);
1257 if (ret < 0 || ret >= end - pos) {
1258 printf("Too long OTP command.\n");
1259 return -1;
1260 }
1261 pos += ret;
1262 for (i = 2; i < argc; i++) {
1263 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1264 if (ret < 0 || ret >= end - pos) {
1265 printf("Too long OTP command.\n");
1266 return -1;
1267 }
1268 pos += ret;
1269 }
1270
1271 return wpa_ctrl_command(ctrl, cmd);
1272}
1273
1274
Dmitry Shmidt051af732013-10-22 13:52:46 -07001275static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1276{
1277 char cmd[256], *pos, *end;
1278 int i, ret;
1279
1280 if (argc < 2) {
1281 printf("Invalid SIM command: needs two arguments "
1282 "(network id and SIM operation response)\n");
1283 return -1;
1284 }
1285
1286 end = cmd + sizeof(cmd);
1287 pos = cmd;
1288 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1289 argv[0], argv[1]);
1290 if (ret < 0 || ret >= end - pos) {
1291 printf("Too long SIM command.\n");
1292 return -1;
1293 }
1294 pos += ret;
1295 for (i = 2; i < argc; i++) {
1296 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1297 if (ret < 0 || ret >= end - pos) {
1298 printf("Too long SIM command.\n");
1299 return -1;
1300 }
1301 pos += ret;
1302 }
1303 return wpa_ctrl_command(ctrl, cmd);
1304}
1305
1306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1308 char *argv[])
1309{
1310 char cmd[256], *pos, *end;
1311 int i, ret;
1312
1313 if (argc < 2) {
1314 printf("Invalid PASSPHRASE command: needs two arguments "
1315 "(network id and passphrase)\n");
1316 return -1;
1317 }
1318
1319 end = cmd + sizeof(cmd);
1320 pos = cmd;
1321 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1322 argv[0], argv[1]);
1323 if (ret < 0 || ret >= end - pos) {
1324 printf("Too long PASSPHRASE command.\n");
1325 return -1;
1326 }
1327 pos += ret;
1328 for (i = 2; i < argc; i++) {
1329 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1330 if (ret < 0 || ret >= end - pos) {
1331 printf("Too long PASSPHRASE command.\n");
1332 return -1;
1333 }
1334 pos += ret;
1335 }
1336
1337 return wpa_ctrl_command(ctrl, cmd);
1338}
1339
1340
1341static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1342{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343 if (argc < 2) {
1344 printf("Invalid BSSID command: needs two arguments (network "
1345 "id and BSSID)\n");
1346 return -1;
1347 }
1348
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001349 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350}
1351
1352
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001353static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1354{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001355 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001356}
1357
1358
1359static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1360{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001361 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001362}
1363
1364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1366 char *argv[])
1367{
1368 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1369}
1370
1371
1372static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1373 char *argv[])
1374{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001375 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376}
1377
1378
1379static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1380 char *argv[])
1381{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001382 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383}
1384
1385
1386static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1387 char *argv[])
1388{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001389 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390}
1391
1392
1393static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1394 char *argv[])
1395{
1396 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1397}
1398
1399
1400static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1401 char *argv[])
1402{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404}
1405
1406
1407static void wpa_cli_show_network_variables(void)
1408{
1409 printf("set_network variables:\n"
1410 " ssid (network name, SSID)\n"
1411 " psk (WPA passphrase or pre-shared key)\n"
1412 " key_mgmt (key management protocol)\n"
1413 " identity (EAP identity)\n"
1414 " password (EAP password)\n"
1415 " ...\n"
1416 "\n"
1417 "Note: Values are entered in the same format as the "
1418 "configuration file is using,\n"
1419 "i.e., strings values need to be inside double quotation "
1420 "marks.\n"
1421 "For example: set_network 1 ssid \"network name\"\n"
1422 "\n"
1423 "Please see wpa_supplicant.conf documentation for full list "
1424 "of\navailable variables.\n");
1425}
1426
1427
1428static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1429 char *argv[])
1430{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431 if (argc == 0) {
1432 wpa_cli_show_network_variables();
1433 return 0;
1434 }
1435
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001436 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001437 printf("Invalid SET_NETWORK command: needs three arguments\n"
1438 "(network id, variable name, and value)\n");
1439 return -1;
1440 }
1441
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001442 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001443}
1444
1445
1446static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1447 char *argv[])
1448{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001449 if (argc == 0) {
1450 wpa_cli_show_network_variables();
1451 return 0;
1452 }
1453
1454 if (argc != 2) {
1455 printf("Invalid GET_NETWORK command: needs two arguments\n"
1456 "(network id and variable name)\n");
1457 return -1;
1458 }
1459
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001460 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461}
1462
1463
Dmitry Shmidt04949592012-07-19 12:16:46 -07001464static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1465 char *argv[])
1466{
1467 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1468}
1469
1470
1471static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1472{
1473 return wpa_ctrl_command(ctrl, "ADD_CRED");
1474}
1475
1476
1477static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1478 char *argv[])
1479{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001480 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001481}
1482
1483
1484static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1485{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001486 if (argc != 3) {
1487 printf("Invalid SET_CRED command: needs three arguments\n"
1488 "(cred id, variable name, and value)\n");
1489 return -1;
1490 }
1491
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001492 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001493}
1494
1495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1497 char *argv[])
1498{
1499 return wpa_ctrl_command(ctrl, "DISCONNECT");
1500}
1501
1502
1503static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1504 char *argv[])
1505{
1506 return wpa_ctrl_command(ctrl, "RECONNECT");
1507}
1508
1509
1510static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1511 char *argv[])
1512{
1513 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1514}
1515
1516
1517static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1518{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001519 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001520}
1521
1522
1523static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1524 char *argv[])
1525{
1526 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1527}
1528
1529
1530static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1531{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001532 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533}
1534
1535
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001536static char ** wpa_cli_complete_bss(const char *str, int pos)
1537{
1538 int arg = get_cmd_arg_num(str, pos);
1539 char **res = NULL;
1540
1541 switch (arg) {
1542 case 1:
1543 res = cli_txt_list_array(&bsses);
1544 break;
1545 }
1546
1547 return res;
1548}
1549
1550
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001551static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1552 char *argv[])
1553{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 if (argc < 1 || argc > 2) {
1555 printf("Invalid GET_CAPABILITY command: need either one or "
1556 "two arguments\n");
1557 return -1;
1558 }
1559
1560 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1561 printf("Invalid GET_CAPABILITY command: second argument, "
1562 "if any, must be 'strict'\n");
1563 return -1;
1564 }
1565
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001566 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001567}
1568
1569
1570static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1571{
1572 printf("Available interfaces:\n");
1573 return wpa_ctrl_command(ctrl, "INTERFACES");
1574}
1575
1576
1577static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1578{
1579 if (argc < 1) {
1580 wpa_cli_list_interfaces(ctrl);
1581 return 0;
1582 }
1583
1584 wpa_cli_close_connection();
1585 os_free(ctrl_ifname);
1586 ctrl_ifname = os_strdup(argv[0]);
1587
1588 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1589 printf("Connected to interface '%s.\n", ctrl_ifname);
1590 } else {
1591 printf("Could not connect to interface '%s' - re-trying\n",
1592 ctrl_ifname);
1593 }
1594 return 0;
1595}
1596
1597
1598static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1599 char *argv[])
1600{
1601 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1602}
1603
1604
1605static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1606 char *argv[])
1607{
1608 return wpa_ctrl_command(ctrl, "TERMINATE");
1609}
1610
1611
1612static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1613 char *argv[])
1614{
1615 char cmd[256];
1616 int res;
1617
1618 if (argc < 1) {
1619 printf("Invalid INTERFACE_ADD command: needs at least one "
1620 "argument (interface name)\n"
1621 "All arguments: ifname confname driver ctrl_interface "
1622 "driver_param bridge_name\n");
1623 return -1;
1624 }
1625
1626 /*
1627 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1628 * <driver_param>TAB<bridge_name>
1629 */
1630 res = os_snprintf(cmd, sizeof(cmd),
1631 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1632 argv[0],
1633 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1634 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1635 argc > 5 ? argv[5] : "");
1636 if (res < 0 || (size_t) res >= sizeof(cmd))
1637 return -1;
1638 cmd[sizeof(cmd) - 1] = '\0';
1639 return wpa_ctrl_command(ctrl, cmd);
1640}
1641
1642
1643static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1644 char *argv[])
1645{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001646 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001647}
1648
1649
1650static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1651 char *argv[])
1652{
1653 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1654}
1655
1656
1657#ifdef CONFIG_AP
1658static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1659{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001660 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661}
1662
1663
1664static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1665 char *addr, size_t addr_len)
1666{
1667 char buf[4096], *pos;
1668 size_t len;
1669 int ret;
1670
1671 if (ctrl_conn == NULL) {
1672 printf("Not connected to hostapd - command dropped.\n");
1673 return -1;
1674 }
1675 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001676 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001677 wpa_cli_msg_cb);
1678 if (ret == -2) {
1679 printf("'%s' command timed out.\n", cmd);
1680 return -2;
1681 } else if (ret < 0) {
1682 printf("'%s' command failed.\n", cmd);
1683 return -1;
1684 }
1685
1686 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001687 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688 return -1;
1689 printf("%s", buf);
1690
1691 pos = buf;
1692 while (*pos != '\0' && *pos != '\n')
1693 pos++;
1694 *pos = '\0';
1695 os_strlcpy(addr, buf, addr_len);
1696 return 0;
1697}
1698
1699
1700static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1701{
1702 char addr[32], cmd[64];
1703
1704 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1705 return 0;
1706 do {
1707 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1708 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1709
1710 return -1;
1711}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001712
1713
1714static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1715 char *argv[])
1716{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001717 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001718}
1719
1720
1721static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1722 char *argv[])
1723{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001724 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001725}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726#endif /* CONFIG_AP */
1727
1728
1729static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1730{
1731 return wpa_ctrl_command(ctrl, "SUSPEND");
1732}
1733
1734
1735static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1736{
1737 return wpa_ctrl_command(ctrl, "RESUME");
1738}
1739
1740
1741static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
1743 return wpa_ctrl_command(ctrl, "DROP_SA");
1744}
1745
1746
1747static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1748{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001749 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750}
1751
1752
1753#ifdef CONFIG_P2P
1754
1755static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1756{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001757 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1758}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001761static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1762{
1763 char **res = NULL;
1764 int arg = get_cmd_arg_num(str, pos);
1765
1766 res = os_calloc(6, sizeof(char *));
1767 if (res == NULL)
1768 return NULL;
1769 res[0] = os_strdup("type=social");
1770 if (res[0] == NULL) {
1771 os_free(res);
1772 return NULL;
1773 }
1774 res[1] = os_strdup("type=progressive");
1775 if (res[1] == NULL)
1776 return res;
1777 res[2] = os_strdup("delay=");
1778 if (res[2] == NULL)
1779 return res;
1780 res[3] = os_strdup("dev_id=");
1781 if (res[3] == NULL)
1782 return res;
1783 if (arg == 1)
1784 res[4] = os_strdup("[timeout]");
1785
1786 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
1790static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1791 char *argv[])
1792{
1793 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1794}
1795
1796
1797static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1798 char *argv[])
1799{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001800 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801}
1802
1803
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001804static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1805{
1806 int arg = get_cmd_arg_num(str, pos);
1807 char **res = NULL;
1808
1809 switch (arg) {
1810 case 1:
1811 res = cli_txt_list_array(&p2p_peers);
1812 break;
1813 }
1814
1815 return res;
1816}
1817
1818
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001822 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823}
1824
1825
1826static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1827 char *argv[])
1828{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001829 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830}
1831
1832
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001833static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1834{
1835 int arg = get_cmd_arg_num(str, pos);
1836 char **res = NULL;
1837
1838 switch (arg) {
1839 case 1:
1840 res = cli_txt_list_array(&p2p_groups);
1841 break;
1842 }
1843
1844 return res;
1845}
1846
1847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1849 char *argv[])
1850{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001851 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852}
1853
1854
1855static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1856 char *argv[])
1857{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001858 if (argc != 2 && argc != 3) {
1859 printf("Invalid P2P_PROV_DISC command: needs at least "
1860 "two arguments, address and config method\n"
1861 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862 return -1;
1863 }
1864
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001865 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866}
1867
1868
1869static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1870 char *argv[])
1871{
1872 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1873}
1874
1875
1876static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1877 char *argv[])
1878{
1879 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880
1881 if (argc != 2 && argc != 4) {
1882 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1883 "arguments (address and TLVs) or four arguments "
1884 "(address, \"upnp\", version, search target "
1885 "(SSDP ST:)\n");
1886 return -1;
1887 }
1888
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001889 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 return wpa_ctrl_command(ctrl, cmd);
1892}
1893
1894
1895static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1896 int argc, char *argv[])
1897{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001898 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899}
1900
1901
1902static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1903 char *argv[])
1904{
1905 char cmd[4096];
1906 int res;
1907
1908 if (argc != 4) {
1909 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1910 "arguments (freq, address, dialog token, and TLVs)\n");
1911 return -1;
1912 }
1913
1914 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1915 argv[0], argv[1], argv[2], argv[3]);
1916 if (res < 0 || (size_t) res >= sizeof(cmd))
1917 return -1;
1918 cmd[sizeof(cmd) - 1] = '\0';
1919 return wpa_ctrl_command(ctrl, cmd);
1920}
1921
1922
1923static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1924 char *argv[])
1925{
1926 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1927}
1928
1929
1930static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1931 int argc, char *argv[])
1932{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001933 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934}
1935
1936
1937static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1938 char *argv[])
1939{
1940 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1941}
1942
1943
1944static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1945 char *argv[])
1946{
1947 char cmd[4096];
1948 int res;
1949
1950 if (argc != 3 && argc != 4) {
1951 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1952 "arguments\n");
1953 return -1;
1954 }
1955
1956 if (argc == 4)
1957 res = os_snprintf(cmd, sizeof(cmd),
1958 "P2P_SERVICE_ADD %s %s %s %s",
1959 argv[0], argv[1], argv[2], argv[3]);
1960 else
1961 res = os_snprintf(cmd, sizeof(cmd),
1962 "P2P_SERVICE_ADD %s %s %s",
1963 argv[0], argv[1], argv[2]);
1964 if (res < 0 || (size_t) res >= sizeof(cmd))
1965 return -1;
1966 cmd[sizeof(cmd) - 1] = '\0';
1967 return wpa_ctrl_command(ctrl, cmd);
1968}
1969
1970
1971static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1972 char *argv[])
1973{
1974 char cmd[4096];
1975 int res;
1976
1977 if (argc != 2 && argc != 3) {
1978 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1979 "arguments\n");
1980 return -1;
1981 }
1982
1983 if (argc == 3)
1984 res = os_snprintf(cmd, sizeof(cmd),
1985 "P2P_SERVICE_DEL %s %s %s",
1986 argv[0], argv[1], argv[2]);
1987 else
1988 res = os_snprintf(cmd, sizeof(cmd),
1989 "P2P_SERVICE_DEL %s %s",
1990 argv[0], argv[1]);
1991 if (res < 0 || (size_t) res >= sizeof(cmd))
1992 return -1;
1993 cmd[sizeof(cmd) - 1] = '\0';
1994 return wpa_ctrl_command(ctrl, cmd);
1995}
1996
1997
1998static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1999 int argc, char *argv[])
2000{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002001 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002}
2003
2004
2005static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2006 int argc, char *argv[])
2007{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002008 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009}
2010
2011
2012static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2013{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002014 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015}
2016
2017
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002018static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2019{
2020 int arg = get_cmd_arg_num(str, pos);
2021 char **res = NULL;
2022
2023 switch (arg) {
2024 case 1:
2025 res = cli_txt_list_array(&p2p_peers);
2026 break;
2027 }
2028
2029 return res;
2030}
2031
2032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002033static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2034 char *addr, size_t addr_len,
2035 int discovered)
2036{
2037 char buf[4096], *pos;
2038 size_t len;
2039 int ret;
2040
2041 if (ctrl_conn == NULL)
2042 return -1;
2043 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002044 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 wpa_cli_msg_cb);
2046 if (ret == -2) {
2047 printf("'%s' command timed out.\n", cmd);
2048 return -2;
2049 } else if (ret < 0) {
2050 printf("'%s' command failed.\n", cmd);
2051 return -1;
2052 }
2053
2054 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002055 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056 return -1;
2057
2058 pos = buf;
2059 while (*pos != '\0' && *pos != '\n')
2060 pos++;
2061 *pos++ = '\0';
2062 os_strlcpy(addr, buf, addr_len);
2063 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2064 printf("%s\n", addr);
2065 return 0;
2066}
2067
2068
2069static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2070{
2071 char addr[32], cmd[64];
2072 int discovered;
2073
2074 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2075
2076 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2077 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002078 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079 do {
2080 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2081 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2082 discovered) == 0);
2083
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002084 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085}
2086
2087
2088static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2089{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002090 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091}
2092
2093
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002094static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2095{
2096 int arg = get_cmd_arg_num(str, pos);
2097 const char *fields[] = {
2098 "discoverability",
2099 "managed",
2100 "listen_channel",
2101 "ssid_postfix",
2102 "noa",
2103 "ps",
2104 "oppps",
2105 "ctwindow",
2106 "disabled",
2107 "conc_pref",
2108 "force_long_sd",
2109 "peer_filter",
2110 "cross_connect",
2111 "go_apsd",
2112 "client_apsd",
2113 "disallow_freq",
2114 "disc_int",
2115 "per_sta_psk",
2116 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002117 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002118
2119 if (arg == 1) {
2120 char **res = os_calloc(num_fields + 1, sizeof(char *));
2121 if (res == NULL)
2122 return NULL;
2123 for (i = 0; i < num_fields; i++) {
2124 res[i] = os_strdup(fields[i]);
2125 if (res[i] == NULL)
2126 return res;
2127 }
2128 return res;
2129 }
2130
2131 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2132 return cli_txt_list_array(&p2p_peers);
2133
2134 return NULL;
2135}
2136
2137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2139{
2140 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2141}
2142
2143
2144static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2145 char *argv[])
2146{
2147 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2148}
2149
2150
2151static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2152 char *argv[])
2153{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002154 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155}
2156
2157
2158static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2159 char *argv[])
2160{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002161 if (argc != 0 && argc != 2 && argc != 4) {
2162 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2163 "(preferred duration, interval; in microsecods).\n"
2164 "Optional second pair can be used to provide "
2165 "acceptable values.\n");
2166 return -1;
2167 }
2168
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002169 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170}
2171
2172
2173static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2174 char *argv[])
2175{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 if (argc != 0 && argc != 2) {
2177 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2178 "(availability period, availability interval; in "
2179 "millisecods).\n"
2180 "Extended Listen Timing can be cancelled with this "
2181 "command when used without parameters.\n");
2182 return -1;
2183 }
2184
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002185 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2186}
2187
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002188
2189static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2190 char *argv[])
2191{
2192 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2193}
2194
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002195#endif /* CONFIG_P2P */
2196
2197#ifdef CONFIG_WIFI_DISPLAY
2198
2199static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2200 char *argv[])
2201{
2202 char cmd[100];
2203 int res;
2204
2205 if (argc != 1 && argc != 2) {
2206 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2207 "arguments (subelem, hexdump)\n");
2208 return -1;
2209 }
2210
2211 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2212 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 if (res < 0 || (size_t) res >= sizeof(cmd))
2214 return -1;
2215 cmd[sizeof(cmd) - 1] = '\0';
2216 return wpa_ctrl_command(ctrl, cmd);
2217}
2218
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002219
2220static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2221 char *argv[])
2222{
2223 char cmd[100];
2224 int res;
2225
2226 if (argc != 1) {
2227 printf("Invalid WFD_SUBELEM_GET command: needs one "
2228 "argument (subelem)\n");
2229 return -1;
2230 }
2231
2232 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2233 argv[0]);
2234 if (res < 0 || (size_t) res >= sizeof(cmd))
2235 return -1;
2236 cmd[sizeof(cmd) - 1] = '\0';
2237 return wpa_ctrl_command(ctrl, cmd);
2238}
2239#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240
2241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002242#ifdef CONFIG_INTERWORKING
2243static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2244 char *argv[])
2245{
2246 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2247}
2248
2249
2250static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2251 char *argv[])
2252{
2253 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2254}
2255
2256
2257static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2258 char *argv[])
2259{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002260 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002261}
2262
2263
2264static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2265 char *argv[])
2266{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002267 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002268}
2269
2270
2271static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2272{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002273 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2274}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002277static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2278 char *argv[])
2279{
2280 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2281}
2282
2283
2284static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2285 char *argv[])
2286{
2287 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002288}
2289#endif /* CONFIG_INTERWORKING */
2290
2291
Dmitry Shmidt04949592012-07-19 12:16:46 -07002292#ifdef CONFIG_HS20
2293
2294static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2295 char *argv[])
2296{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002297 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002298}
2299
2300
2301static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2302 char *argv[])
2303{
2304 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002305
2306 if (argc == 0) {
2307 printf("Command needs one or two arguments (dst mac addr and "
2308 "optional home realm)\n");
2309 return -1;
2310 }
2311
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002312 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2313 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002314 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002315
2316 return wpa_ctrl_command(ctrl, cmd);
2317}
2318
2319#endif /* CONFIG_HS20 */
2320
2321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2323 char *argv[])
2324{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002325 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002326}
2327
2328
2329static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2330 char *argv[])
2331{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002332 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333}
2334
2335
2336static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2337 char *argv[])
2338{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002339 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340}
2341
2342
2343static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2344 char *argv[])
2345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002346 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347}
2348
2349
2350static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2351 char *argv[])
2352{
2353 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2354}
2355
2356
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002357static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2358 char *argv[])
2359{
2360 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2361}
2362
2363
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002364static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2365 char *argv[])
2366{
2367 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2368}
2369
Dmitry Shmidt04949592012-07-19 12:16:46 -07002370
2371#ifdef CONFIG_AUTOSCAN
2372
2373static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2374{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002375 if (argc == 0)
2376 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2377
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002378 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002379}
2380
2381#endif /* CONFIG_AUTOSCAN */
2382
2383
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002384#ifdef CONFIG_WNM
2385
2386static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2387{
2388 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2389}
2390
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002391
2392static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2393{
2394 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2395}
2396
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002397#endif /* CONFIG_WNM */
2398
2399
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002400static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2401{
2402 if (argc == 0)
2403 return -1;
2404 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2405}
2406
2407
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002408#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002409static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2410{
2411 char cmd[256];
2412 int i;
2413 int len;
2414
2415 if (argc < 1) {
2416 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2417 return -1;
2418 }
2419
2420 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2421 for (i=1; i < argc; i++)
2422 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2423 cmd[sizeof(cmd) - 1] = '\0';
2424 printf("%s: %s\n", __func__, cmd);
2425 return wpa_ctrl_command(ctrl, cmd);
2426}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002427#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002428
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002430static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2431{
2432 return wpa_ctrl_command(ctrl, "FLUSH");
2433}
2434
2435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436enum wpa_cli_cmd_flags {
2437 cli_cmd_flag_none = 0x00,
2438 cli_cmd_flag_sensitive = 0x01
2439};
2440
2441struct wpa_cli_cmd {
2442 const char *cmd;
2443 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 enum wpa_cli_cmd_flags flags;
2446 const char *usage;
2447};
2448
2449static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002450 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002451 cli_cmd_flag_none,
2452 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 { "ifname", wpa_cli_cmd_ifname, NULL,
2454 cli_cmd_flag_none,
2455 "= get current interface name" },
2456 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 cli_cmd_flag_none,
2458 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002459 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 cli_cmd_flag_none,
2461 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002462 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002463 cli_cmd_flag_none,
2464 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002465 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 cli_cmd_flag_none,
2467 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 "[command] = show usage help" },
2471 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002474 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 cli_cmd_flag_none,
2476 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002477 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 cli_cmd_flag_none,
2479 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_none,
2482 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002483 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 cli_cmd_flag_none,
2485 "= set variables (shows list of variables when run without "
2486 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 cli_cmd_flag_none,
2489 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002490 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 cli_cmd_flag_none,
2492 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002493 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494 cli_cmd_flag_none,
2495 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002496 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 cli_cmd_flag_none,
2498 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002499 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 cli_cmd_flag_none,
2501 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002502 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503 cli_cmd_flag_none,
2504 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002505 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506 cli_cmd_flag_none,
2507 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002508 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 cli_cmd_flag_sensitive,
2510 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002511 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 cli_cmd_flag_sensitive,
2513 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002514 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 cli_cmd_flag_sensitive,
2516 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002517 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 cli_cmd_flag_sensitive,
2519 "<network id> <password> = configure one-time-password for an SSID"
2520 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002521 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 cli_cmd_flag_sensitive,
2523 "<network id> <passphrase> = configure private key passphrase\n"
2524 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002525 { "sim", wpa_cli_cmd_sim, NULL,
2526 cli_cmd_flag_sensitive,
2527 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002532 cli_cmd_flag_none,
2533 "<BSSID> = add a BSSID to the blacklist\n"
2534 "blacklist clear = clear the blacklist\n"
2535 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002537 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002538 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002539 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 cli_cmd_flag_none,
2542 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_none,
2545 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002546 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547 cli_cmd_flag_none,
2548 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550 cli_cmd_flag_none,
2551 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553 cli_cmd_flag_none,
2554 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002555 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 cli_cmd_flag_none,
2557 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002558 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 cli_cmd_flag_sensitive,
2560 "<network id> <variable> <value> = set network variables (shows\n"
2561 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563 cli_cmd_flag_none,
2564 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002566 cli_cmd_flag_none,
2567 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002569 cli_cmd_flag_none,
2570 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002571 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002572 cli_cmd_flag_none,
2573 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002575 cli_cmd_flag_sensitive,
2576 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_none,
2579 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002580 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 cli_cmd_flag_none,
2582 "= disconnect and wait for reassociate/reconnect command before\n"
2583 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 cli_cmd_flag_none,
2586 "= like reassociate, but only takes effect if already disconnected"
2587 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_none,
2590 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 cli_cmd_flag_none,
2593 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_none,
2596 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002597 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002599 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 "= get capabilies" },
2601 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002602 cli_cmd_flag_none,
2603 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 cli_cmd_flag_none,
2606 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002607 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 cli_cmd_flag_none,
2609 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2610 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2611 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 cli_cmd_flag_none,
2614 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 cli_cmd_flag_none,
2617 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002618 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 cli_cmd_flag_none,
2620 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 cli_cmd_flag_none,
2623 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002624 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 cli_cmd_flag_none,
2626 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002631 cli_cmd_flag_none,
2632 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 cli_cmd_flag_none,
2635 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 cli_cmd_flag_none,
2638 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002639 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 cli_cmd_flag_none,
2641 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 cli_cmd_flag_sensitive,
2644 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2645 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002646 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 cli_cmd_flag_sensitive,
2648 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002651#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002652 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002653 cli_cmd_flag_none,
2654 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002655 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2656 cli_cmd_flag_none,
2657 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002659 cli_cmd_flag_none,
2660 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002661 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002662 cli_cmd_flag_sensitive,
2663 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002664 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2665 cli_cmd_flag_none,
2666 "<NDEF> <WPS> = create NFC handover request" },
2667 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2668 cli_cmd_flag_none,
2669 "<NDEF> <WPS> = create NFC handover select" },
2670 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2671 cli_cmd_flag_none,
2672 "<hexdump of payload> = report received NFC handover request" },
2673 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2674 cli_cmd_flag_none,
2675 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002676 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2677 cli_cmd_flag_none,
2678 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2679 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002680#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002681 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 cli_cmd_flag_sensitive,
2683 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 cli_cmd_flag_sensitive,
2686 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002688 cli_cmd_flag_none,
2689 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 cli_cmd_flag_none,
2692 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002693 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694 cli_cmd_flag_sensitive,
2695 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002696 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 cli_cmd_flag_none,
2698 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 cli_cmd_flag_sensitive,
2701 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002702 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 cli_cmd_flag_none,
2704 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002705 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 cli_cmd_flag_sensitive,
2707 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002708#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002709 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002710 cli_cmd_flag_none,
2711 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2712#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 cli_cmd_flag_none,
2715 "<addr> = request RSN authentication with <addr> in IBSS" },
2716#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 cli_cmd_flag_none,
2719 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 cli_cmd_flag_none,
2722 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002724 cli_cmd_flag_none,
2725 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002727 cli_cmd_flag_none,
2728 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002737 cli_cmd_flag_none,
2738 "<addr> = roam to the specified BSS" },
2739#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2741 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2746 cli_cmd_flag_none,
2747 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2748 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2751 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002752 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2754 "[ht40] = add a new P2P group (local end as GO)" },
2755 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2756 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002759 cli_cmd_flag_none,
2760 "= get the passphrase for a group (GO only)" },
2761 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763 "<addr> <TLVs> = schedule service discovery request" },
2764 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 cli_cmd_flag_none,
2769 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 cli_cmd_flag_none,
2772 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002773 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 cli_cmd_flag_none,
2775 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002776 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 cli_cmd_flag_none,
2778 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 cli_cmd_flag_none,
2781 "<bonjour|upnp> <query|version> <response|service> = add a local "
2782 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002784 cli_cmd_flag_none,
2785 "<bonjour|upnp> <query|version> [|service] = remove a local "
2786 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002788 cli_cmd_flag_none,
2789 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002790 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 cli_cmd_flag_none,
2792 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002793 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002794 "[discovered] = list known (optionally, only fully discovered) P2P "
2795 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002796 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2797 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002798 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002799 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2800 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002806 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2807 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2810 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 "[<duration> <interval>] [<duration> <interval>] = request GO "
2812 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002813 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2814 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002815 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002816 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2817 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2818 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002819#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002820#ifdef CONFIG_WIFI_DISPLAY
2821 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2822 cli_cmd_flag_none,
2823 "<subelem> [contents] = set Wi-Fi Display subelement" },
2824 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2825 cli_cmd_flag_none,
2826 "<subelem> = get Wi-Fi Display subelement" },
2827#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002828#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002829 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002830 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2832 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002833 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002835 cli_cmd_flag_none,
2836 "[auto] = perform Interworking network selection" },
2837 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002838 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002839 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2841 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002842 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2844 cli_cmd_flag_none,
2845 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2846 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2847 wpa_cli_complete_bss, cli_cmd_flag_none,
2848 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002849#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002850#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002851 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2852 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002853 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2854 },
2855 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002857 "<addr> <home realm> = get HS20 nai home realm list" },
2858#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002859 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2860 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002862 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 cli_cmd_flag_none,
2864 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002865 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 cli_cmd_flag_none,
2867 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002868 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002869 cli_cmd_flag_none,
2870 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002871 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002872 cli_cmd_flag_none,
2873 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002874 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002875 cli_cmd_flag_none,
2876 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002877 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2878 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002879 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002880#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002881 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002882 "[params] = Set or unset (if none) autoscan parameters" },
2883#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002884#ifdef CONFIG_WNM
2885 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2886 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002887 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2888 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002889#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002890 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2891 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002892 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2893 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002894#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002895 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002896 cli_cmd_flag_none,
2897 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002898#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002899 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002900};
2901
2902
2903/*
2904 * Prints command usage, lines are padded with the specified string.
2905 */
2906static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2907{
2908 char c;
2909 size_t n;
2910
2911 printf("%s%s ", pad, cmd->cmd);
2912 for (n = 0; (c = cmd->usage[n]); n++) {
2913 printf("%c", c);
2914 if (c == '\n')
2915 printf("%s", pad);
2916 }
2917 printf("\n");
2918}
2919
2920
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002921static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002922{
2923 int n;
2924 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002925 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2926 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2927 print_cmd_help(&wpa_cli_commands[n], " ");
2928 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002929}
2930
2931
2932static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2933{
2934 const char *c, *delim;
2935 int n;
2936 size_t len;
2937
2938 delim = os_strchr(cmd, ' ');
2939 if (delim)
2940 len = delim - cmd;
2941 else
2942 len = os_strlen(cmd);
2943
2944 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2945 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2946 return (wpa_cli_commands[n].flags &
2947 cli_cmd_flag_sensitive);
2948 }
2949 return 0;
2950}
2951
2952
2953static char ** wpa_list_cmd_list(void)
2954{
2955 char **res;
2956 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002957 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002959 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002960 count += dl_list_len(&p2p_groups);
2961 count += dl_list_len(&ifnames);
2962 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963 if (res == NULL)
2964 return NULL;
2965
2966 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2967 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2968 if (res[i] == NULL)
2969 break;
2970 }
2971
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002972 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2973 size_t len = 8 + os_strlen(e->txt);
2974 res[i] = os_malloc(len);
2975 if (res[i] == NULL)
2976 break;
2977 os_snprintf(res[i], len, "ifname=%s", e->txt);
2978 i++;
2979 }
2980
2981 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2982 res[i] = os_strdup(e->txt);
2983 if (res[i] == NULL)
2984 break;
2985 i++;
2986 }
2987
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002988 return res;
2989}
2990
2991
2992static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2993 int pos)
2994{
2995 int i;
2996
2997 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2998 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002999 if (wpa_cli_commands[i].completion)
3000 return wpa_cli_commands[i].completion(str,
3001 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003002 edit_clear_line();
3003 printf("\r%s\n", wpa_cli_commands[i].usage);
3004 edit_redraw();
3005 break;
3006 }
3007 }
3008
3009 return NULL;
3010}
3011
3012
3013static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3014{
3015 char **res;
3016 const char *end;
3017 char *cmd;
3018
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003019 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3020 end = os_strchr(str, ' ');
3021 if (end && pos > end - str) {
3022 pos -= end - str + 1;
3023 str = end + 1;
3024 }
3025 }
3026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027 end = os_strchr(str, ' ');
3028 if (end == NULL || str + pos < end)
3029 return wpa_list_cmd_list();
3030
3031 cmd = os_malloc(pos + 1);
3032 if (cmd == NULL)
3033 return NULL;
3034 os_memcpy(cmd, str, pos);
3035 cmd[end - str] = '\0';
3036 res = wpa_cli_cmd_completion(cmd, str, pos);
3037 os_free(cmd);
3038 return res;
3039}
3040
3041
3042static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3043{
3044 struct wpa_cli_cmd *cmd, *match = NULL;
3045 int count;
3046 int ret = 0;
3047
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003048 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3049 ifname_prefix = argv[0] + 7;
3050 argv = &argv[1];
3051 argc--;
3052 } else
3053 ifname_prefix = NULL;
3054
3055 if (argc == 0)
3056 return -1;
3057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 count = 0;
3059 cmd = wpa_cli_commands;
3060 while (cmd->cmd) {
3061 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3062 {
3063 match = cmd;
3064 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3065 /* we have an exact match */
3066 count = 1;
3067 break;
3068 }
3069 count++;
3070 }
3071 cmd++;
3072 }
3073
3074 if (count > 1) {
3075 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3076 cmd = wpa_cli_commands;
3077 while (cmd->cmd) {
3078 if (os_strncasecmp(cmd->cmd, argv[0],
3079 os_strlen(argv[0])) == 0) {
3080 printf(" %s", cmd->cmd);
3081 }
3082 cmd++;
3083 }
3084 printf("\n");
3085 ret = 1;
3086 } else if (count == 0) {
3087 printf("Unknown command '%s'\n", argv[0]);
3088 ret = 1;
3089 } else {
3090 ret = match->handler(ctrl, argc - 1, &argv[1]);
3091 }
3092
3093 return ret;
3094}
3095
3096
3097static int str_match(const char *a, const char *b)
3098{
3099 return os_strncmp(a, b, os_strlen(b)) == 0;
3100}
3101
3102
3103static int wpa_cli_exec(const char *program, const char *arg1,
3104 const char *arg2)
3105{
3106 char *cmd;
3107 size_t len;
3108 int res;
3109 int ret = 0;
3110
3111 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3112 cmd = os_malloc(len);
3113 if (cmd == NULL)
3114 return -1;
3115 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3116 if (res < 0 || (size_t) res >= len) {
3117 os_free(cmd);
3118 return -1;
3119 }
3120 cmd[len - 1] = '\0';
3121#ifndef _WIN32_WCE
3122 if (system(cmd) < 0)
3123 ret = -1;
3124#endif /* _WIN32_WCE */
3125 os_free(cmd);
3126
3127 return ret;
3128}
3129
3130
3131static void wpa_cli_action_process(const char *msg)
3132{
3133 const char *pos;
3134 char *copy = NULL, *id, *pos2;
3135
3136 pos = msg;
3137 if (*pos == '<') {
3138 /* skip priority */
3139 pos = os_strchr(pos, '>');
3140 if (pos)
3141 pos++;
3142 else
3143 pos = msg;
3144 }
3145
3146 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3147 int new_id = -1;
3148 os_unsetenv("WPA_ID");
3149 os_unsetenv("WPA_ID_STR");
3150 os_unsetenv("WPA_CTRL_DIR");
3151
3152 pos = os_strstr(pos, "[id=");
3153 if (pos)
3154 copy = os_strdup(pos + 4);
3155
3156 if (copy) {
3157 pos2 = id = copy;
3158 while (*pos2 && *pos2 != ' ')
3159 pos2++;
3160 *pos2++ = '\0';
3161 new_id = atoi(id);
3162 os_setenv("WPA_ID", id, 1);
3163 while (*pos2 && *pos2 != '=')
3164 pos2++;
3165 if (*pos2 == '=')
3166 pos2++;
3167 id = pos2;
3168 while (*pos2 && *pos2 != ']')
3169 pos2++;
3170 *pos2 = '\0';
3171 os_setenv("WPA_ID_STR", id, 1);
3172 os_free(copy);
3173 }
3174
3175 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3176
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003177 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003178 wpa_cli_connected = 1;
3179 wpa_cli_last_id = new_id;
3180 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3181 }
3182 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3183 if (wpa_cli_connected) {
3184 wpa_cli_connected = 0;
3185 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3186 }
3187 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3188 wpa_cli_exec(action_file, ctrl_ifname, pos);
3189 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3190 wpa_cli_exec(action_file, ctrl_ifname, pos);
3191 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3192 wpa_cli_exec(action_file, ctrl_ifname, pos);
3193 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3194 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003195 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3196 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3198 wpa_cli_exec(action_file, ctrl_ifname, pos);
3199 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3200 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003201 } else if (str_match(pos, AP_STA_CONNECTED)) {
3202 wpa_cli_exec(action_file, ctrl_ifname, pos);
3203 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3204 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003205 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3206 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003207 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3208 printf("wpa_supplicant is terminating - stop monitoring\n");
3209 wpa_cli_quit = 1;
3210 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211}
3212
3213
3214#ifndef CONFIG_ANSI_C_EXTRA
3215static void wpa_cli_action_cb(char *msg, size_t len)
3216{
3217 wpa_cli_action_process(msg);
3218}
3219#endif /* CONFIG_ANSI_C_EXTRA */
3220
3221
3222static void wpa_cli_reconnect(void)
3223{
3224 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003225 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3226 return;
3227
3228 if (interactive) {
3229 edit_clear_line();
3230 printf("\rConnection to wpa_supplicant re-established\n");
3231 edit_redraw();
3232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003233}
3234
3235
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003236static void cli_event(const char *str)
3237{
3238 const char *start, *s;
3239
3240 start = os_strchr(str, '>');
3241 if (start == NULL)
3242 return;
3243
3244 start++;
3245
3246 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3247 s = os_strchr(start, ' ');
3248 if (s == NULL)
3249 return;
3250 s = os_strchr(s + 1, ' ');
3251 if (s == NULL)
3252 return;
3253 cli_txt_list_add(&bsses, s + 1);
3254 return;
3255 }
3256
3257 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3258 s = os_strchr(start, ' ');
3259 if (s == NULL)
3260 return;
3261 s = os_strchr(s + 1, ' ');
3262 if (s == NULL)
3263 return;
3264 cli_txt_list_del_addr(&bsses, s + 1);
3265 return;
3266 }
3267
3268#ifdef CONFIG_P2P
3269 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3270 s = os_strstr(start, " p2p_dev_addr=");
3271 if (s == NULL)
3272 return;
3273 cli_txt_list_add_addr(&p2p_peers, s + 14);
3274 return;
3275 }
3276
3277 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3278 s = os_strstr(start, " p2p_dev_addr=");
3279 if (s == NULL)
3280 return;
3281 cli_txt_list_del_addr(&p2p_peers, s + 14);
3282 return;
3283 }
3284
3285 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3286 s = os_strchr(start, ' ');
3287 if (s == NULL)
3288 return;
3289 cli_txt_list_add_word(&p2p_groups, s + 1);
3290 return;
3291 }
3292
3293 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3294 s = os_strchr(start, ' ');
3295 if (s == NULL)
3296 return;
3297 cli_txt_list_del_word(&p2p_groups, s + 1);
3298 return;
3299 }
3300#endif /* CONFIG_P2P */
3301}
3302
3303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003304static int check_terminating(const char *msg)
3305{
3306 const char *pos = msg;
3307
3308 if (*pos == '<') {
3309 /* skip priority */
3310 pos = os_strchr(pos, '>');
3311 if (pos)
3312 pos++;
3313 else
3314 pos = msg;
3315 }
3316
3317 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3318 edit_clear_line();
3319 printf("\rConnection to wpa_supplicant lost - trying to "
3320 "reconnect\n");
3321 edit_redraw();
3322 wpa_cli_attached = 0;
3323 wpa_cli_close_connection();
3324 return 1;
3325 }
3326
3327 return 0;
3328}
3329
3330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003331static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3332{
3333 if (ctrl_conn == NULL) {
3334 wpa_cli_reconnect();
3335 return;
3336 }
3337 while (wpa_ctrl_pending(ctrl) > 0) {
3338 char buf[256];
3339 size_t len = sizeof(buf) - 1;
3340 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3341 buf[len] = '\0';
3342 if (action_monitor)
3343 wpa_cli_action_process(buf);
3344 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003345 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003346 if (wpa_cli_show_event(buf)) {
3347 edit_clear_line();
3348 printf("\r%s\n", buf);
3349 edit_redraw();
3350 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003351
3352 if (interactive && check_terminating(buf) > 0)
3353 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 }
3355 } else {
3356 printf("Could not read pending message.\n");
3357 break;
3358 }
3359 }
3360
3361 if (wpa_ctrl_pending(ctrl) < 0) {
3362 printf("Connection to wpa_supplicant lost - trying to "
3363 "reconnect\n");
3364 wpa_cli_reconnect();
3365 }
3366}
3367
3368#define max_args 10
3369
3370static int tokenize_cmd(char *cmd, char *argv[])
3371{
3372 char *pos;
3373 int argc = 0;
3374
3375 pos = cmd;
3376 for (;;) {
3377 while (*pos == ' ')
3378 pos++;
3379 if (*pos == '\0')
3380 break;
3381 argv[argc] = pos;
3382 argc++;
3383 if (argc == max_args)
3384 break;
3385 if (*pos == '"') {
3386 char *pos2 = os_strrchr(pos, '"');
3387 if (pos2)
3388 pos = pos2 + 1;
3389 }
3390 while (*pos != '\0' && *pos != ' ')
3391 pos++;
3392 if (*pos == ' ')
3393 *pos++ = '\0';
3394 }
3395
3396 return argc;
3397}
3398
3399
3400static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3401{
3402 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3403 printf("Connection to wpa_supplicant lost - trying to "
3404 "reconnect\n");
3405 wpa_cli_close_connection();
3406 }
3407 if (!ctrl_conn)
3408 wpa_cli_reconnect();
3409 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3410}
3411
3412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003413static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3414{
3415 wpa_cli_recv_pending(mon_conn, 0);
3416}
3417
3418
3419static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3420{
3421 char *argv[max_args];
3422 int argc;
3423 argc = tokenize_cmd(cmd, argv);
3424 if (argc)
3425 wpa_request(ctrl_conn, argc, argv);
3426}
3427
3428
3429static void wpa_cli_edit_eof_cb(void *ctx)
3430{
3431 eloop_terminate();
3432}
3433
3434
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003435static int warning_displayed = 0;
3436static char *hfile = NULL;
3437static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003438
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003439static void start_edit(void)
3440{
3441 char *home;
3442 char *ps = NULL;
3443
3444#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3445 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3446#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003447
3448 home = getenv("HOME");
3449 if (home) {
3450 const char *fname = ".wpa_cli_history";
3451 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3452 hfile = os_malloc(hfile_len);
3453 if (hfile)
3454 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3455 }
3456
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003457 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3458 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3459 eloop_terminate();
3460 return;
3461 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003463 edit_started = 1;
3464 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3465}
3466
3467
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003468static void update_bssid_list(struct wpa_ctrl *ctrl)
3469{
3470 char buf[4096];
3471 size_t len = sizeof(buf);
3472 int ret;
3473 char *cmd = "BSS RANGE=ALL MASK=0x2";
3474 char *pos, *end;
3475
3476 if (ctrl == NULL)
3477 return;
3478 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3479 if (ret < 0)
3480 return;
3481 buf[len] = '\0';
3482
3483 pos = buf;
3484 while (pos) {
3485 pos = os_strstr(pos, "bssid=");
3486 if (pos == NULL)
3487 break;
3488 pos += 6;
3489 end = os_strchr(pos, '\n');
3490 if (end == NULL)
3491 break;
3492 *end = '\0';
3493 cli_txt_list_add(&bsses, pos);
3494 pos = end + 1;
3495 }
3496}
3497
3498
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003499static void update_ifnames(struct wpa_ctrl *ctrl)
3500{
3501 char buf[4096];
3502 size_t len = sizeof(buf);
3503 int ret;
3504 char *cmd = "INTERFACES";
3505 char *pos, *end;
3506 char txt[200];
3507
3508 cli_txt_list_flush(&ifnames);
3509
3510 if (ctrl == NULL)
3511 return;
3512 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3513 if (ret < 0)
3514 return;
3515 buf[len] = '\0';
3516
3517 pos = buf;
3518 while (pos) {
3519 end = os_strchr(pos, '\n');
3520 if (end == NULL)
3521 break;
3522 *end = '\0';
3523 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3524 if (ret > 0 && ret < (int) sizeof(txt))
3525 cli_txt_list_add(&ifnames, txt);
3526 pos = end + 1;
3527 }
3528}
3529
3530
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003531static void try_connection(void *eloop_ctx, void *timeout_ctx)
3532{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003533 if (ctrl_conn)
3534 goto done;
3535
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003536 if (ctrl_ifname == NULL)
3537 ctrl_ifname = wpa_cli_get_default_ifname();
3538
3539 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3540 if (!warning_displayed) {
3541 printf("Could not connect to wpa_supplicant: "
3542 "%s - re-trying\n", ctrl_ifname);
3543 warning_displayed = 1;
3544 }
3545 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3546 return;
3547 }
3548
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003549 update_bssid_list(ctrl_conn);
3550
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003551 if (warning_displayed)
3552 printf("Connection established.\n");
3553
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003554done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003555 start_edit();
3556}
3557
3558
3559static void wpa_cli_interactive(void)
3560{
3561 printf("\nInteractive mode\n\n");
3562
3563 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003565 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003567 cli_txt_list_flush(&p2p_peers);
3568 cli_txt_list_flush(&p2p_groups);
3569 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003570 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003571 if (edit_started)
3572 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003573 os_free(hfile);
3574 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3575 wpa_cli_close_connection();
3576}
3577
3578
3579static void wpa_cli_action(struct wpa_ctrl *ctrl)
3580{
3581#ifdef CONFIG_ANSI_C_EXTRA
3582 /* TODO: ANSI C version(?) */
3583 printf("Action processing not supported in ANSI C build.\n");
3584#else /* CONFIG_ANSI_C_EXTRA */
3585 fd_set rfds;
3586 int fd, res;
3587 struct timeval tv;
3588 char buf[256]; /* note: large enough to fit in unsolicited messages */
3589 size_t len;
3590
3591 fd = wpa_ctrl_get_fd(ctrl);
3592
3593 while (!wpa_cli_quit) {
3594 FD_ZERO(&rfds);
3595 FD_SET(fd, &rfds);
3596 tv.tv_sec = ping_interval;
3597 tv.tv_usec = 0;
3598 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3599 if (res < 0 && errno != EINTR) {
3600 perror("select");
3601 break;
3602 }
3603
3604 if (FD_ISSET(fd, &rfds))
3605 wpa_cli_recv_pending(ctrl, 1);
3606 else {
3607 /* verify that connection is still working */
3608 len = sizeof(buf) - 1;
3609 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3610 wpa_cli_action_cb) < 0 ||
3611 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3612 printf("wpa_supplicant did not reply to PING "
3613 "command - exiting\n");
3614 break;
3615 }
3616 }
3617 }
3618#endif /* CONFIG_ANSI_C_EXTRA */
3619}
3620
3621
3622static void wpa_cli_cleanup(void)
3623{
3624 wpa_cli_close_connection();
3625 if (pid_file)
3626 os_daemonize_terminate(pid_file);
3627
3628 os_program_deinit();
3629}
3630
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003631
3632static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003634 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635}
3636
3637
3638static char * wpa_cli_get_default_ifname(void)
3639{
3640 char *ifname = NULL;
3641
3642#ifdef CONFIG_CTRL_IFACE_UNIX
3643 struct dirent *dent;
3644 DIR *dir = opendir(ctrl_iface_dir);
3645 if (!dir) {
3646#ifdef ANDROID
3647 char ifprop[PROPERTY_VALUE_MAX];
3648 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3649 ifname = os_strdup(ifprop);
3650 printf("Using interface '%s'\n", ifname);
3651 return ifname;
3652 }
3653#endif /* ANDROID */
3654 return NULL;
3655 }
3656 while ((dent = readdir(dir))) {
3657#ifdef _DIRENT_HAVE_D_TYPE
3658 /*
3659 * Skip the file if it is not a socket. Also accept
3660 * DT_UNKNOWN (0) in case the C library or underlying
3661 * file system does not support d_type.
3662 */
3663 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3664 continue;
3665#endif /* _DIRENT_HAVE_D_TYPE */
3666 if (os_strcmp(dent->d_name, ".") == 0 ||
3667 os_strcmp(dent->d_name, "..") == 0)
3668 continue;
3669 printf("Selected interface '%s'\n", dent->d_name);
3670 ifname = os_strdup(dent->d_name);
3671 break;
3672 }
3673 closedir(dir);
3674#endif /* CONFIG_CTRL_IFACE_UNIX */
3675
3676#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003677 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003678 size_t len;
3679 struct wpa_ctrl *ctrl;
3680 int ret;
3681
3682 ctrl = wpa_ctrl_open(NULL);
3683 if (ctrl == NULL)
3684 return NULL;
3685
3686 len = sizeof(buf) - 1;
3687 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3688 if (ret >= 0) {
3689 buf[len] = '\0';
3690 pos = os_strchr(buf, '\n');
3691 if (pos)
3692 *pos = '\0';
3693 ifname = os_strdup(buf);
3694 }
3695 wpa_ctrl_close(ctrl);
3696#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3697
3698 return ifname;
3699}
3700
3701
3702int main(int argc, char *argv[])
3703{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 int c;
3705 int daemonize = 0;
3706 int ret = 0;
3707 const char *global = NULL;
3708
3709 if (os_program_init())
3710 return -1;
3711
3712 for (;;) {
3713 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3714 if (c < 0)
3715 break;
3716 switch (c) {
3717 case 'a':
3718 action_file = optarg;
3719 break;
3720 case 'B':
3721 daemonize = 1;
3722 break;
3723 case 'g':
3724 global = optarg;
3725 break;
3726 case 'G':
3727 ping_interval = atoi(optarg);
3728 break;
3729 case 'h':
3730 usage();
3731 return 0;
3732 case 'v':
3733 printf("%s\n", wpa_cli_version);
3734 return 0;
3735 case 'i':
3736 os_free(ctrl_ifname);
3737 ctrl_ifname = os_strdup(optarg);
3738 break;
3739 case 'p':
3740 ctrl_iface_dir = optarg;
3741 break;
3742 case 'P':
3743 pid_file = optarg;
3744 break;
3745 default:
3746 usage();
3747 return -1;
3748 }
3749 }
3750
3751 interactive = (argc == optind) && (action_file == NULL);
3752
3753 if (interactive)
3754 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3755
3756 if (eloop_init())
3757 return -1;
3758
3759 if (global) {
3760#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3761 ctrl_conn = wpa_ctrl_open(NULL);
3762#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3763 ctrl_conn = wpa_ctrl_open(global);
3764#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3765 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003766 fprintf(stderr, "Failed to connect to wpa_supplicant "
3767 "global interface: %s error: %s\n",
3768 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003769 return -1;
3770 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003771
3772 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003773 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003774 mon_conn = wpa_ctrl_open(global);
3775 if (mon_conn) {
3776 if (wpa_ctrl_attach(mon_conn) == 0) {
3777 wpa_cli_attached = 1;
3778 eloop_register_read_sock(
3779 wpa_ctrl_get_fd(mon_conn),
3780 wpa_cli_mon_receive,
3781 NULL, NULL);
3782 } else {
3783 printf("Failed to open monitor "
3784 "connection through global "
3785 "control interface\n");
3786 }
3787 }
3788 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003789 }
3790
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003791 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003792
3793 if (ctrl_ifname == NULL)
3794 ctrl_ifname = wpa_cli_get_default_ifname();
3795
3796 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003797 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798 } else {
3799 if (!global &&
3800 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003801 fprintf(stderr, "Failed to connect to non-global "
3802 "ctrl_ifname: %s error: %s\n",
3803 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 return -1;
3805 }
3806
3807 if (action_file) {
3808 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3809 wpa_cli_attached = 1;
3810 } else {
3811 printf("Warning: Failed to attach to "
3812 "wpa_supplicant.\n");
3813 return -1;
3814 }
3815 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003816
3817 if (daemonize && os_daemonize(pid_file))
3818 return -1;
3819
3820 if (action_file)
3821 wpa_cli_action(ctrl_conn);
3822 else
3823 ret = wpa_request(ctrl_conn, argc - optind,
3824 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 }
3826
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827 os_free(ctrl_ifname);
3828 eloop_destroy();
3829 wpa_cli_cleanup();
3830
3831 return ret;
3832}
3833
3834#else /* CONFIG_CTRL_IFACE */
3835int main(int argc, char *argv[])
3836{
3837 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3838 return -1;
3839}
3840#endif /* CONFIG_CTRL_IFACE */