blob: d66e8644368fa16337f398698bb64139264d22e5 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003 * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080031"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700537 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 return 0;
539}
540
541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
567 if (interactive)
568 eloop_terminate();
569 return 0;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700618 "p2p_no_go_freq",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700619 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700620 "p2p_go_vht",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700621 "p2p_ignore_shared_freq", "country", "bss_max_count",
622 "bss_expiration_age", "bss_expiration_scan_count",
623 "filter_ssids", "filter_rssi", "max_num_sta",
624 "disassoc_low_ack", "hs20", "interworking", "hessid",
625 "access_network_type", "pbc_in_m1", "autoscan",
626 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
627 "wps_nfc_dev_pw", "ext_password_backend",
628 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
629 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt97672262014-02-03 13:02:54 -0800630 "ignore_old_scan_res", "freq_list", "external_sim",
631 "tdls_external_control"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700632 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700633 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700634
635 if (arg == 1) {
636 char **res = os_calloc(num_fields + 1, sizeof(char *));
637 if (res == NULL)
638 return NULL;
639 for (i = 0; i < num_fields; i++) {
640 res[i] = os_strdup(fields[i]);
641 if (res[i] == NULL)
642 return res;
643 }
644 return res;
645 }
646
647 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
648 return cli_txt_list_array(&bsses);
649
650 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651}
652
653
654static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700656 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657}
658
659
660static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
661{
662 return wpa_ctrl_command(ctrl, "LOGOFF");
663}
664
665
666static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
668 return wpa_ctrl_command(ctrl, "LOGON");
669}
670
671
672static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "REASSOCIATE");
676}
677
678
679static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
680 char *argv[])
681{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700682 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683}
684
685
686static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700688 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689}
690
691
692static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
693 char *argv[])
694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696}
697
698
699static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
700 char *argv[])
701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700702 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700703}
704
705
706static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
707 char *argv[])
708{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700709 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700710}
711
712
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700713static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
714{
715 char cmd[256];
716 int res;
717
718 if (argc < 1)
719 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
720 else
721 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
722 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
723 printf("Too long BSS_FLUSH command.\n");
724 return -1;
725 }
726 return wpa_ctrl_command(ctrl, cmd);
727}
728
729
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
731 char *argv[])
732{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734}
735
736
737static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
738{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700739 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740}
741
742
743static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700745 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746}
747
748
749static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751 if (argc == 0) {
752 printf("Invalid WPS_PIN command: need one or two arguments:\n"
753 "- BSSID: use 'any' to select any\n"
754 "- PIN: optional, used only with devices that have no "
755 "display\n");
756 return -1;
757 }
758
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700759 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760}
761
762
763static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
764 char *argv[])
765{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700766 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767}
768
769
770static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
771 char *argv[])
772{
773 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
774}
775
776
Dmitry Shmidt04949592012-07-19 12:16:46 -0700777#ifdef CONFIG_WPS_NFC
778
779static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
780{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700781 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700782}
783
784
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800785static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
786 char *argv[])
787{
788 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
789}
790
791
Dmitry Shmidt04949592012-07-19 12:16:46 -0700792static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
793 char *argv[])
794{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700795 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700796}
797
798
799static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
800 char *argv[])
801{
802 int ret;
803 char *buf;
804 size_t buflen;
805
806 if (argc != 1) {
807 printf("Invalid 'wps_nfc_tag_read' command - one argument "
808 "is required.\n");
809 return -1;
810 }
811
812 buflen = 18 + os_strlen(argv[0]);
813 buf = os_malloc(buflen);
814 if (buf == NULL)
815 return -1;
816 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
817
818 ret = wpa_ctrl_command(ctrl, buf);
819 os_free(buf);
820
821 return ret;
822}
823
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800824
825static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
826 char *argv[])
827{
828 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
829}
830
831
832static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
833 char *argv[])
834{
835 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
836}
837
838
839static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
840 char *argv[])
841{
842 int ret;
843 char *buf;
844 size_t buflen;
845
846 if (argc != 1) {
847 printf("Invalid 'nfc_rx_handover_req' command - one argument "
848 "is required.\n");
849 return -1;
850 }
851
852 buflen = 21 + os_strlen(argv[0]);
853 buf = os_malloc(buflen);
854 if (buf == NULL)
855 return -1;
856 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
857
858 ret = wpa_ctrl_command(ctrl, buf);
859 os_free(buf);
860
861 return ret;
862}
863
864
865static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
866 char *argv[])
867{
868 int ret;
869 char *buf;
870 size_t buflen;
871
872 if (argc != 1) {
873 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
874 "is required.\n");
875 return -1;
876 }
877
878 buflen = 21 + os_strlen(argv[0]);
879 buf = os_malloc(buflen);
880 if (buf == NULL)
881 return -1;
882 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
883
884 ret = wpa_ctrl_command(ctrl, buf);
885 os_free(buf);
886
887 return ret;
888}
889
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800890
891static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
892 char *argv[])
893{
894 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
895}
896
Dmitry Shmidt04949592012-07-19 12:16:46 -0700897#endif /* CONFIG_WPS_NFC */
898
899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
901{
902 char cmd[256];
903 int res;
904
905 if (argc == 2)
906 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
907 argv[0], argv[1]);
908 else if (argc == 5 || argc == 6) {
909 char ssid_hex[2 * 32 + 1];
910 char key_hex[2 * 64 + 1];
911 int i;
912
913 ssid_hex[0] = '\0';
914 for (i = 0; i < 32; i++) {
915 if (argv[2][i] == '\0')
916 break;
917 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
918 }
919
920 key_hex[0] = '\0';
921 if (argc == 6) {
922 for (i = 0; i < 64; i++) {
923 if (argv[5][i] == '\0')
924 break;
925 os_snprintf(&key_hex[i * 2], 3, "%02x",
926 argv[5][i]);
927 }
928 }
929
930 res = os_snprintf(cmd, sizeof(cmd),
931 "WPS_REG %s %s %s %s %s %s",
932 argv[0], argv[1], ssid_hex, argv[3], argv[4],
933 key_hex);
934 } else {
935 printf("Invalid WPS_REG command: need two arguments:\n"
936 "- BSSID of the target AP\n"
937 "- AP PIN\n");
938 printf("Alternatively, six arguments can be used to "
939 "reconfigure the AP:\n"
940 "- BSSID of the target AP\n"
941 "- AP PIN\n"
942 "- new SSID\n"
943 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
944 "- new encr (NONE, WEP, TKIP, CCMP)\n"
945 "- new key\n");
946 return -1;
947 }
948
949 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
950 printf("Too long WPS_REG command.\n");
951 return -1;
952 }
953 return wpa_ctrl_command(ctrl, cmd);
954}
955
956
957static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
958 char *argv[])
959{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700960 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961}
962
963
964static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
965 char *argv[])
966{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700967 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968}
969
970
971static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
972 char *argv[])
973{
974 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
975
976}
977
978
979static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
980 char *argv[])
981{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982 if (argc < 2) {
983 printf("Invalid WPS_ER_PIN command: need at least two "
984 "arguments:\n"
985 "- UUID: use 'any' to select any\n"
986 "- PIN: Enrollee PIN\n"
987 "optional: - Enrollee MAC address\n");
988 return -1;
989 }
990
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700991 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700992}
993
994
995static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
996 char *argv[])
997{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700998 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999}
1000
1001
1002static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1003 char *argv[])
1004{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005 if (argc != 2) {
1006 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1007 "- UUID: specify which AP to use\n"
1008 "- PIN: AP PIN\n");
1009 return -1;
1010 }
1011
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001012 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013}
1014
1015
1016static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1017 char *argv[])
1018{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 if (argc != 2) {
1020 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1021 "arguments:\n"
1022 "- UUID: specify which AP to use\n"
1023 "- Network configuration id\n");
1024 return -1;
1025 }
1026
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001027 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001028}
1029
1030
1031static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1032 char *argv[])
1033{
1034 char cmd[256];
1035 int res;
1036
1037 if (argc == 5 || argc == 6) {
1038 char ssid_hex[2 * 32 + 1];
1039 char key_hex[2 * 64 + 1];
1040 int i;
1041
1042 ssid_hex[0] = '\0';
1043 for (i = 0; i < 32; i++) {
1044 if (argv[2][i] == '\0')
1045 break;
1046 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1047 }
1048
1049 key_hex[0] = '\0';
1050 if (argc == 6) {
1051 for (i = 0; i < 64; i++) {
1052 if (argv[5][i] == '\0')
1053 break;
1054 os_snprintf(&key_hex[i * 2], 3, "%02x",
1055 argv[5][i]);
1056 }
1057 }
1058
1059 res = os_snprintf(cmd, sizeof(cmd),
1060 "WPS_ER_CONFIG %s %s %s %s %s %s",
1061 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1062 key_hex);
1063 } else {
1064 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1065 "- AP UUID\n"
1066 "- AP PIN\n"
1067 "- new SSID\n"
1068 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1069 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1070 "- new key\n");
1071 return -1;
1072 }
1073
1074 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1075 printf("Too long WPS_ER_CONFIG command.\n");
1076 return -1;
1077 }
1078 return wpa_ctrl_command(ctrl, cmd);
1079}
1080
1081
Dmitry Shmidt04949592012-07-19 12:16:46 -07001082#ifdef CONFIG_WPS_NFC
1083static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1084 char *argv[])
1085{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001086 if (argc != 2) {
1087 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1088 "arguments:\n"
1089 "- WPS/NDEF: token format\n"
1090 "- UUID: specify which AP to use\n");
1091 return -1;
1092 }
1093
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001094 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001095}
1096#endif /* CONFIG_WPS_NFC */
1097
1098
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1100{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001101 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102}
1103
1104
1105static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1106{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001107 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108}
1109
1110
1111static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1112{
1113 char cmd[256], *pos, *end;
1114 int i, ret;
1115
1116 if (argc < 2) {
1117 printf("Invalid IDENTITY command: needs two arguments "
1118 "(network id and identity)\n");
1119 return -1;
1120 }
1121
1122 end = cmd + sizeof(cmd);
1123 pos = cmd;
1124 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1125 argv[0], argv[1]);
1126 if (ret < 0 || ret >= end - pos) {
1127 printf("Too long IDENTITY command.\n");
1128 return -1;
1129 }
1130 pos += ret;
1131 for (i = 2; i < argc; i++) {
1132 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1133 if (ret < 0 || ret >= end - pos) {
1134 printf("Too long IDENTITY command.\n");
1135 return -1;
1136 }
1137 pos += ret;
1138 }
1139
1140 return wpa_ctrl_command(ctrl, cmd);
1141}
1142
1143
1144static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1145{
1146 char cmd[256], *pos, *end;
1147 int i, ret;
1148
1149 if (argc < 2) {
1150 printf("Invalid PASSWORD command: needs two arguments "
1151 "(network id and password)\n");
1152 return -1;
1153 }
1154
1155 end = cmd + sizeof(cmd);
1156 pos = cmd;
1157 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1158 argv[0], argv[1]);
1159 if (ret < 0 || ret >= end - pos) {
1160 printf("Too long PASSWORD command.\n");
1161 return -1;
1162 }
1163 pos += ret;
1164 for (i = 2; i < argc; i++) {
1165 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1166 if (ret < 0 || ret >= end - pos) {
1167 printf("Too long PASSWORD command.\n");
1168 return -1;
1169 }
1170 pos += ret;
1171 }
1172
1173 return wpa_ctrl_command(ctrl, cmd);
1174}
1175
1176
1177static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1178 char *argv[])
1179{
1180 char cmd[256], *pos, *end;
1181 int i, ret;
1182
1183 if (argc < 2) {
1184 printf("Invalid NEW_PASSWORD command: needs two arguments "
1185 "(network id and password)\n");
1186 return -1;
1187 }
1188
1189 end = cmd + sizeof(cmd);
1190 pos = cmd;
1191 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1192 argv[0], argv[1]);
1193 if (ret < 0 || ret >= end - pos) {
1194 printf("Too long NEW_PASSWORD command.\n");
1195 return -1;
1196 }
1197 pos += ret;
1198 for (i = 2; i < argc; i++) {
1199 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1200 if (ret < 0 || ret >= end - pos) {
1201 printf("Too long NEW_PASSWORD command.\n");
1202 return -1;
1203 }
1204 pos += ret;
1205 }
1206
1207 return wpa_ctrl_command(ctrl, cmd);
1208}
1209
1210
1211static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1212{
1213 char cmd[256], *pos, *end;
1214 int i, ret;
1215
1216 if (argc < 2) {
1217 printf("Invalid PIN command: needs two arguments "
1218 "(network id and pin)\n");
1219 return -1;
1220 }
1221
1222 end = cmd + sizeof(cmd);
1223 pos = cmd;
1224 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1225 argv[0], argv[1]);
1226 if (ret < 0 || ret >= end - pos) {
1227 printf("Too long PIN command.\n");
1228 return -1;
1229 }
1230 pos += ret;
1231 for (i = 2; i < argc; i++) {
1232 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1233 if (ret < 0 || ret >= end - pos) {
1234 printf("Too long PIN command.\n");
1235 return -1;
1236 }
1237 pos += ret;
1238 }
1239 return wpa_ctrl_command(ctrl, cmd);
1240}
1241
1242
1243static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1244{
1245 char cmd[256], *pos, *end;
1246 int i, ret;
1247
1248 if (argc < 2) {
1249 printf("Invalid OTP command: needs two arguments (network "
1250 "id and password)\n");
1251 return -1;
1252 }
1253
1254 end = cmd + sizeof(cmd);
1255 pos = cmd;
1256 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1257 argv[0], argv[1]);
1258 if (ret < 0 || ret >= end - pos) {
1259 printf("Too long OTP command.\n");
1260 return -1;
1261 }
1262 pos += ret;
1263 for (i = 2; i < argc; i++) {
1264 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1265 if (ret < 0 || ret >= end - pos) {
1266 printf("Too long OTP command.\n");
1267 return -1;
1268 }
1269 pos += ret;
1270 }
1271
1272 return wpa_ctrl_command(ctrl, cmd);
1273}
1274
1275
Dmitry Shmidt051af732013-10-22 13:52:46 -07001276static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1277{
1278 char cmd[256], *pos, *end;
1279 int i, ret;
1280
1281 if (argc < 2) {
1282 printf("Invalid SIM command: needs two arguments "
1283 "(network id and SIM operation response)\n");
1284 return -1;
1285 }
1286
1287 end = cmd + sizeof(cmd);
1288 pos = cmd;
1289 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1290 argv[0], argv[1]);
1291 if (ret < 0 || ret >= end - pos) {
1292 printf("Too long SIM command.\n");
1293 return -1;
1294 }
1295 pos += ret;
1296 for (i = 2; i < argc; i++) {
1297 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1298 if (ret < 0 || ret >= end - pos) {
1299 printf("Too long SIM command.\n");
1300 return -1;
1301 }
1302 pos += ret;
1303 }
1304 return wpa_ctrl_command(ctrl, cmd);
1305}
1306
1307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1309 char *argv[])
1310{
1311 char cmd[256], *pos, *end;
1312 int i, ret;
1313
1314 if (argc < 2) {
1315 printf("Invalid PASSPHRASE command: needs two arguments "
1316 "(network id and passphrase)\n");
1317 return -1;
1318 }
1319
1320 end = cmd + sizeof(cmd);
1321 pos = cmd;
1322 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1323 argv[0], argv[1]);
1324 if (ret < 0 || ret >= end - pos) {
1325 printf("Too long PASSPHRASE command.\n");
1326 return -1;
1327 }
1328 pos += ret;
1329 for (i = 2; i < argc; i++) {
1330 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1331 if (ret < 0 || ret >= end - pos) {
1332 printf("Too long PASSPHRASE command.\n");
1333 return -1;
1334 }
1335 pos += ret;
1336 }
1337
1338 return wpa_ctrl_command(ctrl, cmd);
1339}
1340
1341
1342static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1343{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344 if (argc < 2) {
1345 printf("Invalid BSSID command: needs two arguments (network "
1346 "id and BSSID)\n");
1347 return -1;
1348 }
1349
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001350 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001351}
1352
1353
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001354static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1355{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001356 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001357}
1358
1359
1360static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1361{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001362 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001363}
1364
1365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1367 char *argv[])
1368{
1369 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1370}
1371
1372
1373static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1374 char *argv[])
1375{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001376 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001377}
1378
1379
1380static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1381 char *argv[])
1382{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001383 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384}
1385
1386
1387static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1388 char *argv[])
1389{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001390 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001391}
1392
1393
1394static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1395 char *argv[])
1396{
1397 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1398}
1399
1400
1401static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1402 char *argv[])
1403{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001404 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405}
1406
1407
1408static void wpa_cli_show_network_variables(void)
1409{
1410 printf("set_network variables:\n"
1411 " ssid (network name, SSID)\n"
1412 " psk (WPA passphrase or pre-shared key)\n"
1413 " key_mgmt (key management protocol)\n"
1414 " identity (EAP identity)\n"
1415 " password (EAP password)\n"
1416 " ...\n"
1417 "\n"
1418 "Note: Values are entered in the same format as the "
1419 "configuration file is using,\n"
1420 "i.e., strings values need to be inside double quotation "
1421 "marks.\n"
1422 "For example: set_network 1 ssid \"network name\"\n"
1423 "\n"
1424 "Please see wpa_supplicant.conf documentation for full list "
1425 "of\navailable variables.\n");
1426}
1427
1428
1429static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1430 char *argv[])
1431{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001432 if (argc == 0) {
1433 wpa_cli_show_network_variables();
1434 return 0;
1435 }
1436
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001437 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001438 printf("Invalid SET_NETWORK command: needs three arguments\n"
1439 "(network id, variable name, and value)\n");
1440 return -1;
1441 }
1442
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001443 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001444}
1445
1446
1447static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1448 char *argv[])
1449{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001450 if (argc == 0) {
1451 wpa_cli_show_network_variables();
1452 return 0;
1453 }
1454
1455 if (argc != 2) {
1456 printf("Invalid GET_NETWORK command: needs two arguments\n"
1457 "(network id and variable name)\n");
1458 return -1;
1459 }
1460
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001461 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462}
1463
1464
Dmitry Shmidt04949592012-07-19 12:16:46 -07001465static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1466 char *argv[])
1467{
1468 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1469}
1470
1471
1472static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1473{
1474 return wpa_ctrl_command(ctrl, "ADD_CRED");
1475}
1476
1477
1478static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1479 char *argv[])
1480{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001481 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001482}
1483
1484
1485static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1486{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001487 if (argc != 3) {
1488 printf("Invalid SET_CRED command: needs three arguments\n"
1489 "(cred id, variable name, and value)\n");
1490 return -1;
1491 }
1492
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001493 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001494}
1495
1496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1498 char *argv[])
1499{
1500 return wpa_ctrl_command(ctrl, "DISCONNECT");
1501}
1502
1503
1504static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1505 char *argv[])
1506{
1507 return wpa_ctrl_command(ctrl, "RECONNECT");
1508}
1509
1510
1511static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1512 char *argv[])
1513{
1514 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1515}
1516
1517
1518static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1519{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001520 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521}
1522
1523
1524static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1525 char *argv[])
1526{
1527 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1528}
1529
1530
1531static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1532{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001533 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534}
1535
1536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001537static char ** wpa_cli_complete_bss(const char *str, int pos)
1538{
1539 int arg = get_cmd_arg_num(str, pos);
1540 char **res = NULL;
1541
1542 switch (arg) {
1543 case 1:
1544 res = cli_txt_list_array(&bsses);
1545 break;
1546 }
1547
1548 return res;
1549}
1550
1551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1553 char *argv[])
1554{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 if (argc < 1 || argc > 2) {
1556 printf("Invalid GET_CAPABILITY command: need either one or "
1557 "two arguments\n");
1558 return -1;
1559 }
1560
1561 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1562 printf("Invalid GET_CAPABILITY command: second argument, "
1563 "if any, must be 'strict'\n");
1564 return -1;
1565 }
1566
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001567 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001568}
1569
1570
1571static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1572{
1573 printf("Available interfaces:\n");
1574 return wpa_ctrl_command(ctrl, "INTERFACES");
1575}
1576
1577
1578static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1579{
1580 if (argc < 1) {
1581 wpa_cli_list_interfaces(ctrl);
1582 return 0;
1583 }
1584
1585 wpa_cli_close_connection();
1586 os_free(ctrl_ifname);
1587 ctrl_ifname = os_strdup(argv[0]);
1588
1589 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1590 printf("Connected to interface '%s.\n", ctrl_ifname);
1591 } else {
1592 printf("Could not connect to interface '%s' - re-trying\n",
1593 ctrl_ifname);
1594 }
1595 return 0;
1596}
1597
1598
1599static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1600 char *argv[])
1601{
1602 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1603}
1604
1605
1606static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1607 char *argv[])
1608{
1609 return wpa_ctrl_command(ctrl, "TERMINATE");
1610}
1611
1612
1613static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1614 char *argv[])
1615{
1616 char cmd[256];
1617 int res;
1618
1619 if (argc < 1) {
1620 printf("Invalid INTERFACE_ADD command: needs at least one "
1621 "argument (interface name)\n"
1622 "All arguments: ifname confname driver ctrl_interface "
1623 "driver_param bridge_name\n");
1624 return -1;
1625 }
1626
1627 /*
1628 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1629 * <driver_param>TAB<bridge_name>
1630 */
1631 res = os_snprintf(cmd, sizeof(cmd),
1632 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1633 argv[0],
1634 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1635 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1636 argc > 5 ? argv[5] : "");
1637 if (res < 0 || (size_t) res >= sizeof(cmd))
1638 return -1;
1639 cmd[sizeof(cmd) - 1] = '\0';
1640 return wpa_ctrl_command(ctrl, cmd);
1641}
1642
1643
1644static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1645 char *argv[])
1646{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001647 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001648}
1649
1650
1651static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1652 char *argv[])
1653{
1654 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1655}
1656
1657
1658#ifdef CONFIG_AP
1659static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1660{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001661 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662}
1663
1664
1665static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1666 char *addr, size_t addr_len)
1667{
1668 char buf[4096], *pos;
1669 size_t len;
1670 int ret;
1671
1672 if (ctrl_conn == NULL) {
1673 printf("Not connected to hostapd - command dropped.\n");
1674 return -1;
1675 }
1676 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001677 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001678 wpa_cli_msg_cb);
1679 if (ret == -2) {
1680 printf("'%s' command timed out.\n", cmd);
1681 return -2;
1682 } else if (ret < 0) {
1683 printf("'%s' command failed.\n", cmd);
1684 return -1;
1685 }
1686
1687 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001688 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001689 return -1;
1690 printf("%s", buf);
1691
1692 pos = buf;
1693 while (*pos != '\0' && *pos != '\n')
1694 pos++;
1695 *pos = '\0';
1696 os_strlcpy(addr, buf, addr_len);
1697 return 0;
1698}
1699
1700
1701static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1702{
1703 char addr[32], cmd[64];
1704
1705 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1706 return 0;
1707 do {
1708 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1709 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1710
1711 return -1;
1712}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001713
1714
1715static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1716 char *argv[])
1717{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001718 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001719}
1720
1721
1722static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1723 char *argv[])
1724{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001725 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001726}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001727
1728static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1729 char *argv[])
1730{
1731 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1732}
1733
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734#endif /* CONFIG_AP */
1735
1736
1737static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1738{
1739 return wpa_ctrl_command(ctrl, "SUSPEND");
1740}
1741
1742
1743static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1744{
1745 return wpa_ctrl_command(ctrl, "RESUME");
1746}
1747
1748
1749static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1750{
1751 return wpa_ctrl_command(ctrl, "DROP_SA");
1752}
1753
1754
1755static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1756{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001757 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758}
1759
1760
1761#ifdef CONFIG_P2P
1762
1763static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1764{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001765 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1766}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001768
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001769static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1770{
1771 char **res = NULL;
1772 int arg = get_cmd_arg_num(str, pos);
1773
1774 res = os_calloc(6, sizeof(char *));
1775 if (res == NULL)
1776 return NULL;
1777 res[0] = os_strdup("type=social");
1778 if (res[0] == NULL) {
1779 os_free(res);
1780 return NULL;
1781 }
1782 res[1] = os_strdup("type=progressive");
1783 if (res[1] == NULL)
1784 return res;
1785 res[2] = os_strdup("delay=");
1786 if (res[2] == NULL)
1787 return res;
1788 res[3] = os_strdup("dev_id=");
1789 if (res[3] == NULL)
1790 return res;
1791 if (arg == 1)
1792 res[4] = os_strdup("[timeout]");
1793
1794 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795}
1796
1797
1798static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1799 char *argv[])
1800{
1801 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1802}
1803
1804
1805static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1806 char *argv[])
1807{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809}
1810
1811
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001812static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1813{
1814 int arg = get_cmd_arg_num(str, pos);
1815 char **res = NULL;
1816
1817 switch (arg) {
1818 case 1:
1819 res = cli_txt_list_array(&p2p_peers);
1820 break;
1821 }
1822
1823 return res;
1824}
1825
1826
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1828 char *argv[])
1829{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001830 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831}
1832
1833
1834static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1835 char *argv[])
1836{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001837 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838}
1839
1840
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001841static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1842{
1843 int arg = get_cmd_arg_num(str, pos);
1844 char **res = NULL;
1845
1846 switch (arg) {
1847 case 1:
1848 res = cli_txt_list_array(&p2p_groups);
1849 break;
1850 }
1851
1852 return res;
1853}
1854
1855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1857 char *argv[])
1858{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001859 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860}
1861
1862
1863static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1864 char *argv[])
1865{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001866 if (argc != 2 && argc != 3) {
1867 printf("Invalid P2P_PROV_DISC command: needs at least "
1868 "two arguments, address and config method\n"
1869 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001870 return -1;
1871 }
1872
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001873 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001874}
1875
1876
1877static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1878 char *argv[])
1879{
1880 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1881}
1882
1883
1884static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1885 char *argv[])
1886{
1887 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001888
1889 if (argc != 2 && argc != 4) {
1890 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1891 "arguments (address and TLVs) or four arguments "
1892 "(address, \"upnp\", version, search target "
1893 "(SSDP ST:)\n");
1894 return -1;
1895 }
1896
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001897 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899 return wpa_ctrl_command(ctrl, cmd);
1900}
1901
1902
1903static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1904 int argc, char *argv[])
1905{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001906 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907}
1908
1909
1910static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1911 char *argv[])
1912{
1913 char cmd[4096];
1914 int res;
1915
1916 if (argc != 4) {
1917 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1918 "arguments (freq, address, dialog token, and TLVs)\n");
1919 return -1;
1920 }
1921
1922 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1923 argv[0], argv[1], argv[2], argv[3]);
1924 if (res < 0 || (size_t) res >= sizeof(cmd))
1925 return -1;
1926 cmd[sizeof(cmd) - 1] = '\0';
1927 return wpa_ctrl_command(ctrl, cmd);
1928}
1929
1930
1931static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1932 char *argv[])
1933{
1934 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1935}
1936
1937
1938static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1939 int argc, char *argv[])
1940{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001941 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942}
1943
1944
1945static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1946 char *argv[])
1947{
1948 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1949}
1950
1951
1952static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1953 char *argv[])
1954{
1955 char cmd[4096];
1956 int res;
1957
1958 if (argc != 3 && argc != 4) {
1959 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1960 "arguments\n");
1961 return -1;
1962 }
1963
1964 if (argc == 4)
1965 res = os_snprintf(cmd, sizeof(cmd),
1966 "P2P_SERVICE_ADD %s %s %s %s",
1967 argv[0], argv[1], argv[2], argv[3]);
1968 else
1969 res = os_snprintf(cmd, sizeof(cmd),
1970 "P2P_SERVICE_ADD %s %s %s",
1971 argv[0], argv[1], argv[2]);
1972 if (res < 0 || (size_t) res >= sizeof(cmd))
1973 return -1;
1974 cmd[sizeof(cmd) - 1] = '\0';
1975 return wpa_ctrl_command(ctrl, cmd);
1976}
1977
1978
1979static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1980 char *argv[])
1981{
1982 char cmd[4096];
1983 int res;
1984
1985 if (argc != 2 && argc != 3) {
1986 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1987 "arguments\n");
1988 return -1;
1989 }
1990
1991 if (argc == 3)
1992 res = os_snprintf(cmd, sizeof(cmd),
1993 "P2P_SERVICE_DEL %s %s %s",
1994 argv[0], argv[1], argv[2]);
1995 else
1996 res = os_snprintf(cmd, sizeof(cmd),
1997 "P2P_SERVICE_DEL %s %s",
1998 argv[0], argv[1]);
1999 if (res < 0 || (size_t) res >= sizeof(cmd))
2000 return -1;
2001 cmd[sizeof(cmd) - 1] = '\0';
2002 return wpa_ctrl_command(ctrl, cmd);
2003}
2004
2005
2006static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2007 int argc, char *argv[])
2008{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002009 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010}
2011
2012
2013static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2014 int argc, char *argv[])
2015{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002016 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017}
2018
2019
2020static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2021{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002022 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023}
2024
2025
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002026static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2027{
2028 int arg = get_cmd_arg_num(str, pos);
2029 char **res = NULL;
2030
2031 switch (arg) {
2032 case 1:
2033 res = cli_txt_list_array(&p2p_peers);
2034 break;
2035 }
2036
2037 return res;
2038}
2039
2040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002041static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2042 char *addr, size_t addr_len,
2043 int discovered)
2044{
2045 char buf[4096], *pos;
2046 size_t len;
2047 int ret;
2048
2049 if (ctrl_conn == NULL)
2050 return -1;
2051 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002052 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 wpa_cli_msg_cb);
2054 if (ret == -2) {
2055 printf("'%s' command timed out.\n", cmd);
2056 return -2;
2057 } else if (ret < 0) {
2058 printf("'%s' command failed.\n", cmd);
2059 return -1;
2060 }
2061
2062 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002063 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 return -1;
2065
2066 pos = buf;
2067 while (*pos != '\0' && *pos != '\n')
2068 pos++;
2069 *pos++ = '\0';
2070 os_strlcpy(addr, buf, addr_len);
2071 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2072 printf("%s\n", addr);
2073 return 0;
2074}
2075
2076
2077static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2078{
2079 char addr[32], cmd[64];
2080 int discovered;
2081
2082 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2083
2084 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2085 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002086 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002087 do {
2088 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2089 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2090 discovered) == 0);
2091
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002092 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093}
2094
2095
2096static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2097{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002098 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099}
2100
2101
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002102static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2103{
2104 int arg = get_cmd_arg_num(str, pos);
2105 const char *fields[] = {
2106 "discoverability",
2107 "managed",
2108 "listen_channel",
2109 "ssid_postfix",
2110 "noa",
2111 "ps",
2112 "oppps",
2113 "ctwindow",
2114 "disabled",
2115 "conc_pref",
2116 "force_long_sd",
2117 "peer_filter",
2118 "cross_connect",
2119 "go_apsd",
2120 "client_apsd",
2121 "disallow_freq",
2122 "disc_int",
2123 "per_sta_psk",
2124 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002125 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002126
2127 if (arg == 1) {
2128 char **res = os_calloc(num_fields + 1, sizeof(char *));
2129 if (res == NULL)
2130 return NULL;
2131 for (i = 0; i < num_fields; i++) {
2132 res[i] = os_strdup(fields[i]);
2133 if (res[i] == NULL)
2134 return res;
2135 }
2136 return res;
2137 }
2138
2139 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2140 return cli_txt_list_array(&p2p_peers);
2141
2142 return NULL;
2143}
2144
2145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2147{
2148 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2149}
2150
2151
2152static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2153 char *argv[])
2154{
2155 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2156}
2157
2158
2159static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2160 char *argv[])
2161{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002162 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002163}
2164
2165
2166static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2167 char *argv[])
2168{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 if (argc != 0 && argc != 2 && argc != 4) {
2170 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2171 "(preferred duration, interval; in microsecods).\n"
2172 "Optional second pair can be used to provide "
2173 "acceptable values.\n");
2174 return -1;
2175 }
2176
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002177 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178}
2179
2180
2181static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2182 char *argv[])
2183{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 if (argc != 0 && argc != 2) {
2185 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2186 "(availability period, availability interval; in "
2187 "millisecods).\n"
2188 "Extended Listen Timing can be cancelled with this "
2189 "command when used without parameters.\n");
2190 return -1;
2191 }
2192
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002193 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2194}
2195
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002196
2197static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2198 char *argv[])
2199{
2200 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2201}
2202
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002203#endif /* CONFIG_P2P */
2204
2205#ifdef CONFIG_WIFI_DISPLAY
2206
2207static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2208 char *argv[])
2209{
2210 char cmd[100];
2211 int res;
2212
2213 if (argc != 1 && argc != 2) {
2214 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2215 "arguments (subelem, hexdump)\n");
2216 return -1;
2217 }
2218
2219 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2220 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 if (res < 0 || (size_t) res >= sizeof(cmd))
2222 return -1;
2223 cmd[sizeof(cmd) - 1] = '\0';
2224 return wpa_ctrl_command(ctrl, cmd);
2225}
2226
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002227
2228static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
2231 char cmd[100];
2232 int res;
2233
2234 if (argc != 1) {
2235 printf("Invalid WFD_SUBELEM_GET command: needs one "
2236 "argument (subelem)\n");
2237 return -1;
2238 }
2239
2240 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2241 argv[0]);
2242 if (res < 0 || (size_t) res >= sizeof(cmd))
2243 return -1;
2244 cmd[sizeof(cmd) - 1] = '\0';
2245 return wpa_ctrl_command(ctrl, cmd);
2246}
2247#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248
2249
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002250#ifdef CONFIG_INTERWORKING
2251static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2252 char *argv[])
2253{
2254 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2255}
2256
2257
2258static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
2261 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2262}
2263
2264
2265static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2266 char *argv[])
2267{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002268 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002269}
2270
2271
2272static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2273 char *argv[])
2274{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002275 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276}
2277
2278
2279static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2280{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002281 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2282}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002283
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002284
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002285static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2286 char *argv[])
2287{
2288 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2289}
2290
2291
2292static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2293 char *argv[])
2294{
2295 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002296}
2297#endif /* CONFIG_INTERWORKING */
2298
2299
Dmitry Shmidt04949592012-07-19 12:16:46 -07002300#ifdef CONFIG_HS20
2301
2302static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2303 char *argv[])
2304{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002306}
2307
2308
2309static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2310 char *argv[])
2311{
2312 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002313
2314 if (argc == 0) {
2315 printf("Command needs one or two arguments (dst mac addr and "
2316 "optional home realm)\n");
2317 return -1;
2318 }
2319
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002320 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2321 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002322 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002323
2324 return wpa_ctrl_command(ctrl, cmd);
2325}
2326
2327#endif /* CONFIG_HS20 */
2328
2329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2331 char *argv[])
2332{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002333 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002334}
2335
2336
2337static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2338 char *argv[])
2339{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002340 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002341}
2342
2343
2344static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2345 char *argv[])
2346{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002347 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348}
2349
2350
2351static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2352 char *argv[])
2353{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002354 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002355}
2356
2357
2358static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2359 char *argv[])
2360{
2361 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2362}
2363
2364
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002365static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2366 char *argv[])
2367{
2368 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2369}
2370
2371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002372static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2373 char *argv[])
2374{
2375 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2376}
2377
Dmitry Shmidt04949592012-07-19 12:16:46 -07002378
2379#ifdef CONFIG_AUTOSCAN
2380
2381static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2382{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002383 if (argc == 0)
2384 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2385
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002387}
2388
2389#endif /* CONFIG_AUTOSCAN */
2390
2391
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002392#ifdef CONFIG_WNM
2393
2394static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2395{
2396 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2397}
2398
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002399
2400static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2401{
2402 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2403}
2404
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002405#endif /* CONFIG_WNM */
2406
2407
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002408static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2409{
2410 if (argc == 0)
2411 return -1;
2412 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2413}
2414
2415
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002416#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002417static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2418{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002419 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002420}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002421#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002422
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002424static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2425{
2426 return wpa_ctrl_command(ctrl, "FLUSH");
2427}
2428
2429
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002430static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2431{
2432 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
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 Shmidte0e48dc2013-11-18 12:00:06 -08002729 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2730 cli_cmd_flag_none,
2731 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2732 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2733 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002735 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002736 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002739 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 cli_cmd_flag_none,
2743 "<addr> = roam to the specified BSS" },
2744#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2746 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2751 cli_cmd_flag_none,
2752 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2753 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002755 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2756 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2759 "[ht40] = add a new P2P group (local end as GO)" },
2760 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2761 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 cli_cmd_flag_none,
2765 "= get the passphrase for a group (GO only)" },
2766 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 "<addr> <TLVs> = schedule service discovery request" },
2769 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002772 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773 cli_cmd_flag_none,
2774 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002775 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776 cli_cmd_flag_none,
2777 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002778 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 cli_cmd_flag_none,
2780 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002781 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 cli_cmd_flag_none,
2783 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002784 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002785 cli_cmd_flag_none,
2786 "<bonjour|upnp> <query|version> <response|service> = add a local "
2787 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 cli_cmd_flag_none,
2790 "<bonjour|upnp> <query|version> [|service] = remove a local "
2791 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 cli_cmd_flag_none,
2794 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 cli_cmd_flag_none,
2797 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002798 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002799 "[discovered] = list known (optionally, only fully discovered) P2P "
2800 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2802 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002804 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2805 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002810 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2812 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2815 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 "[<duration> <interval>] [<duration> <interval>] = request GO "
2817 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002818 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2819 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002820 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002821 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2822 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2823 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002825#ifdef CONFIG_WIFI_DISPLAY
2826 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2827 cli_cmd_flag_none,
2828 "<subelem> [contents] = set Wi-Fi Display subelement" },
2829 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2830 cli_cmd_flag_none,
2831 "<subelem> = get Wi-Fi Display subelement" },
2832#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002833#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002835 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002836 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2837 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002838 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002839 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002840 cli_cmd_flag_none,
2841 "[auto] = perform Interworking network selection" },
2842 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002843 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002844 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002845 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2846 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002847 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002848 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2849 cli_cmd_flag_none,
2850 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2851 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2852 wpa_cli_complete_bss, cli_cmd_flag_none,
2853 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002854#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002855#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2857 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002858 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2859 },
2860 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002861 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002862 "<addr> <home realm> = get HS20 nai home realm list" },
2863#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2865 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002867 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868 cli_cmd_flag_none,
2869 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002870 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002871 cli_cmd_flag_none,
2872 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002873 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002874 cli_cmd_flag_none,
2875 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002876 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 cli_cmd_flag_none,
2878 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002880 cli_cmd_flag_none,
2881 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2883 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002884 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002885#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002886 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002887 "[params] = Set or unset (if none) autoscan parameters" },
2888#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002889#ifdef CONFIG_WNM
2890 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2891 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002892 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2893 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002894#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002895 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2896 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002897 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2898 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002899#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002900 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002901 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002902#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002903 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2904 "= radio_work <show/add/done>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002905 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906};
2907
2908
2909/*
2910 * Prints command usage, lines are padded with the specified string.
2911 */
2912static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2913{
2914 char c;
2915 size_t n;
2916
2917 printf("%s%s ", pad, cmd->cmd);
2918 for (n = 0; (c = cmd->usage[n]); n++) {
2919 printf("%c", c);
2920 if (c == '\n')
2921 printf("%s", pad);
2922 }
2923 printf("\n");
2924}
2925
2926
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002927static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928{
2929 int n;
2930 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002931 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2932 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2933 print_cmd_help(&wpa_cli_commands[n], " ");
2934 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002935}
2936
2937
2938static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2939{
2940 const char *c, *delim;
2941 int n;
2942 size_t len;
2943
2944 delim = os_strchr(cmd, ' ');
2945 if (delim)
2946 len = delim - cmd;
2947 else
2948 len = os_strlen(cmd);
2949
2950 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2951 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2952 return (wpa_cli_commands[n].flags &
2953 cli_cmd_flag_sensitive);
2954 }
2955 return 0;
2956}
2957
2958
2959static char ** wpa_list_cmd_list(void)
2960{
2961 char **res;
2962 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002963 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002965 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002966 count += dl_list_len(&p2p_groups);
2967 count += dl_list_len(&ifnames);
2968 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002969 if (res == NULL)
2970 return NULL;
2971
2972 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2973 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2974 if (res[i] == NULL)
2975 break;
2976 }
2977
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002978 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2979 size_t len = 8 + os_strlen(e->txt);
2980 res[i] = os_malloc(len);
2981 if (res[i] == NULL)
2982 break;
2983 os_snprintf(res[i], len, "ifname=%s", e->txt);
2984 i++;
2985 }
2986
2987 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2988 res[i] = os_strdup(e->txt);
2989 if (res[i] == NULL)
2990 break;
2991 i++;
2992 }
2993
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994 return res;
2995}
2996
2997
2998static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2999 int pos)
3000{
3001 int i;
3002
3003 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3004 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003005 if (wpa_cli_commands[i].completion)
3006 return wpa_cli_commands[i].completion(str,
3007 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003008 edit_clear_line();
3009 printf("\r%s\n", wpa_cli_commands[i].usage);
3010 edit_redraw();
3011 break;
3012 }
3013 }
3014
3015 return NULL;
3016}
3017
3018
3019static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3020{
3021 char **res;
3022 const char *end;
3023 char *cmd;
3024
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003025 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3026 end = os_strchr(str, ' ');
3027 if (end && pos > end - str) {
3028 pos -= end - str + 1;
3029 str = end + 1;
3030 }
3031 }
3032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033 end = os_strchr(str, ' ');
3034 if (end == NULL || str + pos < end)
3035 return wpa_list_cmd_list();
3036
3037 cmd = os_malloc(pos + 1);
3038 if (cmd == NULL)
3039 return NULL;
3040 os_memcpy(cmd, str, pos);
3041 cmd[end - str] = '\0';
3042 res = wpa_cli_cmd_completion(cmd, str, pos);
3043 os_free(cmd);
3044 return res;
3045}
3046
3047
3048static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3049{
3050 struct wpa_cli_cmd *cmd, *match = NULL;
3051 int count;
3052 int ret = 0;
3053
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003054 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3055 ifname_prefix = argv[0] + 7;
3056 argv = &argv[1];
3057 argc--;
3058 } else
3059 ifname_prefix = NULL;
3060
3061 if (argc == 0)
3062 return -1;
3063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003064 count = 0;
3065 cmd = wpa_cli_commands;
3066 while (cmd->cmd) {
3067 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3068 {
3069 match = cmd;
3070 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3071 /* we have an exact match */
3072 count = 1;
3073 break;
3074 }
3075 count++;
3076 }
3077 cmd++;
3078 }
3079
3080 if (count > 1) {
3081 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3082 cmd = wpa_cli_commands;
3083 while (cmd->cmd) {
3084 if (os_strncasecmp(cmd->cmd, argv[0],
3085 os_strlen(argv[0])) == 0) {
3086 printf(" %s", cmd->cmd);
3087 }
3088 cmd++;
3089 }
3090 printf("\n");
3091 ret = 1;
3092 } else if (count == 0) {
3093 printf("Unknown command '%s'\n", argv[0]);
3094 ret = 1;
3095 } else {
3096 ret = match->handler(ctrl, argc - 1, &argv[1]);
3097 }
3098
3099 return ret;
3100}
3101
3102
3103static int str_match(const char *a, const char *b)
3104{
3105 return os_strncmp(a, b, os_strlen(b)) == 0;
3106}
3107
3108
3109static int wpa_cli_exec(const char *program, const char *arg1,
3110 const char *arg2)
3111{
3112 char *cmd;
3113 size_t len;
3114 int res;
3115 int ret = 0;
3116
3117 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3118 cmd = os_malloc(len);
3119 if (cmd == NULL)
3120 return -1;
3121 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3122 if (res < 0 || (size_t) res >= len) {
3123 os_free(cmd);
3124 return -1;
3125 }
3126 cmd[len - 1] = '\0';
3127#ifndef _WIN32_WCE
3128 if (system(cmd) < 0)
3129 ret = -1;
3130#endif /* _WIN32_WCE */
3131 os_free(cmd);
3132
3133 return ret;
3134}
3135
3136
3137static void wpa_cli_action_process(const char *msg)
3138{
3139 const char *pos;
3140 char *copy = NULL, *id, *pos2;
3141
3142 pos = msg;
3143 if (*pos == '<') {
3144 /* skip priority */
3145 pos = os_strchr(pos, '>');
3146 if (pos)
3147 pos++;
3148 else
3149 pos = msg;
3150 }
3151
3152 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3153 int new_id = -1;
3154 os_unsetenv("WPA_ID");
3155 os_unsetenv("WPA_ID_STR");
3156 os_unsetenv("WPA_CTRL_DIR");
3157
3158 pos = os_strstr(pos, "[id=");
3159 if (pos)
3160 copy = os_strdup(pos + 4);
3161
3162 if (copy) {
3163 pos2 = id = copy;
3164 while (*pos2 && *pos2 != ' ')
3165 pos2++;
3166 *pos2++ = '\0';
3167 new_id = atoi(id);
3168 os_setenv("WPA_ID", id, 1);
3169 while (*pos2 && *pos2 != '=')
3170 pos2++;
3171 if (*pos2 == '=')
3172 pos2++;
3173 id = pos2;
3174 while (*pos2 && *pos2 != ']')
3175 pos2++;
3176 *pos2 = '\0';
3177 os_setenv("WPA_ID_STR", id, 1);
3178 os_free(copy);
3179 }
3180
3181 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3182
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003183 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 wpa_cli_connected = 1;
3185 wpa_cli_last_id = new_id;
3186 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3187 }
3188 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3189 if (wpa_cli_connected) {
3190 wpa_cli_connected = 0;
3191 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3192 }
3193 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3194 wpa_cli_exec(action_file, ctrl_ifname, pos);
3195 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3196 wpa_cli_exec(action_file, ctrl_ifname, pos);
3197 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3198 wpa_cli_exec(action_file, ctrl_ifname, pos);
3199 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3200 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003201 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3202 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003203 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3204 wpa_cli_exec(action_file, ctrl_ifname, pos);
3205 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3206 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003207 } else if (str_match(pos, AP_STA_CONNECTED)) {
3208 wpa_cli_exec(action_file, ctrl_ifname, pos);
3209 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3210 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003211 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3212 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003213 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3214 printf("wpa_supplicant is terminating - stop monitoring\n");
3215 wpa_cli_quit = 1;
3216 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217}
3218
3219
3220#ifndef CONFIG_ANSI_C_EXTRA
3221static void wpa_cli_action_cb(char *msg, size_t len)
3222{
3223 wpa_cli_action_process(msg);
3224}
3225#endif /* CONFIG_ANSI_C_EXTRA */
3226
3227
3228static void wpa_cli_reconnect(void)
3229{
3230 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003231 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3232 return;
3233
3234 if (interactive) {
3235 edit_clear_line();
3236 printf("\rConnection to wpa_supplicant re-established\n");
3237 edit_redraw();
3238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239}
3240
3241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003242static void cli_event(const char *str)
3243{
3244 const char *start, *s;
3245
3246 start = os_strchr(str, '>');
3247 if (start == NULL)
3248 return;
3249
3250 start++;
3251
3252 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3253 s = os_strchr(start, ' ');
3254 if (s == NULL)
3255 return;
3256 s = os_strchr(s + 1, ' ');
3257 if (s == NULL)
3258 return;
3259 cli_txt_list_add(&bsses, s + 1);
3260 return;
3261 }
3262
3263 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3264 s = os_strchr(start, ' ');
3265 if (s == NULL)
3266 return;
3267 s = os_strchr(s + 1, ' ');
3268 if (s == NULL)
3269 return;
3270 cli_txt_list_del_addr(&bsses, s + 1);
3271 return;
3272 }
3273
3274#ifdef CONFIG_P2P
3275 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3276 s = os_strstr(start, " p2p_dev_addr=");
3277 if (s == NULL)
3278 return;
3279 cli_txt_list_add_addr(&p2p_peers, s + 14);
3280 return;
3281 }
3282
3283 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3284 s = os_strstr(start, " p2p_dev_addr=");
3285 if (s == NULL)
3286 return;
3287 cli_txt_list_del_addr(&p2p_peers, s + 14);
3288 return;
3289 }
3290
3291 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3292 s = os_strchr(start, ' ');
3293 if (s == NULL)
3294 return;
3295 cli_txt_list_add_word(&p2p_groups, s + 1);
3296 return;
3297 }
3298
3299 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3300 s = os_strchr(start, ' ');
3301 if (s == NULL)
3302 return;
3303 cli_txt_list_del_word(&p2p_groups, s + 1);
3304 return;
3305 }
3306#endif /* CONFIG_P2P */
3307}
3308
3309
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003310static int check_terminating(const char *msg)
3311{
3312 const char *pos = msg;
3313
3314 if (*pos == '<') {
3315 /* skip priority */
3316 pos = os_strchr(pos, '>');
3317 if (pos)
3318 pos++;
3319 else
3320 pos = msg;
3321 }
3322
3323 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3324 edit_clear_line();
3325 printf("\rConnection to wpa_supplicant lost - trying to "
3326 "reconnect\n");
3327 edit_redraw();
3328 wpa_cli_attached = 0;
3329 wpa_cli_close_connection();
3330 return 1;
3331 }
3332
3333 return 0;
3334}
3335
3336
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003337static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3338{
3339 if (ctrl_conn == NULL) {
3340 wpa_cli_reconnect();
3341 return;
3342 }
3343 while (wpa_ctrl_pending(ctrl) > 0) {
3344 char buf[256];
3345 size_t len = sizeof(buf) - 1;
3346 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3347 buf[len] = '\0';
3348 if (action_monitor)
3349 wpa_cli_action_process(buf);
3350 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003351 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 if (wpa_cli_show_event(buf)) {
3353 edit_clear_line();
3354 printf("\r%s\n", buf);
3355 edit_redraw();
3356 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003357
3358 if (interactive && check_terminating(buf) > 0)
3359 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003360 }
3361 } else {
3362 printf("Could not read pending message.\n");
3363 break;
3364 }
3365 }
3366
3367 if (wpa_ctrl_pending(ctrl) < 0) {
3368 printf("Connection to wpa_supplicant lost - trying to "
3369 "reconnect\n");
3370 wpa_cli_reconnect();
3371 }
3372}
3373
3374#define max_args 10
3375
3376static int tokenize_cmd(char *cmd, char *argv[])
3377{
3378 char *pos;
3379 int argc = 0;
3380
3381 pos = cmd;
3382 for (;;) {
3383 while (*pos == ' ')
3384 pos++;
3385 if (*pos == '\0')
3386 break;
3387 argv[argc] = pos;
3388 argc++;
3389 if (argc == max_args)
3390 break;
3391 if (*pos == '"') {
3392 char *pos2 = os_strrchr(pos, '"');
3393 if (pos2)
3394 pos = pos2 + 1;
3395 }
3396 while (*pos != '\0' && *pos != ' ')
3397 pos++;
3398 if (*pos == ' ')
3399 *pos++ = '\0';
3400 }
3401
3402 return argc;
3403}
3404
3405
3406static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3407{
3408 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3409 printf("Connection to wpa_supplicant lost - trying to "
3410 "reconnect\n");
3411 wpa_cli_close_connection();
3412 }
3413 if (!ctrl_conn)
3414 wpa_cli_reconnect();
3415 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3416}
3417
3418
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3420{
3421 wpa_cli_recv_pending(mon_conn, 0);
3422}
3423
3424
3425static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3426{
3427 char *argv[max_args];
3428 int argc;
3429 argc = tokenize_cmd(cmd, argv);
3430 if (argc)
3431 wpa_request(ctrl_conn, argc, argv);
3432}
3433
3434
3435static void wpa_cli_edit_eof_cb(void *ctx)
3436{
3437 eloop_terminate();
3438}
3439
3440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003441static int warning_displayed = 0;
3442static char *hfile = NULL;
3443static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003445static void start_edit(void)
3446{
3447 char *home;
3448 char *ps = NULL;
3449
3450#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3451 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3452#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453
3454 home = getenv("HOME");
3455 if (home) {
3456 const char *fname = ".wpa_cli_history";
3457 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3458 hfile = os_malloc(hfile_len);
3459 if (hfile)
3460 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3461 }
3462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003463 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3464 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3465 eloop_terminate();
3466 return;
3467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003469 edit_started = 1;
3470 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3471}
3472
3473
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003474static void update_bssid_list(struct wpa_ctrl *ctrl)
3475{
3476 char buf[4096];
3477 size_t len = sizeof(buf);
3478 int ret;
3479 char *cmd = "BSS RANGE=ALL MASK=0x2";
3480 char *pos, *end;
3481
3482 if (ctrl == NULL)
3483 return;
3484 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3485 if (ret < 0)
3486 return;
3487 buf[len] = '\0';
3488
3489 pos = buf;
3490 while (pos) {
3491 pos = os_strstr(pos, "bssid=");
3492 if (pos == NULL)
3493 break;
3494 pos += 6;
3495 end = os_strchr(pos, '\n');
3496 if (end == NULL)
3497 break;
3498 *end = '\0';
3499 cli_txt_list_add(&bsses, pos);
3500 pos = end + 1;
3501 }
3502}
3503
3504
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003505static void update_ifnames(struct wpa_ctrl *ctrl)
3506{
3507 char buf[4096];
3508 size_t len = sizeof(buf);
3509 int ret;
3510 char *cmd = "INTERFACES";
3511 char *pos, *end;
3512 char txt[200];
3513
3514 cli_txt_list_flush(&ifnames);
3515
3516 if (ctrl == NULL)
3517 return;
3518 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3519 if (ret < 0)
3520 return;
3521 buf[len] = '\0';
3522
3523 pos = buf;
3524 while (pos) {
3525 end = os_strchr(pos, '\n');
3526 if (end == NULL)
3527 break;
3528 *end = '\0';
3529 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3530 if (ret > 0 && ret < (int) sizeof(txt))
3531 cli_txt_list_add(&ifnames, txt);
3532 pos = end + 1;
3533 }
3534}
3535
3536
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003537static void try_connection(void *eloop_ctx, void *timeout_ctx)
3538{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003539 if (ctrl_conn)
3540 goto done;
3541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003542 if (ctrl_ifname == NULL)
3543 ctrl_ifname = wpa_cli_get_default_ifname();
3544
3545 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3546 if (!warning_displayed) {
3547 printf("Could not connect to wpa_supplicant: "
3548 "%s - re-trying\n", ctrl_ifname);
3549 warning_displayed = 1;
3550 }
3551 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3552 return;
3553 }
3554
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003555 update_bssid_list(ctrl_conn);
3556
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003557 if (warning_displayed)
3558 printf("Connection established.\n");
3559
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003560done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003561 start_edit();
3562}
3563
3564
3565static void wpa_cli_interactive(void)
3566{
3567 printf("\nInteractive mode\n\n");
3568
3569 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003571 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003572
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003573 cli_txt_list_flush(&p2p_peers);
3574 cli_txt_list_flush(&p2p_groups);
3575 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003576 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003577 if (edit_started)
3578 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003579 os_free(hfile);
3580 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3581 wpa_cli_close_connection();
3582}
3583
3584
3585static void wpa_cli_action(struct wpa_ctrl *ctrl)
3586{
3587#ifdef CONFIG_ANSI_C_EXTRA
3588 /* TODO: ANSI C version(?) */
3589 printf("Action processing not supported in ANSI C build.\n");
3590#else /* CONFIG_ANSI_C_EXTRA */
3591 fd_set rfds;
3592 int fd, res;
3593 struct timeval tv;
3594 char buf[256]; /* note: large enough to fit in unsolicited messages */
3595 size_t len;
3596
3597 fd = wpa_ctrl_get_fd(ctrl);
3598
3599 while (!wpa_cli_quit) {
3600 FD_ZERO(&rfds);
3601 FD_SET(fd, &rfds);
3602 tv.tv_sec = ping_interval;
3603 tv.tv_usec = 0;
3604 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3605 if (res < 0 && errno != EINTR) {
3606 perror("select");
3607 break;
3608 }
3609
3610 if (FD_ISSET(fd, &rfds))
3611 wpa_cli_recv_pending(ctrl, 1);
3612 else {
3613 /* verify that connection is still working */
3614 len = sizeof(buf) - 1;
3615 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3616 wpa_cli_action_cb) < 0 ||
3617 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3618 printf("wpa_supplicant did not reply to PING "
3619 "command - exiting\n");
3620 break;
3621 }
3622 }
3623 }
3624#endif /* CONFIG_ANSI_C_EXTRA */
3625}
3626
3627
3628static void wpa_cli_cleanup(void)
3629{
3630 wpa_cli_close_connection();
3631 if (pid_file)
3632 os_daemonize_terminate(pid_file);
3633
3634 os_program_deinit();
3635}
3636
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003637
3638static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003640 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641}
3642
3643
3644static char * wpa_cli_get_default_ifname(void)
3645{
3646 char *ifname = NULL;
3647
3648#ifdef CONFIG_CTRL_IFACE_UNIX
3649 struct dirent *dent;
3650 DIR *dir = opendir(ctrl_iface_dir);
3651 if (!dir) {
3652#ifdef ANDROID
3653 char ifprop[PROPERTY_VALUE_MAX];
3654 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3655 ifname = os_strdup(ifprop);
3656 printf("Using interface '%s'\n", ifname);
3657 return ifname;
3658 }
3659#endif /* ANDROID */
3660 return NULL;
3661 }
3662 while ((dent = readdir(dir))) {
3663#ifdef _DIRENT_HAVE_D_TYPE
3664 /*
3665 * Skip the file if it is not a socket. Also accept
3666 * DT_UNKNOWN (0) in case the C library or underlying
3667 * file system does not support d_type.
3668 */
3669 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3670 continue;
3671#endif /* _DIRENT_HAVE_D_TYPE */
3672 if (os_strcmp(dent->d_name, ".") == 0 ||
3673 os_strcmp(dent->d_name, "..") == 0)
3674 continue;
3675 printf("Selected interface '%s'\n", dent->d_name);
3676 ifname = os_strdup(dent->d_name);
3677 break;
3678 }
3679 closedir(dir);
3680#endif /* CONFIG_CTRL_IFACE_UNIX */
3681
3682#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003683 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003684 size_t len;
3685 struct wpa_ctrl *ctrl;
3686 int ret;
3687
3688 ctrl = wpa_ctrl_open(NULL);
3689 if (ctrl == NULL)
3690 return NULL;
3691
3692 len = sizeof(buf) - 1;
3693 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3694 if (ret >= 0) {
3695 buf[len] = '\0';
3696 pos = os_strchr(buf, '\n');
3697 if (pos)
3698 *pos = '\0';
3699 ifname = os_strdup(buf);
3700 }
3701 wpa_ctrl_close(ctrl);
3702#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3703
3704 return ifname;
3705}
3706
3707
3708int main(int argc, char *argv[])
3709{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710 int c;
3711 int daemonize = 0;
3712 int ret = 0;
3713 const char *global = NULL;
3714
3715 if (os_program_init())
3716 return -1;
3717
3718 for (;;) {
3719 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3720 if (c < 0)
3721 break;
3722 switch (c) {
3723 case 'a':
3724 action_file = optarg;
3725 break;
3726 case 'B':
3727 daemonize = 1;
3728 break;
3729 case 'g':
3730 global = optarg;
3731 break;
3732 case 'G':
3733 ping_interval = atoi(optarg);
3734 break;
3735 case 'h':
3736 usage();
3737 return 0;
3738 case 'v':
3739 printf("%s\n", wpa_cli_version);
3740 return 0;
3741 case 'i':
3742 os_free(ctrl_ifname);
3743 ctrl_ifname = os_strdup(optarg);
3744 break;
3745 case 'p':
3746 ctrl_iface_dir = optarg;
3747 break;
3748 case 'P':
3749 pid_file = optarg;
3750 break;
3751 default:
3752 usage();
3753 return -1;
3754 }
3755 }
3756
3757 interactive = (argc == optind) && (action_file == NULL);
3758
3759 if (interactive)
3760 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3761
3762 if (eloop_init())
3763 return -1;
3764
3765 if (global) {
3766#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3767 ctrl_conn = wpa_ctrl_open(NULL);
3768#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3769 ctrl_conn = wpa_ctrl_open(global);
3770#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3771 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003772 fprintf(stderr, "Failed to connect to wpa_supplicant "
3773 "global interface: %s error: %s\n",
3774 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003775 return -1;
3776 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003777
3778 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003779 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003780 mon_conn = wpa_ctrl_open(global);
3781 if (mon_conn) {
3782 if (wpa_ctrl_attach(mon_conn) == 0) {
3783 wpa_cli_attached = 1;
3784 eloop_register_read_sock(
3785 wpa_ctrl_get_fd(mon_conn),
3786 wpa_cli_mon_receive,
3787 NULL, NULL);
3788 } else {
3789 printf("Failed to open monitor "
3790 "connection through global "
3791 "control interface\n");
3792 }
3793 }
3794 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003795 }
3796
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003797 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798
3799 if (ctrl_ifname == NULL)
3800 ctrl_ifname = wpa_cli_get_default_ifname();
3801
3802 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003803 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 } else {
3805 if (!global &&
3806 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003807 fprintf(stderr, "Failed to connect to non-global "
3808 "ctrl_ifname: %s error: %s\n",
3809 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 return -1;
3811 }
3812
3813 if (action_file) {
3814 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3815 wpa_cli_attached = 1;
3816 } else {
3817 printf("Warning: Failed to attach to "
3818 "wpa_supplicant.\n");
3819 return -1;
3820 }
3821 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003822
3823 if (daemonize && os_daemonize(pid_file))
3824 return -1;
3825
3826 if (action_file)
3827 wpa_cli_action(ctrl_conn);
3828 else
3829 ret = wpa_request(ctrl_conn, argc - optind,
3830 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 }
3832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 os_free(ctrl_ifname);
3834 eloop_destroy();
3835 wpa_cli_cleanup();
3836
3837 return ret;
3838}
3839
3840#else /* CONFIG_CTRL_IFACE */
3841int main(int argc, char *argv[])
3842{
3843 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3844 return -1;
3845}
3846#endif /* CONFIG_CTRL_IFACE */